There is a great amount of detail on that in the OS X and iOS Internals book (http://www.newosxbook.com). Listing 11-21 (ibid) in the book actually shows sample code to do so. In a nutshell, you've two options:
A) look at the exception itself from the exception data - convert the state to an arm_thread_state, something like so:
struct arm_thread_state *atsh = &exc.old_state;
printf ("CPSR is %p, PC is %p, etc.\n", atsh->cpsr, atsh->pc);
Or
B) call thread_get_state to the thread port (since you have that right there as argument #2), and get pc (the instruction pointer) or any of the other registers
EDIT
I'm not sure how to make A) work, but the following works (found here) for B) on the 32-bit iOS Simulator. I'm not sure what the arm register equivalent is for __faultvaddr
, so you'd have to figure that out before trying arm.
// types from thread_status.h
x86_exception_state32_t x86_exception_state32;
mach_msg_type_number_t sc = x86_EXCEPTION_STATE32_COUNT;
thread_get_state(thread,
x86_EXCEPTION_STATE32,
(thread_state_t)&x86_exception_state32,
&sc);