12

我正在尝试手写一个 Mach-O 可执行文件。共有三个加载命令:

  • LC_SEGMENT_64加载__PAGEZERO
  • LC_SEGMENT_64加载__TEXT,单__text
  • LC_UNIXTHREAD用适当的设置rip

每个命令都匹配中的结构mach/loader.h和相关的标头。otool -l按预期列出信息并且不报告任何错误。众所周知,它是一个格式良好的目标文件——但 OS X 10.10.5 终止了该任务 (SIGKILL)。

在 OS X 加载之前检查 Mach-O 可执行文件的哪些功能?此信息位于何处?这些功能是否会因版本而异?(经常被引用的“OS X ABI Mach-O Reference”显然不见了。)


这是二进制文件的部分注释十六进制转储。

otool健全性检查(摘录):

$ otool -l machtest
machtest:
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __PAGEZERO
…
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 152
  segname __TEXT
…
Section
  sectname __text
   segname __TEXT
…
Load command 2
        cmd LC_UNIXTHREAD
…
4

2 回答 2

11

从 10.10.5 Yosemite 开始,可执行文件的长度必须至少为4096字节(PAGE_SIZE),否则会立即被杀死。@Siguza 在XNU kernel exec_activate_image函数中找到的相关代码https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/bsd/kern/kern_exec.c#L1456

没有 dyld

假设您想要一个仅使用系统调用的 64 位 macOS 可执行文件,您需要:

  • Mach-O 64 位标头
  • LC_SEGMENT_64 __PAGEZERO(非零大小,名称可以是任何东西)
  • LC_SEGMENT_64 __TEXT(名称可以是任何东西;必须是可读和可执行的;部分是可选的)
  • LC_UNIXTHREAD

这是的例子。

与 dyld

没有 dyld 你不能做很多事情,所以如果你想使用它,最小的集合是:

  • Mach-O 64 位标头
  • LC_SEGMENT_64 __PAGEZERO(非零大小)
  • LC_SEGMENT_64 __TEXT(名称可以是任何东西;必须是可读和可执行的;部分是可选的)
  • LC_SEGMENT_64 __LINKEDIT(必须是可写的,因为 dyld 需要一个可写段,在ld链接的二进制文件中,可写段通常是__DATA
  • LC_DYLD_INFO_ONLY(指定实际dyld加载命令在可执行文件中的物理位置,通常会找到它们,__LINKEDIT但对此没有限制)或者有趣的是LC_SYMTABdyld如果没有LC_DYLD_INFO_ONLY.
  • LC_DYSYMTAB(这可以是空的)
  • LC_LOAD_DYLINKER
  • LC_MAIN或者LC_UNIXTHREAD
  • LC_LOAD_DYLIB(至少要加载一个实际的 dylib,它最终取决于 libSystem 或 libSystem 本身LC_MAIN才能工作)

LC_UNIXTHREADLC_MAIN

在现代可执行文件(自 10.7 Mountain Lion 起)中,LC_UNIXTHREAD被替换为LC_MAIN, 这需要dyld- 但LC_UNIXTHREAD自 10.12 Sierra 起仍然支持任何可执行文件(它应该在未来的 MacOS 版本中,因为它被dyld可执行文件本身用于实际启动)。

为了dyld工作,额外的步骤取决于绑定的类型:
bind at load是最省力的方法,其中LC_DYLD_INFO_ONLY指向有效dyld load commands指向可写段就可以了。
lazy binding另外需要额外的平台特定代码,__TEXT其中利用在加载时绑定到加载函数dyld_stub_binder的延迟加载地址。 还有其他类型我在这里不介绍。dyld
dyld binding

更多细节可以在这里找到:https ://github.com/opensource-apple/dyld/blob/master/src/ImageLoaderMachO.cpp

于 2017-02-22T18:07:20.633 回答
0

不是 100% 肯定,但您需要LC_LOAD_DYLINKER加载命令才能在可执行文件之前运行 dyld,我很确定如果加载命令不可用,OSX不会自动映射到。/usr/lib/dyld

你需要/usr/lib/libSystem.B.dylib加载LC_LOAD_DYLIB命令吗?我不这么认为,但这两者都很好,而且成本也不高。

于 2016-11-14T21:10:56.983 回答