summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2013-07-24 22:53:23 +0000
committerRui Ueyama <ruiu@google.com>2013-07-24 22:53:23 +0000
commitfd50283c3c4be8f46d13ea1aae45de025f3a4e59 (patch)
tree38ff46f32915cc6cb85a1f48ae5b4fdb8d3e6d19
parented696c3dc17b628d0b465e3ef4e2835d1f2d2afa (diff)
downloadbcm5719-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.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