summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp6
-rw-r--r--lld/ELF/Driver.h3
-rw-r--r--lld/ELF/ScriptParser.cpp20
-rw-r--r--lld/test/ELF/linkerscript/target.s18
5 files changed, 42 insertions, 6 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 622324c13e2..763111c6ac3 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -139,6 +139,7 @@ struct Configuration {
bool ExecuteOnly;
bool ExportDynamic;
bool FixCortexA53Errata843419;
+ bool FormatBinary = false;
bool GcSections;
bool GdbIndex;
bool GnuHash = false;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 796b84fdead..814c7fe8491 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -183,7 +183,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
return;
MemoryBufferRef MBRef = *Buffer;
- if (InBinary) {
+ if (Config->FormatBinary) {
Files.push_back(make<BinaryFile>(MBRef));
return;
}
@@ -999,7 +999,7 @@ static void setConfigs(opt::InputArgList &Args) {
}
// Returns a value of "-format" option.
-static bool getBinaryOption(StringRef S) {
+static bool isFormatBinary(StringRef S) {
if (S == "binary")
return true;
if (S == "elf" || S == "default")
@@ -1041,7 +1041,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
Config->AsNeeded = true;
break;
case OPT_format:
- InBinary = getBinaryOption(Arg->getValue());
+ Config->FormatBinary = isFormatBinary(Arg->getValue());
break;
case OPT_no_as_needed:
Config->AsNeeded = false;
diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h
index 99e194d9b66..81d7f608e58 100644
--- a/lld/ELF/Driver.h
+++ b/lld/ELF/Driver.h
@@ -42,9 +42,6 @@ private:
// True if we are in --start-lib and --end-lib.
bool InLib = false;
- // True if we are in -format=binary and -format=elf.
- bool InBinary = false;
-
std::vector<InputFile *> Files;
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index ddb4a49a3e5..ffc69b265f7 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -72,6 +72,7 @@ private:
void readRegionAlias();
void readSearchDir();
void readSections();
+ void readTarget();
void readVersion();
void readVersionScriptCommand();
@@ -255,6 +256,8 @@ void ScriptParser::readLinkerScript() {
readSearchDir();
} else if (Tok == "SECTIONS") {
readSections();
+ } else if (Tok == "TARGET") {
+ readTarget();
} else if (Tok == "VERSION") {
readVersion();
} else if (SymbolAssignment *Cmd = readAssignment(Tok)) {
@@ -522,6 +525,23 @@ void ScriptParser::readSections() {
V.end());
}
+void ScriptParser::readTarget() {
+ // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers,
+ // we accept only a limited set of BFD names (i.e. "elf" or "binary")
+ // for --format. We recognize only /^elf/ and "binary" in the linker
+ // script as well.
+ expect("(");
+ StringRef Tok = next();
+ expect(")");
+
+ if (Tok.startswith("elf"))
+ Config->FormatBinary = false;
+ else if (Tok == "binary")
+ Config->FormatBinary = true;
+ else
+ setError("unknown target: " + Tok);
+}
+
static int precedence(StringRef Op) {
return StringSwitch<int>(Op)
.Cases("*", "/", "%", 8)
diff --git a/lld/test/ELF/linkerscript/target.s b/lld/test/ELF/linkerscript/target.s
new file mode 100644
index 00000000000..32db5b7866c
--- /dev/null
+++ b/lld/test/ELF/linkerscript/target.s
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "TARGET(binary) INPUT(\"%t.o\") TARGET(elf64-x86-64) INPUT(\"%t.o\")" > %t.script
+# RUN: ld.lld --script %t.script -o %t.exe
+# RUN: llvm-readelf -symbols %t.exe | FileCheck %s
+
+# CHECK: _binary_
+# CHECK: foobar
+
+# RUN: echo "TARGET(foo)" > %t2.script
+# RUN: not ld.lld --script %t2.script -o /dev/null 2>&1 | FileCheck -check-prefix=ERR %s
+
+# ERR: unknown target: foo
+
+.global foobar
+foobar:
+ nop
OpenPOWER on IntegriCloud