diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 27 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 10 | ||||
-rw-r--r-- | bfd/elflink.h | 76 | ||||
-rw-r--r-- | bfd/elfxx-target.h | 8 |
4 files changed, 104 insertions, 17 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 32e923f..17aa2d2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,30 @@ +2001-06-20 Catherine Moore <clm@redhat.com> + + * elf-bfd.h (struct elf_backend_data): + elf_backend_emit_relocs: New field: Function for emitting + relocs. + elf_backend_count_relocs: New field: Function for determining + the number of relocs to be emitted. + * elfxx-target.h: Provide default (NULL) values for + elf_backend_emit_relocs and elf_backend_count_relocs. + * elflink.h (elf_link_size_reloc_section): Make the hash table + big enough to hold the relocs counted by either reloc_count or + o->reloc_count. + (elf_bfd_final_link) emit_relocs: New boolean, set if relocs + should be emitted, either because of a command line option + stored in the info structure or because the target provides a + special reloc emitting function. + If the target provides a reloc counting function use it, + unless performing a relocatable link or emitting all relocs. + Also set the SEC_RELOC flag on any output section which will + contain relocs. + (elf_link_input_bfd): emit_relocs: New boolean, set if relocs + should be emitted, either because of a command line option + stored in the info structure or because the target provides a + special reloc emitting function. + If the target provides a reloc emitting function, use it, + unless performing a relocatable link or emitting all relocs. + 2001-06-20 H.J. Lu <hjl@gnu.org> * elf32-i386.c (elf_i386_size_dynamic_sections): Always diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index f5b74e9..a5693ff 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -618,6 +618,16 @@ struct elf_backend_data void (*elf_backend_hide_symbol) PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); + /* Emit relocations. Overrides default routine for emitting relocs, + except during a relocatable link, or if all relocs are being emitted. */ + void (*elf_backend_emit_relocs) + PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *)); + + /* Count relocations. Not called for relocatable links + or if all relocs are being preserved in the output. */ + unsigned int (*elf_backend_count_relocs) + PARAMS ((asection *, Elf_Internal_Rela *)); + /* The swapping table to use when dealing with ECOFF information. Used for the MIPS ELF .mdebug section. */ const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; diff --git a/bfd/elflink.h b/bfd/elflink.h index 21ebc03..fab9bdc 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -4135,6 +4135,7 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) asection *o; { unsigned reloc_count; + unsigned num_rel_hashes; /* Figure out how many relocations there will be. */ if (rel_hdr == &elf_section_data (o)->rel_hdr) @@ -4142,6 +4143,10 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) 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; + /* That allows us to calculate the size of the section. */ rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count; @@ -4155,14 +4160,15 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) /* 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) + if (elf_section_data (o)->rel_hashes == NULL + && num_rel_hashes) { struct elf_link_hash_entry **p; p = ((struct elf_link_hash_entry **) - bfd_zmalloc (o->reloc_count + bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *))); - if (p == NULL && o->reloc_count != 0) + if (p == NULL) return false; elf_section_data (o)->rel_hashes = p; @@ -4268,6 +4274,7 @@ elf_bfd_final_link (abfd, info) struct bfd_link_info *info; { boolean dynamic; + boolean emit_relocs; bfd *dynobj; struct elf_final_link_info finfo; register asection *o; @@ -4292,6 +4299,10 @@ elf_bfd_final_link (abfd, info) dynamic = elf_hash_table (info)->dynamic_sections_created; dynobj = elf_hash_table (info)->dynobj; + emit_relocs = (info->relocateable + || info->emitrelocations + || bed->elf_backend_emit_relocs); + finfo.info = info; finfo.output_bfd = abfd; finfo.symstrtab = elf_stringtab_init (); @@ -4357,6 +4368,20 @@ elf_bfd_final_link (abfd, info) if (info->relocateable || info->emitrelocations) o->reloc_count += sec->reloc_count; + else if (bed->elf_backend_count_relocs) + { + Elf_Internal_Rela * relocs; + + relocs = (NAME(_bfd_elf,link_read_relocs) + (abfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, info->keep_memory)); + + o->reloc_count += (*bed->elf_backend_count_relocs) + (sec, relocs); + + if (!info->keep_memory) + free (relocs); + } if (sec->_raw_size > max_contents_size) max_contents_size = sec->_raw_size; @@ -4427,7 +4452,7 @@ elf_bfd_final_link (abfd, info) /* 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 (info->relocateable || info->emitrelocations) + if (emit_relocs) for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) for (o = sub->sections; o != NULL; o = o->next) { @@ -4467,6 +4492,7 @@ elf_bfd_final_link (abfd, info) *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; } } @@ -4533,7 +4559,8 @@ elf_bfd_final_link (abfd, info) /* Start writing out the symbol table. The first symbol is always a dummy symbol. */ - if (info->strip != strip_all || info->relocateable || info->emitrelocations) + if (info->strip != strip_all + || emit_relocs) { elfsym.st_value = 0; elfsym.st_size = 0; @@ -4566,7 +4593,8 @@ elf_bfd_final_link (abfd, info) symbols have no names. We store the index of each one in the index field of the section, so that we can find it again when outputting relocs. */ - if (info->strip != strip_all || info->relocateable || info->emitrelocations) + if (info->strip != strip_all + || emit_relocs) { elfsym.st_size = 0; elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); @@ -5018,7 +5046,7 @@ elf_bfd_final_link (abfd, info) { if ((o->flags & SEC_RELOC) != 0 && elf_section_data (o)->rel_hashes != NULL) - free (elf_section_data (o)->rel_hashes); + free (elf_section_data (o)->rel_hashes); } elf_tdata (abfd)->linker = true; @@ -5572,6 +5600,7 @@ elf_link_input_bfd (finfo, input_bfd) asection **ppsection; asection *o; struct elf_backend_data *bed; + boolean emit_relocs; output_bfd = finfo->output_bfd; bed = get_elf_backend_data (output_bfd); @@ -5583,6 +5612,10 @@ elf_link_input_bfd (finfo, input_bfd) if ((input_bfd->flags & DYNAMIC) != 0) return true; + emit_relocs = (finfo->info->relocateable + || finfo->info->emitrelocations + || bed->elf_backend_emit_relocs); + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (elf_bad_symtab (input_bfd)) { @@ -5860,13 +5893,16 @@ elf_link_input_bfd (finfo, input_bfd) finfo->sections)) return false; - if (finfo->info->relocateable || finfo->info->emitrelocations) + if (emit_relocs) { Elf_Internal_Rela *irela; Elf_Internal_Rela *irelaend; struct elf_link_hash_entry **rel_hash; Elf_Internal_Shdr *input_rel_hdr; unsigned int next_erel; + void (* reloc_emitter) PARAMS ((bfd *, asection *, + Elf_Internal_Shdr *, + Elf_Internal_Rela *)); /* Adjust the reloc addresses and symbol indices. */ @@ -6008,17 +6044,23 @@ elf_link_input_bfd (finfo, input_bfd) } /* Swap out the relocs. */ + if (bed->elf_backend_emit_relocs + && ! (finfo->info->relocateable || finfo->info->emitrelocations)) + reloc_emitter = bed->elf_backend_emit_relocs; + else + reloc_emitter = elf_link_output_relocs; + input_rel_hdr = &elf_section_data (o)->rel_hdr; - elf_link_output_relocs (output_bfd, o, - input_rel_hdr, - internal_relocs); - internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr) - * bed->s->int_rels_per_ext_rel; + (*reloc_emitter) (output_bfd, o, input_rel_hdr, internal_relocs); + input_rel_hdr = elf_section_data (o)->rel_hdr2; - if (input_rel_hdr) - elf_link_output_relocs (output_bfd, o, - input_rel_hdr, - internal_relocs); + if (input_rel_hdr) + { + internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr) + * bed->s->int_rels_per_ext_rel; + reloc_emitter (output_bfd, o, input_rel_hdr, internal_relocs); + } + } } diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 82ea204..8258a6a 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -323,6 +323,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef elf_backend_hide_symbol #define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol #endif +#ifndef elf_backend_emit_relocs +#define elf_backend_emit_relocs NULL +#endif +#ifndef elf_backend_count_relocs +#define elf_backend_count_relocs NULL +#endif /* Previously, backends could only use SHT_REL or SHT_RELA relocation sections, but not both. They defined USE_REL to indicate SHT_REL @@ -404,6 +410,8 @@ static CONST struct elf_backend_data elfNN_bed = elf_backend_output_arch_syms, elf_backend_copy_indirect_symbol, elf_backend_hide_symbol, + elf_backend_emit_relocs, + elf_backend_count_relocs, elf_backend_ecoff_debug_swap, ELF_MACHINE_ALT1, ELF_MACHINE_ALT2, |