diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 4e0678282eed0..3fde9c84d977d 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -30,7 +30,6 @@ #include "llvm/LTO/LTO.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/COFFImportFile.h" -#include "llvm/Object/COFFModuleDefinition.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -1012,67 +1011,6 @@ void LinkerDriver::createImportLibrary(bool asLib) { } } -void LinkerDriver::parseModuleDefs(StringRef path) { - llvm::TimeTraceScope timeScope("Parse def file"); - std::unique_ptr mb = - CHECK(MemoryBuffer::getFile(path, /*IsText=*/false, - /*RequiresNullTerminator=*/false, - /*IsVolatile=*/true), - "could not open " + path); - COFFModuleDefinition m = check(parseCOFFModuleDefinition( - mb->getMemBufferRef(), ctx.config.machine, ctx.config.mingw)); - - // Include in /reproduce: output if applicable. - ctx.driver.takeBuffer(std::move(mb)); - - if (ctx.config.outputFile.empty()) - ctx.config.outputFile = std::string(saver().save(m.OutputFile)); - ctx.config.importName = std::string(saver().save(m.ImportName)); - if (m.ImageBase) - ctx.config.imageBase = m.ImageBase; - if (m.StackReserve) - ctx.config.stackReserve = m.StackReserve; - if (m.StackCommit) - ctx.config.stackCommit = m.StackCommit; - if (m.HeapReserve) - ctx.config.heapReserve = m.HeapReserve; - if (m.HeapCommit) - ctx.config.heapCommit = m.HeapCommit; - if (m.MajorImageVersion) - ctx.config.majorImageVersion = m.MajorImageVersion; - if (m.MinorImageVersion) - ctx.config.minorImageVersion = m.MinorImageVersion; - if (m.MajorOSVersion) - ctx.config.majorOSVersion = m.MajorOSVersion; - if (m.MinorOSVersion) - ctx.config.minorOSVersion = m.MinorOSVersion; - - for (COFFShortExport e1 : m.Exports) { - Export e2; - // Renamed exports are parsed and set as "ExtName = Name". If Name has - // the form "OtherDll.Func", it shouldn't be a normal exported - // function but a forward to another DLL instead. This is supported - // by both MS and GNU linkers. - if (!e1.ExtName.empty() && e1.ExtName != e1.Name && - StringRef(e1.Name).contains('.')) { - e2.name = saver().save(e1.ExtName); - e2.forwardTo = saver().save(e1.Name); - } else { - e2.name = saver().save(e1.Name); - e2.extName = saver().save(e1.ExtName); - } - e2.exportAs = saver().save(e1.ExportAs); - e2.importName = saver().save(e1.ImportName); - e2.ordinal = e1.Ordinal; - e2.noname = e1.Noname; - e2.data = e1.Data; - e2.isPrivate = e1.Private; - e2.constant = e1.Constant; - e2.source = ExportSource::ModuleDefinition; - ctx.symtab.exports.push_back(e2); - } -} - void LinkerDriver::enqueueTask(std::function task) { taskQueue.push_back(std::move(task)); } @@ -2352,7 +2290,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // Handle /def if (auto *arg = args.getLastArg(OPT_deffile)) { // parseModuleDefs mutates Config object. - parseModuleDefs(arg->getValue()); + mainSymtab.parseModuleDefs(arg->getValue()); } // Handle generation of import library from a def file. diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 12724cbd1eef4..58dc5458e9a54 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -143,8 +143,6 @@ class LinkerDriver { // Used by the resolver to parse .drectve section contents. void parseDirectives(InputFile *file); - void parseModuleDefs(StringRef path); - // Parse an /order file. If an option is given, the linker places COMDAT // sections int he same order as their names appear in the given file. void parseOrderFile(StringRef arg); diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index ecccc7d6ed70c..32ea4a5b2e1fc 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Mangler.h" #include "llvm/LTO/LTO.h" +#include "llvm/Object/COFFModuleDefinition.h" #include "llvm/Support/Debug.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/Parallel.h" @@ -29,6 +30,7 @@ using namespace llvm; using namespace llvm::COFF; +using namespace llvm::object; using namespace llvm::support; namespace lld::coff { @@ -1253,6 +1255,67 @@ void SymbolTable::assignExportOrdinals() { << Twine(std::numeric_limits::max()) << ")"; } +void SymbolTable::parseModuleDefs(StringRef path) { + llvm::TimeTraceScope timeScope("Parse def file"); + std::unique_ptr mb = + CHECK(MemoryBuffer::getFile(path, /*IsText=*/false, + /*RequiresNullTerminator=*/false, + /*IsVolatile=*/true), + "could not open " + path); + COFFModuleDefinition m = check(parseCOFFModuleDefinition( + mb->getMemBufferRef(), machine, ctx.config.mingw)); + + // Include in /reproduce: output if applicable. + ctx.driver.takeBuffer(std::move(mb)); + + if (ctx.config.outputFile.empty()) + ctx.config.outputFile = std::string(saver().save(m.OutputFile)); + ctx.config.importName = std::string(saver().save(m.ImportName)); + if (m.ImageBase) + ctx.config.imageBase = m.ImageBase; + if (m.StackReserve) + ctx.config.stackReserve = m.StackReserve; + if (m.StackCommit) + ctx.config.stackCommit = m.StackCommit; + if (m.HeapReserve) + ctx.config.heapReserve = m.HeapReserve; + if (m.HeapCommit) + ctx.config.heapCommit = m.HeapCommit; + if (m.MajorImageVersion) + ctx.config.majorImageVersion = m.MajorImageVersion; + if (m.MinorImageVersion) + ctx.config.minorImageVersion = m.MinorImageVersion; + if (m.MajorOSVersion) + ctx.config.majorOSVersion = m.MajorOSVersion; + if (m.MinorOSVersion) + ctx.config.minorOSVersion = m.MinorOSVersion; + + for (COFFShortExport e1 : m.Exports) { + Export e2; + // Renamed exports are parsed and set as "ExtName = Name". If Name has + // the form "OtherDll.Func", it shouldn't be a normal exported + // function but a forward to another DLL instead. This is supported + // by both MS and GNU linkers. + if (!e1.ExtName.empty() && e1.ExtName != e1.Name && + StringRef(e1.Name).contains('.')) { + e2.name = saver().save(e1.ExtName); + e2.forwardTo = saver().save(e1.Name); + } else { + e2.name = saver().save(e1.Name); + e2.extName = saver().save(e1.ExtName); + } + e2.exportAs = saver().save(e1.ExportAs); + e2.importName = saver().save(e1.ImportName); + e2.ordinal = e1.Ordinal; + e2.noname = e1.Noname; + e2.data = e1.Data; + e2.isPrivate = e1.Private; + e2.constant = e1.Constant; + e2.source = ExportSource::ModuleDefinition; + exports.push_back(e2); + } +} + Symbol *SymbolTable::addUndefined(StringRef name) { return addUndefined(name, nullptr, false); } diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index e5b02ce5904c4..c8d7251838842 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -160,6 +160,7 @@ class SymbolTable { void fixupExports(); void assignExportOrdinals(); + void parseModuleDefs(StringRef path); // Iterates symbols in non-determinstic hash table order. template void forEachSymbol(T callback) { diff --git a/lld/test/COFF/arm64x-export.test b/lld/test/COFF/arm64x-export.test index 526be63397358..a78b291cedbe1 100644 --- a/lld/test/COFF/arm64x-export.test +++ b/lld/test/COFF/arm64x-export.test @@ -55,6 +55,13 @@ RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj arm64ec-drectve.obj -n RUN: llvm-objdump -d out-drectve-ec.dll | FileCheck --check-prefix=DISASM-EC %s RUN: llvm-readobj --headers --coff-exports out-drectve-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s +# A command-line def file applies only to EC exports. + +RUN: lld-link -machine:arm64x -dll -out:out-def-ec.dll arm64ec-func.obj arm64-func.obj \ +RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -def:func.def -noentry +RUN: llvm-objdump -d out-def-ec.dll | FileCheck --check-prefix=DISASM-EC %s +RUN: llvm-readobj --headers --coff-exports out-def-ec.dll | FileCheck --check-prefix=EXPORTS-EC %s + # Export using the EC .edata section. RUN: lld-link -machine:arm64x -dll -out:out-edata-ec.dll arm64ec-func.obj arm64-func.obj \ @@ -227,3 +234,8 @@ funcname_func: name: .asciz "out-edata.dll" + +#--- func.def +LIBRARY out.dll +EXPORTS + func