diff options
| author | Rui Ueyama <ruiu@google.com> | 2013-07-24 22:53:23 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2013-07-24 22:53:23 +0000 |
| commit | fd50283c3c4be8f46d13ea1aae45de025f3a4e59 (patch) | |
| tree | 38ff46f32915cc6cb85a1f48ae5b4fdb8d3e6d19 | |
| parent | ed696c3dc17b628d0b465e3ef4e2835d1f2d2afa (diff) | |
| download | bcm5719-llvm-fd50283c3c4be8f46d13ea1aae45de025f3a4e59.tar.gz bcm5719-llvm-fd50283c3c4be8f46d13ea1aae45de025f3a4e59.zip | |
[PECOFF] Add /include command line option.
The /include command line option is equivalent to Unix --undefined
option, which forces the linker to resolve the given symbol name
as if it's an unresolved symbol in one of its input files. This feature
is used to link an additional object file or a shared library that no
input files refer to.
llvm-svn: 187084
| -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()); |

