virtual void addPasses(PassManager &pm) const;
+ virtual void addImplicitFiles(InputFiles &) const;
+
void appendInputSearchPath(StringRef dirPath) {
_inputSearchPaths.push_back(dirPath);
}
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;
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
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());
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>;
//
//===----------------------------------------------------------------------===//
+#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 {
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(
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) {
--- /dev/null
+# 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
EXPECT_FALSE(_info.getLargeAddressAware());
EXPECT_TRUE(_info.getBaseRelocationEnabled());
EXPECT_TRUE(_info.isTerminalServerAware());
+ EXPECT_TRUE(_info.initialUndefinedSymbols().empty());
}
TEST_F(WinLinkParserTest, WindowsStyleOption) {
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());