<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 - LLD lets a weak reference replace a strong reference in some cases with dynamic libraries."
href="https://bugs.llvm.org/show_bug.cgi?id=42442">42442</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>LLD lets a weak reference replace a strong reference in some cases with dynamic libraries.
</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>bmoses@google.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, peter.smith@linaro.org
</td>
</tr></table>
<p>
<div>
<pre>Consider the following case: We have a function, bar(), provided by libbar.so.
Our main program (foo.o) has a strong reference to bar. We also have a second
shared library, libbaz.so, which has a weak reference to bar.
If we call "lld foo.o libbar.so", we get a strong reference to bar in the
resulting binary, as expected.
However, if we append libbaz.so to the end of that command line, the resulting
binary now has a weak reference to bar. This is clearly wrong; the code in
foo.o still requires bar to exist, and if the dynamic loader treats it as a
weak symbols and allows it to be unresolved at runtime, it will break. This
should still produce a strong reference.
For reference, this came up originally in the context of bootstrapping Go with
lld, as <a href="https://github.com/golang/go/issues/31912">https://github.com/golang/go/issues/31912</a>.
-------------------------
Sample code:
$ cat foo.c
// A program with a strong reference to bar()
int bar();
int main() { return bar(); }
$ cat bar.c
// A strong definition of bar().
int bar() { return 23; }
$ cat baz.c
// An unused function with a weak reference to bar()
int __attribute__((weak)) bar();
int baz() { return bar ? bar() : 0; }
$ gcc foo.c -c -o foo.o
$ gcc bar.c -shared -o libbar.so
$ gcc baz.c -shared -o libbaz.so
First, to confirm foo.o has a strong reference:
$ readelf -s foo.o | grep bar
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar
If we link without libbaz.so, we retain a strong reference, as expected:
$ ld.lld foo.o libbar.so -o foo1
ld.lld: warning: cannot find entry symbol _start; defaulting to 0x201000
$ readelf --dyn-sym foo1 | grep bar
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND bar
However, if we append libbaz.so to the end of the command line, it's a weak
reference:
$ ld.lld foo.o libbar.so libbaz.so -o foo2
ld.lld: warning: cannot find entry symbol _start; defaulting to 0x201000
$ readelf --dyn-sym foo2 | grep bar
1: 0000000000000000 0 FUNC WEAK DEFAULT UND bar
Interestingly, swapping libbaz.so and libbar.so on the command line gets us
back to a strong reference:
$ ld.lld foo.o libbar.so libbaz.so -o foo3
ld.lld: warning: cannot find entry symbol _start; defaulting to 0x201000
$ readelf --dyn-sym foo3 | grep bar
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND bar</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>