This is an archive of the discontinued LLVM Phabricator instance.

[lld/mac] Mark private externs with GOT relocs as LOCAL in indirect symbtab
ClosedPublic

Authored by thakis on Oct 14 2021, 4:20 PM.

Details

Summary

prepareSymbolRelocation() in Writer.cpp adds both symbols that need binding and
symbols relocated with a pointer relocation to the got.

Pointer relocations are emitted for non-movq GOTPCREL(%rip) loads. (movqs
become GOT_LOADs so that the linker knows they can be relaxed to leaqs, while
others, such as addq, become just GOT -- a pointer relocation -- since they
can't be relaxed in that way).

For example, this C file produces a private_extern GOT relocation when
compiled with -O2 with clang:

extern const char kString[];
const char* g(int a) { return kString + a; }

Linkers need to put pointer-relocated symbols into the GOT, but ld64 marks them
as LOCAL in the indirect symbol table. This matters, since strip -x looks at
the indirect symbol table when deciding what to strip.

The indirect symtab emitting code was assuming that only symbols that need
binding are in the GOT, but pointer relocations where there too. Hence, the
code needs to explicitly check if a symbol is a private extern.

Fixes https://crbug.com/1242638, which has some more information in comments 14
and 15. With this patch, the output of nm -U on Chromium Framework after
stripping now contains just two symbols when using lld, just like with ld64.

Diff Detail

Event Timeline

thakis created this revision.Oct 14 2021, 4:20 PM
Herald added a project: Restricted Project. · View Herald Transcript
thakis requested review of this revision.Oct 14 2021, 4:20 PM
thakis added a subscriber: oontvoo.Oct 14 2021, 4:31 PM

@oontvoo This apparently breaks compact-unwind-both-local-and-dylib-personality.s which is new since I originally wrote this patch. Does the failure there make sense for you?

Looking at https://reviews.llvm.org/D107533, apparently we just ignore the symbol in UnwindInfoSection.cpp and pick a different one, but still write the old one in the symbol table. That looks pretty sketch :/

thakis updated this revision to Diff 379880.Oct 14 2021, 4:41 PM

don't break existing test

Looking at https://reviews.llvm.org/D107533, apparently we just ignore the symbol in UnwindInfoSection.cpp and pick a different one, but still write the old one in the symbol table. That looks pretty sketch :/

It is absolutely sketchy as I was trying to imitate LD64's behaviour, which we'd agreed was inconsistent. The only reason I put it in was because it unbroke a lot of Chromium/Cronet based tests and it seemed fairly harmless to others at the time.

TBH, I've been pondering removing it - esp. jyknight@ has suggested a different solution (ie., removing chrome personality function - see the email he sent a month ago ...)

If it's blocking you, we could remove it now?

don't break existing test

P.S: Oh, good then! 👍

Thanks :)

Want to review the entire change while you're here? :)

oontvoo accepted this revision.Oct 15 2021, 7:40 AM
oontvoo added inline comments.
lld/test/MachO/compact-unwind-both-local-and-dylib-personality.s
42–45

LD64 seems to only produced the three personality that are "picked" here. (ie., GXX_PERSONALITY_HI isn't present).
I guess that's fine?

This revision is now accepted and ready to land.Oct 15 2021, 7:40 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 15 2021, 10:24 AM