<div dir="ltr">Sounds like it is related to this:<div><br></div><div><a href="http://www.airs.com/blog/archives/42">http://www.airs.com/blog/archives/42</a><br></div><div>"""</div><div><p style="font-size:12.48px;line-height:1.5em;margin:1.2em 0px;color:rgb(51,51,51);font-family:'Lucida Grande','Lucida Sans Unicode',Verdana,Arial,sans-serif">The fact that C permits taking the address of a function introduces an interesting wrinkle. In C you are permitted to take the address of a function, and you are permitted to compare that address to another function address. The problem is that if you take the address of a function in a shared library, the natural result would be to get the address of the PLT entry. After all, that is address to which a call to the function will jump. However, each shared library has its own PLT, and thus the address of a particular function would differ in each shared library. That means that comparisons of function pointers generated in different shraed libraries may be different when they should be the same. This is not a purely hypothetical problem; when I did a port which got it wrong, before I fixed the bug I saw failures in the Tcl shared library when it compared function pointers.</p><p style="font-size:12.48px;line-height:1.5em;margin:1.2em 0px;color:rgb(51,51,51);font-family:'Lucida Grande','Lucida Sans Unicode',Verdana,Arial,sans-serif">The fix for this bug on most processors is a special marking for a symbol which has a PLT entry but is not defined. Typically the symbol will be marked as undefined, but with a non-zero value–the value will be set to the address of the PLT entry. When the dynamic linker is searching for the value of a symbol to use for a reloc other than a <code style="color:rgb(102,102,102)">JMP_SLOT</code> reloc, if it finds such a specially marked symbol, it will use the non-zero value. This will ensure that all references to the symbol which are not function calls will use the same value. To make this work, the compiler and assembler must make sure that any reference to a function which does not involve calling it will not carry a standard <code style="color:rgb(102,102,102)">PLT</code> reloc. This special handling of function addresses needs to be implemented in both the program linker and the dynamic linker.</p></div><div>"""</div><div><br></div><div><br></div><div>Indeed, comparing the `llvm-readobj -dyn-symbols` output on the executables from gold and lld, I see:</div><div><br></div><div><br></div><div><div>--- a.out.gold.readobj<span class="" style="white-space:pre">    </span>2016-02-08 14:08:52.678160575 -0800</div><div>+++ a.out.lld.readobj<span class="" style="white-space:pre">   </span>2016-02-08 14:08:52.678160575 -0800</div><div><br></div><div>   Symbol {</div><div>-    Name: set_data@ (142)</div><div>-    Value: 0x400560</div><div>-    Size: 0</div><div>+    Name: set_data@ (46)</div><div>+    Value: 0x0</div><div>+    Size: 10</div><div>     Binding: Global (0x1)</div><div>     Type: Function (0x2)</div><div>     Other: 0</div><div>     Section: Undefined (0x0)</div><div>   }</div></div><div><br></div><div>You can also see this in LD_DEBUG=all when running the executables (to avoid extraneous diffs, both executables are called "./a.out.lld"; look at the diff header to know which is output from the gold executable vs lld executable):</div><div><br></div><div><div>--- ld_debug-a.out.gold<span class="" style="white-space:pre">     </span>2016-02-08 14:07:27.255734743 -0800</div><div>+++ ld_debug-a.out.lld<span class="" style="white-space:pre">  </span>2016-02-08 14:07:27.255734743 -0800</div></div><div><div>      <span class="" style="white-space:pre">       </span>relocation processing: ./libdump.so (lazy)</div><div>      <span class="" style="white-space:pre">        </span>symbol=set_data;  lookup in file=./a.out.lld [0]</div><div>-     <span class="" style="white-space:pre">  </span>binding file ./libdump.so [0] to ./a.out.lld [0]: normal symbol `set_data'</div><div>+     <span class="" style="white-space:pre">     </span>symbol=set_data;  lookup in file=./libdump.so [0]</div><div>+     <span class="" style="white-space:pre"> </span>binding file ./libdump.so [0] to ./libdump.so [0]: normal symbol `set_data'</div></div><div><br></div><div>For gold, the symbol is bound to the one in a.out (the PLT entry), while for lld it is bound to the one in libdump.so.</div><div><br></div><div>-- Sean Silva</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 8, 2016 at 7:55 AM, Simon Atanasyan via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
It looks like I have found a bug in LLD. Suppose DSO defines a global<br>
variable 'data' and initializes it by the address of function<br>
'set_data' defined in the same DSO. If an executable file (linked by<br>
LLD) gets address of the '&set_data' function and compares it with a<br>
value stored in the 'data' variable it gets different result. If the<br>
executable is linked by BFD or Gold linker it gets the same result.<br>
<br>
Right now I do not have a time to investigate this problem further. I<br>
will plan to do that later. But maybe the reason of this problem is<br>
obvious to somebody?<br>
<br>
The reproduction script:<br>
<br>
% cat so.c<br>
void set_data(void *v) {}<br>
void *data = &set_data;<br>
<br>
% cat main.c<br>
int printf(const char *, ...);<br>
<br>
extern void *data;<br>
void set_data(void *v);<br>
<br>
int main(void)<br>
{<br>
  printf("%p = %p\n", &set_data, data);<br>
}<br>
<br>
% clang -fPIC -shared so.c -o libdump.so<br>
% clang -c main.c<br>
<br>
% clang main.o -Wl,-rpath -Wl,. -L. -ldump<br>
% ./a.out<br>
0x400600 = 0x400600  # The same addresses<br>
<br>
% lld -flavor gnu --sysroot=/ --build-id --no-add-needed --eh-frame-hdr \<br>
    -m elf_x86_64 --hash-style=both \<br>
    -dynamic-linker /lib64/ld-linux-x86-64.so.2 \<br>
    /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o \<br>
    /usr/lib/gcc/x86_64-linux-gnu/4.7/crtbegin.o \<br>
    -L. -L/usr/lib/gcc/x86_64-linux-gnu/4.7 \<br>
    -L/usr/lib/x86_64-linux-gnu \<br>
    -L/usr/lib -L/lib/x86_64-linux-gnu -L/lib \<br>
    -L/usr/lib/x86_64-linux-gnu -L/usr/lib \<br>
    main.o -rpath . -ldump -lgcc --as-needed -lgcc_s --no-as-needed \<br>
    -lc -lgcc --as-needed -lgcc_s --no-as-needed \<br>
    /usr/lib/gcc/x86_64-linux-gnu/4.7/crtend.o \<br>
    /usr/lib/x86_64-linux-gnu/crtn.o<br>
% ./a.out<br>
0x11250 = 0x7f02915bd6b0 # garbage in 'data'<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Simon Atanasyan<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</font></span></blockquote></div><br></div>