#include "llvm/Support/raw_ostream.h"
#include <memory>
+#include <set>
#include <vector>
namespace lld {
/// Returns true iff there was an error.
static bool parse(int argc, const char *argv[], PECOFFLinkingContext &info,
raw_ostream &diagnostics = llvm::errs(),
- bool isDirective = false);
+ bool isDirective = false,
+ std::set<StringRef> *undefinedSymbols = nullptr);
private:
WinLinkDriver() LLVM_DELETED_FUNCTION;
bool WinLinkDriver::parse(int argc, const char *argv[],
PECOFFLinkingContext &ctx, raw_ostream &diag,
- bool isReadingDirectiveSection) {
+ bool isReadingDirectiveSection,
+ std::set<StringRef> *undefinedSymbols) {
// Parse may be called from multiple threads simultaneously to parse .drectve
// sections. This function is not thread-safe because it mutates the context
// object. So acquire the lock.
break;
}
- case OPT_incl:
- ctx.addInitialUndefinedSymbol(ctx.allocate(inputArg->getValue()));
+ case OPT_incl: {
+ StringRef sym = ctx.allocate(inputArg->getValue());
+ if (isReadingDirectiveSection) {
+ undefinedSymbols->insert(sym);
+ } else {
+ ctx.addInitialUndefinedSymbol(sym);
+ }
break;
+ }
case OPT_noentry:
ctx.setHasEntry(false);
_definedAtoms._atoms.push_back(atom);
}
+ void addUndefinedSymbol(StringRef sym) {
+ _undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym));
+ }
+
mutable llvm::BumpPtrAllocator _alloc;
private:
if (ec)
return ec;
+ // The set to contain the symbols specified as arguments of
+ // /INCLUDE option.
+ std::set<StringRef> undefinedSymbols;
+
// Interpret .drectve section if the section has contents.
StringRef directives = file->getLinkerDirectives();
if (!directives.empty())
- if (std::error_code ec = handleDirectiveSection(directives))
+ if (std::error_code ec = handleDirectiveSection(
+ directives, &undefinedSymbols))
return ec;
if (std::error_code ec = file->parse())
// function iterate over defined atoms and create alias atoms if needed.
createAlternateNameAtoms(*file);
+ for (StringRef sym : undefinedSymbols) {
+ file->addUndefinedSymbol(sym);
+ if (_ctx.deadStrip())
+ _ctx.addDeadStripRoot(sym);
+ }
+
result.push_back(std::move(file));
return std::error_code();
}
//
// The section mainly contains /defaultlib (-l in Unix), but can contain any
// options as long as they are valid.
- std::error_code handleDirectiveSection(StringRef directives) const {
+ std::error_code handleDirectiveSection(StringRef directives,
+ std::set<StringRef> *undefinedSymbols) const {
DEBUG(llvm::dbgs() << ".drectve: " << directives << "\n");
// Split the string into tokens, as the shell would do for argv.
std::string errorMessage;
llvm::raw_string_ostream stream(errorMessage);
bool parseFailed = !WinLinkDriver::parse(argc, argv, _ctx, stream,
- /*isDirective*/ true);
+ /*isDirective*/ true,
+ undefinedSymbols);
stream.flush();
// Print error message if error.
if (parseFailed) {
--- /dev/null
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f696e636c7564653a666f6f00
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 31
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 3595596940
+ Number: 0
+ - Name: _main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 13
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+...
IMPORT-NEXT: 1
ERROR-NOT: foo
+
+
+# drectve2.obj contains "/include:foo".
+# RUN: yaml2obj %p/Inputs/drectve2.obj.yaml > %t2.obj
+# RUN: not lld -flavor link /out:%t2.exe /entry:main -- %t2.obj >& %t2.log
+# RUN: FileCheck -check-prefix=UNDEF %s < %t2.log
+
+UNDEF: Undefined symbol: {{.*}}: foo