Rev 5197 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5197 | Rev 6324 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* .eh_frame section optimization. |
1 | /* .eh_frame section optimization. |
2 | Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, |
- | |
3 | 2012 Free Software Foundation, Inc. |
2 | Copyright (C) 2001-2015 Free Software Foundation, Inc. |
4 | Written by Jakub Jelinek |
3 | Written by Jakub Jelinek |
Line 5... | Line 4... | ||
5 | 4 | ||
Line 6... | Line 5... | ||
6 | This file is part of BFD, the Binary File Descriptor library. |
5 | This file is part of BFD, the Binary File Descriptor library. |
Line 39... | Line 38... | ||
39 | bfd_signed_vma data_align; |
38 | bfd_signed_vma data_align; |
40 | bfd_vma ra_column; |
39 | bfd_vma ra_column; |
41 | bfd_vma augmentation_size; |
40 | bfd_vma augmentation_size; |
42 | union { |
41 | union { |
43 | struct elf_link_hash_entry *h; |
42 | struct elf_link_hash_entry *h; |
- | 43 | struct { |
|
- | 44 | unsigned int bfd_id; |
|
- | 45 | unsigned int index; |
|
44 | bfd_vma val; |
46 | } sym; |
45 | unsigned int reloc_index; |
47 | unsigned int reloc_index; |
46 | } personality; |
48 | } personality; |
47 | asection *output_sec; |
- | |
48 | struct eh_cie_fde *cie_inf; |
49 | struct eh_cie_fde *cie_inf; |
49 | unsigned char per_encoding; |
50 | unsigned char per_encoding; |
50 | unsigned char lsda_encoding; |
51 | unsigned char lsda_encoding; |
51 | unsigned char fde_encoding; |
52 | unsigned char fde_encoding; |
52 | unsigned char initial_insn_length; |
53 | unsigned char initial_insn_length; |
Line 228... | Line 229... | ||
228 | && c1->data_align == c2->data_align |
229 | && c1->data_align == c2->data_align |
229 | && c1->ra_column == c2->ra_column |
230 | && c1->ra_column == c2->ra_column |
230 | && c1->augmentation_size == c2->augmentation_size |
231 | && c1->augmentation_size == c2->augmentation_size |
231 | && memcmp (&c1->personality, &c2->personality, |
232 | && memcmp (&c1->personality, &c2->personality, |
232 | sizeof (c1->personality)) == 0 |
233 | sizeof (c1->personality)) == 0 |
233 | && c1->output_sec == c2->output_sec |
234 | && (c1->cie_inf->u.cie.u.sec->output_section |
- | 235 | == c2->cie_inf->u.cie.u.sec->output_section) |
|
234 | && c1->per_encoding == c2->per_encoding |
236 | && c1->per_encoding == c2->per_encoding |
235 | && c1->lsda_encoding == c2->lsda_encoding |
237 | && c1->lsda_encoding == c2->lsda_encoding |
236 | && c1->fde_encoding == c2->fde_encoding |
238 | && c1->fde_encoding == c2->fde_encoding |
237 | && c1->initial_insn_length == c2->initial_insn_length |
239 | && c1->initial_insn_length == c2->initial_insn_length |
- | 240 | && c1->initial_insn_length <= sizeof (c1->initial_instructions) |
|
238 | && memcmp (c1->initial_instructions, |
241 | && memcmp (c1->initial_instructions, |
239 | c2->initial_instructions, |
242 | c2->initial_instructions, |
240 | c1->initial_insn_length) == 0) |
243 | c1->initial_insn_length) == 0) |
241 | return 1; |
244 | return 1; |
Line 252... | Line 255... | ||
252 | 255 | ||
253 | static hashval_t |
256 | static hashval_t |
254 | cie_compute_hash (struct cie *c) |
257 | cie_compute_hash (struct cie *c) |
255 | { |
258 | { |
- | 259 | hashval_t h = 0; |
|
256 | hashval_t h = 0; |
260 | size_t len; |
257 | h = iterative_hash_object (c->length, h); |
261 | h = iterative_hash_object (c->length, h); |
258 | h = iterative_hash_object (c->version, h); |
262 | h = iterative_hash_object (c->version, h); |
259 | h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h); |
263 | h = iterative_hash (c->augmentation, strlen (c->augmentation) + 1, h); |
260 | h = iterative_hash_object (c->code_align, h); |
264 | h = iterative_hash_object (c->code_align, h); |
261 | h = iterative_hash_object (c->data_align, h); |
265 | h = iterative_hash_object (c->data_align, h); |
262 | h = iterative_hash_object (c->ra_column, h); |
266 | h = iterative_hash_object (c->ra_column, h); |
263 | h = iterative_hash_object (c->augmentation_size, h); |
267 | h = iterative_hash_object (c->augmentation_size, h); |
264 | h = iterative_hash_object (c->personality, h); |
268 | h = iterative_hash_object (c->personality, h); |
265 | h = iterative_hash_object (c->output_sec, h); |
269 | h = iterative_hash_object (c->cie_inf->u.cie.u.sec->output_section, h); |
266 | h = iterative_hash_object (c->per_encoding, h); |
270 | h = iterative_hash_object (c->per_encoding, h); |
267 | h = iterative_hash_object (c->lsda_encoding, h); |
271 | h = iterative_hash_object (c->lsda_encoding, h); |
268 | h = iterative_hash_object (c->fde_encoding, h); |
272 | h = iterative_hash_object (c->fde_encoding, h); |
- | 273 | h = iterative_hash_object (c->initial_insn_length, h); |
|
- | 274 | len = c->initial_insn_length; |
|
- | 275 | if (len > sizeof (c->initial_instructions)) |
|
269 | h = iterative_hash_object (c->initial_insn_length, h); |
276 | len = sizeof (c->initial_instructions); |
270 | h = iterative_hash (c->initial_instructions, c->initial_insn_length, h); |
277 | h = iterative_hash (c->initial_instructions, len, h); |
271 | c->hash = h; |
278 | c->hash = h; |
272 | return h; |
279 | return h; |
Line 273... | Line 280... | ||
273 | } |
280 | } |
Line 443... | Line 450... | ||
443 | break; |
450 | break; |
444 | } |
451 | } |
445 | return encoding | DW_EH_PE_pcrel; |
452 | return encoding | DW_EH_PE_pcrel; |
446 | } |
453 | } |
Line 447... | Line 454... | ||
447 | 454 | ||
448 | /* Called before calling _bfd_elf_parse_eh_frame on every input bfd's |
455 | /* Examine each .eh_frame_entry section and discard those |
Line 449... | Line 456... | ||
449 | .eh_frame section. */ |
456 | those that are marked SEC_EXCLUDE. */ |
- | 457 | ||
- | 458 | static void |
|
- | 459 | bfd_elf_discard_eh_frame_entry (struct eh_frame_hdr_info *hdr_info) |
|
- | 460 | { |
|
- | 461 | unsigned int i; |
|
- | 462 | for (i = 0; i < hdr_info->array_count; i++) |
|
- | 463 | { |
|
- | 464 | if (hdr_info->u.compact.entries[i]->flags & SEC_EXCLUDE) |
|
- | 465 | { |
|
- | 466 | unsigned int j; |
|
- | 467 | for (j = i + 1; j < hdr_info->array_count; j++) |
|
- | 468 | hdr_info->u.compact.entries[j-1] = hdr_info->u.compact.entries[j]; |
|
- | 469 | ||
- | 470 | hdr_info->array_count--; |
|
- | 471 | hdr_info->u.compact.entries[hdr_info->array_count] = NULL; |
|
- | 472 | i--; |
|
- | 473 | } |
|
- | 474 | } |
|
- | 475 | } |
|
- | 476 | ||
- | 477 | /* Add a .eh_frame_entry section. */ |
|
450 | 478 | ||
- | 479 | static void |
|
- | 480 | bfd_elf_record_eh_frame_entry (struct eh_frame_hdr_info *hdr_info, |
|
- | 481 | asection *sec) |
|
451 | void |
482 | { |
- | 483 | if (hdr_info->array_count == hdr_info->u.compact.allocated_entries) |
|
- | 484 | { |
|
- | 485 | if (hdr_info->u.compact.allocated_entries == 0) |
|
- | 486 | { |
|
- | 487 | hdr_info->frame_hdr_is_compact = TRUE; |
|
- | 488 | hdr_info->u.compact.allocated_entries = 2; |
|
- | 489 | hdr_info->u.compact.entries = |
|
- | 490 | bfd_malloc (hdr_info->u.compact.allocated_entries |
|
- | 491 | * sizeof (hdr_info->u.compact.entries[0])); |
|
- | 492 | } |
|
- | 493 | else |
|
- | 494 | { |
|
- | 495 | hdr_info->u.compact.allocated_entries *= 2; |
|
- | 496 | hdr_info->u.compact.entries = |
|
- | 497 | bfd_realloc (hdr_info->u.compact.entries, |
|
- | 498 | hdr_info->u.compact.allocated_entries |
|
- | 499 | * sizeof (hdr_info->u.compact.entries[0])); |
|
- | 500 | } |
|
- | 501 | ||
- | 502 | BFD_ASSERT (hdr_info->u.compact.entries); |
|
- | 503 | } |
|
- | 504 | ||
- | 505 | hdr_info->u.compact.entries[hdr_info->array_count++] = sec; |
|
- | 506 | } |
|
- | 507 | ||
- | 508 | /* Parse a .eh_frame_entry section. Figure out which text section it |
|
- | 509 | references. */ |
|
- | 510 | ||
- | 511 | bfd_boolean |
|
- | 512 | _bfd_elf_parse_eh_frame_entry (struct bfd_link_info *info, |
|
- | 513 | asection *sec, struct elf_reloc_cookie *cookie) |
|
452 | _bfd_elf_begin_eh_frame_parsing (struct bfd_link_info *info) |
514 | { |
- | 515 | struct elf_link_hash_table *htab; |
|
- | 516 | struct eh_frame_hdr_info *hdr_info; |
|
Line 453... | Line 517... | ||
453 | { |
517 | unsigned long r_symndx; |
454 | struct eh_frame_hdr_info *hdr_info; |
518 | asection *text_sec; |
- | 519 | ||
- | 520 | htab = elf_hash_table (info); |
|
- | 521 | hdr_info = &htab->eh_info; |
|
- | 522 | ||
- | 523 | if (sec->size == 0 |
|
- | 524 | || sec->sec_info_type != SEC_INFO_TYPE_NONE) |
|
- | 525 | { |
|
- | 526 | return TRUE; |
|
- | 527 | } |
|
- | 528 | ||
- | 529 | if (sec->output_section && bfd_is_abs_section (sec->output_section)) |
|
- | 530 | { |
|
- | 531 | /* At least one of the sections is being discarded from the |
|
- | 532 | link, so we should just ignore them. */ |
|
- | 533 | return TRUE; |
|
- | 534 | } |
|
- | 535 | ||
- | 536 | if (cookie->rel == cookie->relend) |
|
- | 537 | return FALSE; |
|
- | 538 | ||
- | 539 | /* The first relocation is the function start. */ |
|
- | 540 | r_symndx = cookie->rel->r_info >> cookie->r_sym_shift; |
|
- | 541 | if (r_symndx == STN_UNDEF) |
|
- | 542 | return FALSE; |
|
- | 543 | ||
- | 544 | text_sec = _bfd_elf_section_for_symbol (cookie, r_symndx, FALSE); |
|
- | 545 | ||
- | 546 | if (text_sec == NULL) |
|
- | 547 | return FALSE; |
|
- | 548 | ||
- | 549 | elf_section_eh_frame_entry (text_sec) = sec; |
|
- | 550 | if (text_sec->output_section |
|
- | 551 | && bfd_is_abs_section (text_sec->output_section)) |
|
- | 552 | sec->flags |= SEC_EXCLUDE; |
|
- | 553 | ||
- | 554 | sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME_ENTRY; |
|
455 | 555 | elf_section_data (sec)->sec_info = text_sec; |
|
Line 456... | Line 556... | ||
456 | hdr_info = &elf_hash_table (info)->eh_info; |
556 | bfd_elf_record_eh_frame_entry (hdr_info, sec); |
457 | hdr_info->merge_cies = !info->relocatable; |
557 | return TRUE; |
458 | } |
558 | } |
Line 485... | Line 585... | ||
485 | unsigned int num_entries; |
585 | unsigned int num_entries; |
486 | elf_gc_mark_hook_fn gc_mark_hook; |
586 | elf_gc_mark_hook_fn gc_mark_hook; |
Line 487... | Line 587... | ||
487 | 587 | ||
488 | htab = elf_hash_table (info); |
588 | htab = elf_hash_table (info); |
489 | hdr_info = &htab->eh_info; |
- | |
490 | if (hdr_info->parsed_eh_frames) |
- | |
Line 491... | Line 589... | ||
491 | return; |
589 | hdr_info = &htab->eh_info; |
492 | 590 | ||
493 | if (sec->size == 0 |
591 | if (sec->size == 0 |
494 | || sec->sec_info_type != SEC_INFO_TYPE_NONE) |
592 | || sec->sec_info_type != SEC_INFO_TYPE_NONE) |
Line 561... | Line 659... | ||
561 | local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies)); |
659 | local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies)); |
562 | REQUIRE (local_cies); |
660 | REQUIRE (local_cies); |
Line 563... | Line 661... | ||
563 | 661 | ||
564 | /* FIXME: octets_per_byte. */ |
662 | /* FIXME: octets_per_byte. */ |
565 | #define ENSURE_NO_RELOCS(buf) \ |
663 | #define ENSURE_NO_RELOCS(buf) \ |
566 | REQUIRE (!(cookie->rel < cookie->relend \ |
664 | while (cookie->rel < cookie->relend \ |
567 | && (cookie->rel->r_offset \ |
665 | && (cookie->rel->r_offset \ |
- | 666 | < (bfd_size_type) ((buf) - ehbuf))) \ |
|
568 | < (bfd_size_type) ((buf) - ehbuf)) \ |
667 | { \ |
- | 668 | REQUIRE (cookie->rel->r_info == 0); \ |
|
- | 669 | cookie->rel++; \ |
|
Line 569... | Line 670... | ||
569 | && cookie->rel->r_info != 0)) |
670 | } |
570 | 671 | ||
571 | /* FIXME: octets_per_byte. */ |
672 | /* FIXME: octets_per_byte. */ |
572 | #define SKIP_RELOCS(buf) \ |
673 | #define SKIP_RELOCS(buf) \ |
Line 630... | Line 731... | ||
630 | /* Point CIE to one of the section-local cie structures. */ |
731 | /* Point CIE to one of the section-local cie structures. */ |
631 | cie = local_cies + cie_count++; |
732 | cie = local_cies + cie_count++; |
Line 632... | Line 733... | ||
632 | 733 | ||
633 | cie->cie_inf = this_inf; |
734 | cie->cie_inf = this_inf; |
634 | cie->length = hdr_length; |
- | |
635 | cie->output_sec = sec->output_section; |
735 | cie->length = hdr_length; |
636 | start = buf; |
736 | start = buf; |
Line 637... | Line 737... | ||
637 | REQUIRE (read_byte (&buf, end, &cie->version)); |
737 | REQUIRE (read_byte (&buf, end, &cie->version)); |
638 | 738 | ||
Line 731... | Line 831... | ||
731 | } |
831 | } |
732 | } |
832 | } |
Line 733... | Line 833... | ||
733 | 833 | ||
734 | /* For shared libraries, try to get rid of as many RELATIVE relocs |
834 | /* For shared libraries, try to get rid of as many RELATIVE relocs |
735 | as possible. */ |
835 | as possible. */ |
736 | if (info->shared |
836 | if (bfd_link_pic (info) |
737 | && (get_elf_backend_data (abfd) |
837 | && (get_elf_backend_data (abfd) |
738 | ->elf_backend_can_make_relative_eh_frame |
838 | ->elf_backend_can_make_relative_eh_frame |
739 | (abfd, info, sec))) |
839 | (abfd, info, sec))) |
740 | { |
840 | { |
Line 760... | Line 860... | ||
760 | DW_EH_absptr. */ |
860 | DW_EH_absptr. */ |
761 | if (cie->fde_encoding == DW_EH_PE_omit) |
861 | if (cie->fde_encoding == DW_EH_PE_omit) |
762 | cie->fde_encoding = DW_EH_PE_absptr; |
862 | cie->fde_encoding = DW_EH_PE_absptr; |
Line 763... | Line 863... | ||
763 | 863 | ||
764 | initial_insn_length = end - buf; |
- | |
765 | if (initial_insn_length <= sizeof (cie->initial_instructions)) |
- | |
766 | { |
864 | initial_insn_length = end - buf; |
767 | cie->initial_insn_length = initial_insn_length; |
865 | cie->initial_insn_length = initial_insn_length; |
768 | memcpy (cie->initial_instructions, buf, initial_insn_length); |
866 | memcpy (cie->initial_instructions, buf, |
- | 867 | initial_insn_length <= sizeof (cie->initial_instructions) |
|
769 | } |
868 | ? initial_insn_length : sizeof (cie->initial_instructions)); |
770 | insns = buf; |
869 | insns = buf; |
771 | buf += initial_insn_length; |
870 | buf += initial_insn_length; |
Line 772... | Line 871... | ||
772 | ENSURE_NO_RELOCS (buf); |
871 | ENSURE_NO_RELOCS (buf); |
- | 872 | ||
- | 873 | if (!bfd_link_relocatable (info)) |
|
773 | 874 | { |
|
774 | if (hdr_info->merge_cies) |
875 | /* Keep info for merging cies. */ |
775 | this_inf->u.cie.u.full_cie = cie; |
876 | this_inf->u.cie.u.full_cie = cie; |
776 | this_inf->u.cie.per_encoding_relative |
877 | this_inf->u.cie.per_encoding_relative |
- | 878 | = (cie->per_encoding & 0x70) == DW_EH_PE_pcrel; |
|
777 | = (cie->per_encoding & 0x70) == DW_EH_PE_pcrel; |
879 | } |
778 | } |
880 | } |
779 | else |
881 | else |
780 | { |
882 | { |
781 | /* Find the corresponding CIE. */ |
883 | /* Find the corresponding CIE. */ |
Line 798... | Line 900... | ||
798 | asection *rsec; |
900 | asection *rsec; |
Line 799... | Line 901... | ||
799 | 901 | ||
Line 800... | Line 902... | ||
800 | REQUIRE (GET_RELOC (buf)); |
902 | REQUIRE (GET_RELOC (buf)); |
801 | 903 | ||
- | 904 | /* Chain together the FDEs for each section. */ |
|
802 | /* Chain together the FDEs for each section. */ |
905 | rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, |
803 | rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); |
906 | cookie, NULL); |
804 | /* RSEC will be NULL if FDE was cleared out as it was belonging to |
907 | /* RSEC will be NULL if FDE was cleared out as it was belonging to |
805 | a discarded SHT_GROUP. */ |
908 | a discarded SHT_GROUP. */ |
806 | if (rsec) |
909 | if (rsec) |
Line 814... | Line 917... | ||
814 | /* Skip the initial location and address range. */ |
917 | /* Skip the initial location and address range. */ |
815 | start = buf; |
918 | start = buf; |
816 | length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size); |
919 | length = get_DW_EH_PE_width (cie->fde_encoding, ptr_size); |
817 | REQUIRE (skip_bytes (&buf, end, 2 * length)); |
920 | REQUIRE (skip_bytes (&buf, end, 2 * length)); |
Line -... | Line 921... | ||
- | 921 | ||
- | 922 | SKIP_RELOCS (buf - length); |
|
- | 923 | if (!GET_RELOC (buf - length) |
|
- | 924 | && read_value (abfd, buf - length, length, FALSE) == 0) |
|
- | 925 | { |
|
- | 926 | (*info->callbacks->minfo) |
|
- | 927 | (_("discarding zero address range FDE in %B(%A).\n"), |
|
- | 928 | abfd, sec); |
|
- | 929 | this_inf->u.fde.cie_inf = NULL; |
|
- | 930 | } |
|
818 | 931 | ||
819 | /* Skip the augmentation size, if present. */ |
932 | /* Skip the augmentation size, if present. */ |
820 | if (cie->augmentation[0] == 'z') |
933 | if (cie->augmentation[0] == 'z') |
821 | REQUIRE (read_uleb128 (&buf, end, &length)); |
934 | REQUIRE (read_uleb128 (&buf, end, &length)); |
822 | else |
935 | else |
Line 903... | Line 1016... | ||
903 | BFD_ASSERT (sec_info->count == num_entries); |
1016 | BFD_ASSERT (sec_info->count == num_entries); |
904 | BFD_ASSERT (cie_count == num_cies); |
1017 | BFD_ASSERT (cie_count == num_cies); |
Line 905... | Line 1018... | ||
905 | 1018 | ||
906 | elf_section_data (sec)->sec_info = sec_info; |
1019 | elf_section_data (sec)->sec_info = sec_info; |
907 | sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME; |
1020 | sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME; |
908 | if (hdr_info->merge_cies) |
1021 | if (!bfd_link_relocatable (info)) |
- | 1022 | { |
|
909 | { |
1023 | /* Keep info for merging cies. */ |
910 | sec_info->cies = local_cies; |
1024 | sec_info->cies = local_cies; |
911 | local_cies = NULL; |
1025 | local_cies = NULL; |
912 | } |
1026 | } |
Line 913... | Line 1027... | ||
913 | goto success; |
1027 | goto success; |
914 | 1028 | ||
915 | free_no_table: |
1029 | free_no_table: |
916 | (*info->callbacks->einfo) |
1030 | (*info->callbacks->einfo) |
917 | (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), |
1031 | (_("%P: error in %B(%A); no .eh_frame_hdr table will be created.\n"), |
918 | abfd, sec); |
1032 | abfd, sec); |
919 | hdr_info->table = FALSE; |
1033 | hdr_info->u.dwarf.table = FALSE; |
920 | if (sec_info) |
1034 | if (sec_info) |
921 | free (sec_info); |
1035 | free (sec_info); |
922 | success: |
1036 | success: |
923 | if (ehbuf) |
1037 | if (ehbuf) |
924 | free (ehbuf); |
1038 | free (ehbuf); |
925 | if (local_cies) |
1039 | if (local_cies) |
926 | free (local_cies); |
1040 | free (local_cies); |
Line 927... | Line 1041... | ||
927 | #undef REQUIRE |
1041 | #undef REQUIRE |
Line -... | Line 1042... | ||
- | 1042 | } |
|
- | 1043 | ||
- | 1044 | /* Order eh_frame_hdr entries by the VMA of their text section. */ |
|
- | 1045 | ||
- | 1046 | static int |
|
- | 1047 | cmp_eh_frame_hdr (const void *a, const void *b) |
|
- | 1048 | { |
|
- | 1049 | bfd_vma text_a; |
|
- | 1050 | bfd_vma text_b; |
|
- | 1051 | asection *sec; |
|
- | 1052 | ||
- | 1053 | sec = *(asection *const *)a; |
|
- | 1054 | sec = (asection *) elf_section_data (sec)->sec_info; |
|
- | 1055 | text_a = sec->output_section->vma + sec->output_offset; |
|
- | 1056 | sec = *(asection *const *)b; |
|
- | 1057 | sec = (asection *) elf_section_data (sec)->sec_info; |
|
- | 1058 | text_b = sec->output_section->vma + sec->output_offset; |
|
- | 1059 | ||
- | 1060 | if (text_a < text_b) |
|
- | 1061 | return -1; |
|
- | 1062 | return text_a > text_b; |
|
- | 1063 | ||
- | 1064 | } |
|
928 | } |
1065 | |
- | 1066 | /* Add space for a CANTUNWIND terminator to SEC if the text sections |
|
- | 1067 | referenced by it and NEXT are not contiguous, or NEXT is NULL. */ |
|
- | 1068 | ||
- | 1069 | static void |
|
- | 1070 | add_eh_frame_hdr_terminator (asection *sec, |
|
- | 1071 | asection *next) |
|
- | 1072 | { |
|
- | 1073 | bfd_vma end; |
|
- | 1074 | bfd_vma next_start; |
|
- | 1075 | asection *text_sec; |
|
- | 1076 | ||
- | 1077 | if (next) |
|
- | 1078 | { |
|
- | 1079 | /* See if there is a gap (presumably a text section without unwind info) |
|
- | 1080 | between these two entries. */ |
|
- | 1081 | text_sec = (asection *) elf_section_data (sec)->sec_info; |
|
- | 1082 | end = text_sec->output_section->vma + text_sec->output_offset |
|
- | 1083 | + text_sec->size; |
|
- | 1084 | text_sec = (asection *) elf_section_data (next)->sec_info; |
|
- | 1085 | next_start = text_sec->output_section->vma + text_sec->output_offset; |
|
- | 1086 | if (end == next_start) |
|
- | 1087 | return; |
|
- | 1088 | } |
|
- | 1089 | ||
- | 1090 | /* Add space for a CANTUNWIND terminator. */ |
|
- | 1091 | if (!sec->rawsize) |
|
- | 1092 | sec->rawsize = sec->size; |
|
- | 1093 | ||
- | 1094 | bfd_set_section_size (sec->owner, sec, sec->size + 8); |
|
- | 1095 | } |
|
929 | 1096 | ||
930 | /* Finish a pass over all .eh_frame sections. */ |
1097 | /* Finish a pass over all .eh_frame_entry sections. */ |
931 | 1098 | ||
- | 1099 | bfd_boolean |
|
Line 932... | Line 1100... | ||
932 | void |
1100 | _bfd_elf_end_eh_frame_parsing (struct bfd_link_info *info) |
- | 1101 | { |
|
- | 1102 | struct eh_frame_hdr_info *hdr_info; |
|
- | 1103 | unsigned int i; |
|
- | 1104 | ||
- | 1105 | hdr_info = &elf_hash_table (info)->eh_info; |
|
- | 1106 | ||
- | 1107 | if (info->eh_frame_hdr_type != COMPACT_EH_HDR |
|
- | 1108 | || hdr_info->array_count == 0) |
|
- | 1109 | return FALSE; |
|
- | 1110 | ||
- | 1111 | bfd_elf_discard_eh_frame_entry (hdr_info); |
|
- | 1112 | ||
- | 1113 | qsort (hdr_info->u.compact.entries, hdr_info->array_count, |
|
933 | _bfd_elf_end_eh_frame_parsing (struct bfd_link_info *info) |
1114 | sizeof (asection *), cmp_eh_frame_hdr); |
- | 1115 | ||
- | 1116 | for (i = 0; i < hdr_info->array_count - 1; i++) |
|
- | 1117 | { |
|
- | 1118 | add_eh_frame_hdr_terminator (hdr_info->u.compact.entries[i], |
|
- | 1119 | hdr_info->u.compact.entries[i + 1]); |
|
934 | { |
1120 | } |
Line 935... | Line 1121... | ||
935 | struct eh_frame_hdr_info *hdr_info; |
1121 | |
936 | 1122 | /* Add a CANTUNWIND terminator after the last entry. */ |
|
937 | hdr_info = &elf_hash_table (info)->eh_info; |
1123 | add_eh_frame_hdr_terminator (hdr_info->u.compact.entries[i], NULL); |
Line 975... | Line 1161... | ||
975 | return FALSE; |
1161 | return FALSE; |
Line 976... | Line 1162... | ||
976 | 1162 | ||
977 | /* At this stage, all cie_inf fields point to local CIEs, so we |
1163 | /* At this stage, all cie_inf fields point to local CIEs, so we |
978 | can use the same cookie to refer to them. */ |
1164 | can use the same cookie to refer to them. */ |
979 | cie = fde->u.fde.cie_inf; |
1165 | cie = fde->u.fde.cie_inf; |
980 | if (!cie->u.cie.gc_mark) |
1166 | if (cie != NULL && !cie->u.cie.gc_mark) |
981 | { |
1167 | { |
982 | cie->u.cie.gc_mark = 1; |
1168 | cie->u.cie.gc_mark = 1; |
983 | if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie)) |
1169 | if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie)) |
984 | return FALSE; |
1170 | return FALSE; |
Line 1025... | Line 1211... | ||
1025 | 1211 | ||
1026 | if (cie->per_encoding != DW_EH_PE_omit) |
1212 | if (cie->per_encoding != DW_EH_PE_omit) |
1027 | { |
1213 | { |
Line 1028... | Line 1214... | ||
1028 | bfd_boolean per_binds_local; |
1214 | bfd_boolean per_binds_local; |
- | 1215 | ||
- | 1216 | /* Work out the address of personality routine, or at least |
|
- | 1217 | enough info that we could calculate the address had we made a |
|
- | 1218 | final section layout. The symbol on the reloc is enough, |
|
1029 | 1219 | either the hash for a global, or (bfd id, index) pair for a |
|
1030 | /* Work out the address of personality routine, either as an absolute |
1220 | local. The assumption here is that no one uses addends on |
1031 | value or as a symbol. */ |
1221 | the reloc. */ |
1032 | rel = cookie->rels + cie->personality.reloc_index; |
1222 | rel = cookie->rels + cie->personality.reloc_index; |
1033 | memset (&cie->personality, 0, sizeof (cie->personality)); |
1223 | memset (&cie->personality, 0, sizeof (cie->personality)); |
1034 | #ifdef BFD64 |
1224 | #ifdef BFD64 |
Line 1066... | Line 1256... | ||
1066 | sym_sec = sym_sec->kept_section; |
1256 | sym_sec = sym_sec->kept_section; |
1067 | if (sym_sec->output_section == NULL) |
1257 | if (sym_sec->output_section == NULL) |
1068 | return cie_inf; |
1258 | return cie_inf; |
Line 1069... | Line 1259... | ||
1069 | 1259 | ||
1070 | cie->local_personality = 1; |
1260 | cie->local_personality = 1; |
1071 | cie->personality.val = (sym->st_value |
- | |
1072 | + sym_sec->output_offset |
1261 | cie->personality.sym.bfd_id = abfd->id; |
1073 | + sym_sec->output_section->vma); |
1262 | cie->personality.sym.index = r_symndx; |
1074 | per_binds_local = TRUE; |
1263 | per_binds_local = TRUE; |
Line 1075... | Line 1264... | ||
1075 | } |
1264 | } |
1076 | 1265 | ||
1077 | if (per_binds_local |
1266 | if (per_binds_local |
1078 | && info->shared |
1267 | && bfd_link_pic (info) |
1079 | && (cie->per_encoding & 0x70) == DW_EH_PE_absptr |
1268 | && (cie->per_encoding & 0x70) == DW_EH_PE_absptr |
1080 | && (get_elf_backend_data (abfd) |
1269 | && (get_elf_backend_data (abfd) |
1081 | ->elf_backend_can_make_relative_eh_frame (abfd, info, sec))) |
1270 | ->elf_backend_can_make_relative_eh_frame (abfd, info, sec))) |
1082 | { |
1271 | { |
1083 | cie_inf->u.cie.make_per_encoding_relative = 1; |
1272 | cie_inf->u.cie.make_per_encoding_relative = 1; |
1084 | cie_inf->u.cie.per_encoding_relative = 1; |
1273 | cie_inf->u.cie.per_encoding_relative = 1; |
Line 1085... | Line 1274... | ||
1085 | } |
1274 | } |
1086 | } |
- | |
1087 | 1275 | } |
|
1088 | /* See if we can merge this CIE with an earlier one. */ |
1276 | |
1089 | cie->output_sec = sec->output_section; |
1277 | /* See if we can merge this CIE with an earlier one. */ |
1090 | cie_compute_hash (cie); |
1278 | cie_compute_hash (cie); |
1091 | if (hdr_info->cies == NULL) |
1279 | if (hdr_info->u.dwarf.cies == NULL) |
1092 | { |
1280 | { |
1093 | hdr_info->cies = htab_try_create (1, cie_hash, cie_eq, free); |
1281 | hdr_info->u.dwarf.cies = htab_try_create (1, cie_hash, cie_eq, free); |
1094 | if (hdr_info->cies == NULL) |
1282 | if (hdr_info->u.dwarf.cies == NULL) |
- | 1283 | return cie_inf; |
|
1095 | return cie_inf; |
1284 | } |
1096 | } |
1285 | loc = htab_find_slot_with_hash (hdr_info->u.dwarf.cies, cie, |
Line 1097... | Line 1286... | ||
1097 | loc = htab_find_slot_with_hash (hdr_info->cies, cie, cie->hash, INSERT); |
1286 | cie->hash, INSERT); |
1098 | if (loc == NULL) |
1287 | if (loc == NULL) |
Line 1151... | Line 1340... | ||
1151 | for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent) |
1340 | for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent) |
1152 | if (ent->size == 4) |
1341 | if (ent->size == 4) |
1153 | /* There should only be one zero terminator, on the last input |
1342 | /* There should only be one zero terminator, on the last input |
1154 | file supplying .eh_frame (crtend.o). Remove any others. */ |
1343 | file supplying .eh_frame (crtend.o). Remove any others. */ |
1155 | ent->removed = sec->map_head.s != NULL; |
1344 | ent->removed = sec->map_head.s != NULL; |
1156 | else if (!ent->cie) |
1345 | else if (!ent->cie && ent->u.fde.cie_inf != NULL) |
1157 | { |
1346 | { |
1158 | bfd_boolean keep; |
1347 | bfd_boolean keep; |
1159 | if ((sec->flags & SEC_LINKER_CREATED) != 0 && cookie->rels == NULL) |
1348 | if ((sec->flags & SEC_LINKER_CREATED) != 0 && cookie->rels == NULL) |
1160 | { |
1349 | { |
1161 | unsigned int width |
1350 | unsigned int width |
Line 1173... | Line 1362... | ||
1173 | && cookie->rel->r_offset == ent->offset + 8); |
1362 | && cookie->rel->r_offset == ent->offset + 8); |
1174 | keep = !(*reloc_symbol_deleted_p) (ent->offset + 8, cookie); |
1363 | keep = !(*reloc_symbol_deleted_p) (ent->offset + 8, cookie); |
1175 | } |
1364 | } |
1176 | if (keep) |
1365 | if (keep) |
1177 | { |
1366 | { |
1178 | if (info->shared |
1367 | if (bfd_link_pic (info) |
1179 | && (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr |
1368 | && (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr |
1180 | && ent->make_relative == 0) |
1369 | && ent->make_relative == 0) |
1181 | || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned)) |
1370 | || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned)) |
1182 | { |
1371 | { |
1183 | /* If a shared library uses absolute pointers |
1372 | /* If a shared library uses absolute pointers |
1184 | which we cannot turn into PC relative, |
1373 | which we cannot turn into PC relative, |
1185 | don't create the binary search table, |
1374 | don't create the binary search table, |
1186 | since it is affected by runtime relocations. */ |
1375 | since it is affected by runtime relocations. */ |
1187 | hdr_info->table = FALSE; |
1376 | hdr_info->u.dwarf.table = FALSE; |
1188 | (*info->callbacks->einfo) |
1377 | (*info->callbacks->einfo) |
1189 | (_("%P: fde encoding in %B(%A) prevents .eh_frame_hdr" |
1378 | (_("%P: FDE encoding in %B(%A) prevents .eh_frame_hdr" |
1190 | " table being created.\n"), abfd, sec); |
1379 | " table being created.\n"), abfd, sec); |
1191 | } |
1380 | } |
1192 | ent->removed = 0; |
1381 | ent->removed = 0; |
1193 | hdr_info->fde_count++; |
1382 | hdr_info->u.dwarf.fde_count++; |
1194 | ent->u.fde.cie_inf = find_merged_cie (abfd, info, sec, hdr_info, |
1383 | ent->u.fde.cie_inf = find_merged_cie (abfd, info, sec, hdr_info, |
1195 | cookie, ent->u.fde.cie_inf); |
1384 | cookie, ent->u.fde.cie_inf); |
1196 | } |
1385 | } |
1197 | } |
1386 | } |
Line 1227... | Line 1416... | ||
1227 | asection *sec; |
1416 | asection *sec; |
Line 1228... | Line 1417... | ||
1228 | 1417 | ||
1229 | htab = elf_hash_table (info); |
1418 | htab = elf_hash_table (info); |
Line 1230... | Line 1419... | ||
1230 | hdr_info = &htab->eh_info; |
1419 | hdr_info = &htab->eh_info; |
1231 | 1420 | ||
1232 | if (hdr_info->cies != NULL) |
1421 | if (!hdr_info->frame_hdr_is_compact && hdr_info->u.dwarf.cies != NULL) |
1233 | { |
1422 | { |
1234 | htab_delete (hdr_info->cies); |
1423 | htab_delete (hdr_info->u.dwarf.cies); |
Line 1235... | Line 1424... | ||
1235 | hdr_info->cies = NULL; |
1424 | hdr_info->u.dwarf.cies = NULL; |
1236 | } |
1425 | } |
1237 | 1426 | ||
Line -... | Line 1427... | ||
- | 1427 | sec = hdr_info->hdr_sec; |
|
- | 1428 | if (sec == NULL) |
|
- | 1429 | return FALSE; |
|
- | 1430 | ||
- | 1431 | if (info->eh_frame_hdr_type == COMPACT_EH_HDR) |
|
- | 1432 | { |
|
- | 1433 | /* For compact frames we only add the header. The actual table comes |
|
- | 1434 | from the .eh_frame_entry sections. */ |
|
1238 | sec = hdr_info->hdr_sec; |
1435 | sec->size = 8; |
1239 | if (sec == NULL) |
1436 | } |
1240 | return FALSE; |
1437 | else |
- | 1438 | { |
|
Line 1241... | Line 1439... | ||
1241 | 1439 | sec->size = EH_FRAME_HDR_SIZE; |
|
1242 | sec->size = EH_FRAME_HDR_SIZE; |
1440 | if (hdr_info->u.dwarf.table) |
1243 | if (hdr_info->table) |
1441 | sec->size += 4 + hdr_info->u.dwarf.fde_count * 8; |
Line 1244... | Line 1442... | ||
1244 | sec->size += 4 + hdr_info->fde_count * 8; |
1442 | } |
1245 | 1443 | ||
1246 | elf_eh_frame_hdr (abfd) = sec; |
1444 | elf_eh_frame_hdr (abfd) = sec; |
- | 1445 | return TRUE; |
|
1247 | return TRUE; |
1446 | } |
1248 | } |
1447 | |
1249 | 1448 | /* Return true if there is at least one non-empty .eh_frame section in |
|
1250 | /* Return true if there is at least one non-empty .eh_frame section in |
1449 | input files. Can only be called after ld has mapped input to |
Line 1265... | Line 1464... | ||
1265 | return TRUE; |
1464 | return TRUE; |
Line 1266... | Line 1465... | ||
1266 | 1465 | ||
1267 | return FALSE; |
1466 | return FALSE; |
Line -... | Line 1467... | ||
- | 1467 | } |
|
- | 1468 | ||
- | 1469 | /* Return true if there is at least one .eh_frame_entry section in |
|
- | 1470 | input files. */ |
|
- | 1471 | ||
- | 1472 | bfd_boolean |
|
- | 1473 | _bfd_elf_eh_frame_entry_present (struct bfd_link_info *info) |
|
- | 1474 | { |
|
- | 1475 | asection *o; |
|
- | 1476 | bfd *abfd; |
|
- | 1477 | ||
- | 1478 | for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) |
|
- | 1479 | { |
|
- | 1480 | for (o = abfd->sections; o; o = o->next) |
|
- | 1481 | { |
|
- | 1482 | const char *name = bfd_get_section_name (abfd, o); |
|
- | 1483 | ||
- | 1484 | if (strcmp (name, ".eh_frame_entry") |
|
- | 1485 | && !bfd_is_abs_section (o->output_section)) |
|
- | 1486 | return TRUE; |
|
- | 1487 | } |
|
- | 1488 | } |
|
- | 1489 | return FALSE; |
|
1268 | } |
1490 | } |
1269 | 1491 | ||
1270 | /* This function is called from size_dynamic_sections. |
1492 | /* This function is called from size_dynamic_sections. |
1271 | It needs to decide whether .eh_frame_hdr should be output or not, |
1493 | It needs to decide whether .eh_frame_hdr should be output or not, |
Line 1272... | Line 1494... | ||
1272 | because when the dynamic symbol table has been sized it is too late |
1494 | because when the dynamic symbol table has been sized it is too late |
1273 | to strip sections. */ |
1495 | to strip sections. */ |
1274 | 1496 | ||
1275 | bfd_boolean |
1497 | bfd_boolean |
1276 | _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) |
1498 | _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info) |
- | 1499 | { |
|
- | 1500 | struct elf_link_hash_table *htab; |
|
Line 1277... | Line 1501... | ||
1277 | { |
1501 | struct eh_frame_hdr_info *hdr_info; |
1278 | struct elf_link_hash_table *htab; |
1502 | struct bfd_link_hash_entry *bh = NULL; |
1279 | struct eh_frame_hdr_info *hdr_info; |
1503 | struct elf_link_hash_entry *h; |
1280 | 1504 | ||
Line 1281... | Line 1505... | ||
1281 | htab = elf_hash_table (info); |
1505 | htab = elf_hash_table (info); |
1282 | hdr_info = &htab->eh_info; |
1506 | hdr_info = &htab->eh_info; |
- | 1507 | if (hdr_info->hdr_sec == NULL) |
|
1283 | if (hdr_info->hdr_sec == NULL) |
1508 | return TRUE; |
- | 1509 | ||
- | 1510 | if (bfd_is_abs_section (hdr_info->hdr_sec->output_section) |
|
1284 | return TRUE; |
1511 | || info->eh_frame_hdr_type == 0 |
1285 | 1512 | || (info->eh_frame_hdr_type == DWARF2_EH_HDR |
|
1286 | if (bfd_is_abs_section (hdr_info->hdr_sec->output_section) |
1513 | && !_bfd_elf_eh_frame_present (info)) |
1287 | || !info->eh_frame_hdr |
1514 | || (info->eh_frame_hdr_type == COMPACT_EH_HDR |
1288 | || !_bfd_elf_eh_frame_present (info)) |
1515 | && !_bfd_elf_eh_frame_entry_present (info))) |
Line -... | Line 1516... | ||
- | 1516 | { |
|
- | 1517 | hdr_info->hdr_sec->flags |= SEC_EXCLUDE; |
|
- | 1518 | hdr_info->hdr_sec = NULL; |
|
- | 1519 | return TRUE; |
|
- | 1520 | } |
|
- | 1521 | ||
- | 1522 | /* Add a hidden symbol so that systems without access to PHDRs can |
|
- | 1523 | find the table. */ |
|
- | 1524 | if (! (_bfd_generic_link_add_one_symbol |
|
- | 1525 | (info, info->output_bfd, "__GNU_EH_FRAME_HDR", BSF_LOCAL, |
|
- | 1526 | hdr_info->hdr_sec, 0, NULL, FALSE, FALSE, &bh))) |
|
- | 1527 | return FALSE; |
|
- | 1528 | ||
- | 1529 | h = (struct elf_link_hash_entry *) bh; |
|
1289 | { |
1530 | h->def_regular = 1; |
1290 | hdr_info->hdr_sec->flags |= SEC_EXCLUDE; |
1531 | h->other = STV_HIDDEN; |
1291 | hdr_info->hdr_sec = NULL; |
1532 | get_elf_backend_data |
Line 1292... | Line 1533... | ||
1292 | return TRUE; |
1533 | (info->output_bfd)->elf_backend_hide_symbol (info, h, TRUE); |
1293 | } |
1534 | |
Line 1381... | Line 1622... | ||
1381 | - sec_info->entry[mid].offset |
1622 | - sec_info->entry[mid].offset |
1382 | + extra_augmentation_string_bytes (sec_info->entry + mid) |
1623 | + extra_augmentation_string_bytes (sec_info->entry + mid) |
1383 | + extra_augmentation_data_bytes (sec_info->entry + mid)); |
1624 | + extra_augmentation_data_bytes (sec_info->entry + mid)); |
1384 | } |
1625 | } |
Line -... | Line 1626... | ||
- | 1626 | ||
- | 1627 | /* Write out .eh_frame_entry section. Add CANTUNWIND terminator if needed. |
|
- | 1628 | Also check that the contents look sane. */ |
|
- | 1629 | ||
- | 1630 | bfd_boolean |
|
- | 1631 | _bfd_elf_write_section_eh_frame_entry (bfd *abfd, struct bfd_link_info *info, |
|
- | 1632 | asection *sec, bfd_byte *contents) |
|
- | 1633 | { |
|
- | 1634 | const struct elf_backend_data *bed; |
|
- | 1635 | bfd_byte cantunwind[8]; |
|
- | 1636 | bfd_vma addr; |
|
- | 1637 | bfd_vma last_addr; |
|
- | 1638 | bfd_vma offset; |
|
- | 1639 | asection *text_sec = (asection *) elf_section_data (sec)->sec_info; |
|
- | 1640 | ||
- | 1641 | if (!sec->rawsize) |
|
- | 1642 | sec->rawsize = sec->size; |
|
- | 1643 | ||
- | 1644 | BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_EH_FRAME_ENTRY); |
|
- | 1645 | ||
- | 1646 | /* Check to make sure that the text section corresponding to this eh_frame_entry |
|
- | 1647 | section has not been excluded. In particular, mips16 stub entries will be |
|
- | 1648 | excluded outside of the normal process. */ |
|
- | 1649 | if (sec->flags & SEC_EXCLUDE |
|
- | 1650 | || text_sec->flags & SEC_EXCLUDE) |
|
- | 1651 | return TRUE; |
|
- | 1652 | ||
- | 1653 | if (!bfd_set_section_contents (abfd, sec->output_section, contents, |
|
- | 1654 | sec->output_offset, sec->rawsize)) |
|
- | 1655 | return FALSE; |
|
- | 1656 | ||
- | 1657 | last_addr = bfd_get_signed_32 (abfd, contents); |
|
- | 1658 | /* Check that all the entries are in order. */ |
|
- | 1659 | for (offset = 8; offset < sec->rawsize; offset += 8) |
|
- | 1660 | { |
|
- | 1661 | addr = bfd_get_signed_32 (abfd, contents + offset) + offset; |
|
- | 1662 | if (addr <= last_addr) |
|
- | 1663 | { |
|
- | 1664 | (*_bfd_error_handler) (_("%B: %s not in order"), sec->owner, sec->name); |
|
- | 1665 | return FALSE; |
|
- | 1666 | } |
|
- | 1667 | ||
- | 1668 | last_addr = addr; |
|
- | 1669 | } |
|
- | 1670 | ||
- | 1671 | addr = text_sec->output_section->vma + text_sec->output_offset |
|
- | 1672 | + text_sec->size; |
|
- | 1673 | addr &= ~1; |
|
- | 1674 | addr -= (sec->output_section->vma + sec->output_offset + sec->rawsize); |
|
- | 1675 | if (addr & 1) |
|
- | 1676 | { |
|
- | 1677 | (*_bfd_error_handler) (_("%B: %s invalid input section size"), |
|
- | 1678 | sec->owner, sec->name); |
|
- | 1679 | bfd_set_error (bfd_error_bad_value); |
|
- | 1680 | return FALSE; |
|
- | 1681 | } |
|
- | 1682 | if (last_addr >= addr + sec->rawsize) |
|
- | 1683 | { |
|
- | 1684 | (*_bfd_error_handler) (_("%B: %s points past end of text section"), |
|
- | 1685 | sec->owner, sec->name); |
|
- | 1686 | bfd_set_error (bfd_error_bad_value); |
|
- | 1687 | return FALSE; |
|
- | 1688 | } |
|
- | 1689 | ||
- | 1690 | if (sec->size == sec->rawsize) |
|
- | 1691 | return TRUE; |
|
- | 1692 | ||
- | 1693 | bed = get_elf_backend_data (abfd); |
|
- | 1694 | BFD_ASSERT (sec->size == sec->rawsize + 8); |
|
- | 1695 | BFD_ASSERT ((addr & 1) == 0); |
|
- | 1696 | BFD_ASSERT (bed->cant_unwind_opcode); |
|
- | 1697 | ||
- | 1698 | bfd_put_32 (abfd, addr, cantunwind); |
|
- | 1699 | bfd_put_32 (abfd, (*bed->cant_unwind_opcode) (info), cantunwind + 4); |
|
- | 1700 | return bfd_set_section_contents (abfd, sec->output_section, cantunwind, |
|
- | 1701 | sec->output_offset + sec->rawsize, 8); |
|
- | 1702 | } |
|
1385 | 1703 | ||
1386 | /* Write out .eh_frame section. This is called with the relocated |
1704 | /* Write out .eh_frame section. This is called with the relocated |
Line 1387... | Line 1705... | ||
1387 | contents. */ |
1705 | contents. */ |
1388 | 1706 | ||
Line 1395... | Line 1713... | ||
1395 | struct eh_frame_sec_info *sec_info; |
1713 | struct eh_frame_sec_info *sec_info; |
1396 | struct elf_link_hash_table *htab; |
1714 | struct elf_link_hash_table *htab; |
1397 | struct eh_frame_hdr_info *hdr_info; |
1715 | struct eh_frame_hdr_info *hdr_info; |
1398 | unsigned int ptr_size; |
1716 | unsigned int ptr_size; |
1399 | struct eh_cie_fde *ent; |
1717 | struct eh_cie_fde *ent; |
- | 1718 | bfd_size_type sec_size; |
|
Line 1400... | Line 1719... | ||
1400 | 1719 | ||
1401 | if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME) |
1720 | if (sec->sec_info_type != SEC_INFO_TYPE_EH_FRAME) |
1402 | /* FIXME: octets_per_byte. */ |
1721 | /* FIXME: octets_per_byte. */ |
1403 | return bfd_set_section_contents (abfd, sec->output_section, contents, |
1722 | return bfd_set_section_contents (abfd, sec->output_section, contents, |
Line 1409... | Line 1728... | ||
1409 | 1728 | ||
1410 | sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; |
1729 | sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; |
1411 | htab = elf_hash_table (info); |
1730 | htab = elf_hash_table (info); |
Line 1412... | Line 1731... | ||
1412 | hdr_info = &htab->eh_info; |
1731 | hdr_info = &htab->eh_info; |
- | 1732 | ||
- | 1733 | if (hdr_info->u.dwarf.table && hdr_info->u.dwarf.array == NULL) |
|
1413 | 1734 | { |
|
1414 | if (hdr_info->table && hdr_info->array == NULL) |
1735 | hdr_info->frame_hdr_is_compact = FALSE; |
- | 1736 | hdr_info->u.dwarf.array = (struct eh_frame_array_ent *) |
|
- | 1737 | bfd_malloc (hdr_info->u.dwarf.fde_count |
|
1415 | hdr_info->array = (struct eh_frame_array_ent *) |
1738 | * sizeof (*hdr_info->u.dwarf.array)); |
1416 | bfd_malloc (hdr_info->fde_count * sizeof(*hdr_info->array)); |
1739 | } |
Line 1417... | Line 1740... | ||
1417 | if (hdr_info->array == NULL) |
1740 | if (hdr_info->u.dwarf.array == NULL) |
1418 | hdr_info = NULL; |
1741 | hdr_info = NULL; |
1419 | 1742 | ||
Line 1581... | Line 1904... | ||
1581 | cie = ent->u.fde.cie_inf; |
1904 | cie = ent->u.fde.cie_inf; |
1582 | buf += 4; |
1905 | buf += 4; |
1583 | value = ((ent->new_offset + sec->output_offset + 4) |
1906 | value = ((ent->new_offset + sec->output_offset + 4) |
1584 | - (cie->new_offset + cie->u.cie.u.sec->output_offset)); |
1907 | - (cie->new_offset + cie->u.cie.u.sec->output_offset)); |
1585 | bfd_put_32 (abfd, value, buf); |
1908 | bfd_put_32 (abfd, value, buf); |
- | 1909 | if (bfd_link_relocatable (info)) |
|
- | 1910 | continue; |
|
1586 | buf += 4; |
1911 | buf += 4; |
1587 | width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size); |
1912 | width = get_DW_EH_PE_width (ent->fde_encoding, ptr_size); |
1588 | value = read_value (abfd, buf, width, |
1913 | value = read_value (abfd, buf, width, |
1589 | get_DW_EH_PE_signed (ent->fde_encoding)); |
1914 | get_DW_EH_PE_signed (ent->fde_encoding)); |
1590 | address = value; |
1915 | address = value; |
Line 1645... | Line 1970... | ||
1645 | /* The address calculation may overflow, giving us a |
1970 | /* The address calculation may overflow, giving us a |
1646 | value greater than 4G on a 32-bit target when |
1971 | value greater than 4G on a 32-bit target when |
1647 | dwarf_vma is 64-bit. */ |
1972 | dwarf_vma is 64-bit. */ |
1648 | if (sizeof (address) > 4 && ptr_size == 4) |
1973 | if (sizeof (address) > 4 && ptr_size == 4) |
1649 | address &= 0xffffffff; |
1974 | address &= 0xffffffff; |
1650 | hdr_info->array[hdr_info->array_count].initial_loc = address; |
1975 | hdr_info->u.dwarf.array[hdr_info->array_count].initial_loc |
- | 1976 | = address; |
|
- | 1977 | hdr_info->u.dwarf.array[hdr_info->array_count].range |
|
- | 1978 | = read_value (abfd, buf + width, width, FALSE); |
|
1651 | hdr_info->array[hdr_info->array_count++].fde |
1979 | hdr_info->u.dwarf.array[hdr_info->array_count++].fde |
1652 | = (sec->output_section->vma |
1980 | = (sec->output_section->vma |
1653 | + sec->output_offset |
1981 | + sec->output_offset |
1654 | + ent->new_offset); |
1982 | + ent->new_offset); |
1655 | } |
1983 | } |
Line 1716... | Line 2044... | ||
1716 | /* We don't align the section to its section alignment since the |
2044 | /* We don't align the section to its section alignment since the |
1717 | runtime library only expects all CIE/FDE records aligned at |
2045 | runtime library only expects all CIE/FDE records aligned at |
1718 | the pointer size. _bfd_elf_discard_section_eh_frame should |
2046 | the pointer size. _bfd_elf_discard_section_eh_frame should |
1719 | have padded CIE/FDE records to multiple of pointer size with |
2047 | have padded CIE/FDE records to multiple of pointer size with |
1720 | size_of_output_cie_fde. */ |
2048 | size_of_output_cie_fde. */ |
- | 2049 | sec_size = sec->size; |
|
- | 2050 | if (sec_info->count != 0 |
|
- | 2051 | && sec_info->entry[sec_info->count - 1].size == 4) |
|
- | 2052 | sec_size -= 4; |
|
1721 | if ((sec->size % ptr_size) != 0) |
2053 | if ((sec_size % ptr_size) != 0) |
1722 | abort (); |
2054 | abort (); |
Line 1723... | Line 2055... | ||
1723 | 2055 | ||
1724 | /* FIXME: octets_per_byte. */ |
2056 | /* FIXME: octets_per_byte. */ |
1725 | return bfd_set_section_contents (abfd, sec->output_section, |
2057 | return bfd_set_section_contents (abfd, sec->output_section, |
Line 1737... | Line 2069... | ||
1737 | const struct eh_frame_array_ent *q = (const struct eh_frame_array_ent *) b; |
2069 | const struct eh_frame_array_ent *q = (const struct eh_frame_array_ent *) b; |
1738 | if (p->initial_loc > q->initial_loc) |
2070 | if (p->initial_loc > q->initial_loc) |
1739 | return 1; |
2071 | return 1; |
1740 | if (p->initial_loc < q->initial_loc) |
2072 | if (p->initial_loc < q->initial_loc) |
1741 | return -1; |
2073 | return -1; |
- | 2074 | if (p->range > q->range) |
|
- | 2075 | return 1; |
|
- | 2076 | if (p->range < q->range) |
|
- | 2077 | return -1; |
|
1742 | return 0; |
2078 | return 0; |
1743 | } |
2079 | } |
Line 1744... | Line 2080... | ||
1744 | 2080 | ||
- | 2081 | /* Reorder .eh_frame_entry sections to match the associated text sections. |
|
1745 | /* Write out .eh_frame_hdr section. This must be called after |
2082 | This routine is called during the final linking step, just before writing |
- | 2083 | the contents. At this stage, sections in the eh_frame_hdr_info are already |
|
- | 2084 | sorted in order of increasing text section address and so we simply need |
|
- | 2085 | to make the .eh_frame_entrys follow that same order. Note that it is |
|
1746 | _bfd_elf_write_section_eh_frame has been called on all input |
2086 | invalid for a linker script to try to force a particular order of |
- | 2087 | .eh_frame_entry sections. */ |
|
- | 2088 | ||
- | 2089 | bfd_boolean |
|
- | 2090 | _bfd_elf_fixup_eh_frame_hdr (struct bfd_link_info *info) |
|
- | 2091 | { |
|
- | 2092 | asection *sec = NULL; |
|
- | 2093 | asection *osec; |
|
- | 2094 | struct eh_frame_hdr_info *hdr_info; |
|
- | 2095 | unsigned int i; |
|
- | 2096 | bfd_vma offset; |
|
- | 2097 | struct bfd_link_order *p; |
|
- | 2098 | ||
- | 2099 | hdr_info = &elf_hash_table (info)->eh_info; |
|
- | 2100 | ||
- | 2101 | if (hdr_info->hdr_sec == NULL |
|
- | 2102 | || info->eh_frame_hdr_type != COMPACT_EH_HDR |
|
- | 2103 | || hdr_info->array_count == 0) |
|
- | 2104 | return TRUE; |
|
- | 2105 | ||
- | 2106 | /* Change section output offsets to be in text section order. */ |
|
- | 2107 | offset = 8; |
|
- | 2108 | osec = hdr_info->u.compact.entries[0]->output_section; |
|
- | 2109 | for (i = 0; i < hdr_info->array_count; i++) |
|
- | 2110 | { |
|
- | 2111 | sec = hdr_info->u.compact.entries[i]; |
|
- | 2112 | if (sec->output_section != osec) |
|
- | 2113 | { |
|
- | 2114 | (*_bfd_error_handler) |
|
- | 2115 | (_("Invalid output section for .eh_frame_entry: %s"), |
|
- | 2116 | sec->output_section->name); |
|
- | 2117 | return FALSE; |
|
- | 2118 | } |
|
- | 2119 | sec->output_offset = offset; |
|
- | 2120 | offset += sec->size; |
|
- | 2121 | } |
|
- | 2122 | ||
- | 2123 | ||
- | 2124 | /* Fix the link_order to match. */ |
|
- | 2125 | for (p = sec->output_section->map_head.link_order; p != NULL; p = p->next) |
|
- | 2126 | { |
|
- | 2127 | if (p->type != bfd_indirect_link_order) |
|
- | 2128 | abort(); |
|
- | 2129 | ||
- | 2130 | p->offset = p->u.indirect.section->output_offset; |
|
- | 2131 | if (p->next != NULL) |
|
- | 2132 | i--; |
|
- | 2133 | } |
|
- | 2134 | ||
- | 2135 | if (i != 0) |
|
- | 2136 | { |
|
- | 2137 | (*_bfd_error_handler) |
|
- | 2138 | (_("Invalid contents in %s section"), osec->name); |
|
- | 2139 | return FALSE; |
|
- | 2140 | } |
|
- | 2141 | ||
- | 2142 | return TRUE; |
|
- | 2143 | } |
|
- | 2144 | ||
- | 2145 | /* The .eh_frame_hdr format for Compact EH frames: |
|
- | 2146 | ubyte version (2) |
|
- | 2147 | ubyte eh_ref_enc (DW_EH_PE_* encoding of typinfo references) |
|
- | 2148 | uint32_t count (Number of entries in table) |
|
- | 2149 | [array from .eh_frame_entry sections] */ |
|
- | 2150 | ||
- | 2151 | static bfd_boolean |
|
- | 2152 | write_compact_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) |
|
- | 2153 | { |
|
- | 2154 | struct elf_link_hash_table *htab; |
|
- | 2155 | struct eh_frame_hdr_info *hdr_info; |
|
- | 2156 | asection *sec; |
|
- | 2157 | const struct elf_backend_data *bed; |
|
- | 2158 | bfd_vma count; |
|
- | 2159 | bfd_byte contents[8]; |
|
- | 2160 | unsigned int i; |
|
- | 2161 | ||
- | 2162 | htab = elf_hash_table (info); |
|
- | 2163 | hdr_info = &htab->eh_info; |
|
- | 2164 | sec = hdr_info->hdr_sec; |
|
- | 2165 | ||
- | 2166 | if (sec->size != 8) |
|
- | 2167 | abort(); |
|
- | 2168 | ||
- | 2169 | for (i = 0; i < sizeof (contents); i++) |
|
- | 2170 | contents[i] = 0; |
|
- | 2171 | ||
- | 2172 | contents[0] = COMPACT_EH_HDR; |
|
- | 2173 | bed = get_elf_backend_data (abfd); |
|
- | 2174 | ||
- | 2175 | BFD_ASSERT (bed->compact_eh_encoding); |
|
- | 2176 | contents[1] = (*bed->compact_eh_encoding) (info); |
|
- | 2177 | ||
- | 2178 | count = (sec->output_section->size - 8) / 8; |
|
- | 2179 | bfd_put_32 (abfd, count, contents + 4); |
|
- | 2180 | return bfd_set_section_contents (abfd, sec->output_section, contents, |
|
- | 2181 | (file_ptr) sec->output_offset, sec->size); |
|
- | 2182 | } |
|
1747 | .eh_frame sections. |
2183 | |
- | 2184 | /* The .eh_frame_hdr format for DWARF frames: |
|
1748 | .eh_frame_hdr format: |
2185 | |
1749 | ubyte version (currently 1) |
2186 | ubyte version (currently 1) |
1750 | ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of |
2187 | ubyte eh_frame_ptr_enc (DW_EH_PE_* encoding of pointer to start of |
1751 | .eh_frame section) |
2188 | .eh_frame section) |
1752 | ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count |
2189 | ubyte fde_count_enc (DW_EH_PE_* encoding of total FDE count |
Line 1762... | Line 2199... | ||
1762 | fde_count x [encoded] initial_loc, fde |
2199 | fde_count x [encoded] initial_loc, fde |
1763 | (array of encoded pairs containing |
2200 | (array of encoded pairs containing |
1764 | FDE initial_location field and FDE address, |
2201 | FDE initial_location field and FDE address, |
1765 | sorted by increasing initial_loc). */ |
2202 | sorted by increasing initial_loc). */ |
Line 1766... | Line 2203... | ||
1766 | 2203 | ||
1767 | bfd_boolean |
2204 | static bfd_boolean |
1768 | _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) |
2205 | write_dwarf_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) |
1769 | { |
2206 | { |
1770 | struct elf_link_hash_table *htab; |
2207 | struct elf_link_hash_table *htab; |
1771 | struct eh_frame_hdr_info *hdr_info; |
2208 | struct eh_frame_hdr_info *hdr_info; |
1772 | asection *sec; |
2209 | asection *sec; |
Line 1773... | Line 2210... | ||
1773 | bfd_boolean retval = TRUE; |
2210 | bfd_boolean retval = TRUE; |
1774 | 2211 | ||
1775 | htab = elf_hash_table (info); |
2212 | htab = elf_hash_table (info); |
1776 | hdr_info = &htab->eh_info; |
- | |
1777 | sec = hdr_info->hdr_sec; |
- | |
1778 | - | ||
1779 | if (info->eh_frame_hdr && sec != NULL) |
2213 | hdr_info = &htab->eh_info; |
1780 | { |
2214 | sec = hdr_info->hdr_sec; |
1781 | bfd_byte *contents; |
2215 | bfd_byte *contents; |
1782 | asection *eh_frame_sec; |
2216 | asection *eh_frame_sec; |
Line 1783... | Line 2217... | ||
1783 | bfd_size_type size; |
2217 | bfd_size_type size; |
- | 2218 | bfd_vma encoded_eh_frame; |
|
1784 | bfd_vma encoded_eh_frame; |
2219 | |
1785 | 2220 | size = EH_FRAME_HDR_SIZE; |
|
1786 | size = EH_FRAME_HDR_SIZE; |
2221 | if (hdr_info->u.dwarf.array |
1787 | if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count) |
2222 | && hdr_info->array_count == hdr_info->u.dwarf.fde_count) |
1788 | size += 4 + hdr_info->fde_count * 8; |
2223 | size += 4 + hdr_info->u.dwarf.fde_count * 8; |
Line 1789... | Line 2224... | ||
1789 | contents = (bfd_byte *) bfd_malloc (size); |
2224 | contents = (bfd_byte *) bfd_malloc (size); |
Line 1802... | Line 2237... | ||
1802 | contents[0] = 1; |
2237 | contents[0] = 1; |
1803 | /* .eh_frame offset. */ |
2238 | /* .eh_frame offset. */ |
1804 | contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address |
2239 | contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address |
1805 | (abfd, info, eh_frame_sec, 0, sec, 4, &encoded_eh_frame); |
2240 | (abfd, info, eh_frame_sec, 0, sec, 4, &encoded_eh_frame); |
Line -... | Line 2241... | ||
- | 2241 | ||
1806 | 2242 | if (hdr_info->u.dwarf.array |
|
1807 | if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count) |
2243 | && hdr_info->array_count == hdr_info->u.dwarf.fde_count) |
1808 | { |
2244 | { |
1809 | /* FDE count encoding. */ |
2245 | /* FDE count encoding. */ |
1810 | contents[2] = DW_EH_PE_udata4; |
2246 | contents[2] = DW_EH_PE_udata4; |
1811 | /* Search table encoding. */ |
2247 | /* Search table encoding. */ |
Line 1819... | Line 2255... | ||
1819 | bfd_put_32 (abfd, encoded_eh_frame, contents + 4); |
2255 | bfd_put_32 (abfd, encoded_eh_frame, contents + 4); |
Line 1820... | Line 2256... | ||
1820 | 2256 | ||
1821 | if (contents[2] != DW_EH_PE_omit) |
2257 | if (contents[2] != DW_EH_PE_omit) |
1822 | { |
2258 | { |
- | 2259 | unsigned int i; |
|
- | 2260 | bfd_boolean overlap, overflow; |
|
- | 2261 | ||
- | 2262 | bfd_put_32 (abfd, hdr_info->u.dwarf.fde_count, |
|
- | 2263 | contents + EH_FRAME_HDR_SIZE); |
|
- | 2264 | qsort (hdr_info->u.dwarf.array, hdr_info->u.dwarf.fde_count, |
|
- | 2265 | sizeof (*hdr_info->u.dwarf.array), vma_compare); |
|
- | 2266 | overlap = FALSE; |
|
- | 2267 | overflow = FALSE; |
|
- | 2268 | for (i = 0; i < hdr_info->u.dwarf.fde_count; i++) |
|
- | 2269 | { |
|
Line -... | Line 2270... | ||
- | 2270 | bfd_vma val; |
|
- | 2271 | ||
- | 2272 | val = hdr_info->u.dwarf.array[i].initial_loc |
|
- | 2273 | - sec->output_section->vma; |
|
- | 2274 | val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; |
|
- | 2275 | if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 |
|
- | 2276 | && (hdr_info->u.dwarf.array[i].initial_loc |
|
1823 | unsigned int i; |
2277 | != sec->output_section->vma + val)) |
1824 | 2278 | overflow = TRUE; |
|
- | 2279 | bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 4); |
|
- | 2280 | val = hdr_info->u.dwarf.array[i].fde - sec->output_section->vma; |
|
1825 | bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE); |
2281 | val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; |
1826 | qsort (hdr_info->array, hdr_info->fde_count, |
2282 | if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 |
- | 2283 | && (hdr_info->u.dwarf.array[i].fde |
|
- | 2284 | != sec->output_section->vma + val)) |
|
1827 | sizeof (*hdr_info->array), vma_compare); |
2285 | overflow = TRUE; |
1828 | for (i = 0; i < hdr_info->fde_count; i++) |
2286 | bfd_put_32 (abfd, val, contents + EH_FRAME_HDR_SIZE + i * 8 + 8); |
1829 | { |
2287 | if (i != 0 |
1830 | bfd_put_32 (abfd, |
2288 | && (hdr_info->u.dwarf.array[i].initial_loc |
- | 2289 | < (hdr_info->u.dwarf.array[i - 1].initial_loc |
|
- | 2290 | + hdr_info->u.dwarf.array[i - 1].range))) |
|
- | 2291 | overlap = TRUE; |
|
1831 | hdr_info->array[i].initial_loc |
2292 | } |
1832 | - sec->output_section->vma, |
2293 | if (overflow) |
- | 2294 | (*info->callbacks->einfo) (_("%P: .eh_frame_hdr entry overflow.\n")); |
|
1833 | contents + EH_FRAME_HDR_SIZE + i * 8 + 4); |
2295 | if (overlap) |
- | 2296 | (*info->callbacks->einfo) |
|
- | 2297 | (_("%P: .eh_frame_hdr refers to overlapping FDEs.\n")); |
|
1834 | bfd_put_32 (abfd, |
2298 | if (overflow || overlap) |
- | 2299 | { |
|
1835 | hdr_info->array[i].fde - sec->output_section->vma, |
2300 | bfd_set_error (bfd_error_bad_value); |
1836 | contents + EH_FRAME_HDR_SIZE + i * 8 + 8); |
2301 | retval = FALSE; |
Line 1837... | Line 2302... | ||
1837 | } |
2302 | } |
1838 | } |
2303 | } |
1839 | 2304 | ||
1840 | /* FIXME: octets_per_byte. */ |
2305 | /* FIXME: octets_per_byte. */ |
- | 2306 | if (!bfd_set_section_contents (abfd, sec->output_section, contents, |
|
1841 | retval = bfd_set_section_contents (abfd, sec->output_section, contents, |
2307 | (file_ptr) sec->output_offset, |
1842 | (file_ptr) sec->output_offset, |
2308 | sec->size)) |
1843 | sec->size); |
2309 | retval = FALSE; |
1844 | free (contents); |
2310 | free (contents); |
1845 | } |
2311 | |
1846 | if (hdr_info->array != NULL) |
2312 | if (hdr_info->u.dwarf.array != NULL) |
Line -... | Line 2313... | ||
- | 2313 | free (hdr_info->u.dwarf.array); |
|
- | 2314 | return retval; |
|
- | 2315 | } |
|
- | 2316 | ||
- | 2317 | /* Write out .eh_frame_hdr section. This must be called after |
|
- | 2318 | _bfd_elf_write_section_eh_frame has been called on all input |
|
- | 2319 | .eh_frame sections. */ |
|
- | 2320 | ||
- | 2321 | bfd_boolean |
|
- | 2322 | _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) |
|
- | 2323 | { |
|
- | 2324 | struct elf_link_hash_table *htab; |
|
- | 2325 | struct eh_frame_hdr_info *hdr_info; |
|
- | 2326 | asection *sec; |
|
- | 2327 | ||
- | 2328 | htab = elf_hash_table (info); |
|
- | 2329 | hdr_info = &htab->eh_info; |
|
- | 2330 | sec = hdr_info->hdr_sec; |
|
- | 2331 | ||
- | 2332 | if (info->eh_frame_hdr_type == 0 || sec == NULL) |
|
- | 2333 | return TRUE; |
|
- | 2334 | ||
- | 2335 | if (info->eh_frame_hdr_type == COMPACT_EH_HDR) |
|
- | 2336 | return write_compact_eh_frame_hdr (abfd, info); |
|
1847 | free (hdr_info->array); |
2337 | else |
Line 1848... | Line 2338... | ||
1848 | return retval; |
2338 | return write_dwarf_eh_frame_hdr (abfd, info); |
1849 | } |
2339 | } |
1850 | 2340 |