Skip to content

[ELF] OUTPUT_FORMAT: support "binary" and ignore extra OUTPUT_FORMAT commands #98837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

MaskRay
Copy link
Member

@MaskRay MaskRay commented Jul 14, 2024

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.

Created using spr 1.3.5-bogner
@llvmbot
Copy link
Member

llvmbot commented Jul 14, 2024

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-elf

Author: Fangrui Song (MaskRay)

Changes

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

Copy link
Collaborator

@igorkudrin igorkudrin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@smithp35 smithp35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM too.

Created using spr 1.3.5-bogner
@MaskRay MaskRay merged commit 6464dd2 into main Jul 16, 2024
6 of 7 checks passed
@MaskRay MaskRay deleted the users/MaskRay/spr/elf-output_format-support-binary-and-ignore-extra-output_format-commands branch July 16, 2024 17:28
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…commands

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.

Pull Request: #98837

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251671
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Linker script OUTPUT_FORMAT command does not support binary option
4 participants