Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -139,6 +139,7 @@ bool ExecuteOnly; bool ExportDynamic; bool FixCortexA53Errata843419; + bool FormatBinary = false; bool GcSections; bool GdbIndex; bool GnuHash = false; Index: lld/trunk/ELF/Driver.h =================================================================== --- lld/trunk/ELF/Driver.h +++ lld/trunk/ELF/Driver.h @@ -42,9 +42,6 @@ // 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 Files; }; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -183,7 +183,7 @@ return; MemoryBufferRef MBRef = *Buffer; - if (InBinary) { + if (Config->FormatBinary) { Files.push_back(make(MBRef)); return; } @@ -999,7 +999,7 @@ } // 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 @@ 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; Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -72,6 +72,7 @@ void readRegionAlias(); void readSearchDir(); void readSections(); + void readTarget(); void readVersion(); void readVersionScriptCommand(); @@ -255,6 +256,8 @@ 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 @@ 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(Op) .Cases("*", "/", "%", 8) Index: lld/trunk/test/ELF/linkerscript/target.s =================================================================== --- lld/trunk/test/ELF/linkerscript/target.s +++ lld/trunk/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