问题;
I used to get exception details from apps running in the simulator like so:
po $eax
Ever since I upgraded to XCode 4.6 it's stopped working; I always get this error:
error: warning: couldn't get object pointer (substituting NULL):
Couldn't find '_cmd' with appropriate type in scope
Couldn't materialize struct: Couldn't read eax (materialize)
Errored out in Execute, couldn't PrepareToExecuteJITExpression
I've seen people recommend using this:
register read eax
But that gives me this error:
eax = error: unavailable
How do I get exception details in XCode 4.6?
解答一:
You're hitting a bug in the lldb in Xcode 4.5.x with its volatile register list on i386.
Registers fall in to two classes: volatile and non-volatile (or callee-saved). When a function calls another function, all of the "volatile" registers may have their contents overwritten. All non-volatile/callee saved registers will be preserved by the called function (callee function) before they are reused, and their previous values restored before returning.
Sometimes the debug info will say that a variable is stored in a volatile register. If that function is in the middle of your stack and you want to examine that variable, the debugger cannot reconstruct that register's value -- it is lost. gdb would simply copy the volatile register's value up to the middle of the stack and print the variable with a (potentially) bogus value, leading developers to be very confused.
lldb knows the difference between volatile and non-volatile registers and won't let volatile registers be reused in the middle of a stack like that -- they'll say that the register value is unavailable instead.
Unfortunately in this case, you're seeing lldb claim it cannot reconstruct variables that are available. They are mis-categorized as volatile when they should be non-volatile. Without doing a lot of assembly-language inspection, this is not going to be easy for you to work around. The only solution here is to resume execution until you're back in that function again (i.e. it is now frame 0) and then all of the register values will be correctly marked as available.
This should be fixed in the next Xcode release.
解答2:
If you break on objc_exception_throw
the stack frame selected is the last frame in your code, before calling any libraries that might have thrown the exception. At that point lldb doesn't let you access some of the registers (see this answer for a possible explanation.
To get the exception details you have to select the objc_exception_throw
stack frame:
Now po $eax
(po $rax
if you are running on OS X 64 bit, po $r0
on iPhone/iPad, po $x0
on arm64) should give you the exception details.