This is the mail archive of the binutils@sourceware.cygnus.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]

Re: Patch for ppc _SDA_BASE_ value


Ian Lance Taylor wrote:
> Oh yeah.  Might as well do it in a callback from final_link, then, as
> you suggested.  Or elf32-ppc.c could simply override final_link, and
> call the default one after setting the symbol values.

Overriding final_link looks better. So, here's the patch.
In short: 
  If _SDA_BASE_(_SDA2_BASE_) is already created by a linker
  script, we don't touch it.
  Otherwise it is created and its value is set to the address
  of the first .sdata(.sdata2) section plus 32768.
  ("first" means with lowest vma).
  Removed are output section errors for R_PPC_SDAREL16 and
  R_PPC_EMB_SDA2REL relocations.
  Linker sections are always created with SEC_LINKER_CREATED
  flag. Otherwise their contents is not allocated in
  ppc_elf_size_dynamic_sections() and the linker gets
  a fatal signal in bfd_elf32_finish_pointer_linker_section().
  Fixed the computation of the relocation value in 
  bfd_elf32_finish_pointer_linker_section() as the linker
  allocated entry and _SDA_BASE_(_SDA2_BASE_) can be
  in different sections. (In fact, now they are *always*
  in different sections, because of the SEC_LINKER_CREATED flag.

Regards,
-velco
2000-03-25  Momchil Velikov  <velco@fadata.bg>

	* elflink.h (elf_finish_pointer_linker_section): Fix the
	computation of `relocation'. The base symbol can be in another
	section.

	* elf32-ppc.c (ppc_elf_create_linker_section): Create the linker
	sections with `SEC_LINKER_CREATE' flag set, so their contents
	is allocated in `ppc_elf_size_dynamic_sections'. Do not
	create _SDA_BASE_ and _SDA2_BASE_ here ...
	(ppc_elf_create_sda_base): ... but here. New function. Finds a proper value
	for a small data section base symbol and creates it (the symbol),
	if not already created.  
	(ppc_elf_gc_final_link): New function. Makes sure _SDA_BASE_
	and _SDA2_BASE_ are created before the final link.  
	(ppc_elf_relocate_section): Do not fail with an error if
	the target of R_PPC_SDAREL16 and R_PPC_EMB_SDA2REL relocations
	is not in .sdata and .sbss, or not in .sdata2 and .sbss2, respectively.
	(bfd_elf32_bfd_final_link): Define it to `ppc_elf_gc_final_link'.


--- elf32-ppc.c.orig	Sat Mar 25 01:39:52 2000
+++ elf32-ppc.c	Sat Mar 25 04:39:50 2000
@@ -82,6 +82,12 @@
 
 static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
 
+static boolean ppc_elf_create_sda_base PARAMS ((bfd *,
+						struct bfd_link_info *,
+						enum elf_linker_section_enum));
+
+static boolean ppc_elf_gc_final_link PARAMS ((bfd *, struct bfd_link_info *));
+
 static boolean ppc_elf_relocate_section PARAMS ((bfd *,
 						 struct bfd_link_info *info,
 						 bfd *,
@@ -1561,16 +1567,17 @@
       defaults.hole_written_p = false;
       defaults.alignment = 2;
 
-      /* Both of these sections are (technically) created by the user
-	 putting data in them, so they shouldn't be marked
-	 SEC_LINKER_CREATED.
+      /* Both of these sections should be marked SEC_LINKER_CREATED
+	 so their contents is allocated in ppc_elf_size_dynamic_sections.  
 
 	 The linker creates them so it has somewhere to attach their
 	 respective symbols. In fact, if they were empty it would
 	 be OK to leave the symbol set to 0 (or any random number), because
-	 the appropriate register should never be used.  */
+	 the appropriate register should never be used.  
+	 Also, the implicit symbol pointer entries for R_PPC_EMB_SDAI16
+	 and R_PPC_EMB_SDA2I16 relocations are put there.  */
       defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-			| SEC_IN_MEMORY);
+			| SEC_IN_MEMORY | SEC_LINKER_CREATED);
 
       switch (which)
 	{
@@ -1586,16 +1593,12 @@
 	  defaults.name		  = ".sdata";
 	  defaults.rel_name	  = ".rela.sdata";
 	  defaults.bss_name	  = ".sbss";
-	  defaults.sym_name	  = "_SDA_BASE_";
-	  defaults.sym_offset	  = 32768;
 	  break;
 
 	case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
 	  defaults.name		  = ".sdata2";
 	  defaults.rel_name	  = ".rela.sdata2";
 	  defaults.bss_name	  = ".sbss2";
-	  defaults.sym_name	  = "_SDA2_BASE_";
-	  defaults.sym_offset	  = 32768;
 	  defaults.flags	 |= SEC_READONLY;
 	  break;
 	}
@@ -2868,6 +2871,92 @@
 }
 
 
+/* Create a small data base symbol and give it a convenient value.  */
+static boolean
+ppc_elf_create_sda_base (abfd, info, which)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     enum elf_linker_section_enum which;
+{
+  struct elf_link_hash_entry *h;
+  elf_linker_section_t *lsect;
+  bfd *sdata_bfd                 = NULL;
+  asection *sdata_min            = NULL;
+  bfd_vma sdata_min_vma          = 0;
+  
+  const char *sec_name;
+  const char *sym_name;
+  switch (which)
+    {
+    default:
+      (*_bfd_error_handler) (_("%s: Unknown special linker type %d"),
+			     bfd_get_filename (abfd),
+			     (int)which);
+
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+
+    case LINKER_SECTION_SDATA:
+      sec_name = ".sdata";
+      sym_name = "_SDA_BASE_";
+      break;
+
+    case LINKER_SECTION_SDATA2:
+      sec_name = ".sdata2";
+      sym_name = "_SDA2_BASE_";
+      break;
+    }
+  
+  h = (struct elf_link_hash_entry *)
+    bfd_link_hash_lookup (info->hash, sym_name, false, false, false);
+
+  if (h == NULL || h->root.type == bfd_link_hash_undefined)
+    {
+      /* Find the small data section with the lowest VMA.  
+	 The base symbol's value will be at offset 32768 from the
+	 beginning of that section.  */
+      for (abfd = info->input_bfds; abfd; abfd = abfd->link_next)
+	{
+	  asection *sdata = bfd_get_section_by_name (abfd, sec_name);
+	  if (sdata && sdata->output_section )
+	    {
+	      if (sdata_min == NULL
+		  || sdata_min_vma > sdata->output_section->vma + sdata->output_offset)
+		{
+		  sdata_min_vma = sdata->output_section->vma + sdata->output_offset;
+		  sdata_min = sdata;
+		  sdata_bfd = abfd;
+		}
+	    }
+	}
+      
+      if (sdata_min
+	  && !_bfd_generic_link_add_one_symbol (info, sdata_bfd, sym_name, BSF_GLOBAL,
+						sdata_min, 32768, (const char *) NULL,
+						false, false,
+						(struct bfd_link_hash_entry **)&h))
+	return false;
+    }
+  
+  abfd = elf_hash_table (info)->dynobj;
+  lsect = elf_linker_section (abfd, which);
+  lsect->sym_hash = h;
+  return true;
+}
+
+boolean
+ppc_elf_gc_final_link (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  if (!info->relocateable
+      && (!ppc_elf_create_sda_base (abfd, info, LINKER_SECTION_SDATA)
+	  || !ppc_elf_create_sda_base (abfd, info, LINKER_SECTION_SDATA2)))
+    return false;
+  return _bfd_elf32_gc_common_final_link (abfd,info);
+}
+
+
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
@@ -3480,53 +3569,18 @@
 
 	/* relocate against _SDA_BASE_ */
 	case (int)R_PPC_SDAREL16:
-	  {
-	    const char *name;
-
-	    BFD_ASSERT (sec != (asection *)0);
-	    name = bfd_get_section_name (abfd, sec->output_section);
-	    if (strcmp (name, ".sdata") != 0
-		&& strcmp (name, ".sbss") != 0)
-	      {
-		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
-				       bfd_get_filename (input_bfd),
-				       sym_name,
-				       ppc_elf_howto_table[ (int)r_type ]->name,
-				       name);
-	      }
-	    addend -= (sdata->sym_hash->root.u.def.value
-		       + sdata->sym_hash->root.u.def.section->output_section->vma
-		       + sdata->sym_hash->root.u.def.section->output_offset);
-	  }
+	  addend -= (sdata->sym_hash->root.u.def.value
+		     + sdata->sym_hash->root.u.def.section->output_section->vma
+		     + sdata->sym_hash->root.u.def.section->output_offset);
 	  break;
 
-
 	/* relocate against _SDA2_BASE_ */
 	case (int)R_PPC_EMB_SDA2REL:
-	  {
-	    const char *name;
-
-	    BFD_ASSERT (sec != (asection *)0);
-	    name = bfd_get_section_name (abfd, sec->output_section);
-	    if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0)
-	      {
-		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
-				       bfd_get_filename (input_bfd),
-				       sym_name,
-				       ppc_elf_howto_table[ (int)r_type ]->name,
-				       name);
-		
-		bfd_set_error (bfd_error_bad_value);
-		ret = false;
-		continue;
-	      }
-	    addend -= (sdata2->sym_hash->root.u.def.value
-		       + sdata2->sym_hash->root.u.def.section->output_section->vma
-		       + sdata2->sym_hash->root.u.def.section->output_offset);
-	  }
+	  addend -= (sdata2->sym_hash->root.u.def.value
+		     + sdata2->sym_hash->root.u.def.section->output_section->vma
+		     + sdata2->sym_hash->root.u.def.section->output_offset);
 	  break;
 
-
 	/* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */
 	case (int)R_PPC_EMB_SDA21:
 	case (int)R_PPC_EMB_RELSDA:
@@ -3741,7 +3795,7 @@
 #define bfd_elf32_bfd_relax_section             ppc_elf_relax_section
 #define bfd_elf32_bfd_reloc_type_lookup		ppc_elf_reloc_type_lookup
 #define bfd_elf32_bfd_set_private_flags		ppc_elf_set_private_flags
-#define bfd_elf32_bfd_final_link		_bfd_elf32_gc_common_final_link
+#define bfd_elf32_bfd_final_link		ppc_elf_gc_final_link
 
 #define elf_backend_gc_mark_hook		ppc_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook		ppc_elf_gc_sweep_hook
--- elflink.h.orig	Sat Mar 25 01:40:29 2000
+++ elflink.h	Sat Mar 25 00:52:52 2000
@@ -6029,11 +6029,14 @@
 	    }
 	}
     }
-
-  relocation = (lsect->section->output_offset
-		+ linker_section_ptr->offset
-		- lsect->hole_offset
-		- lsect->sym_offset);
+  
+  /* FIXME: How about lsect->hole_offset ?  */
+  relocation = ( (lsect->section->output_section->vma
+		  + lsect->section->output_offset
+		  + linker_section_ptr->offset)
+		 - (lsect->sym_hash->root.u.def.section->output_section->vma
+		    + lsect->sym_hash->root.u.def.section->output_offset
+		    + lsect->sym_hash->root.u.def.value));
 
 #ifdef DEBUG
   fprintf (stderr, "Finish pointer in linker section %s, offset = %ld (0x%lx)\n",


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