summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/ReaderWriter/PECOFFTargetInfo.h6
-rw-r--r--lld/lib/Driver/WinLinkDriver.cpp4
-rw-r--r--lld/lib/Driver/WinLinkOptions.td4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp28
-rw-r--r--lld/test/pecoff/include.test7
-rw-r--r--lld/unittests/DriverTests/WinLinkDriverTest.cpp10
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());
OpenPOWER on IntegriCloud