This patch adds a support for OUTPUT_FORMAT linker script directive.
Since I'm not 100% confident with BFD names you can use in the directive
for all architectures, I added only a few in this patch. We can add
other names for other archtiectures later.
We still do not support triple-style OUTPUT_FORMAT directive, namely,
OUTPUT_FORMAT(bfdname, big, little). If you pass -EL (little endian)
or -EB (big endian) to the linker, GNU linkers pick up big or little
as a BFD name, correspondingly, so that you can use a single linker
script for bi-endian processor. I'm not sure if we really need to
support that, so I'll leave it alone for now.
Note that -m takes precedence over OUTPUT_FORAMT, but we always parse
a BFD name given to OUTPUT_FORMAT for error checking. You cannot write
an invalid name in the OUTPUT_FORMAT directive.
Differential Revision: https://reviews.llvm.org/D53495
llvm-svn: 344952
SortSectionPolicy readSortKind();
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
SymbolAssignment *readAssignment(StringRef Tok);
+ std::pair<ELFKind, uint16_t> readBfdName();
void readSort();
Expr readAssert();
Expr readConstant();
skip();
}
+std::pair<ELFKind, uint16_t> ScriptParser::readBfdName() {
+ StringRef S = next();
+ if (S == "elf32-i386")
+ return {ELF32LEKind, EM_386};
+ if (S == "elf32-iamcu")
+ return {ELF32LEKind, EM_IAMCU};
+ if (S == "elf32-x86-64")
+ return {ELF32LEKind, EM_X86_64};
+ if (S == "elf64-littleaarch64")
+ return {ELF64LEKind, EM_AARCH64};
+ if (S == "elf64-x86-64")
+ return {ELF64LEKind, EM_X86_64};
+
+ setError("unknown output format name: " + S);
+ return {ELFNoneKind, EM_NONE};
+}
+
+// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little).
+// Currently we ignore big and little parameters.
void ScriptParser::readOutputFormat() {
- // Error checking only for now.
expect("(");
- skip();
+
+ std::pair<ELFKind, uint16_t> P = readBfdName();
+ if (Config->EKind == ELFNoneKind) {
+ Config->EKind = P.first;
+ Config->EMachine = P.second;
+ }
+
if (consume(")"))
return;
expect(",");
# RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s
# RUN: ld.lld %tx64 -o %t3x64
# RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s
+# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t4x64.script
+# RUN: ld.lld %t4x64.script %tx64 -o %t4x64
+# RUN: ld.lld %tx64 -o %t4x64 %t4x64.script
+# RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=X86-64 %s
# X86-64: ElfHeader {
# X86-64-NEXT: Ident {
# X86-64-NEXT: Magic: (7F 45 4C 46)
# RUN: llvm-readobj -file-headers %t2x32 | FileCheck --check-prefix=X32 %s
# RUN: ld.lld %tx32 -o %t3x32
# RUN: llvm-readobj -file-headers %t3x32 | FileCheck --check-prefix=X32 %s
+# RUN: echo 'OUTPUT_FORMAT(elf32-x86-64)' > %t4x32.script
+# RUN: ld.lld %t4x32.script %tx32 -o %t4x32
+# RUN: llvm-readobj -file-headers %t4x32 | FileCheck --check-prefix=X32 %s
# X32: ElfHeader {
# X32-NEXT: Ident {
# X32-NEXT: Magic: (7F 45 4C 46)
# RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s
# RUN: ld.lld %tx86 -o %t3x86
# RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s
+# RUN: echo 'OUTPUT_FORMAT(elf32-i386)' > %t4x86.script
+# RUN: ld.lld %t4x86.script %tx86 -o %t4x86
+# RUN: llvm-readobj -file-headers %t4x86 | FileCheck --check-prefix=X86 %s
# X86: ElfHeader {
# X86-NEXT: Ident {
# X86-NEXT: Magic: (7F 45 4C 46)
# RUN: llvm-readobj -file-headers %t2iamcu | FileCheck --check-prefix=IAMCU %s
# RUN: ld.lld %tiamcu -o %t3iamcu
# RUN: llvm-readobj -file-headers %t3iamcu | FileCheck --check-prefix=IAMCU %s
+# RUN: echo 'OUTPUT_FORMAT(elf32-iamcu)' > %t4iamcu.script
+# RUN: ld.lld %t4iamcu.script %tiamcu -o %t4iamcu
+# RUN: llvm-readobj -file-headers %t4iamcu | FileCheck --check-prefix=IAMCU %s
# IAMCU: ElfHeader {
# IAMCU-NEXT: Ident {
# IAMCU-NEXT: Magic: (7F 45 4C 46)
# RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s
# RUN: ld.lld %taarch64 -o %t5aarch64
# RUN: llvm-readobj -file-headers %t5aarch64 | FileCheck --check-prefix=AARCH64 %s
+# RUN: echo 'OUTPUT_FORMAT(elf64-littleaarch64)' > %t4aarch64.script
+# RUN: ld.lld %t4aarch64.script %taarch64 -o %t4aarch64
+# RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s
# AARCH64: ElfHeader {
# AARCH64-NEXT: Ident {
# AARCH64-NEXT: Magic: (7F 45 4C 46)
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }
+
+# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t.script
+# RUN: ld.lld -b binary %t.binary -T %t.script -o %t.out
+# RUN: llvm-readobj %t.out -sections -section-data -symbols | FileCheck -check-prefix=X86-64 %s
+
+# X86-64: Format: ELF64-x86-64
# RUN: echo "OUTPUT_FORMAT(x y z)" > %t8
# RUN: not ld.lld %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s
-# ERR8: , expected, but got y
+# 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: cannot open no-such-file:
+
+# RUN: echo "OUTPUT_FORMAT(elf64-x86-64 y z)" > %t9
+# 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:
+++ /dev/null
-# REQUIRES: x86
-# RUN: echo "OUTPUT_FORMAT(x, y, z)" > %t.script
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
-# RUN: ld.lld -shared -o %t2 %t1 %t.script
-# RUN: llvm-readobj %t2 > /dev/null
-
-# RUN: echo "OUTPUT_FORMAT(x, y)" > %t.script
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
-# RUN: not ld.lld -shared -o %t2 %t1 %t.script