[PATCH] D96914: [ELF] Don't let __start_/__stop_ retain C identifier name sections

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 17 15:59:31 PST 2021


MaskRay created this revision.
MaskRay added reviewers: grimar, jhenderson, mcgrathr, peter.smith, phosek.
Herald added subscribers: pengfei, steven_wu, hiraditya, arichardson, emaste.
MaskRay requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

For one metadata section usage, each text section references a metadata section.
The metadata sections have a C identifier name to allow the runtime to collect them via __start_/__stop_.
They have the SHF_LINK_ORDER flag just to defeat the "__start_/__stop_ references retain them" semantics.

This happens with `__sancov_guards` (`-fsanitize-coverage=trace-pc-guard`).
Function A (in the section .text.A) references its `__sancov_guard` section.
Function B inlines A (so now .text.B references `__sancov_guard` - this is invalid with the semantics of SHF_LINK_ORDER).

In the linking stage,
if `.text.A` gets discarded, and `__sancov_guard` is retained via the reference from `.text.B`,
the output will be invalid because `__sancov_guard` references the discarded `.text.A`.
LLD errors "sh_link points to discarded section".

To workaround the invalid SHF_LINK_ORDER issue, we could leverage the self-link SHF_LINK_ORDER trick.
See D76802 <https://reviews.llvm.org/D76802> for another use case with `__llvm_prf_cnts` (when compiled with `-fprofile-generate/-fprofile-instr-generate`).

It seems that the "__start_/__stop_ references retain C identifier name sections" rule does not carry its weight.
Let's try dropping the rule. Unfortunately, dropping the rule entirely will cause

  // __llvm_prf_cnts/__llvm_prf_data usually exist, but {names,vnds} may not exist.
  // Such diagnostics will happen with {cnts,data} as well if no input object file is instrumented.
  % clang++ -fprofile-generate a.cc -fuse-ld=lld -Wl,--gc-sections
  ld.lld: error: undefined hidden symbol: __start___llvm_prf_names
  >>> referenced by InstrProfilingPlatformLinux.c
  >>>               InstrProfilingPlatformLinux.c.o:(__llvm_profile_begin_names) in archive /tmp/RelA/lib/clang/13.0.0/lib/linux/libclang_rt.profile-x86_64.a
  ...
  
  // More diagnostics (__llvm_prf_cnts/__llvm_prf_data) if no input object file is instrumented.
  % clang++ -c a.cc; clang++ -fprofile-generate a.o -fuse-ld=lld -Wl,--gc-sections
  ld.lld: error: undefined hidden symbol: __start___llvm_prf_cnts
  >>> referenced by InstrProfilingPlatformLinux.c
  >>>               InstrProfilingPlatformLinux.c.o:(__llvm_profile_begin_cnts) in archive /tmp/RelA/lib/clang/13.0.0/lib/linux/libclang_rt.profile-x86_64.a
  ...

If the intention is to treat C identifier name sections GC roots,
such use cases can annotate the sections with the SHF_GNU_RETAIN flag (D95730 <https://reviews.llvm.org/D95730>).
GCC 11 and (expected) Clang 13 will allow `__attribute__((used))` to mark the containing section SHF_GNU_RETAIN.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D96914

Files:
  lld/ELF/MarkLive.cpp
  lld/test/ELF/gc-sections-metadata-startstop.s
  lld/test/ELF/linkerscript/sections-gc2.s
  lld/test/ELF/lto/section-name.ll
  lld/test/ELF/relocatable-gc.s
  lld/test/ELF/startstop-gccollect.s

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D96914.324454.patch
Type: text/x-patch
Size: 4773 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210217/60548d46/attachment.bin>


More information about the llvm-commits mailing list