[lld] [ELF] OUTPUT_FORMAT: support "binary" and ignore extra OUTPUT_FORMAT commands (PR #98837)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 14 14:26:09 PDT 2024


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/98837

This patch improves GNU ld compatibility.

Close #87891: Support `OUTPUT_FORMAT(binary)`, which is like
--oformat=binary. --oformat=binary takes precedence over an ELF
`OUTPUT_FORMAT`.

In addition, if more than one OUTPUT_FORMAT command is specified, only
check the first one.


>From 31c2dbfe857aa69e6f80a7bfac880e1fc97dcd38 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 14 Jul 2024 14:25:59 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5-bogner
---
 lld/ELF/ScriptParser.cpp               | 22 +++++++++++++++-------
 lld/test/ELF/invalid-linkerscript.test |  4 ++++
 lld/test/ELF/oformat-binary.s          | 17 +++++++++++++++--
 3 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 41bd9a95053f7..649e2d0e29c22 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -461,20 +461,28 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
 void ScriptParser::readOutputFormat() {
   expect("(");
 
-  StringRef s;
-  config->bfdname = unquote(next());
+  StringRef s = unquote(next());
   if (!consume(")")) {
     expect(",");
-    s = unquote(next());
+    StringRef tmp = unquote(next());
     if (config->optEB)
-      config->bfdname = s;
+      s = tmp;
     expect(",");
-    s = unquote(next());
+    tmp = unquote(next());
     if (config->optEL)
-      config->bfdname = s;
+      s = tmp;
     consume(")");
   }
-  s = config->bfdname;
+  // If more than one OUTPUT_FORMAT is specified, only the first is checked.
+  if (!config->bfdname.empty())
+    return;
+  config->bfdname = s;
+
+  if (s == "binary") {
+    config->oFormatBinary = true;
+    return;
+  }
+
   if (s.consume_back("-freebsd"))
     config->osabi = ELFOSABI_FREEBSD;
 
diff --git a/lld/test/ELF/invalid-linkerscript.test b/lld/test/ELF/invalid-linkerscript.test
index c8770bd6aa720..4cbedf639cb1a 100644
--- a/lld/test/ELF/invalid-linkerscript.test
+++ b/lld/test/ELF/invalid-linkerscript.test
@@ -58,3 +58,7 @@
 # RUN: not ld.lld %t9 no-such-file 2>&1 | FileCheck -check-prefix=ERR9 %s
 # ERR9: , expected, but got y
 # ERR9: cannot open no-such-file:
+
+# RUN: echo 'OUTPUT_FORMAT("")' > %t10
+# RUN: not ld.lld %t10 2>&1 | FileCheck -check-prefix=ERR10 %s
+# ERR10: error: {{.*}}:1: unknown output format name:
diff --git a/lld/test/ELF/oformat-binary.s b/lld/test/ELF/oformat-binary.s
index 38af6805140fc..a3780a68b24e1 100644
--- a/lld/test/ELF/oformat-binary.s
+++ b/lld/test/ELF/oformat-binary.s
@@ -6,8 +6,17 @@
 # CHECK:      0000000 90 11 22
 # CHECK-NEXT: 0000003
 
-## Check case when linkerscript is used.
-# RUN: echo "SECTIONS { . = 0x1000; }" > %t.script
+## OUTPUT_FORMAT(binary) selects the binary format as well.
+# RUN: echo "OUTPUT_FORMAT(binary)" > %t.script
+# RUN: ld.lld -o %t2.out -T %t.script %t
+# RUN: od -t x1 -v %t2.out | FileCheck %s
+## More OUTPUT_FORMAT commands are ignored.
+# RUN: echo "OUTPUT_FORMAT("binary")OUTPUT_FORMAT(elf64-x86-64)" > %t.script
+# RUN: ld.lld -o %t2.out -T %t.script %t
+# RUN: od -t x1 -v %t2.out | FileCheck %s
+
+## --oformat=binary overrides an ELF OUTPUT_FORMAT.
+# RUN: echo "OUTPUT_FORMAT(elf64-x86-64) SECTIONS { . = 0x1000; }" > %t.script
 # RUN: ld.lld -o %t2.out --script %t.script %t --oformat binary
 # RUN: od -t x1 -v %t2.out | FileCheck %s
 
@@ -45,6 +54,10 @@
 # RUN:   | FileCheck %s --check-prefix ERR
 # ERR: unknown --oformat value: foo
 
+# RUN: echo "OUTPUT_FORMAT(binary-freebsd)" > %t.script
+# RUN: not ld.lld -T %t.script %t -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
+# ERR2: error: {{.*}}.script:1: unknown output format name: binary-freebsd
+
 # RUN: ld.lld -o /dev/null %t --oformat elf
 # RUN: ld.lld -o /dev/null %t --oformat=elf-foo
 



More information about the llvm-commits mailing list