[LLD] [COFF] Fix autoexport from LTO objects with comdat symbols

Make sure that comdat symbols also have a non-null dummy
SectionChunk associated.

This requires moving around an existing FIXME regarding comdats in
LTO.

Differential Revision: https://reviews.llvm.org/D103012
This commit is contained in:
Martin Storsjö 2021-05-24 15:06:56 +03:00
parent 7c234ae549
commit 728cc0075e
2 changed files with 37 additions and 17 deletions

View File

@ -503,14 +503,9 @@ void ObjFile::handleComdatSelection(
SectionChunk *leaderChunk = nullptr; SectionChunk *leaderChunk = nullptr;
COMDATType leaderSelection = IMAGE_COMDAT_SELECT_ANY; COMDATType leaderSelection = IMAGE_COMDAT_SELECT_ANY;
if (leader->data) { assert(leader->data && "Comdat leader without SectionChunk?");
leaderChunk = leader->getChunk(); leaderChunk = leader->getChunk();
leaderSelection = leaderChunk->selection; leaderSelection = leaderChunk->selection;
} else {
// FIXME: comdats from LTO files don't know their selection; treat them
// as "any".
selection = leaderSelection;
}
if ((selection == IMAGE_COMDAT_SELECT_ANY && if ((selection == IMAGE_COMDAT_SELECT_ANY &&
leaderSelection == IMAGE_COMDAT_SELECT_LARGEST) || leaderSelection == IMAGE_COMDAT_SELECT_LARGEST) ||
@ -1051,10 +1046,22 @@ public:
coff_section section; coff_section section;
}; };
// Convenience class for initializing a SectionChunk with specific flags.
class FakeSectionChunk {
public:
FakeSectionChunk(const coff_section *section) : chunk(nullptr, section) {
// FIXME: comdats from LTO files don't know their selection; treat them
// as "any".
chunk.selection = IMAGE_COMDAT_SELECT_ANY;
}
SectionChunk chunk;
};
FakeSection ltoTextSection(IMAGE_SCN_MEM_EXECUTE); FakeSection ltoTextSection(IMAGE_SCN_MEM_EXECUTE);
FakeSection ltoDataSection(IMAGE_SCN_CNT_INITIALIZED_DATA); FakeSection ltoDataSection(IMAGE_SCN_CNT_INITIALIZED_DATA);
SectionChunk ltoTextSectionChunk(nullptr, &ltoTextSection.section); FakeSectionChunk ltoTextSectionChunk(&ltoTextSection.section);
SectionChunk ltoDataSectionChunk(nullptr, &ltoDataSection.section); FakeSectionChunk ltoDataSectionChunk(&ltoDataSection.section);
} // namespace } // namespace
void BitcodeFile::parse() { void BitcodeFile::parse() {
@ -1069,9 +1076,9 @@ void BitcodeFile::parse() {
Symbol *sym; Symbol *sym;
SectionChunk *fakeSC = nullptr; SectionChunk *fakeSC = nullptr;
if (objSym.isExecutable()) if (objSym.isExecutable())
fakeSC = &ltoTextSectionChunk; fakeSC = &ltoTextSectionChunk.chunk;
else else
fakeSC = &ltoDataSectionChunk; fakeSC = &ltoDataSectionChunk.chunk;
if (objSym.isUndefined()) { if (objSym.isUndefined()) {
sym = symtab->addUndefined(symName, this, false); sym = symtab->addUndefined(symName, this, false);
} else if (objSym.isCommon()) { } else if (objSym.isCommon()) {
@ -1083,12 +1090,15 @@ void BitcodeFile::parse() {
Symbol *alias = symtab->addUndefined(saver.save(fallback)); Symbol *alias = symtab->addUndefined(saver.save(fallback));
checkAndSetWeakAlias(symtab, this, sym, alias); checkAndSetWeakAlias(symtab, this, sym, alias);
} else if (comdatIndex != -1) { } else if (comdatIndex != -1) {
if (symName == obj->getComdatTable()[comdatIndex]) if (symName == obj->getComdatTable()[comdatIndex]) {
sym = comdat[comdatIndex].first; sym = comdat[comdatIndex].first;
else if (comdat[comdatIndex].second) if (cast<DefinedRegular>(sym)->data == nullptr)
cast<DefinedRegular>(sym)->data = &fakeSC->repl;
} else if (comdat[comdatIndex].second) {
sym = symtab->addRegular(this, symName, nullptr, fakeSC); sym = symtab->addRegular(this, symName, nullptr, fakeSC);
else } else {
sym = symtab->addUndefined(symName, this, false); sym = symtab->addUndefined(symName, this, false);
}
} else { } else {
sym = symtab->addRegular(this, symName, nullptr, fakeSC); sym = symtab->addRegular(this, symName, nullptr, fakeSC);
} }

View File

@ -6,18 +6,28 @@
; RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s ; RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s
; RUN: cat %t.def | FileCheck --check-prefix=IMPLIB %s ; RUN: cat %t.def | FileCheck --check-prefix=IMPLIB %s
; CHECK: Name: MyComdatFunc
; CHECK: Name: MyExtData ; CHECK: Name: MyExtData
; CHECK: Name: MyLibFunc ; CHECK: Name: MyLibFunc
; IMPLIB: MyExtData @1 DATA ; IMPLIB: MyComdatFunc @1{{$}}
; IMPLIB: MyLibFunc @2{{$}} ; IMPLIB: MyExtData @2 DATA
; IMPLIB: MyLibFunc @3{{$}}
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu" target triple = "x86_64-w64-windows-gnu"
@MyExtData = dso_local global i32 42, align 4 @MyExtData = dso_local global i32 42, align 4
$MyComdatFunc = comdat any
define dso_local void @MyLibFunc() { define dso_local void @MyLibFunc() {
entry:
call void @MyComdatFunc()
ret void
}
define linkonce_odr void @MyComdatFunc() comdat {
entry: entry:
ret void ret void
} }