diff --git a/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test b/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test --- a/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test +++ b/llvm/test/tools/llvm-objcopy/ELF/bad-output-format.test @@ -3,6 +3,11 @@ # RUN: not llvm-objcopy -O xyz %t.o %t.2.o 2>&1 \ # RUN: | FileCheck %s --check-prefix=BAD-OUTPUT-FORMAT +# FreeBSD has some special output format parsing that looks up the name without +# the trailing "-freebsd". Make sure we include the full output format name. +# RUN: not llvm-objcopy -O xyz-freebsd %t.o %t.2.o 2>&1 \ +# RUN: | FileCheck %s --check-prefix=BAD-OUTPUT-FORMAT-BSD + !ELF FileHeader: Class: ELFCLASS32 @@ -11,3 +16,4 @@ Machine: EM_386 # BAD-OUTPUT-FORMAT: Invalid output format: 'xyz' +# BAD-OUTPUT-FORMAT-BSD: Invalid output format: 'xyz-freebsd' diff --git a/llvm/test/tools/llvm-objcopy/ELF/cross-arch-headers.test b/llvm/test/tools/llvm-objcopy/ELF/cross-arch-headers.test --- a/llvm/test/tools/llvm-objcopy/ELF/cross-arch-headers.test +++ b/llvm/test/tools/llvm-objcopy/ELF/cross-arch-headers.test @@ -6,36 +6,88 @@ # Without --output-format, the format should match the input. # RUN: llvm-objcopy %t.o %t.default.o --split-dwo=%t.default.dwo -# RUN: llvm-readobj --file-headers %t.default.o | FileCheck %s --check-prefixes=CHECK,DEFAULT,32 -# RUN: llvm-readobj --file-headers %t.default.dwo | FileCheck %s --check-prefixes=CHECK,DEFAULT,32 +# RUN: llvm-readobj --file-headers %t.default.o | FileCheck %s --check-prefixes=CHECK,LE,DEFAULT,32 +# RUN: llvm-readobj --file-headers %t.default.dwo | FileCheck %s --check-prefixes=CHECK,LE,DEFAULT,32 # RUN: llvm-objcopy %t.o -O elf32-i386 %t.elf32_i386.o --split-dwo=%t.elf32_i386.dwo -# RUN: llvm-readobj --file-headers %t.elf32_i386.o | FileCheck %s --check-prefixes=CHECK,I386,32,SYSV -# RUN: llvm-readobj --file-headers %t.elf32_i386.dwo | FileCheck %s --check-prefixes=CHECK,I386,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_i386.o | FileCheck %s --check-prefixes=CHECK,LE,I386,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_i386.dwo | FileCheck %s --check-prefixes=CHECK,LE,I386,32,SYSV # RUN: llvm-objcopy %t.o -O elf32-i386-freebsd %t.elf32_i386_freebsd.o --split-dwo=%t.elf32_i386_freebsd.dwo -# RUN: llvm-readobj --file-headers %t.elf32_i386_freebsd.o | FileCheck %s --check-prefixes=CHECK,I386,32,FREEBSD -# RUN: llvm-readobj --file-headers %t.elf32_i386_freebsd.dwo | FileCheck %s --check-prefixes=CHECK,I386,32,FREEBSD +# RUN: llvm-readobj --file-headers %t.elf32_i386_freebsd.o | FileCheck %s --check-prefixes=CHECK,LE,I386,32,FREEBSD +# RUN: llvm-readobj --file-headers %t.elf32_i386_freebsd.dwo | FileCheck %s --check-prefixes=CHECK,LE,I386,32,FREEBSD + +# RUN: llvm-objcopy %t.o -O elf32-iamcu %t.elf32_iamcu.o --split-dwo=%t.elf32_iamcu.dwo +# RUN: llvm-readobj --file-headers %t.elf32_iamcu.o | FileCheck %s --check-prefixes=CHECK,LE,IAMCU,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_iamcu.dwo | FileCheck %s --check-prefixes=CHECK,LE,IAMCU,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-littlearm %t.elf32_littlearm.o --split-dwo=%t.elf32_littlearm.dwo +# RUN: llvm-readobj --file-headers %t.elf32_littlearm.o | FileCheck %s --check-prefixes=CHECK,LE,ARM,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_littlearm.dwo | FileCheck %s --check-prefixes=CHECK,LE,ARM,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf64-aarch64 %t.elf64_aarch64.o --split-dwo=%t.elf64_aarch64.dwo +# RUN: llvm-readobj --file-headers %t.elf64_aarch64.o | FileCheck %s --check-prefixes=CHECK,LE,AARCH,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_aarch64.dwo | FileCheck %s --check-prefixes=CHECK,LE,AARCH,64,SYSV + +# RUN: llvm-objcopy %t.o -O elf64-littleaarch64 %t.elf64_littleaarch64.o --split-dwo=%t.elf64_littleaarch64.dwo +# RUN: llvm-readobj --file-headers %t.elf64_littleaarch64.o | FileCheck %s --check-prefixes=CHECK,LE,AARCH,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_littleaarch64.dwo | FileCheck %s --check-prefixes=CHECK,LE,AARCH,64,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-powerpc %t.elf32_powerpc.o --split-dwo=%t.elf32_powerpc.dwo +# RUN: llvm-readobj --file-headers %t.elf32_powerpc.o | FileCheck %s --check-prefixes=CHECK,BE,PPC,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_powerpc.dwo | FileCheck %s --check-prefixes=CHECK,BE,PPC,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf64-powerpc %t.elf64_powerpc.o --split-dwo=%t.elf64_powerpc.dwo +# RUN: llvm-readobj --file-headers %t.elf64_powerpc.o | FileCheck %s --check-prefixes=CHECK,BE,PPC64BE,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_powerpc.dwo | FileCheck %s --check-prefixes=CHECK,BE,PPC64BE,64,SYSV # RUN: llvm-objcopy %t.o -O elf32-powerpcle %t.elf32_ppcle.o --split-dwo=%t.elf32_ppcle.dwo -# RUN: llvm-readobj --file-headers %t.elf32_ppcle.o | FileCheck %s --check-prefixes=CHECK,PPC,32,SYSV -# RUN: llvm-readobj --file-headers %t.elf32_ppcle.dwo | FileCheck %s --check-prefixes=CHECK,PPC,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_ppcle.o | FileCheck %s --check-prefixes=CHECK,LE,PPC,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_ppcle.dwo | FileCheck %s --check-prefixes=CHECK,LE,PPC,32,SYSV # RUN: llvm-objcopy %t.o -O elf32-x86-64 %t.elf32_x86_64.o --split-dwo=%t.elf32_x86_64.dwo -# RUN: llvm-readobj --file-headers %t.elf32_x86_64.o | FileCheck %s --check-prefixes=CHECK,X86-64,32,SYSV -# RUN: llvm-readobj --file-headers %t.elf32_x86_64.dwo | FileCheck %s --check-prefixes=CHECK,X86-64,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_x86_64.o | FileCheck %s --check-prefixes=CHECK,LE,X86-64,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_x86_64.dwo | FileCheck %s --check-prefixes=CHECK,LE,X86-64,32,SYSV # RUN: llvm-objcopy %t.o -O elf64-powerpcle %t.elf64_ppcle.o --split-dwo=%t.elf64_ppcle.dwo -# RUN: llvm-readobj --file-headers %t.elf64_ppcle.o | FileCheck %s --check-prefixes=CHECK,PPC64,64,SYSV -# RUN: llvm-readobj --file-headers %t.elf64_ppcle.dwo | FileCheck %s --check-prefixes=CHECK,PPC64,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_ppcle.o | FileCheck %s --check-prefixes=CHECK,LE,PPC64LE,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_ppcle.dwo | FileCheck %s --check-prefixes=CHECK,LE,PPC64LE,64,SYSV # RUN: llvm-objcopy %t.o -O elf64-x86-64 %t.elf64_x86_64.o --split-dwo=%t.elf64_x86_64.dwo -# RUN: llvm-readobj --file-headers %t.elf64_x86_64.o | FileCheck %s --check-prefixes=CHECK,X86-64,64,SYSV -# RUN: llvm-readobj --file-headers %t.elf64_x86_64.dwo | FileCheck %s --check-prefixes=CHECK,X86-64,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_x86_64.o | FileCheck %s --check-prefixes=CHECK,LE,X86-64,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_x86_64.dwo | FileCheck %s --check-prefixes=CHECK,LE,X86-64,64,SYSV # RUN: llvm-objcopy %t.o -O elf64-x86-64-freebsd %t.elf64_x86_64_freebsd.o --split-dwo=%t.elf64_x86_64_freebsd.dwo -# RUN: llvm-readobj --file-headers %t.elf64_x86_64_freebsd.o | FileCheck %s --check-prefixes=CHECK,X86-64,64,FREEBSD -# RUN: llvm-readobj --file-headers %t.elf64_x86_64_freebsd.dwo | FileCheck %s --check-prefixes=CHECK,X86-64,64,FREEBSD +# RUN: llvm-readobj --file-headers %t.elf64_x86_64_freebsd.o | FileCheck %s --check-prefixes=CHECK,LE,X86-64,64,FREEBSD +# RUN: llvm-readobj --file-headers %t.elf64_x86_64_freebsd.dwo | FileCheck %s --check-prefixes=CHECK,LE,X86-64,64,FREEBSD + +# RUN: llvm-objcopy %t.o -O elf32-tradbigmips %t.elf32_tradbigmips.o --split-dwo=%t.elf32_tradbigmips.dwo +# RUN: llvm-readobj --file-headers %t.elf32_tradbigmips.o | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_tradbigmips.dwo | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-bigmips %t.elf32_bigmips.o --split-dwo=%t.elf32_bigmips.dwo +# RUN: llvm-readobj --file-headers %t.elf32_bigmips.o | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_bigmips.dwo | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-ntradbigmips %t.elf32_ntradbigmips.o --split-dwo=%t.elf32_ntradbigmips.dwo +# RUN: llvm-readobj --file-headers %t.elf32_ntradbigmips.o | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_ntradbigmips.dwo | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPSBE,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-tradlittlemips %t.elf32_tradlittlemips.o --split-dwo=%t.elf32_tradlittlemips.dwo +# RUN: llvm-readobj --file-headers %t.elf32_tradlittlemips.o | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPSLE,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_tradlittlemips.dwo | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPSLE,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf32-ntradlittlemips %t.elf32_ntradlittlemips.o --split-dwo=%t.elf32_ntradlittlemips.dwo +# RUN: llvm-readobj --file-headers %t.elf32_ntradlittlemips.o | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPSLE,32,SYSV +# RUN: llvm-readobj --file-headers %t.elf32_ntradlittlemips.dwo | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPSLE,32,SYSV + +# RUN: llvm-objcopy %t.o -O elf64-tradbigmips %t.elf64_tradbigmips.o --split-dwo=%t.elf64_tradbigmips.dwo +# RUN: llvm-readobj --file-headers %t.elf64_tradbigmips.o | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPS64BE,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_tradbigmips.dwo | FileCheck %s --check-prefixes=CHECK,BE,MIPS,MIPS64BE,64,SYSV + +# RUN: llvm-objcopy %t.o -O elf64-tradlittlemips %t.elf64_tradlittlemips.o --split-dwo=%t.elf64_tradlittlemips.dwo +# RUN: llvm-readobj --file-headers %t.elf64_tradlittlemips.o | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPS64LE,64,SYSV +# RUN: llvm-readobj --file-headers %t.elf64_tradlittlemips.dwo | FileCheck %s --check-prefixes=CHECK,LE,MIPS,MIPS64LE,64,SYSV !ELF FileHeader: @@ -68,29 +120,47 @@ # 32-SAME: ELF32- # 64-SAME: ELF64- # I386-SAME: i386 +# IAMCU-SAME: iamcu +# AARCH-SAME: aarch64 +# ARM-SAME: arm-little +# MIPS-SAME: mips # PPC-SAME: ppc{{$}} -# PPC64-SAME: ppc64 +# PPC64BE-SAME: ppc64{{$}} +# PPC64LE-SAME: ppc64{{$}} # X86-64-SAME: x86-64 # DEFAULT-SAME: unknown -# I386-NEXT: Arch: i386 -# PPC-NEXT: Arch: powerpc{{$}} -# PPC64-NEXT: Arch: powerpc64le -# X86-64-NEXT: Arch: x86_64 -# DEFAULT-NEXT: Arch: unknown +# I386-NEXT: Arch: i386 +# IAMCU-NEXT: Arch: i386 +# AARCH-NEXT: Arch: aarch64 +# ARM-NEXT: Arch: arm +# MIPSBE-NEXT: Arch: mips{{$}} +# MIPSLE-NEXT: Arch: mipsel{{$}} +# MIPS64BE-NEXT: Arch: mips64{{$}} +# MIPS64LE-NEXT: Arch: mips64el{{$}} +# PPC-NEXT: Arch: powerpc{{$}} +# PPC64BE-NEXT: Arch: powerpc64{{$}} +# PPC64LE-NEXT: Arch: powerpc64le +# X86-64-NEXT: Arch: x86_64 +# DEFAULT-NEXT: Arch: unknown # 32-NEXT: AddressSize: 32bit # 64-NEXT: AddressSize: 64bit -# 32: Class: 32-bit -# 64: Class: 64-bit -# CHECK: DataEncoding: LittleEndian +# 32: Class: 32-bit +# 64: Class: 64-bit +# LE: DataEncoding: LittleEndian +# BE: DataEncoding: BigEndian # SYSV: OS/ABI: SystemV (0x0) # FREEBSD: OS/ABI: FreeBSD (0x9) # DEFAULT: OS/ABI: Standalone (0xFF) +# AARCH: Machine: EM_AARCH64 (0xB7) +# ARM: Machine: EM_ARM (0x28) # I386: Machine: EM_386 (0x3) +# IAMCU: Machine: EM_IAMCU (0x6) +# MIPS: Machine: EM_MIPS (0x8) # PPC: Machine: EM_PPC (0x14) # PPC64: Machine: EM_PPC64 (0x15) # X86-64: Machine: EM_X86_64 (0x3E) diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h --- a/llvm/tools/llvm-objcopy/CopyConfig.h +++ b/llvm/tools/llvm-objcopy/CopyConfig.h @@ -30,6 +30,13 @@ // lets us map architecture names to ELF types and the e_machine value of the // ELF file. struct MachineInfo { + MachineInfo(uint16_t EM, uint8_t ABI, bool Is64, bool IsLittle) + : EMachine(EM), OSABI(ABI), Is64Bit(Is64), IsLittleEndian(IsLittle) {} + // Alternative constructor that defaults to NONE for OSABI. + MachineInfo(uint16_t EM, bool Is64, bool IsLittle) + : MachineInfo(EM, ELF::ELFOSABI_NONE, Is64, IsLittle) {} + // Default constructor for unset fields. + MachineInfo() : MachineInfo(0, 0, false, false) {} uint16_t EMachine; uint8_t OSABI; bool Is64Bit; diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp --- a/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -253,14 +253,14 @@ } static const StringMap ArchMap{ - // Name, {EMachine, OS/ABI, 64bit, LittleEndian} - {"aarch64", {ELF::EM_AARCH64, ELF::ELFOSABI_NONE, true, true}}, - {"arm", {ELF::EM_ARM, ELF::ELFOSABI_NONE, false, true}}, - {"i386", {ELF::EM_386, ELF::ELFOSABI_NONE, false, true}}, - {"i386:x86-64", {ELF::EM_X86_64, ELF::ELFOSABI_NONE, true, true}}, - {"powerpc:common64", {ELF::EM_PPC64, ELF::ELFOSABI_NONE, true, true}}, - {"sparc", {ELF::EM_SPARC, ELF::ELFOSABI_NONE, false, true}}, - {"x86-64", {ELF::EM_X86_64, ELF::ELFOSABI_NONE, true, true}}, + // Name, {EMachine, 64bit, LittleEndian} + {"aarch64", {ELF::EM_AARCH64, true, true}}, + {"arm", {ELF::EM_ARM, false, true}}, + {"i386", {ELF::EM_386, false, true}}, + {"i386:x86-64", {ELF::EM_X86_64, true, true}}, + {"powerpc:common64", {ELF::EM_PPC64, true, true}}, + {"sparc", {ELF::EM_SPARC, false, true}}, + {"x86-64", {ELF::EM_X86_64, true, true}}, }; static Expected getMachineInfo(StringRef Arch) { @@ -271,26 +271,41 @@ return Iter->getValue(); } +// FIXME: consolidate with the bfd parsing used by lld. static const StringMap OutputFormatMap{ - // Name, {EMachine, OSABI, 64bit, LittleEndian} - {"elf32-i386", {ELF::EM_386, ELF::ELFOSABI_NONE, false, true}}, - {"elf32-i386-freebsd", {ELF::EM_386, ELF::ELFOSABI_FREEBSD, false, true}}, - {"elf32-powerpcle", {ELF::EM_PPC, ELF::ELFOSABI_NONE, false, true}}, - {"elf32-x86-64", {ELF::EM_X86_64, ELF::ELFOSABI_NONE, false, true}}, - {"elf64-powerpcle", {ELF::EM_PPC64, ELF::ELFOSABI_NONE, true, true}}, - {"elf64-x86-64", {ELF::EM_X86_64, ELF::ELFOSABI_NONE, true, true}}, - {"elf64-x86-64-freebsd", - {ELF::EM_X86_64, ELF::ELFOSABI_FREEBSD, true, true}}, + // Name, {EMachine, 64bit, LittleEndian} + {"elf32-i386", {ELF::EM_386, false, true}}, + {"elf32-iamcu", {ELF::EM_IAMCU, false, true}}, + {"elf32-littlearm", {ELF::EM_ARM, false, true}}, + {"elf32-x86-64", {ELF::EM_X86_64, false, true}}, + {"elf64-aarch64", {ELF::EM_AARCH64, true, true}}, + {"elf64-littleaarch64", {ELF::EM_AARCH64, true, true}}, + {"elf32-powerpc", {ELF::EM_PPC, false, false}}, + {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, + {"elf64-powerpc", {ELF::EM_PPC64, true, false}}, + {"elf64-powerpcle", {ELF::EM_PPC64, true, true}}, + {"elf64-x86-64", {ELF::EM_X86_64, true, true}}, + {"elf32-tradbigmips", {ELF::EM_MIPS, false, false}}, + {"elf32-bigmips", {ELF::EM_MIPS, false, false}}, + {"elf32-ntradbigmips", {ELF::EM_MIPS, false, false}}, + {"elf32-tradlittlemips", {ELF::EM_MIPS, false, true}}, + {"elf32-ntradlittlemips", {ELF::EM_MIPS, false, true}}, + {"elf64-tradbigmips", {ELF::EM_MIPS, true, false}}, + {"elf64-tradlittlemips", {ELF::EM_MIPS, true, true}}, }; -static Expected -getOutputFormatMachineInfo(StringRef Format) { +static Expected getOutputFormatMachineInfo(StringRef Format) { + StringRef OriginalFormat = Format; + bool IsFreeBSD = Format.consume_back("-freebsd"); auto Iter = OutputFormatMap.find(Format); if (Iter == std::end(OutputFormatMap)) return createStringError(errc::invalid_argument, "Invalid output format: '%s'", - Format.str().c_str()); - return Iter->getValue(); + OriginalFormat.str().c_str()); + MachineInfo MI = Iter->getValue(); + if (IsFreeBSD) + MI.OSABI = ELF::ELFOSABI_FREEBSD; + return {MI}; } static Error addSymbolsFromFile(std::vector &Symbols, @@ -431,8 +446,7 @@ Config.BinaryArch = *MI; } if (!Config.OutputFormat.empty() && Config.OutputFormat != "binary") { - Expected MI = - getOutputFormatMachineInfo(Config.OutputFormat); + Expected MI = getOutputFormatMachineInfo(Config.OutputFormat); if (!MI) return MI.takeError(); Config.OutputArch = *MI;