<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Missing dyn symbol for a weak wrapped function when using --wrap"
href="https://bugs.llvm.org/show_bug.cgi?id=49897">49897</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Missing dyn symbol for a weak wrapped function when using --wrap
</td>
</tr>
<tr>
<th>Product</th>
<td>lld
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>ELF
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>shuralnik@snapchat.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, smithp352@googlemail.com
</td>
</tr></table>
<p>
<div>
<pre>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 (<a href="https://github.com/llvm/llvm-project.git">https://github.com/llvm/llvm-project.git</a>
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@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@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@plt>:
17d0: ff 25 02 22 00 00 jmpq *0x2202(%rip) # 39d8
<foo@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.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>