diff options
-rw-r--r-- | bfd/ChangeLog | 73 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 52 | ||||
-rw-r--r-- | bfd/elf.c | 176 | ||||
-rw-r--r-- | bfd/elf32-m32r.c | 34 | ||||
-rw-r--r-- | bfd/elf32-microblaze.c | 2 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 5 | ||||
-rw-r--r-- | bfd/elf32-spu.c | 2 | ||||
-rw-r--r-- | bfd/elf32-tic6x.c | 39 | ||||
-rw-r--r-- | bfd/elf64-alpha.c | 2 | ||||
-rw-r--r-- | bfd/elf64-hppa.c | 2 | ||||
-rw-r--r-- | bfd/elf64-mips.c | 33 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 27 | ||||
-rw-r--r-- | bfd/elf64-sparc.c | 13 | ||||
-rw-r--r-- | bfd/elfcode.h | 23 | ||||
-rw-r--r-- | bfd/elflink.c | 325 | ||||
-rw-r--r-- | bfd/elfxx-ia64.c | 2 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 41 | ||||
-rw-r--r-- | bfd/elfxx-sparc.c | 4 | ||||
-rw-r--r-- | ld/ChangeLog | 5 | ||||
-rw-r--r-- | ld/emultempl/xtensaelf.em | 8 |
20 files changed, 455 insertions, 413 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f9aba1c..f7d2587 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,76 @@ +2010-10-04 Bernd Schmidt <bernds@codesourcery.com> + + * elf-bfd.h (struct bfd_elf_section_reloc_data): New structure. + (struct bfd_elf_section_data): New members REL and RELA; delete + members REL_HDR, REL_HDR2, REL_COUNT, REL_COUNT2, REL_IDX, + REL_IDX2, REL_HASHES. + (_bfd_elf_init_reloc_shdr): Adjust declaration. + (_bfd_elf_single_rel_hdr): Declare. + (RELOC_AGAINST_DISCARDED_SECTION): Use it. + * elf.c (bfd_section_from_shdr): Adjusted to match changes in + data structures. + (_bfd_elf_init_reloc_shdr): New arg RELDATA. Remove arg REL_HDR. + All callers changed. Allocate memory for the Elf_Internal_Shdr + structure. + (_bfd_elf_single_rel_hdr): New function. + (struct fake_section_arg): New structure. + (elf_fake_section): Expect to see a pointer to it in the third + argument. If doing a relocatable link, allocate both REL and RELA + sections as needed. + (assign_section_numbers): Adjusted to match changes in + data structures. + (_bfd_elf_compute_section_file_positions): Call elf_fake_sections + with a struct fake_section_args argument. + * elfcode.h (elf_write_relocs): Adjusted to match changes in + data structures. + (elf_slurp_reloc_table): Likewise. + * elflink.c (_bfd_elf_link_read_relocs): Likewise. + (_bfd_elf_link_size_reloc_section): Remove arg REL_HDR, replace with + RELDATA. Remove argument O. All callers changed. Remove code to + discover the right rel_hdr and count. + (_bfd_elf_link_output_relocs): Adjusted to match changes in + data structures. + (elf_link_adjust_relocs): Remove args REL_HDR, COUNT and REL_HASH; + replace with RELDATA. All callers changed. + (elf_link_input_bfd): Correctly generate rel_hash data when both + REL and RELA sections are present. + (elf_reloc_link_order): Adjusted to match changes in + data structures. + (bfd_elf_final_link): Simplify code to count relocs. Free the + hashes array for both REL and RELA. + (get_dynamic_reloc_section_name): Use _bfd_elf_single_reloc_hdr + * elf32-m32r.c (m32r_elf_fake_sections, elf_backend_fake_sections): + Delete. + * elf32-tic6x.c (elf32_tic6x_fake_sections, elf_backend_fake_sections): + Delete. + (elf32_tic6x_rel_relocation_p): Adjusted to match changes in + data structures. + * elf32-microblaze.c (microblaze_elf_check_relocs): Use + _bfd_elf_single_rel_hdr. + * elf32-ppc.c (ppc_elf_relax_section): Likewise. + * elf32-spu.c (spu_elf_relocate_section): Likewise. + * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. + * elf64-hppa.c (get_reloc_section): Likewise. + * elf64-mips.c (mips_elf64_slurp_reloc_table): Adjusted to match + changes in data structures. + (mips_elf64_write_relocs): Use _bfd_elf_single_rel_hdr. + * elf64-ppc.c (ppc64_elf_edit_opd): Likewise. + (ppc64_elf_edit_toc): Likewise. + (get_relocs): Adjusted to match changes in data structures. + Allocate an Elf_Internal_Shdr structure if necessary. + (ppc64_elf_finish_dynamic_sections): Use _bfd_elf_single_rel_hdr. + * elf64-sparc.c (elf64_sparc_slurp_reloc_table): Adjusted to match + changes in data structures. + * elfxx-ia64.c (get_reloc_section): Use _bfd_elf_single_rel_hdr. + * elfxx-mips.c (MIPS_RELOC_RELA_P): Remove macro. + (mips_elf_rel_relocation_p): Adjusted to match changes in data + structures. + (_bfd_mips_elf_relocate_section): Use mips_elf_rel_relocation_p rather + than MIPS_RELOC_RELOCA_P. + * elfxx-sparc.c (_bfd_sparc_elf_check_relocs): Use + _bfd_elf_single_rel_hdr. + (_bfd_sparc_elf_relocate_section): Likewise. + 2010-10-01 Thomas Schwinge <thomas@codesourcery.com> * elf32-arm.c (elf32_arm_size_stubs): Don't choke on local symbols in diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dbcebd2..66dcbcd 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1319,6 +1319,23 @@ struct elf_backend_data unsigned default_execstack : 1; }; +/* Information about reloc sections associated with a bfd_elf_section_data + structure. */ +struct bfd_elf_section_reloc_data +{ + /* The ELF header for the reloc section associated with this + section, if any. */ + Elf_Internal_Shdr *hdr; + /* The number of relocations currently assigned to HDR. */ + unsigned int count; + /* The ELF section number of the reloc section. Only used for an + output file. */ + int idx; + /* Used by the backend linker to store the symbol hash table entries + associated with relocs against global symbols. */ + struct elf_link_hash_entry **hashes; +}; + /* Information stored for each BFD section in an ELF file. This structure is allocated by elf_new_section_hook. */ @@ -1327,31 +1344,13 @@ struct bfd_elf_section_data /* The ELF header for this section. */ Elf_Internal_Shdr this_hdr; - /* The ELF header for the reloc section associated with this - section, if any. */ - Elf_Internal_Shdr rel_hdr; - - /* If there is a second reloc section associated with this section, - as can happen on Irix 6, this field points to the header. */ - Elf_Internal_Shdr *rel_hdr2; - - /* The number of relocations currently assigned to REL_HDR. */ - unsigned int rel_count; - - /* The number of relocations currently assigned to REL_HDR2. */ - unsigned int rel_count2; + /* Information about the REL and RELA reloc sections associated + with this section, if any. */ + struct bfd_elf_section_reloc_data rel, rela; /* The ELF section number of this section. */ int this_idx; - /* The ELF section number of the reloc section indicated by - REL_HDR if any. Only used for an output file. */ - int rel_idx; - - /* The ELF section number of the reloc section indicated by - REL_HDR2 if any. Only used for an output file. */ - int rel_idx2; - /* Used by the backend linker when generating a shared library to record the dynamic symbol index for a section symbol corresponding to this section. A value of 0 means that there is @@ -1361,10 +1360,6 @@ struct bfd_elf_section_data /* A pointer to the linked-to section for SHF_LINK_ORDER. */ asection *linked_to; - /* Used by the backend linker to store the symbol hash table entries - associated with relocs against global symbols. */ - struct elf_link_hash_entry **rel_hashes; - /* A pointer to the swapped relocs. If the section uses REL relocs, rather than RELA, all the r_addend fields will be zero. This pointer may be NULL. It is used by the backend linker. */ @@ -1852,7 +1847,7 @@ extern int _bfd_elf_sizeof_headers extern bfd_boolean _bfd_elf_new_section_hook (bfd *, asection *); extern bfd_boolean _bfd_elf_init_reloc_shdr - (bfd *, Elf_Internal_Shdr *, asection *, bfd_boolean); + (bfd *, struct bfd_elf_section_reloc_data *, asection *, bfd_boolean); extern const struct bfd_elf_special_section *_bfd_elf_get_special_section (const char *, const struct bfd_elf_special_section *, unsigned int); extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr @@ -2237,6 +2232,7 @@ extern void _bfd_elf_copy_obj_attributes (bfd *, bfd *); extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int); extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *); extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *); +extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec); /* The linker may needs to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. @@ -2363,13 +2359,13 @@ extern asection _bfd_elf_large_com_section; sections may require relocations. */ \ Elf_Internal_Shdr *rel_hdr; \ \ - rel_hdr = &elf_section_data (input_section->output_section)->rel_hdr; \ + rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section); \ \ /* Avoid empty output section. */ \ if (rel_hdr->sh_size > rel_hdr->sh_entsize) \ { \ rel_hdr->sh_size -= rel_hdr->sh_entsize; \ - rel_hdr = &elf_section_data (input_section)->rel_hdr; \ + rel_hdr = _bfd_elf_single_rel_hdr (input_section); \ rel_hdr->sh_size -= rel_hdr->sh_entsize; \ \ memmove (rel, rel + 1, (relend - rel) * sizeof (*rel)); \ @@ -1710,8 +1710,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* *These* do a lot of work -- but build no sections! */ { asection *target_sect; - Elf_Internal_Shdr *hdr2; + Elf_Internal_Shdr *hdr2, **p_hdr; unsigned int num_sec = elf_numsections (abfd); + struct bfd_elf_section_data *esdt; + bfd_size_type amt; if (hdr->sh_entsize != (bfd_size_type) (hdr->sh_type == SHT_REL @@ -1790,20 +1792,19 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) if (target_sect == NULL) return FALSE; - if ((target_sect->flags & SEC_RELOC) == 0 - || target_sect->reloc_count == 0) - hdr2 = &elf_section_data (target_sect)->rel_hdr; + esdt = elf_section_data (target_sect); + if (hdr->sh_type == SHT_RELA) + p_hdr = &esdt->rela.hdr; else - { - bfd_size_type amt; - BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL); - amt = sizeof (*hdr2); - hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); - if (hdr2 == NULL) - return FALSE; - elf_section_data (target_sect)->rel_hdr2 = hdr2; - } + p_hdr = &esdt->rel.hdr; + + BFD_ASSERT (*p_hdr == NULL); + amt = sizeof (*hdr2); + hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); + if (hdr2 == NULL) + return FALSE; *hdr2 = *hdr; + *p_hdr = hdr2; elf_elfsections (abfd)[shindex] = hdr2; target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr); target_sect->flags |= SEC_RELOC; @@ -1812,7 +1813,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex) /* In the section to which the relocations apply, mark whether its relocations are of the REL or RELA variety. */ if (hdr->sh_size != 0) - target_sect->use_rela_p = hdr->sh_type == SHT_RELA; + { + if (hdr->sh_type == SHT_RELA) + target_sect->use_rela_p = 1; + } abfd->flags |= HAS_RELOC; return TRUE; } @@ -2410,20 +2414,43 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) } } -/* Initialize REL_HDR, the section-header for new section, containing - relocations against ASECT. If USE_RELA_P is TRUE, we use RELA - relocations; otherwise, we use REL relocations. */ +/* Return the REL_HDR for SEC, assuming there is only a single one, either + REL or RELA. */ + +Elf_Internal_Shdr * +_bfd_elf_single_rel_hdr (asection *sec) +{ + if (elf_section_data (sec)->rel.hdr) + { + BFD_ASSERT (elf_section_data (sec)->rela.hdr == NULL); + return elf_section_data (sec)->rel.hdr; + } + else + return elf_section_data (sec)->rela.hdr; +} + +/* Allocate and initialize a section-header for a new reloc section, + containing relocations against ASECT. It is stored in RELDATA. If + USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL + relocations. */ bfd_boolean _bfd_elf_init_reloc_shdr (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, + struct bfd_elf_section_reloc_data *reldata, asection *asect, bfd_boolean use_rela_p) { + Elf_Internal_Shdr *rel_hdr; char *name; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_size_type amt = sizeof ".rela" + strlen (asect->name); + bfd_size_type amt; + + amt = sizeof (Elf_Internal_Shdr); + BFD_ASSERT (reldata->hdr == NULL); + rel_hdr = bfd_zalloc (abfd, amt); + reldata->hdr = rel_hdr; + amt = sizeof ".rela" + strlen (asect->name); name = (char *) bfd_alloc (abfd, amt); if (name == NULL) return FALSE; @@ -2457,30 +2484,37 @@ bfd_elf_get_default_section_type (flagword flags) return SHT_PROGBITS; } +struct fake_section_arg +{ + struct bfd_link_info *link_info; + bfd_boolean failed; +}; + /* Set up an ELF internal section header for a section. */ static void -elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) +elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) { + struct fake_section_arg *arg = (struct fake_section_arg *)fsarg; const struct elf_backend_data *bed = get_elf_backend_data (abfd); - bfd_boolean *failedptr = (bfd_boolean *) failedptrarg; + struct bfd_elf_section_data *esd = elf_section_data (asect); Elf_Internal_Shdr *this_hdr; unsigned int sh_type; - if (*failedptr) + if (arg->failed) { /* We already failed; just get out of the bfd_map_over_sections loop. */ return; } - this_hdr = &elf_section_data (asect)->this_hdr; + this_hdr = &esd->this_hdr; this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), asect->name, FALSE); if (this_hdr->sh_name == (unsigned int) -1) { - *failedptr = TRUE; + arg->failed = TRUE; return; } @@ -2632,11 +2666,45 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE) this_hdr->sh_flags |= SHF_EXCLUDE; + /* If the section has relocs, set up a section header for the + SHT_REL[A] section. If two relocation sections are required for + this section, it is up to the processor-specific back-end to + create the other. */ + if ((asect->flags & SEC_RELOC) != 0) + { + /* When doing a relocatable link, create both REL and RELA sections if + needed. */ + if (arg->link_info + /* Do the normal setup if we wouldn't create any sections here. */ + && esd->rel.count + esd->rela.count > 0 + && (arg->link_info->relocatable || arg->link_info->emitrelocations)) + { + if (esd->rel.count && esd->rel.hdr == NULL + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE)) + { + arg->failed = TRUE; + return; + } + if (esd->rela.count && esd->rela.hdr == NULL + && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE)) + { + arg->failed = TRUE; + return; + } + } + else if (!_bfd_elf_init_reloc_shdr (abfd, + (asect->use_rela_p + ? &esd->rela : &esd->rel), + asect, + asect->use_rela_p)) + arg->failed = TRUE; + } + /* Check for processor-specific section types. */ sh_type = this_hdr->sh_type; if (bed->elf_backend_fake_sections && !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect)) - *failedptr = TRUE; + arg->failed = TRUE; if (sh_type == SHT_NOBITS && asect->size != 0) { @@ -2644,17 +2712,6 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) called for objcopy --only-keep-debug. */ this_hdr->sh_type = sh_type; } - - /* If the section has relocs, set up a section header for the - SHT_REL[A] section. If two relocation sections are required for - this section, it is up to the processor-specific back-end to - create the other. */ - if ((asect->flags & SEC_RELOC) != 0 - && !_bfd_elf_init_reloc_shdr (abfd, - &elf_section_data (asect)->rel_hdr, - asect, - asect->use_rela_p)) - *failedptr = TRUE; } /* Fill in the contents of a SHT_GROUP section. Called from @@ -2820,21 +2877,21 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) if (d->this_hdr.sh_type != SHT_GROUP) d->this_idx = section_number++; _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name); - if ((sec->flags & SEC_RELOC) == 0) - d->rel_idx = 0; - else + if (d->rel.hdr) { - d->rel_idx = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name); + d->rel.idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name); } + else + d->rel.idx = 0; - if (d->rel_hdr2) + if (d->rela.hdr) { - d->rel_idx2 = section_number++; - _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name); + d->rela.idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name); } else - d->rel_idx2 = 0; + d->rela.idx = 0; } t->shstrtab_section = section_number++; @@ -2906,25 +2963,25 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) d = elf_section_data (sec); i_shdrp[d->this_idx] = &d->this_hdr; - if (d->rel_idx != 0) - i_shdrp[d->rel_idx] = &d->rel_hdr; - if (d->rel_idx2 != 0) - i_shdrp[d->rel_idx2] = d->rel_hdr2; + if (d->rel.idx != 0) + i_shdrp[d->rel.idx] = d->rel.hdr; + if (d->rela.idx != 0) + i_shdrp[d->rela.idx] = d->rela.hdr; /* Fill in the sh_link and sh_info fields while we're at it. */ /* sh_link of a reloc section is the section index of the symbol table. sh_info is the section index of the section to which the relocation entries apply. */ - if (d->rel_idx != 0) + if (d->rel.idx != 0) { - d->rel_hdr.sh_link = t->symtab_section; - d->rel_hdr.sh_info = d->this_idx; + d->rel.hdr->sh_link = t->symtab_section; + d->rel.hdr->sh_info = d->this_idx; } - if (d->rel_idx2 != 0) + if (d->rela.idx != 0) { - d->rel_hdr2->sh_link = t->symtab_section; - d->rel_hdr2->sh_info = d->this_idx; + d->rela.hdr->sh_link = t->symtab_section; + d->rela.hdr->sh_info = d->this_idx; } /* We need to set up sh_link for SHF_LINK_ORDER. */ @@ -3278,6 +3335,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, struct bfd_link_info *link_info) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct fake_section_arg fsargs; bfd_boolean failed; struct bfd_strtab_hash *strtab = NULL; Elf_Internal_Shdr *shstrtab_hdr; @@ -3297,9 +3355,10 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, if (bed->elf_backend_post_process_headers) (*bed->elf_backend_post_process_headers) (abfd, link_info); - failed = FALSE; - bfd_map_over_sections (abfd, elf_fake_sections, &failed); - if (failed) + fsargs.failed = FALSE; + fsargs.link_info = link_info; + bfd_map_over_sections (abfd, elf_fake_sections, &fsargs); + if (fsargs.failed) return FALSE; if (!assign_section_numbers (abfd, link_info)) @@ -3319,6 +3378,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, return FALSE; } + failed = FALSE; if (link_info == NULL) { bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed); diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index 3df6add..db7dcf9 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -4034,39 +4034,6 @@ static const struct bfd_elf_special_section m32r_elf_special_sections[] = { NULL, 0, 0, 0, 0 } }; -static bfd_boolean -m32r_elf_fake_sections (bfd *abfd, - Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED, - asection *sec) -{ - /* The generic elf_fake_sections will set up REL_HDR using the - default kind of relocations. But, we may actually need both - kinds of relocations, so we set up the second header here. - - This is not necessary for the O32 ABI since that only uses Elf32_Rel - relocations (cf. System V ABI, MIPS RISC Processor Supplement, - 3rd Edition, p. 4-17). It breaks the IRIX 5/6 32-bit ld, since one - of the resulting empty .rela.<section> sections starts with - sh_offset == object size, and ld doesn't allow that. While the check - is arguably bogus for empty or SHT_NOBITS sections, it can easily be - avoided by not emitting those useless sections in the first place. */ - if ((sec->flags & SEC_RELOC) != 0) - { - struct bfd_elf_section_data *esd; - bfd_size_type amt = sizeof (Elf_Internal_Shdr); - - esd = elf_section_data (sec); - BFD_ASSERT (esd->rel_hdr2 == NULL); - esd->rel_hdr2 = bfd_zalloc (abfd, amt); - if (!esd->rel_hdr2) - return FALSE; - _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, - !sec->use_rela_p); - } - - return TRUE; -} - static enum elf_reloc_type_class m32r_elf_reloc_type_class (const Elf_Internal_Rela *rela) { @@ -4128,7 +4095,6 @@ m32r_elf_reloc_type_class (const Elf_Internal_Rela *rela) #else #define elf_backend_default_use_rela_p 1 #define elf_backend_may_use_rela_p 1 -#define elf_backend_fake_sections m32r_elf_fake_sections #endif #define elf_backend_object_p m32r_elf_object_p diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c index e260c55..f32e06e 100644 --- a/bfd/elf32-microblaze.c +++ b/bfd/elf32-microblaze.c @@ -2060,7 +2060,7 @@ microblaze_elf_check_relocs (bfd * abfd, const char *name; bfd *dynobj; unsigned int strndx = elf_elfheader (abfd)->e_shstrndx; - unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name; + unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->sh_name; name = bfd_elf_string_from_elf_section (abfd, strndx, shnam); if (name == NULL) diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 2b457d6..58e9807 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -6391,6 +6391,7 @@ ppc_elf_relax_section (bfd *abfd, { /* Append sufficient NOP relocs so we can write out relocation information for the trampolines. */ + Elf_Internal_Shdr *rel_hdr; Elf_Internal_Rela *new_relocs = bfd_malloc ((changes + isec->reloc_count) * sizeof (*new_relocs)); unsigned ix; @@ -6409,8 +6410,8 @@ ppc_elf_relax_section (bfd *abfd, free (internal_relocs); elf_section_data (isec)->relocs = new_relocs; isec->reloc_count += changes; - elf_section_data (isec)->rel_hdr.sh_size - += changes * elf_section_data (isec)->rel_hdr.sh_entsize; + rel_hdr = _bfd_elf_single_rel_hdr (isec); + rel_hdr->sh_size += changes * rel_hdr->sh_entsize; } else if (elf_section_data (isec)->relocs != internal_relocs) free (internal_relocs); diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c index b1ea43c..ed52c64 100644 --- a/bfd/elf32-spu.c +++ b/bfd/elf32-spu.c @@ -5091,7 +5091,7 @@ spu_elf_relocate_section (bfd *output_bfd, } input_section->reloc_count = wrel - relocs; /* Backflips for _bfd_elf_link_output_relocs. */ - rel_hdr = &elf_section_data (input_section)->rel_hdr; + rel_hdr = _bfd_elf_single_rel_hdr (input_section); rel_hdr->sh_size = input_section->reloc_count * rel_hdr->sh_entsize; ret = 2; } diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c index ed3d3d9..a570f88 100644 --- a/bfd/elf32-tic6x.c +++ b/bfd/elf32-tic6x.c @@ -1348,31 +1348,6 @@ elf32_tic6x_set_use_rela_p (bfd *abfd, bfd_boolean use_rela_p) } static bfd_boolean -elf32_tic6x_fake_sections (bfd *abfd, - Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED, - asection *sec) -{ - /* The generic elf_fake_sections will set up REL_HDR using the - default kind of relocations. But, we may actually need both - kinds of relocations, so we set up the second header here. */ - if ((sec->flags & SEC_RELOC) != 0) - { - struct bfd_elf_section_data *esd; - bfd_size_type amt = sizeof (Elf_Internal_Shdr); - - esd = elf_section_data (sec); - BFD_ASSERT (esd->rel_hdr2 == NULL); - esd->rel_hdr2 = bfd_zalloc (abfd, amt); - if (!esd->rel_hdr2) - return FALSE; - _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, - !sec->use_rela_p); - } - - return TRUE; -} - -static bfd_boolean elf32_tic6x_mkobject (bfd *abfd) { bfd_boolean ret; @@ -1408,14 +1383,13 @@ elf32_tic6x_rel_relocation_p (bfd *abfd, asection *sec, const struct elf_backend_data *bed; /* To determine which flavor of relocation this is, we depend on the - fact that the INPUT_SECTION's REL_HDR is read before its - REL_HDR2. */ - rel_hdr = &elf_section_data (sec)->rel_hdr; + fact that the INPUT_SECTION's REL_HDR is read before RELA_HDR. */ + rel_hdr = elf_section_data (sec)->rel.hdr; + if (rel_hdr == NULL) + return FALSE; bed = get_elf_backend_data (abfd); - if ((size_t) (rel - relocs) - >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel)) - rel_hdr = elf_section_data (sec)->rel_hdr2; - return rel_hdr->sh_entsize == bed->s->sizeof_rel; + return ((size_t) (rel - relocs) + < NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel); } static bfd_boolean @@ -1790,7 +1764,6 @@ elf32_tic6x_merge_private_bfd_data (bfd *ibfd, bfd *obfd) #define elf_backend_default_use_rela_p 1 #define elf_backend_may_use_rel_p 1 #define elf_backend_may_use_rela_p 1 -#define elf_backend_fake_sections elf32_tic6x_fake_sections #define elf_backend_obj_attrs_arg_type elf32_tic6x_obj_attrs_arg_type #define elf_backend_obj_attrs_section "__TI_build_attributes" #define elf_backend_obj_attrs_section_type SHT_C6000_ATTRIBUTES diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 1df020c..a6a795d 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -4086,7 +4086,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, const char *section_name; section_name = (bfd_elf_string_from_elf_section (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, - elf_section_data(input_section)->rel_hdr.sh_name)); + _bfd_elf_single_rel_hdr (input_section)->sh_name)); BFD_ASSERT(section_name != NULL); srel = bfd_get_section_by_name (dynobj, section_name); } diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 4efab4f..e7e61a1 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -407,7 +407,7 @@ get_reloc_section (bfd *abfd, srel_name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, - elf_section_data(sec)->rel_hdr.sh_name)); + _bfd_elf_single_rel_hdr(sec)->sh_name)); if (srel_name == NULL) return FALSE; diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 5001d42..7ed54fa 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -2722,13 +2722,13 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect, || asect->reloc_count == 0) return TRUE; - rel_hdr = &d->rel_hdr; - reloc_count = NUM_SHDR_ENTRIES (rel_hdr); - rel_hdr2 = d->rel_hdr2; + rel_hdr = d->rel.hdr; + reloc_count = rel_hdr ? NUM_SHDR_ENTRIES (rel_hdr) : 0; + rel_hdr2 = d->rela.hdr; reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0); BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2); - BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset) || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); } @@ -2756,19 +2756,18 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect, /* The slurp_one_reloc_table routine increments reloc_count. */ asect->reloc_count = 0; - if (! mips_elf64_slurp_one_reloc_table (abfd, asect, - rel_hdr, reloc_count, - relents, - symbols, dynamic)) + if (rel_hdr != NULL + && ! mips_elf64_slurp_one_reloc_table (abfd, asect, + rel_hdr, reloc_count, + relents, + symbols, dynamic)) + return FALSE; + if (rel_hdr2 != NULL + && ! mips_elf64_slurp_one_reloc_table (abfd, asect, + rel_hdr2, reloc_count2, + relents + reloc_count * 3, + symbols, dynamic)) return FALSE; - if (d->rel_hdr2 != NULL) - { - if (! mips_elf64_slurp_one_reloc_table (abfd, asect, - rel_hdr2, reloc_count2, - relents + reloc_count * 3, - symbols, dynamic)) - return FALSE; - } asect->relocation = relents; return TRUE; @@ -2827,7 +2826,7 @@ mips_elf64_write_relocs (bfd *abfd, asection *sec, void *data) } } - rel_hdr = &elf_section_data (sec)->rel_hdr; + rel_hdr = _bfd_elf_single_rel_hdr (sec); /* Do the actual relocation. */ diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index a4f3064..2cdb0a2 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -7073,6 +7073,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) if (need_edit || add_aux_fields) { Elf_Internal_Rela *write_rel; + Elf_Internal_Shdr *rel_hdr; bfd_byte *rptr, *wptr; bfd_byte *new_contents; bfd_boolean skip; @@ -7252,9 +7253,8 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping) /* Fudge the header size too, as this is used later in elf_bfd_final_link if we are emitting relocs. */ - elf_section_data (sec)->rel_hdr.sh_size - = sec->reloc_count * elf_section_data (sec)->rel_hdr.sh_entsize; - BFD_ASSERT (elf_section_data (sec)->rel_hdr2 == NULL); + rel_hdr = _bfd_elf_single_rel_hdr (sec); + rel_hdr->sh_size = sec->reloc_count * rel_hdr->sh_entsize; some_edited = TRUE; } else if (elf_section_data (sec)->relocs != relstart) @@ -8413,6 +8413,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) if (toc->reloc_count != 0) { + Elf_Internal_Shdr *rel_hdr; Elf_Internal_Rela *wrel; bfd_size_type sz; @@ -8438,9 +8439,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) goto error_ret; toc->reloc_count = wrel - relstart; - sz = elf_section_data (toc)->rel_hdr.sh_entsize; - elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz; - BFD_ASSERT (elf_section_data (toc)->rel_hdr2 == NULL); + rel_hdr = _bfd_elf_single_rel_hdr (toc); + sz = rel_hdr->sh_entsize; + rel_hdr->sh_size = toc->reloc_count * sz; } } @@ -9376,9 +9377,13 @@ get_relocs (asection *sec, int count) if (relocs == NULL) return NULL; elfsec_data->relocs = relocs; - elfsec_data->rel_hdr.sh_size = (sec->reloc_count - * sizeof (Elf64_External_Rela)); - elfsec_data->rel_hdr.sh_entsize = sizeof (Elf64_External_Rela); + elfsec_data->rela.hdr = bfd_zalloc (sec->owner, + sizeof (Elf_Internal_Shdr)); + if (elfsec_data->rela.hdr == NULL) + return NULL; + elfsec_data->rela.hdr->sh_size = (sec->reloc_count + * sizeof (Elf64_External_Rela)); + elfsec_data->rela.hdr->sh_entsize = sizeof (Elf64_External_Rela); sec->reloc_count = 0; } relocs += sec->reloc_count; @@ -13472,7 +13477,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, && htab->brlt->reloc_count != 0 && !_bfd_elf_link_output_relocs (output_bfd, htab->brlt, - &elf_section_data (htab->brlt)->rel_hdr, + elf_section_data (htab->brlt)->rela.hdr, elf_section_data (htab->brlt)->relocs, NULL)) return FALSE; @@ -13481,7 +13486,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, && htab->glink->reloc_count != 0 && !_bfd_elf_link_output_relocs (output_bfd, htab->glink, - &elf_section_data (htab->glink)->rel_hdr, + elf_section_data (htab->glink)->rela.hdr, elf_section_data (htab->glink)->relocs, NULL)) return FALSE; diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index ca692d2..1ad0c14 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -163,10 +163,10 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, || asect->reloc_count == 0) return TRUE; - rel_hdr = &d->rel_hdr; - rel_hdr2 = d->rel_hdr2; + rel_hdr = d->rel.hdr; + rel_hdr2 = d->rela.hdr; - BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset) || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); } else @@ -193,8 +193,9 @@ elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, canon_reloc_count. */ canon_reloc_count (asect) = 0; - if (!elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, - dynamic)) + if (rel_hdr + && !elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, + dynamic)) return FALSE; if (rel_hdr2 @@ -325,7 +326,7 @@ elf64_sparc_write_relocs (bfd *abfd, asection *sec, PTR data) } } - rela_hdr = &elf_section_data (sec)->rel_hdr; + rela_hdr = elf_section_data (sec)->rela.hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * count; rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 0cd1183..5ef4610 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -959,7 +959,9 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data) if (sec->orelocation == NULL) return; - rela_hdr = &elf_section_data (sec)->rel_hdr; + rela_hdr = elf_section_data (sec)->rela.hdr; + if (rela_hdr == NULL) + rela_hdr = elf_section_data (sec)->rel.hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size); @@ -1530,13 +1532,13 @@ elf_slurp_reloc_table (bfd *abfd, || asect->reloc_count == 0) return TRUE; - rel_hdr = &d->rel_hdr; - reloc_count = NUM_SHDR_ENTRIES (rel_hdr); - rel_hdr2 = d->rel_hdr2; - reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0); + rel_hdr = d->rel.hdr; + reloc_count = rel_hdr ? NUM_SHDR_ENTRIES (rel_hdr) : 0; + rel_hdr2 = d->rela.hdr; + reloc_count2 = rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0; BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2); - BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset) || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); } @@ -1560,10 +1562,11 @@ elf_slurp_reloc_table (bfd *abfd, if (relents == NULL) return FALSE; - if (!elf_slurp_reloc_table_from_section (abfd, asect, - rel_hdr, reloc_count, - relents, - symbols, dynamic)) + if (rel_hdr + && !elf_slurp_reloc_table_from_section (abfd, asect, + rel_hdr, reloc_count, + relents, + symbols, dynamic)) return FALSE; if (rel_hdr2 diff --git a/bfd/elflink.c b/bfd/elflink.c index 46f1e25..2c45649 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2196,7 +2196,7 @@ elf_link_read_relocs_from_section (bfd *abfd, according to the KEEP_MEMORY argument. If O has two relocation sections (both REL and RELA relocations), then the REL_HDR relocations will appear first in INTERNAL_RELOCS, followed by the - REL_HDR2 relocations. */ + RELA_HDR relocations. */ Elf_Internal_Rela * _bfd_elf_link_read_relocs (bfd *abfd, @@ -2205,19 +2205,18 @@ _bfd_elf_link_read_relocs (bfd *abfd, Elf_Internal_Rela *internal_relocs, bfd_boolean keep_memory) { - Elf_Internal_Shdr *rel_hdr; void *alloc1 = NULL; Elf_Internal_Rela *alloc2 = NULL; const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct bfd_elf_section_data *esdo = elf_section_data (o); + Elf_Internal_Rela *internal_rela_relocs; - if (elf_section_data (o)->relocs != NULL) - return elf_section_data (o)->relocs; + if (esdo->relocs != NULL) + return esdo->relocs; if (o->reloc_count == 0) return NULL; - rel_hdr = &elf_section_data (o)->rel_hdr; - if (internal_relocs == NULL) { bfd_size_type size; @@ -2234,32 +2233,41 @@ _bfd_elf_link_read_relocs (bfd *abfd, if (external_relocs == NULL) { - bfd_size_type size = rel_hdr->sh_size; + bfd_size_type size = 0; + + if (esdo->rel.hdr) + size += esdo->rel.hdr->sh_size; + if (esdo->rela.hdr) + size += esdo->rela.hdr->sh_size; - if (elf_section_data (o)->rel_hdr2) - size += elf_section_data (o)->rel_hdr2->sh_size; alloc1 = bfd_malloc (size); if (alloc1 == NULL) goto error_return; external_relocs = alloc1; } - if (!elf_link_read_relocs_from_section (abfd, o, rel_hdr, - external_relocs, - internal_relocs)) - goto error_return; - if (elf_section_data (o)->rel_hdr2 - && (!elf_link_read_relocs_from_section - (abfd, o, - elf_section_data (o)->rel_hdr2, - ((bfd_byte *) external_relocs) + rel_hdr->sh_size, - internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr) - * bed->s->int_rels_per_ext_rel)))) + internal_rela_relocs = internal_relocs; + if (esdo->rel.hdr) + { + if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr, + external_relocs, + internal_relocs)) + goto error_return; + external_relocs = (((bfd_byte *) external_relocs) + + esdo->rel.hdr->sh_size); + internal_rela_relocs += (NUM_SHDR_ENTRIES (esdo->rel.hdr) + * bed->s->int_rels_per_ext_rel); + } + + if (esdo->rela.hdr + && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, + external_relocs, + internal_rela_relocs))) goto error_return; /* Cache the results for next time, if we can. */ if (keep_memory) - elf_section_data (o)->relocs = internal_relocs; + esdo->relocs = internal_relocs; if (alloc1 != NULL) free (alloc1); @@ -2287,24 +2295,12 @@ _bfd_elf_link_read_relocs (bfd *abfd, static bfd_boolean _bfd_elf_link_size_reloc_section (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, - asection *o) + struct bfd_elf_section_reloc_data *reldata) { - bfd_size_type reloc_count; - bfd_size_type num_rel_hashes; - - /* Figure out how many relocations there will be. */ - if (rel_hdr == &elf_section_data (o)->rel_hdr) - reloc_count = elf_section_data (o)->rel_count; - else - reloc_count = elf_section_data (o)->rel_count2; - - num_rel_hashes = o->reloc_count; - if (num_rel_hashes < reloc_count) - num_rel_hashes = reloc_count; + Elf_Internal_Shdr *rel_hdr = reldata->hdr; /* That allows us to calculate the size of the section. */ - rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count; + rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count; /* The contents field must last into write_object_contents, so we allocate it with bfd_alloc rather than malloc. Also since we @@ -2314,19 +2310,16 @@ _bfd_elf_link_size_reloc_section (bfd *abfd, if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0) return FALSE; - /* We only allocate one set of hash entries, so we only do it the - first time we are called. */ - if (elf_section_data (o)->rel_hashes == NULL - && num_rel_hashes) + if (reldata->hashes == NULL && reldata->count) { struct elf_link_hash_entry **p; p = (struct elf_link_hash_entry **) - bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *)); + bfd_zmalloc (reldata->count * sizeof (struct elf_link_hash_entry *)); if (p == NULL) return FALSE; - elf_section_data (o)->rel_hashes = p; + reldata->hashes = p; } return TRUE; @@ -2347,27 +2340,28 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, Elf_Internal_Rela *irela; Elf_Internal_Rela *irelaend; bfd_byte *erel; + struct bfd_elf_section_reloc_data *output_reldata; Elf_Internal_Shdr *output_rel_hdr; asection *output_section; - unsigned int *rel_countp = NULL; const struct elf_backend_data *bed; void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); + struct bfd_elf_section_data *esdo; output_section = input_section->output_section; output_rel_hdr = NULL; - if (elf_section_data (output_section)->rel_hdr.sh_entsize - == input_rel_hdr->sh_entsize) + bed = get_elf_backend_data (output_bfd); + esdo = elf_section_data (output_section); + if (esdo->rel.hdr && esdo->rel.hdr->sh_entsize == input_rel_hdr->sh_entsize) { - output_rel_hdr = &elf_section_data (output_section)->rel_hdr; - rel_countp = &elf_section_data (output_section)->rel_count; + output_reldata = &esdo->rel; + swap_out = bed->s->swap_reloc_out; } - else if (elf_section_data (output_section)->rel_hdr2 - && (elf_section_data (output_section)->rel_hdr2->sh_entsize - == input_rel_hdr->sh_entsize)) + else if (esdo->rela.hdr + && esdo->rela.hdr->sh_entsize == input_rel_hdr->sh_entsize) { - output_rel_hdr = elf_section_data (output_section)->rel_hdr2; - rel_countp = &elf_section_data (output_section)->rel_count2; + output_reldata = &esdo->rela; + swap_out = bed->s->swap_reloca_out; } else { @@ -2378,16 +2372,8 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, return FALSE; } - bed = get_elf_backend_data (output_bfd); - if (input_rel_hdr->sh_entsize == bed->s->sizeof_rel) - swap_out = bed->s->swap_reloc_out; - else if (input_rel_hdr->sh_entsize == bed->s->sizeof_rela) - swap_out = bed->s->swap_reloca_out; - else - abort (); - - erel = output_rel_hdr->contents; - erel += *rel_countp * input_rel_hdr->sh_entsize; + erel = output_reldata->hdr->contents; + erel += output_reldata->count * input_rel_hdr->sh_entsize; irela = internal_relocs; irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr) * bed->s->int_rels_per_ext_rel); @@ -2400,7 +2386,7 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, /* Bump the counter, so that we know where to add the next set of relocations. */ - *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr); + output_reldata->count += NUM_SHDR_ENTRIES (input_rel_hdr); return TRUE; } @@ -7928,14 +7914,12 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, /* When performing a relocatable link, the input relocations are preserved. But, if they reference global symbols, the indices - referenced must be updated. Update all the relocations in - REL_HDR (there are COUNT of them), using the data in REL_HASH. */ + referenced must be updated. Update all the relocations found in + RELDATA. */ static void elf_link_adjust_relocs (bfd *abfd, - Elf_Internal_Shdr *rel_hdr, - unsigned int count, - struct elf_link_hash_entry **rel_hash) + struct bfd_elf_section_reloc_data *reldata) { unsigned int i; const struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -7944,13 +7928,15 @@ elf_link_adjust_relocs (bfd *abfd, void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); bfd_vma r_type_mask; int r_sym_shift; + unsigned int count = reldata->count; + struct elf_link_hash_entry **rel_hash = reldata->hashes; - if (rel_hdr->sh_entsize == bed->s->sizeof_rel) + if (reldata->hdr->sh_entsize == bed->s->sizeof_rel) { swap_in = bed->s->swap_reloc_in; swap_out = bed->s->swap_reloc_out; } - else if (rel_hdr->sh_entsize == bed->s->sizeof_rela) + else if (reldata->hdr->sh_entsize == bed->s->sizeof_rela) { swap_in = bed->s->swap_reloca_in; swap_out = bed->s->swap_reloca_out; @@ -7972,8 +7958,8 @@ elf_link_adjust_relocs (bfd *abfd, r_sym_shift = 32; } - erela = rel_hdr->contents; - for (i = 0; i < count; i++, rel_hash++, erela += rel_hdr->sh_entsize) + erela = reldata->hdr->contents; + for (i = 0; i < count; i++, rel_hash++, erela += reldata->hdr->sh_entsize) { Elf_Internal_Rela irela[MAX_INT_RELS_PER_EXT_REL]; unsigned int j; @@ -9563,27 +9549,32 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) || finfo->info->emitrelocations) { Elf_Internal_Rela *irela; - Elf_Internal_Rela *irelaend; + Elf_Internal_Rela *irelaend, *irelamid; bfd_vma last_offset; struct elf_link_hash_entry **rel_hash; - struct elf_link_hash_entry **rel_hash_list; - Elf_Internal_Shdr *input_rel_hdr, *input_rel_hdr2; + struct elf_link_hash_entry **rel_hash_list, **rela_hash_list; + Elf_Internal_Shdr *input_rel_hdr, *input_rela_hdr; unsigned int next_erel; bfd_boolean rela_normal; + struct bfd_elf_section_data *esdi, *esdo; - input_rel_hdr = &elf_section_data (o)->rel_hdr; - rela_normal = (bed->rela_normal - && (input_rel_hdr->sh_entsize - == bed->s->sizeof_rela)); + esdi = elf_section_data (o); + esdo = elf_section_data (o->output_section); + rela_normal = FALSE; /* Adjust the reloc addresses and symbol indices. */ irela = internal_relocs; irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel; - rel_hash = (elf_section_data (o->output_section)->rel_hashes - + elf_section_data (o->output_section)->rel_count - + elf_section_data (o->output_section)->rel_count2); + rel_hash = esdo->rel.hashes + esdo->rel.count; + /* We start processing the REL relocs, if any. When we reach + IRELAMID in the loop, we switch to the RELA relocs. */ + irelamid = irela; + if (esdi->rel.hdr != NULL) + irelamid += (NUM_SHDR_ENTRIES (esdi->rel.hdr) + * bed->s->int_rels_per_ext_rel); rel_hash_list = rel_hash; + rela_hash_list = NULL; last_offset = o->output_offset; if (!finfo->info->relocatable) last_offset += o->output_section->vma; @@ -9599,6 +9590,13 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) next_erel = 0; } + if (irela == irelamid) + { + rel_hash = esdo->rela.hashes + esdo->rela.count; + rela_hash_list = rel_hash; + rela_normal = bed->rela_normal; + } + irela->r_offset = _bfd_elf_section_offset (output_bfd, finfo->info, o, irela->r_offset); @@ -9790,23 +9788,26 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } /* Swap out the relocs. */ - if (input_rel_hdr->sh_size != 0 - && !bed->elf_backend_emit_relocs (output_bfd, o, - input_rel_hdr, - internal_relocs, - rel_hash_list)) - return FALSE; - - input_rel_hdr2 = elf_section_data (o)->rel_hdr2; - if (input_rel_hdr2 && input_rel_hdr2->sh_size != 0) + input_rel_hdr = esdi->rel.hdr; + if (input_rel_hdr && input_rel_hdr->sh_size != 0) { + if (!bed->elf_backend_emit_relocs (output_bfd, o, + input_rel_hdr, + internal_relocs, + rel_hash_list)) + return FALSE; internal_relocs += (NUM_SHDR_ENTRIES (input_rel_hdr) * bed->s->int_rels_per_ext_rel); rel_hash_list += NUM_SHDR_ENTRIES (input_rel_hdr); + } + + input_rela_hdr = esdi->rela.hdr; + if (input_rela_hdr && input_rela_hdr->sh_size != 0) + { if (!bed->elf_backend_emit_relocs (output_bfd, o, - input_rel_hdr2, + input_rela_hdr, internal_relocs, - rel_hash_list)) + rela_hash_list)) return FALSE; } } @@ -9872,12 +9873,14 @@ elf_reloc_link_order (bfd *output_bfd, long indx; bfd_vma offset; bfd_vma addend; + struct bfd_elf_section_reloc_data *reldata; struct elf_link_hash_entry **rel_hash_ptr; Elf_Internal_Shdr *rel_hdr; const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); Elf_Internal_Rela irel[MAX_INT_RELS_PER_EXT_REL]; bfd_byte *erel; unsigned int i; + struct bfd_elf_section_data *esdo = elf_section_data (output_section); howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc); if (howto == NULL) @@ -9888,10 +9891,18 @@ elf_reloc_link_order (bfd *output_bfd, addend = link_order->u.reloc.p->addend; + if (esdo->rel.hdr) + reldata = &esdo->rel; + else if (esdo->rela.hdr) + reldata = &esdo->rela; + else + { + reldata = NULL; + BFD_ASSERT (0); + } + /* Figure out the symbol index. */ - rel_hash_ptr = (elf_section_data (output_section)->rel_hashes - + elf_section_data (output_section)->rel_count - + elf_section_data (output_section)->rel_count2); + rel_hash_ptr = reldata->hashes + reldata->count; if (link_order->type == bfd_section_reloc_link_order) { indx = link_order->u.reloc.p->u.section->target_index; @@ -10003,23 +10014,21 @@ elf_reloc_link_order (bfd *output_bfd, else irel[0].r_info = ELF64_R_INFO (indx, howto->type); - rel_hdr = &elf_section_data (output_section)->rel_hdr; + rel_hdr = reldata->hdr; erel = rel_hdr->contents; if (rel_hdr->sh_type == SHT_REL) { - erel += (elf_section_data (output_section)->rel_count - * bed->s->sizeof_rel); + erel += reldata->count * bed->s->sizeof_rel; (*bed->s->swap_reloc_out) (output_bfd, irel, erel); } else { irel[0].r_addend = addend; - erel += (elf_section_data (output_section)->rel_count - * bed->s->sizeof_rela); + erel += reldata->count * bed->s->sizeof_rela; (*bed->s->swap_reloca_out) (output_bfd, irel, erel); } - ++elf_section_data (output_section)->rel_count; + ++reldata->count; return TRUE; } @@ -10305,7 +10314,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { 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) @@ -10358,11 +10366,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if ((sec->flags & SEC_RELOC) != 0) { - size_t ext_size; + size_t ext_size = 0; - ext_size = esdi->rel_hdr.sh_size; - if (esdi->rel_hdr2 != NULL) - ext_size += esdi->rel_hdr2->sh_size; + if (esdi->rel.hdr != NULL) + ext_size = esdi->rel.hdr->sh_size; + if (esdi->rela.hdr != NULL) + ext_size += esdi->rela.hdr->sh_size; if (ext_size > max_external_reloc_size) max_external_reloc_size = ext_size; @@ -10377,54 +10386,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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) + if (p->type == bfd_indirect_link_order + && (info->relocatable || info->emitrelocations)) { - bfd_boolean same_size; - bfd_size_type entsize1; - - entsize1 = esdi->rel_hdr.sh_entsize; - /* PR 9827: If the header size has not been set yet then - assume that it will match the output section's reloc type. */ - if (entsize1 == 0) - entsize1 = o->use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel; + if (esdi->rel.hdr) + esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + if (esdi->rela.hdr) + esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + } + else + { + if (o->use_rela_p) + esdo->rela.count += reloc_count; else - BFD_ASSERT (entsize1 == bed->s->sizeof_rel - || entsize1 == bed->s->sizeof_rela); - same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_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 == bed->s->sizeof_rel - || entsize2 == bed->s->sizeof_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; - } + esdo->rel.count += reloc_count; } - *rel_count1 += reloc_count; } if (o->reloc_count > 0) @@ -10461,22 +10437,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Set sizes, and assign file positions for reloc sections. */ for (o = abfd->sections; o != NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); if ((o->flags & SEC_RELOC) != 0) { - if (!(_bfd_elf_link_size_reloc_section - (abfd, &elf_section_data (o)->rel_hdr, o))) + if (esdo->rel.hdr + && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rel))) goto error_return; - if (elf_section_data (o)->rel_hdr2 - && !(_bfd_elf_link_size_reloc_section - (abfd, elf_section_data (o)->rel_hdr2, o))) + if (esdo->rela.hdr + && !(_bfd_elf_link_size_reloc_section (abfd, &esdo->rela))) goto error_return; } /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them to count upwards while actually outputting the relocations. */ - elf_section_data (o)->rel_count = 0; - elf_section_data (o)->rel_count2 = 0; + esdo->rel.count = 0; + esdo->rela.count = 0; } _bfd_elf_assign_file_positions_for_relocs (abfd); @@ -10908,17 +10884,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Adjust the relocs to have the correct symbol indices. */ for (o = abfd->sections; o != NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); if ((o->flags & SEC_RELOC) == 0) continue; - elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr, - elf_section_data (o)->rel_count, - elf_section_data (o)->rel_hashes); - if (elf_section_data (o)->rel_hdr2 != NULL) - elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2, - elf_section_data (o)->rel_count2, - (elf_section_data (o)->rel_hashes - + elf_section_data (o)->rel_count)); + if (esdo->rel.hdr != NULL) + elf_link_adjust_relocs (abfd, &esdo->rel); + if (esdo->rela.hdr != NULL) + elf_link_adjust_relocs (abfd, &esdo->rela); /* Set the reloc_count field to 0 to prevent write_relocs from trying to swap the relocs out itself. */ @@ -11213,9 +11186,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) free (finfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { - if ((o->flags & SEC_RELOC) != 0 - && elf_section_data (o)->rel_hashes != NULL) - free (elf_section_data (o)->rel_hashes); + struct bfd_elf_section_data *esdo = elf_section_data (o); + if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL) + free (esdo->rel.hashes); + if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL) + free (esdo->rela.hashes); } elf_tdata (abfd)->linker = TRUE; @@ -11257,9 +11232,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) free (finfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { - if ((o->flags & SEC_RELOC) != 0 - && elf_section_data (o)->rel_hashes != NULL) - free (elf_section_data (o)->rel_hashes); + struct bfd_elf_section_data *esdo = elf_section_data (o); + if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL) + free (esdo->rel.hashes); + if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL) + free (esdo->rela.hashes); } return FALSE; @@ -12603,7 +12580,7 @@ get_dynamic_reloc_section_name (bfd * abfd, { const char * name; unsigned int strndx = elf_elfheader (abfd)->e_shstrndx; - unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name; + unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->sh_name; name = bfd_elf_string_from_elf_section (abfd, strndx, shnam); if (name == NULL) diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index d780909..6b52bc6 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -2598,7 +2598,7 @@ get_reloc_section (bfd *abfd, srel_name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader(abfd)->e_shstrndx, - elf_section_data(sec)->rel_hdr.sh_name)); + _bfd_elf_single_rel_hdr (sec)->sh_name)); if (srel_name == NULL) return NULL; diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index a32a613..8feb5c4 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -783,23 +783,6 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_RTYPE_TO_HOWTO(abfd, rtype, rela) \ (get_elf_backend_data (abfd)->elf_backend_mips_rtype_to_howto (rtype, rela)) -/* Determine whether the internal relocation of index REL_IDX is REL - (zero) or RELA (non-zero). The assumption is that, if there are - two relocation sections for this section, one of them is REL and - the other is RELA. If the index of the relocation we're testing is - in range for the first relocation section, check that the external - relocation size is that for RELA. It is also assumed that, if - rel_idx is not in range for the first section, and this first - section contains REL relocs, then the relocation is in the second - section, that is RELA. */ -#define MIPS_RELOC_RELA_P(abfd, sec, rel_idx) \ - ((NUM_SHDR_ENTRIES (&elf_section_data (sec)->rel_hdr) \ - * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel \ - > (bfd_vma)(rel_idx)) \ - == (elf_section_data (sec)->rel_hdr.sh_entsize \ - == (ABI_64_P (abfd) ? sizeof (Elf64_External_Rela) \ - : sizeof (Elf32_External_Rela)))) - /* The name of the dynamic relocation section. */ #define MIPS_ELF_REL_DYN_NAME(INFO) \ (mips_elf_hash_table (INFO)->is_vxworks ? ".rela.dyn" : ".rel.dyn") @@ -7110,14 +7093,14 @@ mips_elf_rel_relocation_p (bfd *abfd, asection *sec, Elf_Internal_Shdr *rel_hdr; const struct elf_backend_data *bed; - /* To determine which flavor or relocation this is, we depend on the - fact that the INPUT_SECTION's REL_HDR is read before its REL_HDR2. */ - rel_hdr = &elf_section_data (sec)->rel_hdr; + /* To determine which flavor of relocation this is, we depend on the + fact that the INPUT_SECTION's REL_HDR is read before RELA_HDR. */ + rel_hdr = elf_section_data (sec)->rel.hdr; + if (rel_hdr == NULL) + return FALSE; bed = get_elf_backend_data (abfd); - if ((size_t) (rel - relocs) - >= (NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel)) - rel_hdr = elf_section_data (sec)->rel_hdr2; - return rel_hdr->sh_entsize == MIPS_ELF_REL_SIZE (abfd); + return ((size_t) (rel - relocs) + < NUM_SHDR_ENTRIES (rel_hdr) * bed->s->int_rels_per_ext_rel); } /* Read the addend for REL relocation REL, which belongs to bfd ABFD. @@ -8983,13 +8966,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, asection *sec; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry *h; + bfd_boolean rel_reloc; + rel_reloc = (NEWABI_P (input_bfd) + && mips_elf_rel_relocation_p (input_bfd, input_section, + relocs, rel)); /* Find the relocation howto for this relocation. */ - howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type, - NEWABI_P (input_bfd) - && (MIPS_RELOC_RELA_P - (input_bfd, input_section, - rel - relocs))); + howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type, !rel_reloc); r_symndx = ELF_R_SYM (input_bfd, rel->r_info); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 58b1890..979505a 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1343,7 +1343,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, sreloc = NULL; if (ABI_64_P (abfd)) - num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (sec)->rel_hdr); + num_relocs = NUM_SHDR_ENTRIES (_bfd_elf_single_rel_hdr (sec)); else num_relocs = sec->reloc_count; @@ -2884,7 +2884,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, rel = relocs; if (ABI_64_P (output_bfd)) - num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr); + num_relocs = NUM_SHDR_ENTRIES (_bfd_elf_single_rel_hdr (input_section)); else num_relocs = input_section->reloc_count; relend = relocs + num_relocs; diff --git a/ld/ChangeLog b/ld/ChangeLog index 4f64be4..38b2f58 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2010-10-04 Bernd Schmidt <bernds@codesourcery.com> + + * emultempl/xtensaelf.em (replace_insn_sec_with_prop_sec): Use + _bfd_elf_single_rel_hdr. + 2010-10-01 Alan Modra <amodra@gmail.com> PR ld/12066 diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em index 38c4f04..b7da721 100644 --- a/ld/emultempl/xtensaelf.em +++ b/ld/emultempl/xtensaelf.em @@ -98,6 +98,7 @@ replace_insn_sec_with_prop_sec (bfd *abfd, bfd_byte *insn_contents = NULL; unsigned entry_count; unsigned entry; + Elf_Internal_Shdr *rel_hdr; Elf_Internal_Rela *internal_relocs = NULL; unsigned reloc_count; @@ -147,10 +148,9 @@ replace_insn_sec_with_prop_sec (bfd *abfd, /* The entry size and size must be set to allow the linker to compute the number of relocations since it does not use reloc_count. */ - elf_section_data (prop_sec)->rel_hdr.sh_entsize = - sizeof (Elf32_External_Rela); - elf_section_data (prop_sec)->rel_hdr.sh_size = - elf_section_data (insn_sec)->rel_hdr.sh_size; + rel_hdr = _bfd_elf_single_rel_hdr (prop_sec); + rel_hdr->sh_entsize = sizeof (Elf32_External_Rela); + rel_hdr->sh_size = _bfd_elf_single_rel_hdr (insn_sec)->sh_size; if (prop_contents == NULL && prop_sec->size != 0) { |