Page MenuHomePhabricator

[ELF2] Fix binaries so they actually run on FreeBSD.
ClosedPublic

Authored by davide on Sep 24 2015, 10:13 AM.

Details

Summary

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

Event Timeline

davide updated this revision to Diff 35647.Sep 24 2015, 10:13 AM
davide retitled this revision from to [ELF2] Fix binaries so they actually run on FreeBSD..
davide updated this object.
davide added a reviewer: rafael.
davide added a subscriber: llvm-commits.
emaste added a subscriber: joerg.Sep 24 2015, 10:15 AM
emaste added a subscriber: andrew.Sep 24 2015, 10:22 AM

Side note: this matches what gold does on FreeBSD.

Note that by default on FreeBSD/arm64 we currently set OS/ABI to NONE (aka SYSV) and rely on the ELF note:

root@cavium:/zoo/emaste/freebsd # readelf -hn /bin/ls                           
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            SYSV
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x4020e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          27528 (bytes into file)
  Flags:                             0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         28
  Section header string table index: 27

Notes at offset 0x000001e0 with length 0x00000030:
  Owner         Data size       Description
  FreeBSD       0x00000004      NT_FREEBSD_ABI_TAG
  FreeBSD       0x00000004      NT_FREEBSD_NOINIT_TAG

while on amd64 we require OS/ABI == FreeBSD (but also have the ELF note):

feynman% readelf -hn /bin/ls
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 09 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - FreeBSD
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x401d40
  Start of program headers:          64 (bytes into file)
  Start of section headers:          30160 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28

Notes at offset 0x00000218 with length 0x00000030:
  Owner         Data size       Description
  FreeBSD       0x00000004      NT_FREEBSD_ABI_TAG
  FreeBSD       0x00000004      NT_FREEBSD_NOINIT_TAG

After discussion with some other devs I learned some archs use OS/ABI field as fallback but still the PT_NOTE segment put in zero page is mandatory because the kernel looks at it to decide (at least on aarch64/arm). So, I think this should go in still and I'll make another patch to generate PT_NOTE.

What do you think, Ed?

So, I think this should go in still and I'll make another patch to generate PT_NOTE.

I agree.

rafael edited edge metadata.Sep 24 2015, 1:46 PM

Just a nit.

Just a nit.

What nit?

davide added a subscriber: davide.Sep 24 2015, 4:13 PM

I pinged Rafael and he told I can just copy the osabi value blindly
now that he changed MC to always emit OSABINONE for linux.
Phab ate the inline comment :(

I pinged Rafael and he told I can just copy the osabi value blindly
now that he changed MC to always emit OSABINONE for linux.

Ah, sounds good to me.

This revision was automatically updated to reflect the committed changes.