[LLD] [COFF] Fix automatic export of symbols from LTO objects

Differential Revision: https://reviews.llvm.org/D101569
This commit is contained in:
Martin Storsjö 2021-04-29 14:06:24 +03:00
parent 27c3db32c0
commit 33b71ec9c6
4 changed files with 63 additions and 11 deletions

View File

@ -32,12 +32,15 @@ namespace coff {
SectionChunk::SectionChunk(ObjFile *f, const coff_section *h)
: Chunk(SectionKind), file(f), header(h), repl(this) {
// Initialize relocs.
setRelocs(file->getCOFFObj()->getRelocations(header));
if (file)
setRelocs(file->getCOFFObj()->getRelocations(header));
// Initialize sectionName.
StringRef sectionName;
if (Expected<StringRef> e = file->getCOFFObj()->getSectionName(header))
sectionName = *e;
if (file) {
if (Expected<StringRef> e = file->getCOFFObj()->getSectionName(header))
sectionName = *e;
}
sectionNameData = sectionName.data();
sectionNameSize = sectionName.size();
@ -49,7 +52,10 @@ SectionChunk::SectionChunk(ObjFile *f, const coff_section *h)
// enabled, treat non-comdat sections as roots. Generally optimized object
// files will be built with -ffunction-sections or /Gy, so most things worth
// stripping will be in a comdat.
live = !config->doGC || !isCOMDAT();
if (config)
live = !config->doGC || !isCOMDAT();
else
live = true;
}
// SectionChunk is one of the most frequently allocated classes, so it is

View File

@ -1220,6 +1220,7 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
if (Chunk *c = def->getChunk())
if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
e.data = true;
s->isUsedInRegularObj = true;
config->exports.push_back(e);
});
}
@ -2117,6 +2118,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (errorCount())
return;
config->hadExplicitExports = !config->exports.empty();
if (config->mingw) {
// In MinGW, all symbols are automatically exported if no symbols
// are chosen to be exported.
maybeExportMinGWSymbols(args);
}
// Do LTO by compiling bitcode input files to a set of native COFF files then
// link those files (unless -thinlto-index-only was given, in which case we
// resolve symbols and write indices, but don't generate native code or link).
@ -2141,12 +2149,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
if (errorCount())
return;
config->hadExplicitExports = !config->exports.empty();
if (config->mingw) {
// In MinGW, all symbols are automatically exported if no symbols
// are chosen to be exported.
maybeExportMinGWSymbols(args);
// Make sure the crtend.o object is the last object file. This object
// file can contain terminating section chunks that need to be placed
// last. GNU ld processes files and static libraries explicitly in the

View File

@ -1042,6 +1042,21 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
BitcodeFile::~BitcodeFile() = default;
namespace {
// Convenience class for initializing a coff_section with specific flags.
class FakeSection {
public:
FakeSection(int c) { section.Characteristics = c; }
coff_section section;
};
FakeSection ltoTextSection(IMAGE_SCN_MEM_EXECUTE);
FakeSection ltoDataSection(IMAGE_SCN_CNT_INITIALIZED_DATA);
SectionChunk ltoTextSectionChunk(nullptr, &ltoTextSection.section);
SectionChunk ltoDataSectionChunk(nullptr, &ltoDataSection.section);
} // namespace
void BitcodeFile::parse() {
std::vector<std::pair<Symbol *, bool>> comdat(obj->getComdatTable().size());
for (size_t i = 0; i != obj->getComdatTable().size(); ++i)
@ -1052,6 +1067,11 @@ void BitcodeFile::parse() {
StringRef symName = saver.save(objSym.getName());
int comdatIndex = objSym.getComdatIndex();
Symbol *sym;
SectionChunk *fakeSC = nullptr;
if (objSym.isExecutable())
fakeSC = &ltoTextSectionChunk;
else
fakeSC = &ltoDataSectionChunk;
if (objSym.isUndefined()) {
sym = symtab->addUndefined(symName, this, false);
} else if (objSym.isCommon()) {
@ -1066,11 +1086,11 @@ void BitcodeFile::parse() {
if (symName == obj->getComdatTable()[comdatIndex])
sym = comdat[comdatIndex].first;
else if (comdat[comdatIndex].second)
sym = symtab->addRegular(this, symName);
sym = symtab->addRegular(this, symName, nullptr, fakeSC);
else
sym = symtab->addUndefined(symName, this, false);
} else {
sym = symtab->addRegular(this, symName);
sym = symtab->addRegular(this, symName, nullptr, fakeSC);
}
symbols.push_back(sym);
if (objSym.isUsed())

View File

@ -0,0 +1,23 @@
; REQUIRES: x86
; RUN: llvm-as %s -o %t.bc
; RUN: lld-link -lldmingw -dll -out:%t.dll %t.bc -noentry -output-def:%t.def
; RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s
; RUN: cat %t.def | FileCheck --check-prefix=IMPLIB %s
; CHECK: Name: MyExtData
; CHECK: Name: MyLibFunc
; IMPLIB: MyExtData @1 DATA
; IMPLIB: MyLibFunc @2{{$}}
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"
@MyExtData = dso_local global i32 42, align 4
define dso_local void @MyLibFunc() {
entry:
ret void
}