This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Prevent internalizing used comdat symbol
ClosedPublic

Authored by ikudrin on Nov 30 2021, 6:52 AM.

Details

Summary

When a comdat symbol is defined in both bitcode and regular object files, which are contained in the same archive, the linker could lose the flag that the symbol is used in the regular object file and allow LTO to internalize it, which led to "error: undefined symbol".

The issue was introduced in D79300.

Diff Detail

Event Timeline

ikudrin created this revision.Nov 30 2021, 6:52 AM
ikudrin requested review of this revision.Nov 30 2021, 6:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 30 2021, 6:52 AM

Looks good to me, just some suggestions on the comments.

lld/ELF/InputFiles.cpp
1150–1153

Would be good to include LTO in the comment to give some context. For example:

// Prevent LTO from internalizing the symbol in case there is a reference to this symbol from this file.
1151

Presumably we would only need to do this if there were a reference (relocation) from outside the group, i.e. if the caller to foo is getting discarded as well then it doesn't matter. However I don't think it is worth the extra complexity to check for this case.

lld/test/ELF/lto/comdat-mixed-archive.test
46

IIUC we have the sequence:

start.o refs baz
bc.o fetched for baz
Group foo selected from bc.o
obj.o fetched for bar
Group foo rejected from obj.o
foo loses usedInRegularObj
LTO internalizes foo
reference to foo from bar is undefined.

If that is the case may be worth adding

;; group foo in obj.o is rejected in favor of bc.o but we need to prevent LTO from
;; internalizing foo as there is still a reference from outside the group in obj.o.
ikudrin updated this revision to Diff 390905.Nov 30 2021, 10:08 PM
ikudrin marked 3 inline comments as done.
  • Updated comments. Thanks for the suggestions, @psmith!
lld/ELF/InputFiles.cpp
1151

I thought the same.

The fun fact is that moving the definition of foo in bc.ll before declare void @bar() makes the symbol foo at this point Defined, not Lazy, so sym->resolve() will be called instead of replace(), and the flag isUsedInRegularObj will be set.

lld/test/ELF/lto/comdat-mixed-archive.test
46

Your analysis is accurate. I'll add your suggested comment in the common description of the test because this Note is more situational.

MaskRay accepted this revision.Nov 30 2021, 11:45 PM

LGTM. Previously resolve sets the isUsedInRegularObj bit. replace loses the bit.

lld/test/ELF/lto/comdat-mixed-archive.test
49

Maybe use llvm-nm %bc.o to test the symbol order.

You can also name the bitcode *.bc to be different from relocatable object files.

This revision is now accepted and ready to land.Nov 30 2021, 11:45 PM
MaskRay added inline comments.Nov 30 2021, 11:46 PM
lld/test/ELF/lto/comdat-mixed-archive.test
22

If we want this to be robust or detect stale test, test -y foo -y bar output.

ikudrin updated this revision to Diff 390960.Dec 1 2021, 2:29 AM
ikudrin marked 2 inline comments as done.
  • Added checks suggested by @MaskRay. Thanks! Is that what you meant?
MaskRay accepted this revision.Dec 1 2021, 11:47 AM
This revision was automatically updated to reflect the committed changes.