[llvm-bugs] [Bug 42442] New: LLD lets a weak reference replace a strong reference in some cases with dynamic libraries.

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Jun 28 16:43:13 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=42442

            Bug ID: 42442
           Summary: LLD lets a weak reference replace a strong reference
                    in some cases with dynamic libraries.
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: bmoses at google.com
                CC: llvm-bugs at lists.llvm.org, peter.smith at linaro.org

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 https://github.com/golang/go/issues/31912.

-------------------------

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

-- 
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/20190628/211ea6c4/attachment-0001.html>


More information about the llvm-bugs mailing list