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]
Other format: [Raw text]

Serious ld issue on ppc64


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


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