Mach-O符号存根(IOS)

Loc*_*eyu 7 assembly arm mach-o ios

我试图了解Mach-o文件是如何工作的,并且在可用的在线资源方面取得了很大进展(特别是Apple页面: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
Run Code Online (Sandbox Code Playgroud)

但是,当我在十六进制编辑器中查看二进制文件中的数据时,我看到以下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
Run Code Online (Sandbox Code Playgroud)

这看起来像LDR,它将PC增加了固定的数量,但我不明白为什么数量对于符号表中的每个条目都是相同的.

如果有人可以说明为什么会这样,或者提供任何低水平的资源,请告诉我.

谢谢!

Igo*_*sky 13

我将描述当前iOS的情况,它在旧版本中有所不同.

符号存根确实将一个函数指针加载到PC中.对于标准的"惰性"(按需)导入,指针位于该__lazy_symbol部分中,并且最初指向该部分中的辅助例程__stub_helper,例如:

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

该函数dyld_stub_binding_helper是该__stub_helper部分中的第一个,基本上只是dyld_stub_binderdyld中函数的蹦床,传递给它我称之为"符号信息偏移"值.该值是延迟绑定信息流中的偏移量(由LC_DYLD_INFO或LC_DYLD_INFO_ONLY加载命令指向),这是一种带有dyld命令的字节码流.延迟导入的典型序列如下所示:

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

这里dyld会做以下事情:

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

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

注意:您不应该立即查看文件中的偏移量05fc0.该addr字段是虚拟地址,您应该查找包含段命令并查看它启动的VA以及它的文件偏移量,然后进行数学运算.通常__TEXT段从1000开始.

但是,实际的符号存根看起来像你粘贴的那样,可能你有一个胖头,胖头用前1000个字节,因此偏移排列.

  • 名称以trie(前缀树)结构编码,请参阅[此处](http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html)以获得良好的描述. (2认同)