c - HOWTO get the correct Frame Pointer of an arbitrary thread in iOS? -
way frame pointer
on demo app running on iphone 5s device / xcode 7, tried frame pointer
of arbitrary thread using thread_get_state
, result in incorrect 1 :
- (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; }
i read frame pointer this: uintptr_t fp = machinecontext.__ss.__fp;
, according apple doc (armv6 , arm64),
register r7 used frame pointer on armv6
while x29 on arm64
the frame pointer register (x29) must address valid frame record, although functions—such leaf functions or tail calls—may elect not create entry in list. result, stack traces meaningful, without debug information.
_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 32-bit or 64-bit clients */ };
way prove frame pointer wrong
how prove fp (machinecontext.__ss.__fp
) not correct frame pointer?
if parameter current thread, mach_thread_self() example, fp 0, different
__builtin_frame_address(0)
;if parameter not current thread, main thread example, pointer previous frame pointer of
fp
null in 2 or 3 frames, short normal link-list of stack frames;still not current thread, print out call stack addresses using
backtrace
on main thread beforesleep
. on thread, suspend main thread , read frame pointer usingthread_get_state
walk call stack, 2 backtrace buffers totally different;
what confuses me
apple doc says the frame pointer register (x29) must address valid frame record, read zero value it.
furthermore, arm doc
states in variants of procedure call standard, registers r16, r17, r29 , r30 have special roles. in these roles labeled ip0, ip1, fp , lr when being used holding addresses.
below example of part of _struct_mcontext
's value:
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 = {
what looking for
i'm searching method correct value of frame pointer
of arbitrary thread.
thanks help!
update 1
of course, want correct frame pointer
of leaf stack frame of arbitrary thread, , walk call stack along previous pointer
of frame pointer
.
before this, i've read these links:
getting backtrace of other thread
how loop through active thread in ipad app
thanks again.
update 2
i've tried on other platforms, yet same result : wrong frame pointer.
- (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 }
the value framepointerofmachinecontext
returns not same __builtin_frame_address(0)
.
update 3
inspired colleague, tried inline asm , made on i386:
uintptr_t ebp = 1; __asm__ ("mov %%ebp, %0;" :"=r"(ebp)); uintptr_t builtinfp = (uintptr_t)__builtin_frame_address(0);
now ebp
variable holds same value builtinfp
's. howto on arbitrary thread?
i found problem eventually,
- (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; }
thread_get_state
fine, parameter should architecture-specific, such x86_thread_state32
, x86_thread_state64
, etc.
i misunderstood macro machine_thread_state
, gave me universal meaning different architectures.
Comments
Post a Comment