This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Serious ld issue on ppc64
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Alan Modra <amodra at bigpond dot net dot au>
- Cc: binutils at sources dot redhat dot com, roland at redhat dot com
- Date: Thu, 25 Mar 2004 12:28:17 +0100
- Subject: Serious ld issue on ppc64
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Recent binutils (e.g. 2.14.90.0.8 20040114 or current CVS HEAD)
create incorrect binaries on ppc64.
I have two testcases:
#include <unistd.h>
void *p = write;
int main (void)
{
return 0;
}
will result into:
Relocation section '.rela.dyn' at offset 0x2f0 contains 1 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
00000000100109e8 0000000300000026 R_PPC64_ADDR64 0000000000000000 write + 0
Relocation section '.rela.plt' at offset 0x308 contains 1 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000010010ec8 0000000400000015 R_PPC64_JMP_SLOT 0000000000000000 __libc_start_main + 0
Symbol table '.dynsym' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 164 NOTYPE WEAK DEFAULT UND __write@GLIBC_2.3 (2)
2: 0000000000000000 164 NOTYPE GLOBAL DEFAULT UND __libc_write@GLIBC_PRIVATE (3)
3: 0000000000000000 164 NOTYPE GLOBAL DEFAULT UND write@GLIBC_2.3 (2)
4: 0000000000000000 24 NOTYPE GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.3 (2)
Note that together with the needed dynsym entries (0, 3 and 4) there are two
which really don't belong there and especially the
__libc_write@GLIBC_PRIVATE undefined symbol makes such binaries if packaged
e.g. in rpm uninstallable (as rpm, but I think other package managers too,
prevent packages misusing glibc internal symbols from being installed).
Alternate (smaller) testcase:
cat > libtest.c <<EOF
int foo (void) { return 1; } extern int bar (void) __attribute__((alias ("foo"), weak));
EOF
cat > test.c <<EOF
extern int bar (void); void *p = bar; int main (void) { return 0; }
EOF
gcc -shared -fpic -O2 -o libtest.so libtest.c
gcc -o test test.c ./libtest.so
There is no such problem on e.g. x86-64. The difference seems to be that
on PPC64 write@@GLIBC_2.3 is the .opd symbol and does not have STT_FUNC set,
and there is a code I'm not sure I fully understand which for all weak
symbols which will have SHN_UNDEF entries in .dynsym also all their aliases
are added to .dynsym.
The comment above it says:
/* Now set the weakdefs field correctly for all the weak defined
symbols we found. The only way to do this is to search all the
symbols. Since we only need the information for non functions in
dynamic objects, that's the only time we actually put anything on
the list WEAKS. We need this information so that if a regular
object refers to a symbol defined weakly in a dynamic object, the
real symbol in the dynamic object is also put in the dynamic
symbols; we also must arrange for both symbols to point to the
same memory location. We could handle the general case of symbol
aliasing, but a general symbol alias can only be generated in
assembler code, handling it correctly would be very time
consuming, and other ELF linkers don't handle general aliasing
either. */
but I don't think I grok the reason why a nowhere mentioned .dynsym
symbol with SHN_UNDEF and zero st_value matters at all during
dynamic linking.
Jakub