加载Mach-O可执行文件需要什么?

wir*_*yre 7 mach-o xnu

我试图手写一个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参考"显然是缺失的.)


这是二进制文件的部分注释hexdump.

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
…
Run Code Online (Sandbox Code Playgroud)

Kam*_*l.S 5

从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中找到的相关代码

没有戏

假设您只想使用系统调用来执行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_SYMTAB,如果没有,则dyld无法使用实际的加载命令LC_DYLD_INFO_ONLY
  • LC_DYSYMTAB (可以为空)
  • LC_LOAD_DYLINKER
  • LC_MAIN 要么 LC_UNIXTHREAD
  • LC_LOAD_DYLIB(至少需要加载一个实际的dylib 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_binderdyld加载函数的延迟加载地址。
dyld binding此我不介绍其他类型。

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