diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -54,6 +54,7 @@ struct ParsedDirectives { std::vector exports; std::vector includes; + std::vector excludes; llvm::opt::InputArgList args; }; @@ -160,6 +161,7 @@ std::vector resources; llvm::StringSet<> directivesExports; + llvm::StringSet<> excludedSymbols; COFFLinkerContext &ctx; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -372,6 +372,14 @@ for (StringRef inc : directives.includes) addUndefined(inc); + // Handle /exclude-symbols: in bulk. + for (StringRef e : directives.excludes) { + SmallVector vec; + e.split(vec, ','); + for (StringRef sym : vec) + excludedSymbols.insert(mangle(sym)); + } + // https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160 for (auto *arg : directives.args) { switch (arg->getOption().getID()) { @@ -1306,7 +1314,7 @@ return; } - AutoExporter exporter; + AutoExporter exporter(excludedSymbols); for (auto *arg : args.filtered(OPT_wholearchive_file)) if (Optional path = doFindFile(arg->getValue())) diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -909,6 +909,9 @@ else if (tok.startswith_insensitive("/include:") || tok.startswith_insensitive("-include:")) result.includes.push_back(tok.substr(strlen("/include:"))); + else if (tok.startswith_insensitive("/exclude-symbols:") || + tok.startswith_insensitive("-exclude-symbols:")) + result.excludes.push_back(tok.substr(strlen("/exclude-symbols:"))); else { // Copy substrings that are not valid C strings. The tokenizer may have // already copied quoted arguments for us, so those do not need to be diff --git a/lld/COFF/MinGW.h b/lld/COFF/MinGW.h --- a/lld/COFF/MinGW.h +++ b/lld/COFF/MinGW.h @@ -25,7 +25,7 @@ // symbols for MinGW. class AutoExporter { public: - AutoExporter(); + AutoExporter(const llvm::StringSet<> &manualExcludeSymbols); void addWholeArchive(StringRef path); void addExcludedSymbol(StringRef symbol); @@ -36,6 +36,8 @@ llvm::StringSet<> excludeLibs; llvm::StringSet<> excludeObjects; + const llvm::StringSet<> &manualExcludeSymbols; + bool shouldExport(const COFFLinkerContext &ctx, Defined *sym) const; }; diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp --- a/lld/COFF/MinGW.cpp +++ b/lld/COFF/MinGW.cpp @@ -23,7 +23,7 @@ using namespace lld; using namespace lld::coff; -AutoExporter::AutoExporter() { +AutoExporter::AutoExporter(const llvm::StringSet<> &manualExcludeSymbols) : manualExcludeSymbols(manualExcludeSymbols) { excludeLibs = { "libgcc", "libgcc_s", @@ -135,7 +135,7 @@ // disallow import symbols. if (!isa(sym) && !isa(sym)) return false; - if (excludeSymbols.count(sym->getName())) + if (excludeSymbols.count(sym->getName()) || manualExcludeSymbols.count(sym->getName())) return false; for (StringRef prefix : excludeSymbolPrefixes.keys()) diff --git a/lld/test/COFF/exclude-symbols-embedded.s b/lld/test/COFF/exclude-symbols-embedded.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/exclude-symbols-embedded.s @@ -0,0 +1,26 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=i686-win32-gnu %s -o %t.o + +// RUN: lld-link -lldmingw -dll -out:%t.dll %t.o -noentry +// RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s + +// CHECK: Name: +// CHECK-NEXT: Name: sym1 +// CHECK-EMPTY: + +.global _sym1 +_sym1: + ret + +.global _sym2 +_sym2: + ret + +.global _sym3 +_sym3: + ret + +.section .drectve,"yn" +.ascii " -exclude-symbols:sym2" +.ascii " -exclude-symbols:sym3" +