Page MenuHomePhabricator

[lld] Avoid defining reserved symbols from depndent DSOs
Needs RevisionPublic

Authored by thomasanderson on Apr 30 2020, 5:29 PM.



Issue: save this empty program to main.c:

int main() { return 0; }

And build with:

clang main.c -fuse-ld=lld -o main1


clang main.c -fuse-ld=lld -o main2 -lX11

main1 will not have _end or _edata, but main2 will because defines _end and _edata.

With this change, lld only defines _end and _edata if
they're actually used.

Diff Detail

Event Timeline

thomasanderson created this revision.Apr 30 2020, 5:29 PM

I'll punt this to Fangrui, he's a lot more familiar with this area :)

MaskRay added a comment.EditedApr 30 2020, 7:07 PM

I am not sure we want to make this change. I believe lld's current behavior is consistent with GNU ld and gold.

% clang -fuse-ld=bfd a.c -lX11 -o a && readelf -W --dyn-syms a
     3: 0000000000404028     0 NOTYPE  GLOBAL DEFAULT   21 _edata
     4: 0000000000404030     0 NOTYPE  GLOBAL DEFAULT   22 _end

GNU ld's internal linker script includes:

_edata = .; PROVIDE (edata = .);

So _edata is always available (in .symtab). It will end up in .dynsym if it can preempt _edata in a shared object ( or is exported via other mechanisms.

lld's current behavior matches GNU ld w.r.t. .dynsym, but the .symtab entry is optional.

It may be useful to understand why exports _edata and _end. References within will get bound to _edata and _end defined in the main executable (preempted), which may be non-intuitive to many users.

It's definitely odd that some (possibly indirect) dependency's exports has an effect on our own exports. But since bfd and gold have this behavior I guess changing it would have the potential to break things.

It's probably a bug in libX11 that they export _edata, _end, and __bss_start

MaskRay requested changes to this revision.Jul 28 2020, 11:48 AM
This revision now requires changes to proceed.Jul 28 2020, 11:48 AM