This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[patch] Conditionally emit relocations during a final link


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,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]