summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp7
-rw-r--r--lld/ELF/LinkerScript.cpp13
-rw-r--r--lld/test/elf2/linkerscript.s4
-rw-r--r--lld/test/elf2/undefined-opt.s4
5 files changed, 27 insertions, 2 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 8028a6e3e44..59b41ad5648 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -42,6 +42,7 @@ struct Configuration {
llvm::StringRef Sysroot;
std::string RPath;
std::vector<llvm::StringRef> SearchPaths;
+ std::vector<llvm::StringRef> Undefined;
bool AllowMultipleDefinition;
bool AsNeeded = false;
bool Bsymbolic;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 2d7d75ce39a..19639efe170 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -155,6 +155,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
Config->SoName = getString(Args, OPT_soname);
Config->Sysroot = getString(Args, OPT_sysroot);
+ for (auto *Arg : Args.filtered(OPT_undefined))
+ Config->Undefined.push_back(Arg->getValue());
+
for (auto *Arg : Args.filtered(OPT_z))
if (Arg->getValue() == StringRef("now"))
Config->ZNow = true;
@@ -225,8 +228,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (std::unique_ptr<InputFile> &F : Files)
Symtab.addFile(std::move(F));
- for (auto *Arg : Args.filtered(OPT_undefined))
- Symtab.addUndefinedOpt(Arg->getValue());
+ for (auto &U : Config->Undefined)
+ Symtab.addUndefinedOpt(U);
if (Config->OutputFile.empty())
Config->OutputFile = "a.out";
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 2a63be4ca5d..1607247aa98 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -43,6 +43,7 @@ private:
void readAsNeeded();
void readEntry();
+ void readExtern();
void readGroup();
void readInclude();
void readOutput();
@@ -63,6 +64,8 @@ void LinkerScript::run() {
continue;
if (Tok == "ENTRY") {
readEntry();
+ } else if (Tok == "EXTERN") {
+ readExtern();
} else if (Tok == "GROUP" || Tok == "INPUT") {
readGroup();
} else if (Tok == "INCLUDE") {
@@ -181,6 +184,16 @@ void LinkerScript::readEntry() {
expect(")");
}
+void LinkerScript::readExtern() {
+ expect("(");
+ for (;;) {
+ StringRef Tok = next();
+ if (Tok == ")")
+ return;
+ Config->Undefined.push_back(Tok);
+ }
+}
+
void LinkerScript::readGroup() {
expect("(");
for (;;) {
diff --git a/lld/test/elf2/linkerscript.s b/lld/test/elf2/linkerscript.s
index 67d580d06a3..0a45cec7d64 100644
--- a/lld/test/elf2/linkerscript.s
+++ b/lld/test/elf2/linkerscript.s
@@ -6,6 +6,10 @@
# RUN: rm -f %t.dir/libxyz.a
# RUN: llvm-ar rcs %t.dir/libxyz.a %t2.o
+# RUN: echo "EXTERN( undef undef2 )" > %t.script
+# RUN: ld.lld2 %t -o %t2 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
+
# RUN: echo "GROUP(" %t ")" > %t.script
# RUN: ld.lld2 -o %t2 %t.script
# RUN: llvm-readobj %t2 > /dev/null
diff --git a/lld/test/elf2/undefined-opt.s b/lld/test/elf2/undefined-opt.s
index 14e5d879c25..b986f89f8f2 100644
--- a/lld/test/elf2/undefined-opt.s
+++ b/lld/test/elf2/undefined-opt.s
@@ -37,6 +37,10 @@
# TWO-UNDEFINED: Name: bar
# TWO-UNDEFINED: Name: zed
# TWO-UNDEFINED: ]
+# Now the same logic but linker script is used to set undefines
+# RUN: echo "EXTERN( bar abs )" > %t.script
+# RUN: ld.lld2 -o %t3 %t.o %tar.a %t.script
+# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s
# Added undefined symbol may be left undefined without error, but
# shouldn't show up in the dynamic table.
OpenPOWER on IntegriCloud