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

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 14 14:26:37 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-elf

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

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.


---
Full diff: https://github.com/llvm/llvm-project/pull/98837.diff


3 Files Affected:

- (modified) lld/ELF/ScriptParser.cpp (+15-7) 
- (modified) lld/test/ELF/invalid-linkerscript.test (+4) 
- (modified) lld/test/ELF/oformat-binary.s (+15-2) 


``````````diff
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
 

``````````

</details>


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


More information about the llvm-commits mailing list