This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Fix a linker segfault for PPC sdata
- From: Daniel Jacobowitz <drow at false dot org>
- To: binutils at sourceware dot org
- Date: Tue, 17 May 2005 17:28:18 -0400
- Subject: Fix a linker segfault for PPC sdata
This is a slightly weird patch...
One of our customers has an environment which supports both small data
access and shared libraries on PowerPC. Non-PIC code generates sdata
relocations, PIC code doesn't. If it so happens that a variable is defined
in a shared library, referenced in a non-PIC object, and of the appropriate
size, then there will be SDA21 relocations against it. This crashes ld; we
check the output section for the variable unconditionally.
This is the obvious solution: generate a copy relocation into .sbss. There
was already some code to do this, but it hasn't worked lately (I didn't do
the archeology).
OK? Tested on cross binutils to powerpc-linux; without the bfd patch, the
ld test causes a linker segfault.
--
Daniel Jacobowitz
CodeSourcery, LLC
2005-05-17 Daniel Jacobowitz <dan@codesourcery.com>
* bfd/elf32-ppc.c (struct ppc_elf_link_hash_entry): Add new field
has_sda_refs.
(ppc_elf_copy_indirect_symbol): Copy has_sda_refs.
(ppc_elf_check_relocs): Set has_sda_refs.
(ppc_elf_adjust_dynamic_symbol): Check has_sda_refs before eliminating
copy relocations. Use has_sda_refs to place variables in .sbss.
(ppc_elf_finish_dynamic_symbol): Use has_sda_refs to place variables in
.sbss.
2005-05-17 Daniel Jacobowitz <dan@codesourcery.com>
* ld-powerpc/sdalib.s, ld-powerpc/sdadyn.s, ld-powerpc/sdadyn.d: New
files.
* ld-powerpc/powerpc.exp: Run the new test.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.159
diff -u -p -r1.159 elf32-ppc.c
--- bfd/elf32-ppc.c 17 May 2005 13:55:02 -0000 1.159
+++ bfd/elf32-ppc.c 17 May 2005 21:17:30 -0000
@@ -2241,6 +2241,10 @@ struct ppc_elf_link_hash_entry
#define TLS_TLS 16 /* Any TLS reloc. */
#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */
char tls_mask;
+
+ /* Nonzero if we have seen a small data relocation referring to this
+ symbol. */
+ unsigned char has_sda_refs;
};
#define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent))
@@ -2486,6 +2490,7 @@ ppc_elf_copy_indirect_symbol (const stru
}
edir->tls_mask |= eind->tls_mask;
+ edir->has_sda_refs |= eind->has_sda_refs;
if (ELIMINATE_COPY_RELOCS
&& ind->root.type != bfd_link_hash_indirect
@@ -2899,6 +2904,12 @@ ppc_elf_check_relocs (bfd *abfd,
bad_shared_reloc (abfd, r_type);
return FALSE;
}
+ if (h != NULL)
+ {
+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE;
+ /* We may need a copy reloc. */
+ h->non_got_ref = TRUE;
+ }
break;
case R_PPC_PLT32:
@@ -3781,7 +3792,11 @@ ppc_elf_adjust_dynamic_symbol (struct bf
if (!h->non_got_ref)
return TRUE;
- if (ELIMINATE_COPY_RELOCS)
+ /* If we didn't find any dynamic relocs in read-only sections, then we'll
+ be keeping the dynamic relocs and avoiding the copy reloc. We can't
+ do this if there are any small data relocations. */
+ if (ELIMINATE_COPY_RELOCS
+ && !ppc_elf_hash_entry (h)->has_sda_refs)
{
struct ppc_elf_dyn_relocs *p;
for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
@@ -3791,8 +3806,6 @@ ppc_elf_adjust_dynamic_symbol (struct bf
break;
}
- /* If we didn't find any dynamic relocs in read-only sections, then
- we'll be keeping the dynamic relocs and avoiding the copy reloc. */
if (p == NULL)
{
h->non_got_ref = 0;
@@ -3810,11 +3823,10 @@ ppc_elf_adjust_dynamic_symbol (struct bf
both the dynamic object and the regular object will refer to the
same memory location for the variable.
- Of course, if the symbol is sufficiently small, we must instead
- allocate it in .sbss. FIXME: It would be better to do this if and
- only if there were actually SDAREL relocs for that symbol. */
+ Of course, if the symbol is referenced using SDAREL relocs, we
+ must instead allocate it in .sbss. */
- if (h->size <= elf_gp_size (htab->elf.dynobj))
+ if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->dynsbss;
else
s = htab->dynbss;
@@ -3828,7 +3840,7 @@ ppc_elf_adjust_dynamic_symbol (struct bf
{
asection *srel;
- if (h->size <= elf_gp_size (htab->elf.dynobj))
+ if (ppc_elf_hash_entry (h)->has_sda_refs)
srel = htab->relsbss;
else
srel = htab->relbss;
@@ -6265,7 +6277,7 @@ ppc_elf_finish_dynamic_symbol (bfd *outp
BFD_ASSERT (h->dynindx != -1);
- if (h->size <= elf_gp_size (htab->elf.dynobj))
+ if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->relsbss;
else
s = htab->relbss;
Index: ld/testsuite/ld-powerpc/powerpc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/powerpc.exp,v
retrieving revision 1.9
diff -u -p -r1.9 powerpc.exp
--- ld/testsuite/ld-powerpc/powerpc.exp 12 May 2005 07:32:07 -0000 1.9
+++ ld/testsuite/ld-powerpc/powerpc.exp 17 May 2005 21:17:30 -0000
@@ -69,6 +69,10 @@ set ppcelftests {
{{readelf -WSsrl tlsso32.r} {objdump -dr tlsso32.d}
{objdump -sj.got tlsso32.g} {objdump -sj.tdata tlsso32.t}}
"tls32.so"}
+ {"Shared library with global symbol" "-shared -melf32ppc" "" {sdalib.s}
+ {} "sdalib.so"}
+ {"Dynamic application with SDA" "-melf32ppc tmpdir/sdalib.so" "" {sdadyn.s}
+ {{objdump -R sdadyn.d}} "sdadyn"}
}
set ppc64elftests {
Index: ld/testsuite/ld-powerpc/sdadyn.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/sdadyn.d
diff -N ld/testsuite/ld-powerpc/sdadyn.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/sdadyn.d 17 May 2005 21:17:30 -0000
@@ -0,0 +1,8 @@
+
+.*: +file format elf32-powerpc
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+#...
+.* R_PPC_COPY lib_var
+#pass
Index: ld/testsuite/ld-powerpc/sdadyn.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/sdadyn.s
diff -N ld/testsuite/ld-powerpc/sdadyn.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/sdadyn.s 17 May 2005 21:17:30 -0000
@@ -0,0 +1,3 @@
+ .globl _start
+_start:
+ lwz 3,lib_var@sda21(0)
Index: ld/testsuite/ld-powerpc/sdalib.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/sdalib.s
diff -N ld/testsuite/ld-powerpc/sdalib.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/sdalib.s 17 May 2005 21:17:30 -0000
@@ -0,0 +1,4 @@
+ .globl lib_var
+ .type lib_var, @object
+lib_var:
+ .word 1