+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
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)
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;
/* 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;
struct bfd_link_info *info;
{
boolean dynamic;
+ boolean emit_relocs;
bfd *dynobj;
struct elf_final_link_info finfo;
register asection *o;
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 ();
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;
/* 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)
{
*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;
}
}
/* 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;
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);
{
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;
asection **ppsection;
asection *o;
struct elf_backend_data *bed;
+ boolean emit_relocs;
output_bfd = finfo->output_bfd;
bed = get_elf_backend_data (output_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))
{
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. */
}
/* 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);
+ }
+
}
}