From 3f9a32bd0be95e8849906f47e660f1ab94045eff Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 25 Feb 2003 04:14:38 +0000 Subject: * elflink.h (elf_bfd_final_link): Apportion reloc counts to rel_hdr and rel_hdr2 when initially counting input relocs rather than after creating output reloc sections. --- bfd/ChangeLog | 8 +++- bfd/elflink.h | 120 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 65 insertions(+), 63 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 36de77c..eb0e000 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,9 @@ 2003-02-25 Alan Modra + * elflink.h (elf_bfd_final_link): Apportion reloc counts to rel_hdr + and rel_hdr2 when initially counting input relocs rather than after + creating output reloc sections. + * Makefile.am: Run "make dep-am". * Makefile.in: Regenerate. @@ -144,7 +148,7 @@ 2003-02-17 Nick Clifton - * elflink.h (elf_link_output_extsym): Only check + * elflink.h (elf_link_output_extsym): Only check allow_shlib_undefined for shared libraries. * elf32-i386.c (elf_i386_relocate_section): Remove bogus check of allow_shlib_undefined. @@ -169,7 +173,7 @@ * elf.c (SEGMENT_AFTER_SEGMENT): Add third parameter - the address field to use in the comparison. - (SEGMENT_OVERLAPS): Check that LMAs overlap as well. + (SEGMENT_OVERLAPS): Check that LMAs overlap as well. 2003-02-14 Bob Wilson diff --git a/bfd/elflink.h b/bfd/elflink.h index e034e36..bcc7d1f 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -4948,18 +4948,24 @@ elf_bfd_final_link (abfd, info) merged = FALSE; for (o = abfd->sections; o != (asection *) NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); o->reloc_count = 0; for (p = o->link_order_head; p != NULL; p = p->next) { + unsigned int reloc_count = 0; + struct bfd_elf_section_data *esdi = NULL; + unsigned int *rel_count1; + if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) - ++o->reloc_count; + reloc_count = 1; else if (p->type == bfd_indirect_link_order) { asection *sec; sec = p->u.indirect.section; + esdi = elf_section_data (sec); /* Mark all sections which are to be included in the link. This will normally be every section. We need @@ -4971,7 +4977,7 @@ elf_bfd_final_link (abfd, info) merged = TRUE; if (info->relocateable || info->emitrelocations) - o->reloc_count += sec->reloc_count; + reloc_count = sec->reloc_count; else if (bed->elf_backend_count_relocs) { Elf_Internal_Rela * relocs; @@ -4980,8 +4986,7 @@ elf_bfd_final_link (abfd, info) (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); - o->reloc_count - += (*bed->elf_backend_count_relocs) (sec, relocs); + reloc_count = (*bed->elf_backend_count_relocs) (sec, relocs); if (elf_section_data (o)->relocs != relocs) free (relocs); @@ -5024,6 +5029,56 @@ elf_bfd_final_link (abfd, info) } } } + + if (reloc_count == 0) + continue; + + o->reloc_count += reloc_count; + + /* MIPS may have a mix of REL and RELA relocs on sections. + To support this curious ABI we keep reloc counts in + elf_section_data too. We must be careful to add the + relocations from the input section to the right output + count. FIXME: Get rid of one count. We have + o->reloc_count == esdo->rel_count + esdo->rel_count2. */ + rel_count1 = &esdo->rel_count; + if (esdi != NULL) + { + bfd_boolean same_size; + bfd_size_type entsize1; + + entsize1 = esdi->rel_hdr.sh_entsize; + BFD_ASSERT (entsize1 == sizeof (Elf_External_Rel) + || entsize1 == sizeof (Elf_External_Rela)); + same_size = (!o->use_rela_p + == (entsize1 == sizeof (Elf_External_Rel))); + + if (!same_size) + rel_count1 = &esdo->rel_count2; + + if (esdi->rel_hdr2 != NULL) + { + bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize; + unsigned int alt_count; + unsigned int *rel_count2; + + BFD_ASSERT (entsize2 != entsize1 + && (entsize2 == sizeof (Elf_External_Rel) + || entsize2 == sizeof (Elf_External_Rela))); + + rel_count2 = &esdo->rel_count2; + if (!same_size) + rel_count2 = &esdo->rel_count; + + /* The following is probably too simplistic if the + backend counts output relocs unusually. */ + BFD_ASSERT (bed->elf_backend_count_relocs == NULL); + alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2); + *rel_count2 += alt_count; + reloc_count -= alt_count; + } + } + *rel_count1 += reloc_count; } if (o->reloc_count > 0) @@ -5057,63 +5112,6 @@ elf_bfd_final_link (abfd, info) if (! _bfd_elf_compute_section_file_positions (abfd, info)) goto error_return; - /* Figure out how many relocations we will have in each section. - Just using RELOC_COUNT isn't good enough since that doesn't - maintain a separate value for REL vs. RELA relocations. */ - if (emit_relocs) - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) - for (o = sub->sections; o != NULL; o = o->next) - { - asection *output_section; - - if (! o->linker_mark) - { - /* This section was omitted from the link. */ - continue; - } - - output_section = o->output_section; - - if (output_section != NULL - && (o->flags & SEC_RELOC) != 0) - { - struct bfd_elf_section_data *esdi - = elf_section_data (o); - struct bfd_elf_section_data *esdo - = elf_section_data (output_section); - unsigned int *rel_count; - unsigned int *rel_count2; - bfd_size_type entsize; - bfd_size_type entsize2; - - /* We must be careful to add the relocations from the - input section to the right output count. */ - entsize = esdi->rel_hdr.sh_entsize; - entsize2 = esdi->rel_hdr2 ? esdi->rel_hdr2->sh_entsize : 0; - BFD_ASSERT ((entsize == sizeof (Elf_External_Rel) - || entsize == sizeof (Elf_External_Rela)) - && entsize2 != entsize - && (entsize2 == 0 - || entsize2 == sizeof (Elf_External_Rel) - || entsize2 == sizeof (Elf_External_Rela))); - if (entsize == esdo->rel_hdr.sh_entsize) - { - rel_count = &esdo->rel_count; - rel_count2 = &esdo->rel_count2; - } - else - { - rel_count = &esdo->rel_count2; - rel_count2 = &esdo->rel_count; - } - - *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr); - if (esdi->rel_hdr2) - *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2); - output_section->flags |= SEC_RELOC; - } - } - /* That created the reloc sections. Set their sizes, and assign them file positions, and allocate some buffers. */ for (o = abfd->sections; o != NULL; o = o->next) -- cgit v1.1