diff options
-rw-r--r-- | lld/include/lld/ReaderWriter/PECOFFTargetInfo.h | 6 | ||||
-rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 4 | ||||
-rw-r--r-- | lld/lib/Driver/WinLinkOptions.td | 4 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp | 28 | ||||
-rw-r--r-- | lld/test/pecoff/include.test | 7 | ||||
-rw-r--r-- | lld/unittests/DriverTests/WinLinkDriverTest.cpp | 10 |
6 files changed, 57 insertions, 2 deletions
diff --git a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h index f9a1729d013..c62199207ce 100644 --- a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h @@ -46,6 +46,8 @@ public: virtual void addPasses(PassManager &pm) const; + virtual void addImplicitFiles(InputFiles &) const; + void appendInputSearchPath(StringRef dirPath) { _inputSearchPaths.push_back(dirPath); } @@ -92,7 +94,7 @@ public: virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const; StringRef allocateString(const StringRef &ref) { - char *x = _extraStrings.Allocate<char>(ref.size() + 1); + char *x = _alloc.Allocate<char>(ref.size() + 1); memcpy(x, ref.data(), ref.size()); x[ref.size()] = '\0'; return x; @@ -117,7 +119,7 @@ private: std::vector<StringRef> _inputSearchPaths; mutable std::unique_ptr<Reader> _reader; mutable std::unique_ptr<Writer> _writer; - llvm::BumpPtrAllocator _extraStrings; + mutable llvm::BumpPtrAllocator _alloc; }; } // end namespace lld diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 8b235d33279..0d017d0cf28 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -351,6 +351,10 @@ bool WinLinkDriver::parse(int argc, const char *argv[], if (parsedArgs->getLastArg(OPT_no_tsaware)) info.setTerminalServerAware(false); + // Handle -include + if (llvm::opt::Arg *sym = parsedArgs->getLastArg(OPT_incl)) + info.addInitialUndefinedSymbol(sym->getValue()); + // Handle -out if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_out)) info.setOutputPath(outpath->getValue()); diff --git a/lld/lib/Driver/WinLinkOptions.td b/lld/lib/Driver/WinLinkOptions.td index f130230b539..0f0590e85c3 100644 --- a/lld/lib/Driver/WinLinkOptions.td +++ b/lld/lib/Driver/WinLinkOptions.td @@ -60,5 +60,9 @@ def tsaware : Flag<["-", "/"], "tsaware">, def no_tsaware : Flag<["-", "/"], "tsaware:no">, HelpText<"Create non-Terminal Server aware executable">; +def incl : Separate<["-", "/"], "include">, + HelpText<"Force symbol to be added to symbol table as undefined one">; +def incl_c : Joined<["-", "/"], "include:">, Alias<incl>; + def help : Flag<["-", "/"], "help">; def help_q : Flag<["-", "/"], "?">, Alias<help>; diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp index a08d9ab6207..c58ee14fe07 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp @@ -7,15 +7,19 @@ // //===----------------------------------------------------------------------===// +#include "Atoms.h" #include "GroupedSectionsPass.h" #include "IdataPass.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Path.h" +#include "lld/Core/InputFiles.h" #include "lld/Core/PassManager.h" #include "lld/Passes/LayoutPass.h" #include "lld/ReaderWriter/PECOFFTargetInfo.h" #include "lld/ReaderWriter/Reader.h" +#include "lld/ReaderWriter/Simple.h" #include "lld/ReaderWriter/Writer.h" namespace lld { @@ -26,6 +30,24 @@ bool containDirectoryName(StringRef path) { llvm::sys::path::remove_filename(smallStr); return !smallStr.str().empty(); } + +/// An instance of UndefinedSymbolFile has a list of undefined symbols +/// specified by "/include" command line option. This will be added to the +/// input file list to force the core linker to try to resolve the undefined +/// symbols. +class UndefinedSymbolFile : public SimpleFile { +public: + UndefinedSymbolFile(const TargetInfo &ti) + : SimpleFile(ti, "Linker Internal File") { + for (StringRef symbol : ti.initialUndefinedSymbols()) { + UndefinedAtom *atom = new (_alloc) coff::COFFUndefinedAtom(*this, symbol); + addAtom(*atom); + } + }; + +private: + llvm::BumpPtrAllocator _alloc; +}; } // anonymous namespace error_code PECOFFTargetInfo::parseFile( @@ -59,6 +81,12 @@ bool PECOFFTargetInfo::validateImpl(raw_ostream &diagnostics) { return false; } +void PECOFFTargetInfo::addImplicitFiles(InputFiles &files) const { + // Add a pseudo file for "/include" linker option. + auto *file = new (_alloc) UndefinedSymbolFile(*this); + files.prependFile(*file); +} + /// Append the given file to the input file list. The file must be an object /// file or an import library file. bool PECOFFTargetInfo::appendInputFileOrLibrary(std::string path) { diff --git a/lld/test/pecoff/include.test b/lld/test/pecoff/include.test new file mode 100644 index 00000000000..ad7eada4402 --- /dev/null +++ b/lld/test/pecoff/include.test @@ -0,0 +1,7 @@ +# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj +# +# RUN: not lld -flavor link -out %t1 -subsystem console \ +# RUN: -include nosuchsym -- %t.obj 2> %t1 +# RUN: FileCheck %s < %t1 + +CHECK: Undefined Symbol: Linker Internal File : nosuchsym
\ No newline at end of file diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index 25d8170cbbd..d028beccf75 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -54,6 +54,7 @@ TEST_F(WinLinkParserTest, Basic) { EXPECT_FALSE(_info.getLargeAddressAware()); EXPECT_TRUE(_info.getBaseRelocationEnabled()); EXPECT_TRUE(_info.isTerminalServerAware()); + EXPECT_TRUE(_info.initialUndefinedSymbols().empty()); } TEST_F(WinLinkParserTest, WindowsStyleOption) { @@ -172,6 +173,15 @@ TEST_F(WinLinkParserTest, NoTerminalServerAware) { EXPECT_FALSE(_info.isTerminalServerAware()); } +TEST_F(WinLinkParserTest, Include) { + EXPECT_FALSE(parse("link.exe", "-include", "foo", "a.out", nullptr)); + auto symbols = _info.initialUndefinedSymbols(); + EXPECT_FALSE(symbols.empty()); + EXPECT_EQ("foo", symbols[0]); + symbols.pop_front(); + EXPECT_TRUE(symbols.empty()); +} + TEST_F(WinLinkParserTest, NoInputFiles) { EXPECT_TRUE(parse("link.exe", nullptr)); EXPECT_EQ("No input files\n", errorMessage()); |