An attempt to fix PR33145, --wrap doesn't work with lto.
Wrapped symbols need to excluded from inter-procedural optimizations to prevent dropping symbols and allow the linker to process re-directs.
Current limitation: doesn't work with ThinLTO.
Details
Diff Detail
Event Timeline
lld/ELF/SymbolTable.cpp | ||
---|---|---|
159–163 |
This one only requires VisibleToRegularObj, doesn't it? | |
338–340 | Is the purpose of this code just to restore the binding of the original symbol? I think it would be simpler to have a post-LTO step that manually restores the binding for each renamed symbol rather than dealing with it here. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
167 | What about the rename target? If I pass --defsym=foo=bar, the linker should not allow IPO past foo, right? |
Addressed review comments. Added test cases. Tweaked saved pre-LTO bindings to more accurately reflect the state of the symbol table.
This is getting better.
Please rebase the patch because it didn't apply cleanly.
lld/ELF/SymbolTable.cpp | ||
---|---|---|
132 | Convention says all Variable names should start with capital letter. Also, i is a little vague. | |
llvm/include/llvm/LTO/LTO.h | ||
370–372 | Is this formatted? Doesn't seem so. | |
llvm/lib/LTO/LTO.cpp | ||
421 | If I remove this line, all the tests still pass. | |
442–443 | If I comment out this line, all the tests still pass. | |
548–549 | This needs a comment. |
lld/test/ELF/lto/defsym.ll | ||
---|---|---|
13–14 ↗ | (On Diff #100921) | These are addresses of PLT entries, right? Can you avoid magic numbers here and make what you are testing for more explicit? I think you can do that by making the symbols hidden and checking that the calls correspond to the correct symbol addresses. Same for wrap-2.ll. |
llvm/lib/LTO/LTO.cpp | ||
443 | You also need to add support for 'r' to llvm-lto2. Please also add an llvm-lto2 based test that verifies that the linkage has changed. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | Can we now replace these functions with something that applies the rename to each symbol in Config->RenamedSymbols? I think it should be possible with this change to how we declare RenamedSymbols. struct RenamedSymbol { uint8_t OrigBinding; Symbol *Target; }; MapVector<Symbol*, RenamedSymbol> RenamedSymbols; |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | But __wrap_ symbols are different: they need to be on the list, but they are not being replaced. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | They only need to be marked as IsUsedInRegularObj. And that's taken care of for you by addUndefined. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | Map it to NULL? |
lld/ELF/Config.h | ||
---|---|---|
102 ↗ | (On Diff #101247) | This is the only field in Config that has a comment. Not sure how I feel about it, I'll defer it to Rui. |
lld/ELF/SymbolTable.cpp | ||
186–189 | Is this bit needed? I don't see a test for it. | |
190 | Can this ever be null? If so, you should check for it. | |
lld/ELF/SymbolTable.h | ||
42–43 | Unsorted. | |
llvm/lib/LTO/LTO.cpp | ||
407–410 | This comment is now stale after your change. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | I mean that you can just set IsUsedInRegularObj on the __wrap_ symbol before you assign it to Target. Then LTO will keep it alive. There's no need to add it (as a key) to RenamedSymbols then. |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
172–198 | This works fine for -wrap, but not for -defsym. For -wrap, we want to keep the __real_ and the original symbols on the list, so the mappings are: For -defsym, we want to preserve the original symbol, so we would add Orig --> Alias mapping to communicate with LTO. But after we're done, we need to copy Orig --> Alias. I added a flag to the mapping structure to reverse the direction of the copy, so now in the -defsym test the call to bar3() gets inlined and the call to bar2() goes to its alias, bar3. This sounds reasonable to me, just want to make sure it's acceptable. |
lld/ELF/Driver.cpp | ||
---|---|---|
972 | This comment and the one below aren't really accurate any more because this code is used in the non-LTO case as well. | |
lld/ELF/LTO.cpp | ||
133 | I think this can just be Config->RenamedSymbols.count(Sym). | |
lld/ELF/SymbolTable.cpp | ||
161 | Is this function necessary? All callers pass a non-null SymbolBody, so they can just query the binding directly. | |
167–169 | Move this comment to applySymbolRenames. | |
175 | I'd minimise the diff here and rename this variable back. |
This LGTM. I am not a big fan of keeping a copy or the original binding, but it sure saves a lot of plumbing.
Please just wait to see if Davide and Peter have something to add.
LGTM as well
lld/test/ELF/lto/wrap-1.ll | ||
---|---|---|
13 ↗ | (On Diff #101289) | Please update this comment. I think you also want to test 'r' for __real_bar. |
I'm fine with this once Peter's comments are addressed. I'm not a fan of having to carry around the original binding as well, but I think it's tolerable.
lld/ELF/Config.h | ||
---|---|---|
107 ↗ | (On Diff #101289) | Please run clang-format-diff. It should be formatted as <Symbol *, RenamedSymbol> |
lld/ELF/Driver.cpp | ||
972 | I prefer a more concrete comment. Handle -wrap option. | |
976 | Ditto. Handle --defsym=sym=alias option. | |
lld/ELF/SymbolTable.cpp | ||
179 | Add a blank line before a comment. | |
197 | Add a blank line before a comment. | |
203 | It is not obvious why you need this function from the source code. You need to add a comment. | |
204 | What is RSI? I found just KV (short for key-value) makes sense in most cases. | |
208 | Ditto |
lld/ELF/SymbolTable.cpp | ||
---|---|---|
204 | RSI is supposed to be Renamed Symbol Iterator, but KV is ok with me too | |
lld/test/ELF/lto/wrap-1.ll | ||
13 ↗ | (On Diff #101289) | Resolutions file is driven by input file symbol tables. Since __real_bar is not defined in an object, it does not show up there. I added a definition and a test for the 'r' flag. |
There were some comments pending by Rui. You addressed them, but you still need to wait for an explicit LGTM before committing.
I don't think it's worth reverting this patch, but this is not okay and you should consider it next time.