的方式來獲得幀指針
在對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
的。但如何在任意線程上執行此操作?