Mach-O符号存根(IOS)

我想了解Mach-o文件是如何工作的,并且已经在可用的在线资源方面取得了很大进展(特别是苹果页面: http : //developer.apple.com/library/mac/#documentation /developertools/conceptual/MachORuntime/Reference/reference.html ),但是我在理解符号存根如何工作方面遇到了障碍。

使用“otool -l”我看到以下部分:

Section sectname __symbolstub1 segname __TEXT addr 0x00005fc0 size 0x00000040 offset 20416 align 2^2 (4) reloff 0 nreloc 0 flags 0x80000408 

但是,当我在hex编辑器中查看二进制文件中的数据时,我看到以下4个字节重复一遍:

 00005FC0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 00005FD0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 00005FE0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 00005FF0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 

这看起来像一个LDR,它增加了一个固定的个人电脑,但我不明白为什么数额是相同的符号表中的每个条目。

如果有人可以阐明为什么这样,或提供任何资源达到这个低水平,请让我知道。

谢谢!

我会用当前的iOS来描述情况,在旧版本中有所不同。

符号存根确实将一个函数指针加载到PC中。 对于标准的“lazy”(按需)导入,指针驻留在__lazy_symbol部分,最初指向__lazy_symbol部分的一个辅助例程,例如:

 __symbolstub1 _AudioServicesAddSystemSoundCompletion __symbolstub1 LDR PC, _AudioServicesAddSystemSoundCompletion$lazy_ptr __symbolstub1 ; End of function _AudioServicesAddSystemSoundCompletion __lazy_symbol _AudioServicesAddSystemSoundCompletion$lazy_ptr DCD _AudioServicesAddSystemSoundCompletion$stubHelper __stub_helper _AudioServicesAddSystemSoundCompletion$stubHelper __stub_helper LDR R12, =nnn ; symbol info offset in the lazy bind table __stub_helper B dyld_stub_binding_helper 

函数dyld_stub_binding_helper__stub_helper部分中的第一个,本质上是dyld中dyld_stub_binder函数的一个蹦床,传递给我所谓的“symbol info offset”值。 该值是延迟绑定信息stream(由LC_DYLD_INFO或LC_DYLD_INFO_ONLY加载命令指向的内部)中的偏移量,它是一种带有用于dyld的命令的字节码stream。 典型的延迟导入序列如下所示:

 72: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(M, 0xYYYYY) 19: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(NNNN) 40: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x00, '_AudioServicesAddSystemSoundCompletion') 90: BIND_OPCODE_DO_BIND() 

这里dyld会做以下的事情:

  1. 从load命令中列出的dylib列表中的dylib编号NNNN中查找名为“_AudioServicesAddSystemSoundCompletion”的函数。
  2. 查找可执行文件的段号M(最有可能是__DATA)
  3. 把函数指针写在YYYYY的偏移处。
  4. 跳转到查找的地址,以便实际的function完成其工作

写入地址恰好是_AudioServicesAddSystemSoundCompletion$lazy_ptr插槽。 因此,下次调用_AudioServicesAddSystemSoundCompletion ,它将直接跳转到导入的函数,而不用通过dyld。

注意 :你不应该立刻看文件中的偏移量05fc0。 addr字段是虚拟地址,你应该查找包含的段命令,看看它启动的VA和它的文件偏移量,然后做math。 通常__TEXT段从1000开始。

然而,实际的符号存根看起来像是粘贴的,可能你有一个胖头,头标取前1000个字节,所以偏移排成一列。