Xcode调用一个printf都会进行那些操作

背景知识

进程是特殊文件在内存中加载得到的结果。一个IOS app的进程,就是MachO文件在内存中加载得到的结果。

比如这是一个 arm64 架构下的 MachO 文件。Mach 加载器会读取 MachO 文件中的加载命令(Load Commands),这些命令决定了如何布局这个进程的内存空间。

Xcode调用一个printf都会进行那些操作_第1张图片

(这里需要注意:内存地址和 MachO 文件的 offset 是两个概念,对于 TEXT 和 DATA 段中的东西,arm64 架构下,可以认为 0x100000000 + offset + ASLR = 内存地址

printf()的调用过程

我们知道,当发生一个函数调用时,编译器和静态链接器,会把这个函数调用,成“跳转到某个地址继续执行程序”。

那么我们首先看看调用 ​printf()​ 的汇编是什么样的。

Xcode调用一个printf都会进行那些操作_第2张图片

然后在调用 ​printf()​ 时打一个断点。运行到这个断点时,我们看到了这样一行汇编代码:

Xcode调用一个printf都会进行那些操作_第3张图片

    0x10044e694 <+72>: bl     0x10044ea78               ; symbol stub for: printf

意思是跳转到 ​0x10044ea78​ 地址继续执行,并且这个地址,代表了 printf 函数。

0x10044ea78改地址,实际是什么呢?(内存中的地址!)

现在我们想得到MachO中的地址,有公式:内存地址 = ASLR + rebase + offset。

由于 ASLR 技术,我们需要减去 image 的起始地址,才能得到 rebase 之前的地址,用于和 MachO 文件对比。通过 ​image list​ 命令得到各个 image 的起始地址后,我们发现,​0x10044ea78​ 落在起始地址为 ​0x0000000100448000​ 的主二进制中,二者相减,偏移量为 ​0x6a78。

则内存中的0x10044ea78 对应 MachO的主二进制文件中的偏移为????0x6a78地址中(该地址位于TEXT 段 __stubs 节),说明调用printf()​ 首先跳转到了代码段的某个地址上。

符号表中查找

使用 ​otool -v XSQFishhookDemo -s __TEXT __stubs​ 查看,得到  ​0x6a78​ 地址开始的指令为:

0000000100006a78        nop
0000000100006a7c        ldr        x16, #0x15dc
0000000100006a80        br        x16

//nop 为空命令
ldr 这一行的意思是,将当前 pc 寄存器中的值,加上 0x15dc,再存到 x16 寄存器中
br 这一行的意思是,跳转到 x16 寄存器的值指向的地址。

总的来说就是就是跳转到了X16寄存器的地址中(0000000100006a7c​ + ​0x15dc​ = 0x8058

去查看 0x8058 这个地址,它位于 DATA 段 __la_symbol_ptr 节。

Xcode调用一个printf都会进行那些操作_第4张图片

__la_symbol_ptr 节是一系列指针,这些指针指向的,是某一个指令的地址。

这里 ​0x8058​ 这个地址中存的是 ​0x100006b08

这个 0x100006b08 是 MachO 还未 or 刚刚载入内存中时,内存中 0x100008058 地址存的值。但是内存中的值是可以被改变的。事实上,只有第一次调用 printf 的时候,这一步会跳转到 0x100006b08,之后,这个内存会被写入新的地址,即动态库中 printf() 函数的地址。???这就是Lazy bind

接下来0x100006b08 位于 __TEXT 段 __stub_helper 节,它的汇编指令是:

接下来会跳转到0x6a84这个地址,这个地址是 __stub_helper 节的开头。

Xcode调用一个printf都会进行那些操作_第5张图片

执行几个指令后,就回去调用 dyld_stub_binder 函数。

dyld_stub_binder 是 dyld 执行 bind 的函数。这个函数执行完后,__la_symbol_ptr 节中的内容,将不再是指向 __stub_helper 节的地址,而是 printf 函数真正的地址。

那么下次调用 printf 函数的时候,就可以直接通过 __la_symbol_ptr,找到真正的 printf 函数地址了。

你可能感兴趣的:(IOS)