[PATCH] D13140: [ELF2] Fix binaries so they actually run on FreeBSD.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 10:13:12 PDT 2015


davide created this revision.
davide added a reviewer: rafael.
davide added a subscriber: llvm-commits.
Herald added subscribers: emaste, aemerson.

Since FreeBSD 4.1, the kernel expects binaries to be marked with ELFOSABI_FREEBSD in the ELF header to exec() them.
LLD unconditionally sets OSABI to ELF_OSABINONE, and everything linked with it won't run on FreeBSD (unless explicitly rebranded).

% ./aarch64-hello
ELF binary type "0" not known.
zsh: exec format error: ./aarch64-hello

FreeBSD could be modified to accept ELF_OSABINONE, but that would break all existing binaries, so the kernel needs to support both ABINONE and ABIFREEBSD. I plan to push this change in FreeBSD one day, which, unfortunately, is not today. 
This code patches lld so it sets the header field correctly.

For completeness, the rationale of this change is explained in the FreeBSD commit message, and it's apparently to pleasee binutils maintainers at the time.
https://svnweb.freebsd.org/base?view=revision&revision=59342

http://reviews.llvm.org/D13140

Files:
  ELF/InputFiles.h
  ELF/Writer.cpp
  test/elf2/basic-freebsd.s

Index: test/elf2/basic-freebsd.s
===================================================================
--- test/elf2/basic-freebsd.s
+++ test/elf2/basic-freebsd.s
@@ -0,0 +1,25 @@
+# Verify that OSABI is set to the correct value.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t
+# RUN: lld -flavor gnu2 %t -o %t2
+# RUN: llvm-readobj -file-headers %t2 | FileCheck %s
+# REQUIRES: x86
+
+.globl _start
+_start:
+  mov $1, %rax
+  mov $42, %rdi
+  syscall
+
+# CHECK: ElfHeader {
+# CHECK-NEXT:   Ident {
+# CHECK-NEXT:     Magic: (7F 45 4C 46)
+# CHECK-NEXT:     Class: 64-bit (0x2)
+# CHECK-NEXT:     DataEncoding: LittleEndian (0x1)
+# CHECK-NEXT:     FileVersion: 1
+# CHECK-NEXT:     OS/ABI: FreeBSD (0x9)
+# CHECK-NEXT:     ABIVersion: 0
+# CHECK-NEXT:     Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Type: Executable (0x2)
+# CHECK-NEXT:   Machine: EM_X86_64 (0x3E)
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -500,14 +500,25 @@
                                ? ELFDATA2LSB
                                : ELFDATA2MSB;
   EHdr->e_ident[EI_VERSION] = EV_CURRENT;
-  EHdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
+
+  const SymbolTable &Symtab = SymTabSec.getSymTable();
+  auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF());
+  uint8_t ABI = FirstObj.getOSABI();
+  switch (ABI) {
+  default:
+    error("Unsupported ABI");
+  case ELFOSABI_FREEBSD:
+  case ELFOSABI_NONE:
+    break;
+  case ELFOSABI_LINUX:
+    ABI = ELFOSABI_NONE;
+  }
+  EHdr->e_ident[EI_OSABI] = ABI;
 
   // FIXME: Generalize the segment construction similar to how we create
   // output sections.
-  const SymbolTable &Symtab = SymTabSec.getSymTable();
 
   EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
-  auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF());
   EHdr->e_machine = FirstObj.getEMachine();
   EHdr->e_version = EV_CURRENT;
   SymbolBody *Entry = Symtab.getEntrySym();
Index: ELF/InputFiles.h
===================================================================
--- ELF/InputFiles.h
+++ ELF/InputFiles.h
@@ -105,6 +105,9 @@
   llvm::object::ELFFile<ELFT> &getObj() { return ELFObj; }
 
   uint16_t getEMachine() const { return getObj().getHeader()->e_machine; }
+  uint8_t getOSABI() const {
+    return getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];
+  }
 
   StringRef getStringTable() const { return StringTable; }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D13140.35647.patch
Type: text/x-patch
Size: 2475 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150924/711fd72a/attachment.bin>


More information about the llvm-commits mailing list