Freebsd

使用 LLVM 工具將二進制數據嵌入到執行檔中

  • January 18, 2019

過去,我首先.o使用 GNU 連結器將資源文件(圖像)轉換為文件,從而將資源文件(圖像)嵌入到程序中。例如:

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

從 FreeBSD 12 開始,預設連結器已從 GNU 更改為 LLVM。儘管連結器似乎理解命令行選項,但它會導致錯誤。例如:

ld -r -b binary -o file.o file.svg
ld: error: target emulation unknown: -m or at least one .o file required

還嘗試使用ld.lld(1)手冊頁中的命令行選項:

ld --relocatable --format=binary -o file.o file.svg
ld: error: target emulation unknown: -m or at least one .o file required

我使用了正確的工具嗎?我需要為-m選項指定一個值嗎?

看來您需要添加-z noexecstack(這也是在LLD 7.0.0中為 ELF 二進製文件添加的)。預設設置是有一個可執行的堆棧區域,該區域易受堆棧記憶體的利用。您的二進制映像沒有可執行堆棧,我相信這就是它失敗的原因。該錯誤會讓你失望,因為它要求你告訴你的堆棧使用什麼目標仿真(你沒有)。

David Herrmann做了所有艱苦的工作,並找到了一個跨平台的解決方案,其中包括:

  • GNU-ld
  • GNU-黃金
  • GNU-libtool
  • 使用交叉編譯
  • 使用 LLVM
  • 不需要任何外部非標準工具

魔術呼叫是:

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

大多數情況下,您希望該二進制段是只讀的:

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

更新:

我無法測試,因為我的系統是:

$ 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

我用 FreeBSD 12.0 啟動了一個虛擬機來測試它並發現了這個:

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

僅在 7.0.0中-z noexecstack添加,並且未在6.0.1的手冊頁中列出。更煩人的指定不支持的值-z不會觸發錯誤!

我還沒有升級到 LLVM 7 來測試這是否有效。@Richard Smith 通過-m在另一個答案中指定仿真自己找到了一個合適的解決方案。如果 LLD 列出了支持的仿真,那麼這條路線會容易得多-V

如果您使用該file命令,file.o您將看到它標識為 SYSV ELF。這對你來說可能已經足夠好了。但是,如果您想要與系統完全相同,請使用whichelf_amd64_fbsd是. Annoyingly不像 GNU ld 那樣輸出受支持的 LLD 仿真。elf_x86_64_fbsd``ld -V

$ 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_fbsdelf_x86_64_fbsd(參見D7837D24356)的別名。希望 LLD 將仿真添加到-V輸出中。

引用自:https://unix.stackexchange.com/questions/494844