我试图手写一个Mach-O可执行文件.有三个加载命令:
LC_SEGMENT_64 装载 __PAGEZEROLC_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)
从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可执行文件,则需要:
LC_SEGMENT_64 __PAGEZERO (非零大小,名称可以是任何东西)LC_SEGMENT_64 __TEXT (名称可以是任何东西;必须可读且可执行;部分是可选的)LC_UNIXTHREAD这是我的例子针对这种情况的示例。
但是,如果没有dyld,您将无法做很多事情,因此,如果要使用dyld,最小集是:
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_DYLINKERLC_MAIN 要么 LC_UNIXTHREADLC_LOAD_DYLIB(至少需要加载一个实际的dylib LC_MAIN才能正常工作)LC_UNIXTHREAD 和 LC_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
| 归档时间: |
|
| 查看次数: |
1295 次 |
| 最近记录: |