的方式来获得帧指针
在对iPhone 5S设备/ Xcode的7运行的演示应用,我就先用thread_get_state
的任意线程的frame pointer
,但总是导致不正确之一:
- (BOOL)fillThreadState:(thread_t)thread intoMachineContext:(_STRUCT_MCONTEXT *)machineContext {
mach_msg_type_number_t state_count = MACHINE_THREAD_STATE_COUNT;
kern_return_t kr = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)&machineContext->__ss, &state_count);
if (kr != KERN_SUCCESS) {
char *str = mach_error_string(kr);
printf("%s\n", str);
return NO;
}
return YES;
}
予读出的帧指针这样的:uintptr_t fp = machineContext.__ss.__fp;
,根据苹果文件(ARMv6和ARM64),
寄存器R7用作帧指针的ARMv6
同时ARM64
帧指针寄存器(X29)X29必须始终寻址有效帧记录,虽然某些功能 - 如叶子函数或尾部调用 - 可以选择不在此列表中创建条目。因此,即使没有调试信息,堆栈跟踪也将始终有意义。
_STRUCT_ARM_THREAD_STATE64
{
__uint64_t __x[29]; /* General purpose registers x0-x28 */
__uint64_t __fp; /* Frame pointer x29 */
__uint64_t __lr; /* Link register x30 */
__uint64_t __sp; /* Stack pointer x31 */
__uint64_t __pc; /* Program counter */
__uint32_t __cpsr; /* Current program status register */
__uint32_t __pad; /* Same size for 32-bit or 64-bit clients */
};
的方式来证明帧指针是错误的
如何证明FP(machineContext.__ss.__fp
)不是一个正确的帧指针?
如果参数是当前线程,mach_thread_self()例如,FP始终为0,这是从
__builtin_frame_address(0)
不同;如果该参数不是当前线程,例如主线程,则指向前一帧指针
fp
的指针在两个或三个帧中将为NULL,这对于正常的栈帧链接列表来说太短;仍然不是当前线程,我打印出
backtrace
上的调用堆栈地址之前sleep
主线程上。然后在另一个线程中,我暂停主线程并使用thread_get_state
来读取帧指针以遍历调用堆栈,两个回溯缓冲区完全不同;
什么让我困惑
Apple Doc说帧指针寄存器(X29)必须解决一个有效的框架纪录,但我可以读取它ZERO值。
此外,ARM Doc
状态在过程调用标准的所有变体中,寄存器r16,r17,r29和r30都有特殊的作用。在用于保存地址时,这些角色 被标记为IP0,IP1,FP和LR。
下面是_STRUCT_MCONTEXT
的价值的一部分的例子:
Printing description of machineContext:
(__darwin_mcontext64) machineContext = {
__es = (__far = 0, __esr = 0, __exception = 0)
__ss = {
__x = {
[0] = 292057776134
[1] = 6142843584
[2] = 3
[3] = 40
[4] = 624
[5] = 17923
[6] = 0
[7] = 0
[8] = 3968
[9] = 4294966207
[10] = 3603
[11] = 70
[12] = 0
[13] = 33332794515418112
[14] = 0
[15] = 4294967295
[16] = 4294967284
[17] = 18446744073709551585
[18] = 4295035980
[19] = 0
[20] = 0
[21] = 0
[22] = 17923
[23] = 624
[24] = 6142843584
[25] = 3
[26] = 40
[27] = 3
[28] = 0
}
__fp = 0
__lr = 6142843568
__sp = 6877072044
__pc = 6142843488
__cpsr = 2582105136
__pad = 1
}
__ns = {
什么我找
我现在寻找一个方法来获得的Frame Pointer
的正确值一个任意线程。
感谢您的帮助!
更新1
当然,我想要的是得到一个任意线程的叶堆栈帧的正确Frame Pointer
,然后步行沿Frame pointer
的Previous Pointer
调用堆栈。再次
Getting a backtrace of other thread
How To Loop Through All Active Thread in iPad app
Printing a stack trace from another thread
感谢:
在此之前,我读过这些链接。
更新2
我已经在其他平台上尝试过,但还没有相同的结果:错误帧指针。
- (uintptr_t)framePointerOfMachineContext:(_STRUCT_MCONTEXT *)machineContext {
#if defined (__i386__)
return machineContext->__ss.__ebp;
#endif
#if defined (__x86_64__)
return machineContext->__ss.__rbp;
#endif
#if defined (__arm64__)
return machineContext->__ss.__fp;
#endif
}
值framePointerOfMachineContext
返回是不一样的,以__builtin_frame_address(0)
。
UPDATE 3
由同事的启发,我试图联汇编,并使其在i386:
uintptr_t ebp = 1;
__asm__ ("mov %%ebp, %0;"
:"=r"(ebp));
uintptr_t builtinFP = (uintptr_t)__builtin_frame_address(0);
现在ebp
变量保存相同的值来builtinFP
的。但如何在任意线程上执行此操作?