This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Bug in elf_i386_adjust_dynamic_symbol ?
- From: "Martin Schwidefsky" <schwidefsky at de dot ibm dot com>
- To: binutils at sources dot redhat dot com
- Date: Mon, 28 Jan 2002 19:05:12 +0100
- Subject: Bug in elf_i386_adjust_dynamic_symbol ?
Hi,
I think I have found a bug in elf_i386_adjust_dynamic_symbol. Since I
use the i386 bfd as a blue print for s390 and s390x the same bug is
present for these two architectures. The problem hit us on s390x in
the upgrade process from glibc 2.2.4 to 2.2.5. After we identified
the cause I created a small test case that shows the effect on an
intel as well (the glibc upgrade problem does not show up on i386).
Here we go:
weakcaller.c:
--- cut here ---
#include <stdio.h>
#include <dlfcn.h>
extern void weak_function(void) __attribute__((weak));
int main(void)
{
if (weak_function != NULL)
weak_function();
else
printf("weak_function is NULL\n");
return 0;
}
--- cut here ---
weakfunc.c:
--- cut here ---
#include <stdio.h>
void weak_function(void)
{
printf("weak_function was called\n");
}
--- cut here ---
To see the effect you'll have to do the following:
# gcc -o weakcaller weakcaller.c -O2 -fpic -ldl
# gcc -o weakfunc.so weakfunc.c -O2 -fpic -shared
# ./weakcaller
weak_function_is NULL
# LD_PRELOAD=./weakfunc.so ./weakcaller
zsh: segmentation fault LD_PRELOAD=./weakfunc.so ./weakcaller
This happens on my Intel system with binutils-2.11.92.0.12.3 and
gcc 2.95.4. The important piece of code from main() is translated
by gcc as follows:
call .L21
.L21:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L21],%ebx
cmpl $0,weak_function@GOT(%ebx)
je .L18
call weak_function@PLT
jmp .L19
The compare is done using the GOT and the call is done using a PLT. Fine.
But after the final link is done it looks like this:
8048467: e8 00 00 00 00 call 804846c <main+0xc>
804846c: 5b pop %ebx
804846d: 81 c3 8c 11 00 00 add $0x118c,%ebx
8048473: 83 bb 1c 00 00 00 00 cmpl $0x0,0x1c(%ebx)
804847a: 74 07 je 8048483 <main+0x23>
804847c: e8 7f 7b fb f7 call 0 <_init-0x8048308>
8048481: eb 0f jmp 8048492 <main+0x32>
The call to the PLT has been replaced by a call to 0!
I fixed this with the following patch:
--- elf32-i386.c.orig Fri Nov 16 22:05:51 2001
+++ elf32-i386.c Mon Jan 28 18:52:18 2002
@@ -1114,7 +1114,9 @@
if (h->plt.refcount <= 0
|| (! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0))
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
+ && h->root.type != bfd_link_hash_undefweak
+ && h->root.type != bfd_link_hash_undefined))
{
/* This case can occur if we saw a PLT32 reloc in an input
file, but the symbol was never referred to by a dynamic
Big question now is: does this sound reasonable ?
blue skies,
Martin
Linux/390 Design & Development, IBM Deutschland Entwicklung GmbH
Schönaicherstr. 220, D-71032 Böblingen, Telefon: 49 - (0)7031 - 16-2247
E-Mail: schwidefsky@de.ibm.com