Skip to content

Commit

Permalink
[ELF2] Fix binaries so they actually run on FreeBSD.
Browse files Browse the repository at this point in the history
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).

Example:
% ./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

Differential Revision:	 http://reviews.llvm.org/D13140

llvm-svn: 248554
  • Loading branch information
dcci committed Sep 25, 2015
1 parent 8aa9973 commit aa7c533
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lld/ELF/InputFiles.h
Expand Up @@ -105,6 +105,9 @@ template <class ELFT> class ELFData {
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; }

Expand Down
7 changes: 4 additions & 3 deletions lld/ELF/Writer.cpp
Expand Up @@ -500,14 +500,15 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
? 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());
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();

// 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();
Expand Down
25 changes: 25 additions & 0 deletions lld/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)

0 comments on commit aa7c533

Please sign in to comment.