diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -32,12 +32,15 @@ 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 e = file->getCOFFObj()->getSectionName(header)) - sectionName = *e; + if (file) { + if (Expected e = file->getCOFFObj()->getSectionName(header)) + sectionName = *e; + } sectionNameData = sectionName.data(); sectionNameSize = sectionName.size(); @@ -49,7 +52,10 @@ // 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 diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1220,6 +1220,7 @@ 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 @@ 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 @@ 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 diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -1042,6 +1042,21 @@ 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, <oTextSection.section); +SectionChunk ltoDataSectionChunk(nullptr, <oDataSection.section); +} // namespace + void BitcodeFile::parse() { std::vector> comdat(obj->getComdatTable().size()); for (size_t i = 0; i != obj->getComdatTable().size(); ++i) @@ -1052,6 +1067,11 @@ StringRef symName = saver.save(objSym.getName()); int comdatIndex = objSym.getComdatIndex(); Symbol *sym; + SectionChunk *fakeSC = nullptr; + if (objSym.isExecutable()) + fakeSC = <oTextSectionChunk; + else + fakeSC = <oDataSectionChunk; if (objSym.isUndefined()) { sym = symtab->addUndefined(symName, this, false); } else if (objSym.isCommon()) { @@ -1066,11 +1086,11 @@ 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()) diff --git a/lld/test/COFF/export-all-lto.ll b/lld/test/COFF/export-all-lto.ll new file mode 100644 --- /dev/null +++ b/lld/test/COFF/export-all-lto.ll @@ -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 +}