This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
[patch] Linker section contents not allocated (was: Re: Patch for ppc _SDA_BASE_ value)
- To: GNU binutils <binutils at sourceware dot cygnus dot com>
- Subject: [patch] Linker section contents not allocated (was: Re: Patch for ppc _SDA_BASE_ value)
- From: Momchil Velikov <velco at fadata dot bg>
- Date: Sat, 01 Apr 2000 19:36:51 +0300
Hi,
The linker gets a fatal signal in finish_pointer_linker_section, because
the section contents is not allocated. This patch creates the
linker sections with the SEC_LINKER_CREATED flags set, so their contents
is allocated in `ppc_elf_size_dynamic_sections'.
Demo:
$ cat > xx.s
.data
.global var
var:
.long 0
.text
.global foo
foo:
lwz %r3, var@sdai16(%r13)
$ powerpc-svr4-gcc -c xx.s
$ powerpc-svr4-ld -o xx -entry=foo xx.o
Segmentation fault
$
Regards,
-velco
2000-04-01 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.3 Sat Apr 1 15:57:07 2000
+++ elf32-ppc.c Sat Apr 1 19:12:13 2000
@@ -82,6 +82,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 *,
@@ -2872,6 +2878,128 @@
}
+/* 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.
@@ -3710,7 +3838,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