我认为您正在尝试解决EXC_BAD_ACCESS
问题以正确放置它。例如,听起来您在这个示例程序中描述了 dataptr
#include <stdio.h>
int main ()
{
void (*funcptr)(void) = 0;
int *dataptr = 0;
puts ("about to deref dataptr");
printf ("%d\n", *dataptr);
puts ("about to call through f ptr");
funcptr();
puts ("done");
return 0;
}
dataptr
您将在调用中的取消引用中点击第一个 EXC_BAD_ACCESS printf
。您可以将变量更改为有效值以继续执行。这里的一个技巧是dataptr
在我编译的示例中变量存在于堆栈中-O0
,因此您需要设置此时正在读取的寄存器以通过它。这里我只是以这个程序中的起始地址main()
作为有效地址作为一个简单的例子。
* thread #1: tid = 0x1f03, 0x0000000100000eb6 a.out`main + 54 at a.c:7, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
-> 7 printf ("%d\n", *dataptr);
(lldb) disass -c 1 --pc
a.out`main + 54 at a.c:7:
-> 0x100000eb6: movl (%rcx), %esi
(lldb) reg read rcx
rcx = 0x0000000000000000
(lldb) p dataptr
(int *) $0 = 0x0000000000000000
(lldb) p dataptr = (int*) main
(int *) $1 = 0x0000000100000e80
(lldb) reg write rcx `$1`
(lldb) c
Process 77491 resuming
-443987883
about to call through f ptr
* thread #1: tid = 0x1f03, 0x0000000000000000, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
#0: 0x0000000000000000
现在我停止了,因为我通过 NULL 函数指针调用。展开这需要一点额外的 x86_64 ABI 知识,但这并不难——将 pc 设置为调用者的返回地址,将堆栈弹出一个单词,然后你就回来了。
(lldb) reg write pc `*(unsigned long long *)$sp`
(lldb) reg write sp `$sp + 8`
(lldb) c
Process 77522 resuming
done
Process 77522 exited with status = 0 (0x00000000)
当然,这是非常手动的调整 - 自动化并不容易。您可以使用 python 函数表达空函数指针 deref 并添加一个 lldb 命令来轻松完成,但是空数据指针 deref 要求您知道正在访问哪个寄存器 - 也许反汇编指令的一些巧妙的模式匹配可以做到对于常见情况,与一些 python 扩展相同。
希望有帮助。