Embedding binary data into an executable using LLVM tools

It seems you need to add -z noexecstack (This was added for ELF binaries as well in LLD 7.0.0). The default is to have an executable stack region which is vulnerable to exploitation via stack memory. Your binary image does not have an executable stack and I believe that is why it fails. The error throws you off as it asks you to tell what target emulation to use for your stack (which you do not have).

David Herrmann did all the hard work and have found a cross platform solution which covers:

  • GNU-ld
  • GNU-gold
  • GNU-libtool
  • work with cross-compiling
  • work with LLVM
  • do not require any external non-standard tools

The magic invocation is then:

$(LD) -r -o "src/mydata.bin.o" -z noexecstack --format=binary "src/mydata.bin"

And most often you want that binary segment to be read-only:

$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "src/mydata.bin.o"

UPDATE:

I could not test as my system was:

$ uname -r
11.2-STABLE
$ ld -V
GNU ld 2.17.50 [FreeBSD] 2007-07-03
  Supported emulations:
   elf_x86_64_fbsd
   elf_i386_fbsd

I spun up a VM with FreeBSD 12.0 to test this out and found this:

$ uname -r
12.0-RELEASE
$ ld -V
LLD 6.0.1 (FreeBSD 335540-1200005) (compatible with GNU linkers)

The -z noexecstack was only added in 7.0.0 and it is not listed in the man page for 6.0.1. More annoyingly specifying unsupported values for -z does not trigger an error!

I have not upgraded to LLVM 7 to test if that does the trick. @Richard Smith found a proper solution himself by specifying the emulation with -m in another answer. That route would be so much easier if LLD listed supported emulations with -V.

If you use the file command on file.o you will see it identifies as SYSV ELF. This might be good enough for you. But if you want the exact samme as the system then use elf_amd64_fbsd which is an alias for elf_x86_64_fbsd. Annoyingly ld -V does not output supported emulations with LLD as GNU ld does.

$ file /bin/cat
/bin/cat: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 12.0 (1200086), FreeBSD-style, stripped
$ ld -r -b binary -m elf_amd64 -o data.o data.bin
$ file data.o
data.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ ld -r -b binary -m elf_amd64_fbsd -o data.o data.bin
$ file data.o
data.o: ELF 64-bit LSB relocatable, x86-64, version 1 (FreeBSD), not stripped

elf_amd64_fbsd is an alias for elf_x86_64_fbsd (see D7837 and D24356). Hopefully LLD will add the emulations to the -V output.


After looking through the source, the correct target emulation for my platform is elf_amd64. So the conversion from binary to object file works using:

ld -r -b binary -m elf_amd64 -o file.o file.svg