This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[patch] Conditionally emit relocations during a final link
- To: binutils at sourceware dot cygnus dot com
- Subject: [patch] Conditionally emit relocations during a final link
- From: Catherine Moore <clm at cygnus dot com>
- Date: Tue, 12 Jun 2001 13:01:30 -0700
- cc: clm at redhat dot com
I am working on an elf port that requires that only certain
relocations be emitted to the final executable. This patch sets up some
infrastructure in the elf backend that allows a port to define which,
if any, relocations should be emitted into a final executable. It also
changes the elf linker to conditionally emit these relocations should
they exist. Okay to commit?
Thanks,
Catherine
2001-06-12 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.
Index: elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.34
diff -p -r1.34 elf-bfd.h
*** elf-bfd.h 2001/05/23 08:23:27 1.34
- --- elf-bfd.h 2001/06/12 19:48:40
*************** struct elf_backend_data
*** 618,623 ****
- --- 618,633 ----
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;
Index: elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.95
diff -p -r1.95 elflink.h
*** elflink.h 2001/06/12 17:44:37 1.95
- --- elflink.h 2001/06/12 19:48:46
*************** elf_link_size_reloc_section (abfd, rel_h
*** 4109,4114 ****
- --- 4109,4115 ----
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)
*************** elf_link_size_reloc_section (abfd, rel_h
*** 4116,4121 ****
- --- 4117,4126 ----
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;
*************** elf_link_size_reloc_section (abfd, rel_h
*** 4129,4142 ****
/* 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)
{
struct elf_link_hash_entry **p;
p = ((struct elf_link_hash_entry **)
! bfd_zmalloc (o->reloc_count
* sizeof (struct elf_link_hash_entry *)));
! if (p == NULL && o->reloc_count != 0)
return false;
elf_section_data (o)->rel_hashes = p;
- --- 4134,4148 ----
/* 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)
{
struct elf_link_hash_entry **p;
p = ((struct elf_link_hash_entry **)
! bfd_zmalloc (num_rel_hashes
* sizeof (struct elf_link_hash_entry *)));
! if (p == NULL)
return false;
elf_section_data (o)->rel_hashes = p;
*************** elf_bfd_final_link (abfd, info)
*** 4242,4247 ****
- --- 4248,4254 ----
struct bfd_link_info *info;
{
boolean dynamic;
+ boolean emit_relocs;
bfd *dynobj;
struct elf_final_link_info finfo;
register asection *o;
*************** elf_bfd_final_link (abfd, info)
*** 4266,4271 ****
- --- 4273,4282 ----
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 ();
*************** elf_bfd_final_link (abfd, info)
*** 4331,4336 ****
- --- 4342,4358 ----
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, true));
+
+ o->reloc_count += (*bed->elf_backend_count_relocs)
+ (sec, relocs);
+ }
if (sec->_raw_size > max_contents_size)
max_contents_size = sec->_raw_size;
*************** elf_bfd_final_link (abfd, info)
*** 4401,4407 ****
/* 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)
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
for (o = sub->sections; o != NULL; o = o->next)
{
- --- 4423,4429 ----
/* 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)
{
*************** elf_bfd_final_link (abfd, info)
*** 4441,4446 ****
- --- 4463,4469 ----
*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;
}
}
*************** elf_bfd_final_link (abfd, info)
*** 4507,4513 ****
/* Start writing out the symbol table. The first symbol is always a
dummy symbol. */
! if (info->strip != strip_all || info->relocateable || info->emitrelocations)
{
elfsym.st_value = 0;
elfsym.st_size = 0;
- --- 4530,4537 ----
/* Start writing out the symbol table. The first symbol is always a
dummy symbol. */
! if (info->strip != strip_all
! || emit_relocs)
{
elfsym.st_value = 0;
elfsym.st_size = 0;
*************** elf_bfd_final_link (abfd, info)
*** 4540,4546 ****
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)
{
elfsym.st_size = 0;
elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- --- 4564,4571 ----
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
! || emit_relocs)
{
elfsym.st_size = 0;
elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
*************** elf_bfd_final_link (abfd, info)
*** 4992,4998 ****
{
if ((o->flags & SEC_RELOC) != 0
&& elf_section_data (o)->rel_hashes != NULL)
! free (elf_section_data (o)->rel_hashes);
}
elf_tdata (abfd)->linker = true;
- --- 5017,5023 ----
{
if ((o->flags & SEC_RELOC) != 0
&& elf_section_data (o)->rel_hashes != NULL)
! free (elf_section_data (o)->rel_hashes);
}
elf_tdata (abfd)->linker = true;
*************** elf_link_input_bfd (finfo, input_bfd)
*** 5546,5551 ****
- --- 5571,5577 ----
asection **ppsection;
asection *o;
struct elf_backend_data *bed;
+ boolean emit_relocs;
output_bfd = finfo->output_bfd;
bed = get_elf_backend_data (output_bfd);
*************** elf_link_input_bfd (finfo, input_bfd)
*** 5557,5562 ****
- --- 5583,5592 ----
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))
{
*************** elf_link_input_bfd (finfo, input_bfd)
*** 5834,5846 ****
finfo->sections))
return false;
! if (finfo->info->relocateable || finfo->info->emitrelocations)
{
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;
/* Adjust the reloc addresses and symbol indices. */
- --- 5864,5879 ----
finfo->sections))
return false;
! 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. */
*************** elf_link_input_bfd (finfo, input_bfd)
*** 5982,5998 ****
}
/* Swap out the 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;
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);
}
}
- --- 6015,6037 ----
}
/* 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;
! reloc_emitter (output_bfd, o, input_rel_hdr, internal_relocs);
!
input_rel_hdr = elf_section_data (o)->rel_hdr2;
! 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);
! }
!
}
}
Index: elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.21
diff -p -r1.21 elfxx-target.h
*** elfxx-target.h 2001/05/23 17:26:36 1.21
- --- elfxx-target.h 2001/06/12 19:48:47
*************** Foundation, Inc., 59 Temple Place - Suit
*** 323,328 ****
- --- 323,334 ----
#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
*************** static CONST struct elf_backend_data elf
*** 404,409 ****
- --- 410,417 ----
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,