This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Adjusting value of _SDA_BASE_
- To: binutils at sourceware dot cygnus dot com
- Subject: Adjusting value of _SDA_BASE_
- From: Momchil Velikov <velco at fadata dot bg>
- Date: 18 Feb 2001 19:49:11 +0200
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