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]

Adjusting value of _SDA_BASE_



Hi there,

This patch adjust the values of _SDA_BASE_ and _SDA2_BASE_ so the
symbols in small data sections are within range.

Regards,
-velco


2001-02-18  Momchil Velikov  <velco@fadata.bg>

	(ppc_elf_adjust_sda_base): New function. Adjusts the value
	for a small data section base symbols.  
	(ppc_elf_final_link): New function. Makes sure the values of
	_SDA_BASE_ and _SDA2_BASE_ are adjusted before the final link.  
	(bfd_elf32_bfd_final_link): Define it to `ppc_elf_final_link'.

--- elf32-ppc.c.orig.2	Sun Feb 18 19:29:23 2001
+++ elf32-ppc.c	Sun Feb 18 19:37:31 2001
@@ -81,6 +81,12 @@
 
 static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
 
+static boolean ppc_elf_adjust_sda_base PARAMS ((bfd *,
+						struct bfd_link_info *,
+						enum elf_linker_section_enum));
+
+static boolean ppc_elf_final_link PARAMS ((bfd *, struct bfd_link_info *));
+
 static boolean ppc_elf_relocate_section PARAMS ((bfd *,
 						 struct bfd_link_info *info,
 						 bfd *,
@@ -2862,6 +2868,128 @@
   return true;
 }
 
+/* Adjust the value of the small data base symbols so the
+   small data items are within range.  */
+static boolean
+ppc_elf_adjust_sda_base (abfd, info, which)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     enum elf_linker_section_enum which;
+{
+  const char *sdata_name;
+  const char *sbss_name;
+  bfd *dynobj;
+  elf_linker_section_t *lsect;
+
+  dynobj = elf_hash_table (info)->dynobj;
+  if (!dynobj)
+    return true;
+
+  lsect = elf_linker_section (dynobj, which);
+  if (!lsect)
+    return true;
+
+  /* Adjust the symbol's value only if we have created it in
+     ppc_elf_create_linker_section.  */
+  if (lsect->sym_hash->root.u.def.section != lsect->section)
+    return true;
+
+  switch (which)
+    {
+    default: /* Can't happen.  */
+      return false;
+      
+    case LINKER_SECTION_SDATA:
+      sdata_name = ".sdata";
+      sbss_name = ".sbss";
+      break;
+      
+    case LINKER_SECTION_SDATA2:
+      sdata_name = ".sdata2";
+      sbss_name = ".sbss2";
+      break;
+    }
+  
+  /* In shared objects the value of _SDA_BASE_ shall be the same as the
+     value of _GLOBAL_OFFSET_TABLE_.  */
+  if (info->shared)
+    {
+      struct elf_link_hash_entry *got = elf_hash_table (info)->hgot;
+      if (got == NULL)
+	return true;
+      
+      lsect->sym_hash->root.u.def.value = 
+	(got->root.u.def.section->output_section->vma
+	 + got->root.u.def.section->output_offset
+	 + got->root.u.def.value)
+	- (lsect->section->output_section->vma
+	   + lsect->section->output_offset);
+    }
+  else
+    {
+      asection *sdata = NULL;
+      bfd_vma vma     = 0;
+      
+      /* Find the small data section with the lowest VMA.  
+	 The base symbol's value will be adjusted to include the small
+	 data items in this section. Ignore zero sized sections.  */
+      for (abfd = info->input_bfds; abfd; abfd = abfd->link_next)
+	{
+	  asection *sect;
+	  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+	    {
+	      if (strcmp (sect->name, sdata_name)
+		  && strcmp (sect->name, sbss_name))
+		continue;
+	      
+	      if (!sect->output_section
+		  || bfd_is_abs_section (sect->output_section)
+		  || sect->_cooked_size == 0)
+		continue;
+
+	      if (sdata == NULL
+		  || vma > sect->output_section->vma + sect->output_offset)
+		{
+		  vma = sect->output_section->vma + sect->output_offset;
+		  sdata = sect;
+		}
+	    }
+	}
+      
+      if (sdata != NULL)
+	{
+	  lsect->sym_hash->root.u.def.value = ((sdata->output_section->vma
+						+ sdata->output_offset
+						+ 32768)
+					       - (lsect->section->output_section->vma
+						  + lsect->section->output_offset));
+	}
+      else
+	{
+	  /* Set the symbol's value to zero if there no small data sections.  */
+	  lsect->sym_hash->root.u.def.value = - (lsect->section->output_section->vma
+						 + lsect->section->output_offset);
+	}
+    }
+  
+  return true;
+}
+
+boolean
+ppc_elf_final_link (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  if (!info->relocateable)
+    {
+      if (!ppc_elf_adjust_sda_base (abfd, info, LINKER_SECTION_SDATA)
+	  || !ppc_elf_adjust_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.
 
@@ -3705,7 +3833,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_final_link
 
 #define elf_backend_gc_mark_hook		ppc_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook		ppc_elf_gc_sweep_hook


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