eax = error: unavailable

问题;

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:

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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值