[llvm-dev] [RFC] Making .eh_frame more linker-friendly

George Rimar via llvm-dev llvm-dev at lists.llvm.org
Thu Nov 23 07:16:52 PST 2017


I performed tests basing on first diff of https://reviews.llvm.org/D40352.
(Creates .eh_frame for each .text.*, sets SHF_LINK_ORDER and .sh_link of created
.eh_frame section to point to corresponding .text.)

With use of GNU ld (GNU Binutils) 2.29.51.20171006 it reports errors when linking sample apps:
~/LLVM/Release/bin/clang++ test.cpp -ffunction-sections -o test.o
/usr/local/bin/ld: .eh_frame has both ordered [`.eh_frame' in /tmp/test-dbc52e.o] and unordered
                   [`.eh_frame' in /usr/lib/gcc/x86_64-linux-gnu/5.4.1/../../../x86_64-linux-gnu/crt1.o] sections
/usr/local/bin/ld: final link failed: Bad value

Looks it's code explicitly restricts mixing sections with link order flag and without:
https://github.com/gittup/binutils/blob/gittup/bfd/elflink.c#L9991

With GNU gold (GNU Binutils 2.29.51.20171006) 1.14 have an assert:
~/LLVM/Release/bin/clang++ test.cpp -ffunction-sections -o test.o
/usr/local/bin/ld: internal error in layout_eh_frame_section, at .././../gold/object.cc:1309
It is that place: https://github.com/gittup/binutils/blob/gittup/gold/object.cc#L1372
Did not investigate it, but it looks it is place (https://sourceware.org/ml/binutils/2009-06/msg00097.html)
mentioned in comment for https://marc.info/?l=llvm-commits&m=144683596826489.

LLD ~head fails here https://github.com/llvm-mirror/lld/blob/master/ELF/InputFiles.cpp#L392 as
we are trying to do cast to InputSection, though .eh_frame is not regular InputSection but EhInputSection.

Basing on all above I supposed it should be fine to not emit SHF_LINK_ORDER flags for start.
I changed implementation so that it emits multiple .eh_frames and sets sh_link field for
SHT_X86_64_UNWIND sections, but don't set the SHF_LINK_ORDER flag. In that way only
x64 target is affected and SHT_X86_64_UNWIND sections are known to be .eh_frame so can be
handled on linker side not by name, what is also nice for start it seems.
(Uploaded current version as diff 2 here: https://reviews.llvm.org/D40352)

With such change LLD and bfd links fine, and I was able to test clang link time. Clang does not
use exceptions, but x64 ABI still requires .eh_frame sections for functions, and result objects
contains many of them so I think it is reasonable test. What I did: built clang with and without
patch, used result compiler binaries for producing 2 sets of release clang objects
(flags were -fPIC -std=c++11 -ffunction-sections -fdata-sections), used them for testing link time
with use of ld.bfd and LLD.

Results (30 runs for each):
1) ld.bfd link time before patch: 2,922310802 seconds time elapsed ( +-  0,13% )
   Size: 80 667 832 bytes
2) ld.bfd link time after patch: 3,773565826 seconds time elapsed ( +-  0,13% )
   Size: 80 667 832 bytes
3) LLD link time before patch: 0,419247946 seconds time elapsed ( +-  0,48% )
   Size: 80 738 240 bytes
4) LLD link time after patch: 0,460139012 seconds time elapsed ( +-  0,44% )
   Size: 80 738 240 bytes

There is no difference in size (that is probably expected as linkers do deduplication optimization, so looks right for me),
slowdown for bfd is about 29%, for LLD about 9.7%.

What we gonna do next ? My plan is to prepare demo patch for LLD to stop parsing .eh_frames
for GC step and benchmark the results with use of -gc-sections. It also can show amount of LLD
code reduction/simplification we can have.


George.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20171123/84fc462e/attachment.html>


More information about the llvm-dev mailing list