[lld] eea34aa - [ELF] Inspect -EL & -EB for OUTPUT_FORMAT(default, big, little)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 8 10:35:05 PST 2021


Author: Fangrui Song
Date: 2021-02-08T10:34:57-08:00
New Revision: eea34aae2e74e9b6fbdd5b95f479bc7f397bf387

URL: https://github.com/llvm/llvm-project/commit/eea34aae2e74e9b6fbdd5b95f479bc7f397bf387
DIFF: https://github.com/llvm/llvm-project/commit/eea34aae2e74e9b6fbdd5b95f479bc7f397bf387.diff

LOG: [ELF] Inspect -EL & -EB for OUTPUT_FORMAT(default, big, little)

Choose big if -EB is specified, little if -EL is specified, or default if neither is specified.
The new behavior matches GNU ld.

Fixes: https://github.com/ClangBuiltLinux/linux/issues/1025

Differential Revision: https://reviews.llvm.org/D96214

Added: 
    

Modified: 
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/ELF/Options.td
    lld/ELF/ScriptParser.cpp
    lld/docs/ld.lld.1
    lld/test/ELF/emulation-aarch64.s
    lld/test/ELF/invalid-linkerscript.test

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 7881dfe82c87..f80c6fbe4d5e 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -187,6 +187,8 @@ struct Configuration {
   bool nostdlib;
   bool oFormatBinary;
   bool omagic;
+  bool optEB = false;
+  bool optEL = false;
   bool optimizeBBJumps;
   bool optRemarksWithHotness;
   bool picThunk;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 09c2c17de9b2..fe722ebd4891 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1125,6 +1125,13 @@ static void readConfigs(opt::InputArgList &args) {
   config->zWxneeded = hasZOption(args, "wxneeded");
   setUnresolvedSymbolPolicy(args);
 
+  if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
+    if (arg->getOption().matches(OPT_eb))
+      config->optEB = true;
+    else
+      config->optEL = true;
+  }
+
   for (opt::Arg *arg : args.filtered(OPT_z)) {
     std::pair<StringRef, StringRef> option =
         StringRef(arg->getValue()).split('=');

diff  --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 65ef3e824f50..e1eccdbada33 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -159,6 +159,9 @@ defm dynamic_list : Eq<"dynamic-list",
    "shared object. Implies -Bsymbolic but does not set DF_SYMBOLIC">,
    MetaVarName<"<file>">;
 
+def eb: F<"EB">, HelpText<"Select the big-endian format in OUTPUT_FORMAT">;
+def el: F<"EL">, HelpText<"Select the little-endian format in OUTPUT_FORMAT">;
+
 defm eh_frame_hdr: B<"eh-frame-hdr",
     "Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header",
     "Do not create .eh_frame_hdr section">;
@@ -687,8 +690,6 @@ def: F<"stats">;
 def: F<"warn-execstack">;
 def: F<"warn-once">;
 def: F<"warn-shared-textrel">;
-def: F<"EB">;
-def: F<"EL">;
 def: JoinedOrSeparate<["-"], "G">;
 def: F<"Qy">;
 

diff  --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 3af63830f9c0..4b15a71f029b 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -431,13 +431,26 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
       .Default({ELFNoneKind, EM_NONE});
 }
 
-// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little).
-// Currently we ignore big and little parameters.
+// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose
+// big if -EB is specified, little if -EL is specified, or default if neither is
+// specified.
 void ScriptParser::readOutputFormat() {
   expect("(");
 
+  StringRef s;
   config->bfdname = unquote(next());
-  StringRef s = config->bfdname;
+  if (!consume(")")) {
+    expect(",");
+    s = unquote(next());
+    if (config->optEB)
+      config->bfdname = s;
+    expect(",");
+    s = unquote(next());
+    if (config->optEL)
+      config->bfdname = s;
+    consume(")");
+  }
+  s = config->bfdname;
   if (s.consume_back("-freebsd"))
     config->osabi = ELFOSABI_FREEBSD;
 
@@ -448,14 +461,6 @@ void ScriptParser::readOutputFormat() {
     config->mipsN32Abi = true;
   if (config->emachine == EM_MSP430)
     config->osabi = ELFOSABI_STANDALONE;
-
-  if (consume(")"))
-    return;
-  expect(",");
-  skip();
-  expect(",");
-  skip();
-  expect(")");
 }
 
 void ScriptParser::readPhdrs() {

diff  --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 79a684def275..cd9052e678cc 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -161,6 +161,10 @@ Read a list of dynamic symbols from
 (shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Implies
 .Cm -Bsymbolic
 but does not set DF_SYMBOLIC
+.It Fl -EB
+Select the big-endian format in the OUTPUT_FORMAT command.
+.It Fl -EL
+Select the little-endian format in the OUTPUT_FORMAT command.
 .It Fl -eh-frame-hdr
 Request creation of
 .Li .eh_frame_hdr

diff  --git a/lld/test/ELF/emulation-aarch64.s b/lld/test/ELF/emulation-aarch64.s
index e5ba733a5b8f..2d26a1e8e64e 100644
--- a/lld/test/ELF/emulation-aarch64.s
+++ b/lld/test/ELF/emulation-aarch64.s
@@ -23,6 +23,20 @@
 # RUN: ld.lld %t.script %t.be.o -o %t3.be
 # RUN: llvm-readobj --file-headers %t3.be | FileCheck --check-prefixes=AARCH64,BE %s
 
+## Test OUTPUT_FORMAT(default, big, little).
+# RUN: echo 'OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64")' > %t.script
+# RUN: ld.lld -EL -T %t.script %t.o -o %t4.le
+# RUN: llvm-readobj --file-headers %t4.le | FileCheck --check-prefixes=AARCH64,LE %s
+# RUN: not ld.lld -EB -T %t.script %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_BE %s
+
+# RUN: not ld.lld -T %t.script %t.be.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_LE %s
+# RUN: not ld.lld -EL -T %t.script %t.be.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_LE %s
+# RUN: ld.lld -EB -T %t.script %t.be.o -o %t4.be
+# RUN: llvm-readobj --file-headers %t4.be | FileCheck --check-prefixes=AARCH64,BE %s
+
+# ERR_LE: error: {{.*}}.o is incompatible with elf64-littleaarch64
+# ERR_BE: error: {{.*}}.o is incompatible with elf64-bigaarch64
+
 # AARCH64:      ElfHeader {
 # AARCH64-NEXT:   Ident {
 # AARCH64-NEXT:     Magic: (7F 45 4C 46)

diff  --git a/lld/test/ELF/invalid-linkerscript.test b/lld/test/ELF/invalid-linkerscript.test
index e635ae4f2af9..c8770bd6aa72 100644
--- a/lld/test/ELF/invalid-linkerscript.test
+++ b/lld/test/ELF/invalid-linkerscript.test
@@ -51,7 +51,7 @@
 # RUN: echo "OUTPUT_FORMAT(x y z)" > %t8
 # RUN: not ld.lld %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s
 # RUN: not ld.lld -m elf_amd64 %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s
-# ERR8: unknown output format name: x
+# ERR8: , expected, but got y
 # ERR8: cannot open no-such-file:
 
 # RUN: echo "OUTPUT_FORMAT(elf64-x86-64 y z)" > %t9


        


More information about the llvm-commits mailing list