[llvm-bugs] [Bug 49897] New: Missing dyn symbol for a weak wrapped function when using --wrap
via llvm-bugs
llvm-bugs at lists.llvm.org
Thu Apr 8 10:09:48 PDT 2021
https://bugs.llvm.org/show_bug.cgi?id=49897
Bug ID: 49897
Summary: Missing dyn symbol for a weak wrapped function when
using --wrap
Product: lld
Version: unspecified
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: ELF
Assignee: unassignedbugs at nondot.org
Reporter: shuralnik at snapchat.com
CC: llvm-bugs at lists.llvm.org, smithp352 at googlemail.com
Being honest I'm not sure if this is a really justified bug but at least
intuitively it really feels wrong. All below said is about current mainstream:
$ bin/clang -fuse-ld=lld -Wl,--version
LLD 13.0.0 (https://github.com/llvm/llvm-project.git
37878de5036718481e13d5067a17d65eb85c3388) (compatible with GNU linkers)
When linking a DSO that refers to a some weak symbol, for which no shared
library with a definition was provided at the link time, I'm anyways getting
NOTYPE WEAK symbol in the final .dynsym:
$ cat test.c
__attribute__((weak))
extern int foo(int i);
int bar(int i) {
return foo(i + 10);
}
$ bin/clang -fuse-ld=lld -shared -fPIC -Wl,--no-undefined test.c && readelf
--dyn-syms a.out | grep foo
5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo
So that linker tolerates a weak external symbol with a missing definition. And
of course when providing some libfoo.so that has this symbol defined I'm
getting usual FUNC WEAK symbol:
$ bin/clang -fuse-ld=lld -shared -fPIC -Wl,--no-undefined test.c libfoo.so &&
readelf --dyn-syms a.out | grep foo
5: 0000000000000000 0 FUNC WEAK DEFAULT UND foo
Then let's presume we need to wrap foo() in our DSO by linking in an additional
object:
$ cat test_wrap.c
__attribute__((weak))
extern int __real_foo(int i);
int __wrap_foo(int i) {
return __real_foo ? __real_foo(i + 100) : -1;
}
When libfoo.so is given to a linker - everything is OK:
$ bin/clang -fuse-ld=lld -shared -fPIC -Wl,--no-undefined test.c -Wl,--wrap=foo
test_wrap.c libfoo.so && readelf --dyn-syms a.out | grep foo
5: 0000000000000000 0 FUNC WEAK DEFAULT UND foo
9: 0000000000001730 73 FUNC GLOBAL DEFAULT 10 __wrap_foo
__wrap_foo() refers to external foo() as expected:
$ objdump -d a.out
...
0000000000001730 <__wrap_foo>:
1730: 55 push %rbp
1731: 48 89 e5 mov %rsp,%rbp
1734: 48 83 ec 10 sub $0x10,%rsp
1738: 89 7d fc mov %edi,-0x4(%rbp)
173b: 48 8b 05 5e 12 00 00 mov 0x125e(%rip),%rax # 29a0
<foo at Base>
1742: 48 85 c0 test %rax,%rax
1745: 0f 84 18 00 00 00 je 1763 <__wrap_foo+0x33>
174b: e9 00 00 00 00 jmpq 1750 <__wrap_foo+0x20>
1750: 8b 7d fc mov -0x4(%rbp),%edi
1753: 83 c7 64 add $0x64,%edi
1756: e8 75 00 00 00 callq 17d0 <foo at plt>
175b: 89 45 f8 mov %eax,-0x8(%rbp)
175e: e9 0d 00 00 00 jmpq 1770 <__wrap_foo+0x40>
1763: b8 ff ff ff ff mov $0xffffffff,%eax
1768: 89 45 f8 mov %eax,-0x8(%rbp)
176b: e9 00 00 00 00 jmpq 1770 <__wrap_foo+0x40>
1770: 8b 45 f8 mov -0x8(%rbp),%eax
1773: 48 83 c4 10 add $0x10,%rsp
1777: 5d pop %rbp
1778: c3 retq
...
00000000000017d0 <foo at plt>:
17d0: ff 25 02 22 00 00 jmpq *0x2202(%rip) # 39d8
<foo at Base>
17d6: 68 02 00 00 00 pushq $0x2
17db: e9 c0 ff ff ff jmpq 17a0 <_fini+0xc>
But when libfoo.so is not provided it is quite expected to see a reference to
NOTYPE WEAK foo() from __wrap_foo(), exactly like it was with no --wrap. But
instead foo() is completely missing in .dynsym and __wrap_foo() refers to some
garbage:
$ bin/clang -fuse-ld=lld -shared -fPIC -Wl,--no-undefined test.c -Wl,--wrap=foo
test_wrap.c && readelf --dyn-syms a.out | grep foo
8: 0000000000001690 73 FUNC GLOBAL DEFAULT 10 __wrap_foo
$ objdump -d a.out
...
0000000000001690 <__wrap_foo>:
1690: 55 push %rbp
1691: 48 89 e5 mov %rsp,%rbp
1694: 48 83 ec 10 sub $0x10,%rsp
1698: 89 7d fc mov %edi,-0x4(%rbp)
169b: 48 8b 05 4e 12 00 00 mov 0x124e(%rip),%rax # 28f0
<_DYNAMIC+0x1a0>
16a2: 48 85 c0 test %rax,%rax
16a5: 0f 84 18 00 00 00 je 16c3 <__wrap_foo+0x33>
16ab: e9 00 00 00 00 jmpq 16b0 <__wrap_foo+0x20>
16b0: 8b 7d fc mov -0x4(%rbp),%edi
16b3: 83 c7 64 add $0x64,%edi
16b6: e8 75 00 00 00 callq 1730 <*ABS*@plt>
16bb: 89 45 f8 mov %eax,-0x8(%rbp)
16be: e9 0d 00 00 00 jmpq 16d0 <__wrap_foo+0x40>
16c3: b8 ff ff ff ff mov $0xffffffff,%eax
16c8: 89 45 f8 mov %eax,-0x8(%rbp)
16cb: e9 00 00 00 00 jmpq 16d0 <__wrap_foo+0x40>
16d0: 8b 45 f8 mov -0x8(%rbp),%eax
16d3: 48 83 c4 10 add $0x10,%rsp
16d7: 5d pop %rbp
16d8: c3 retq
...
0000000000001730 <*ABS*@plt>:
1730: ff 25 f2 21 00 00 jmpq *0x21f2(%rip) # 3928
<__TMC_END__+0x28>
1736: 68 02 00 00 00 pushq $0x2
173b: e9 c0 ff ff ff jmpq 1700 <_fini+0xc>
At the same time both GNU linkers expectedly emit NOTYPE symbols:
$ bin/clang -fuse-ld=bfd -shared -fPIC -Wl,--no-undefined test.c -Wl,--wrap=foo
test_wrap.c && readelf --dyn-syms a.out | grep foo
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo
12: 0000000000000600 73 FUNC GLOBAL DEFAULT 11 __wrap_foo
$ bin/clang -fuse-ld=gold -shared -fPIC -Wl,--no-undefined test.c
-Wl,--wrap=foo test_wrap.c && readelf --dyn-syms a.out | grep foo
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo
11: 00000000000006a0 73 FUNC GLOBAL DEFAULT 11 __wrap_foo
Apparently LLD should generate NOTYPE as well, because otherwise resulting
binary seems to be broken.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210408/d7154234/attachment.html>
More information about the llvm-bugs
mailing list