OLD | NEW |
1 /* .eh_frame section optimization. | 1 /* .eh_frame section optimization. |
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 | 2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, |
3 Free Software Foundation, Inc. | 3 2012 Free Software Foundation, Inc. |
4 Written by Jakub Jelinek <jakub@redhat.com>. | 4 Written by Jakub Jelinek <jakub@redhat.com>. |
5 | 5 |
6 This file is part of BFD, the Binary File Descriptor library. | 6 This file is part of BFD, the Binary File Descriptor library. |
7 | 7 |
8 This program is free software; you can redistribute it and/or modify | 8 This program is free software; you can redistribute it and/or modify |
9 it under the terms of the GNU General Public License as published by | 9 it under the terms of the GNU General Public License as published by |
10 the Free Software Foundation; either version 3 of the License, or | 10 the Free Software Foundation; either version 3 of the License, or |
11 (at your option) any later version. | 11 (at your option) any later version. |
12 | 12 |
13 This program is distributed in the hope that it will be useful, | 13 This program is distributed in the hope that it will be useful, |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 unsigned int num_cies; | 484 unsigned int num_cies; |
485 unsigned int num_entries; | 485 unsigned int num_entries; |
486 elf_gc_mark_hook_fn gc_mark_hook; | 486 elf_gc_mark_hook_fn gc_mark_hook; |
487 | 487 |
488 htab = elf_hash_table (info); | 488 htab = elf_hash_table (info); |
489 hdr_info = &htab->eh_info; | 489 hdr_info = &htab->eh_info; |
490 if (hdr_info->parsed_eh_frames) | 490 if (hdr_info->parsed_eh_frames) |
491 return; | 491 return; |
492 | 492 |
493 if (sec->size == 0 | 493 if (sec->size == 0 |
494 || sec->sec_info_type != ELF_INFO_TYPE_NONE) | 494 || sec->sec_info_type != SEC_INFO_TYPE_NONE) |
495 { | 495 { |
496 /* This file does not contain .eh_frame information. */ | 496 /* This file does not contain .eh_frame information. */ |
497 return; | 497 return; |
498 } | 498 } |
499 | 499 |
500 if (bfd_is_abs_section (sec->output_section)) | 500 if (bfd_is_abs_section (sec->output_section)) |
501 { | 501 { |
502 /* At least one of the sections is being discarded from the | 502 /* At least one of the sections is being discarded from the |
503 link, so we should just ignore them. */ | 503 link, so we should just ignore them. */ |
504 return; | 504 return; |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 | 897 |
898 this_inf->removed = 1; | 898 this_inf->removed = 1; |
899 this_inf->fde_encoding = cie->fde_encoding; | 899 this_inf->fde_encoding = cie->fde_encoding; |
900 this_inf->lsda_encoding = cie->lsda_encoding; | 900 this_inf->lsda_encoding = cie->lsda_encoding; |
901 sec_info->count++; | 901 sec_info->count++; |
902 } | 902 } |
903 BFD_ASSERT (sec_info->count == num_entries); | 903 BFD_ASSERT (sec_info->count == num_entries); |
904 BFD_ASSERT (cie_count == num_cies); | 904 BFD_ASSERT (cie_count == num_cies); |
905 | 905 |
906 elf_section_data (sec)->sec_info = sec_info; | 906 elf_section_data (sec)->sec_info = sec_info; |
907 sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME; | 907 sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME; |
908 if (hdr_info->merge_cies) | 908 if (hdr_info->merge_cies) |
909 { | 909 { |
910 sec_info->cies = local_cies; | 910 sec_info->cies = local_cies; |
911 local_cies = NULL; | 911 local_cies = NULL; |
912 } | 912 } |
913 goto success; | 913 goto success; |
914 | 914 |
915 free_no_table: | 915 free_no_table: |
916 (*info->callbacks->einfo) | 916 (*info->callbacks->einfo) |
917 (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), | 917 (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 _bfd_elf_discard_section_eh_frame | 1130 _bfd_elf_discard_section_eh_frame |
1131 (bfd *abfd, struct bfd_link_info *info, asection *sec, | 1131 (bfd *abfd, struct bfd_link_info *info, asection *sec, |
1132 bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *), | 1132 bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *), |
1133 struct elf_reloc_cookie *cookie) | 1133 struct elf_reloc_cookie *cookie) |
1134 { | 1134 { |
1135 struct eh_cie_fde *ent; | 1135 struct eh_cie_fde *ent; |
1136 struct eh_frame_sec_info *sec_info; | 1136 struct eh_frame_sec_info *sec_info; |
1137 struct eh_frame_hdr_info *hdr_info; | 1137 struct eh_frame_hdr_info *hdr_info; |
1138 unsigned int ptr_size, offset; | 1138 unsigned int ptr_size, offset; |
1139 | 1139 |
1140 if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) | 1140 if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME) |
1141 return FALSE; | 1141 return FALSE; |
1142 | 1142 |
1143 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; | 1143 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; |
1144 if (sec_info == NULL) | 1144 if (sec_info == NULL) |
1145 return FALSE; | 1145 return FALSE; |
1146 | 1146 |
1147 ptr_size = (get_elf_backend_data (sec->owner) | 1147 ptr_size = (get_elf_backend_data (sec->owner) |
1148 ->elf_backend_eh_frame_address_size (sec->owner, sec)); | 1148 ->elf_backend_eh_frame_address_size (sec->owner, sec)); |
1149 | 1149 |
1150 hdr_info = &elf_hash_table (info)->eh_info; | 1150 hdr_info = &elf_hash_table (info)->eh_info; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 return FALSE; | 1240 return FALSE; |
1241 | 1241 |
1242 sec->size = EH_FRAME_HDR_SIZE; | 1242 sec->size = EH_FRAME_HDR_SIZE; |
1243 if (hdr_info->table) | 1243 if (hdr_info->table) |
1244 sec->size += 4 + hdr_info->fde_count * 8; | 1244 sec->size += 4 + hdr_info->fde_count * 8; |
1245 | 1245 |
1246 elf_tdata (abfd)->eh_frame_hdr = sec; | 1246 elf_tdata (abfd)->eh_frame_hdr = sec; |
1247 return TRUE; | 1247 return TRUE; |
1248 } | 1248 } |
1249 | 1249 |
| 1250 /* Return true if there is at least one non-empty .eh_frame section in |
| 1251 input files. Can only be called after ld has mapped input to |
| 1252 output sections, and before sections are stripped. */ |
| 1253 bfd_boolean |
| 1254 _bfd_elf_eh_frame_present (struct bfd_link_info *info) |
| 1255 { |
| 1256 asection *eh = bfd_get_section_by_name (info->output_bfd, ".eh_frame"); |
| 1257 |
| 1258 if (eh == NULL) |
| 1259 return FALSE; |
| 1260 |
| 1261 /* Count only sections which have at least a single CIE or FDE. |
| 1262 There cannot be any CIE or FDE <= 8 bytes. */ |
| 1263 for (eh = eh->map_head.s; eh != NULL; eh = eh->map_head.s) |
| 1264 if (eh->size > 8) |
| 1265 return TRUE; |
| 1266 |
| 1267 return FALSE; |
| 1268 } |
| 1269 |
1250 /* This function is called from size_dynamic_sections. | 1270 /* This function is called from size_dynamic_sections. |
1251 It needs to decide whether .eh_frame_hdr should be output or not, | 1271 It needs to decide whether .eh_frame_hdr should be output or not, |
1252 because when the dynamic symbol table has been sized it is too late | 1272 because when the dynamic symbol table has been sized it is too late |
1253 to strip sections. */ | 1273 to strip sections. */ |
1254 | 1274 |
1255 bfd_boolean | 1275 bfd_boolean |
1256 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) | 1276 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) |
1257 { | 1277 { |
1258 asection *o; | |
1259 bfd *abfd; | |
1260 struct elf_link_hash_table *htab; | 1278 struct elf_link_hash_table *htab; |
1261 struct eh_frame_hdr_info *hdr_info; | 1279 struct eh_frame_hdr_info *hdr_info; |
1262 | 1280 |
1263 htab = elf_hash_table (info); | 1281 htab = elf_hash_table (info); |
1264 hdr_info = &htab->eh_info; | 1282 hdr_info = &htab->eh_info; |
1265 if (hdr_info->hdr_sec == NULL) | 1283 if (hdr_info->hdr_sec == NULL) |
1266 return TRUE; | 1284 return TRUE; |
1267 | 1285 |
1268 if (bfd_is_abs_section (hdr_info->hdr_sec->output_section)) | 1286 if (bfd_is_abs_section (hdr_info->hdr_sec->output_section) |
1269 { | 1287 || !info->eh_frame_hdr |
1270 hdr_info->hdr_sec = NULL; | 1288 || !_bfd_elf_eh_frame_present (info)) |
1271 return TRUE; | |
1272 } | |
1273 | |
1274 abfd = NULL; | |
1275 if (info->eh_frame_hdr) | |
1276 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next) | |
1277 { | |
1278 » /* Count only sections which have at least a single CIE or FDE. | |
1279 » There cannot be any CIE or FDE <= 8 bytes. */ | |
1280 » o = bfd_get_section_by_name (abfd, ".eh_frame"); | |
1281 » if (o && o->size > 8 && !bfd_is_abs_section (o->output_section)) | |
1282 » break; | |
1283 } | |
1284 | |
1285 if (abfd == NULL) | |
1286 { | 1289 { |
1287 hdr_info->hdr_sec->flags |= SEC_EXCLUDE; | 1290 hdr_info->hdr_sec->flags |= SEC_EXCLUDE; |
1288 hdr_info->hdr_sec = NULL; | 1291 hdr_info->hdr_sec = NULL; |
1289 return TRUE; | 1292 return TRUE; |
1290 } | 1293 } |
1291 | 1294 |
1292 hdr_info->table = TRUE; | 1295 hdr_info->table = TRUE; |
1293 return TRUE; | 1296 return TRUE; |
1294 } | 1297 } |
1295 | 1298 |
1296 /* Adjust an address in the .eh_frame section. Given OFFSET within | 1299 /* Adjust an address in the .eh_frame section. Given OFFSET within |
1297 SEC, this returns the new offset in the adjusted .eh_frame section, | 1300 SEC, this returns the new offset in the adjusted .eh_frame section, |
1298 or -1 if the address refers to a CIE/FDE which has been removed | 1301 or -1 if the address refers to a CIE/FDE which has been removed |
1299 or to offset with dynamic relocation which is no longer needed. */ | 1302 or to offset with dynamic relocation which is no longer needed. */ |
1300 | 1303 |
1301 bfd_vma | 1304 bfd_vma |
1302 _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, | 1305 _bfd_elf_eh_frame_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, |
1303 struct bfd_link_info *info ATTRIBUTE_UNUSED, | 1306 struct bfd_link_info *info ATTRIBUTE_UNUSED, |
1304 asection *sec, | 1307 asection *sec, |
1305 bfd_vma offset) | 1308 bfd_vma offset) |
1306 { | 1309 { |
1307 struct eh_frame_sec_info *sec_info; | 1310 struct eh_frame_sec_info *sec_info; |
1308 unsigned int lo, hi, mid; | 1311 unsigned int lo, hi, mid; |
1309 | 1312 |
1310 if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) | 1313 if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME) |
1311 return offset; | 1314 return offset; |
1312 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; | 1315 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; |
1313 | 1316 |
1314 if (offset >= sec->rawsize) | 1317 if (offset >= sec->rawsize) |
1315 return offset - sec->rawsize + sec->size; | 1318 return offset - sec->rawsize + sec->size; |
1316 | 1319 |
1317 lo = 0; | 1320 lo = 0; |
1318 hi = sec_info->count; | 1321 hi = sec_info->count; |
1319 mid = 0; | 1322 mid = 0; |
1320 while (lo < hi) | 1323 while (lo < hi) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 struct bfd_link_info *info, | 1391 struct bfd_link_info *info, |
1389 asection *sec, | 1392 asection *sec, |
1390 bfd_byte *contents) | 1393 bfd_byte *contents) |
1391 { | 1394 { |
1392 struct eh_frame_sec_info *sec_info; | 1395 struct eh_frame_sec_info *sec_info; |
1393 struct elf_link_hash_table *htab; | 1396 struct elf_link_hash_table *htab; |
1394 struct eh_frame_hdr_info *hdr_info; | 1397 struct eh_frame_hdr_info *hdr_info; |
1395 unsigned int ptr_size; | 1398 unsigned int ptr_size; |
1396 struct eh_cie_fde *ent; | 1399 struct eh_cie_fde *ent; |
1397 | 1400 |
1398 if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) | 1401 if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME) |
1399 /* FIXME: octets_per_byte. */ | 1402 /* FIXME: octets_per_byte. */ |
1400 return bfd_set_section_contents (abfd, sec->output_section, contents, | 1403 return bfd_set_section_contents (abfd, sec->output_section, contents, |
1401 sec->output_offset, sec->size); | 1404 sec->output_offset, sec->size); |
1402 | 1405 |
1403 ptr_size = (get_elf_backend_data (abfd) | 1406 ptr_size = (get_elf_backend_data (abfd) |
1404 ->elf_backend_eh_frame_address_size (abfd, sec)); | 1407 ->elf_backend_eh_frame_address_size (abfd, sec)); |
1405 BFD_ASSERT (ptr_size != 0); | 1408 BFD_ASSERT (ptr_size != 0); |
1406 | 1409 |
1407 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; | 1410 sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; |
1408 htab = elf_hash_table (info); | 1411 htab = elf_hash_table (info); |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1864 _bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED, | 1867 _bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED, |
1865 struct bfd_link_info *info ATTRIBUTE_UNUSED, | 1868 struct bfd_link_info *info ATTRIBUTE_UNUSED, |
1866 asection *osec, bfd_vma offset, | 1869 asection *osec, bfd_vma offset, |
1867 asection *loc_sec, bfd_vma loc_offset, | 1870 asection *loc_sec, bfd_vma loc_offset, |
1868 bfd_vma *encoded) | 1871 bfd_vma *encoded) |
1869 { | 1872 { |
1870 *encoded = osec->vma + offset - | 1873 *encoded = osec->vma + offset - |
1871 (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset); | 1874 (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset); |
1872 return DW_EH_PE_pcrel | DW_EH_PE_sdata4; | 1875 return DW_EH_PE_pcrel | DW_EH_PE_sdata4; |
1873 } | 1876 } |
OLD | NEW |