Xcode/LLDB:如何获取有关刚引发的异常的信息?

Kar*_*tey 81 iphone debugging xcode objective-c lldb

好吧,想象一下我的断点objc_exception_throw刚刚触发.我正坐在调试器提示符下,我想获得有关异常对象的更多信息.我在哪里找到它?

Kar*_*tey 159

异常对象作为第一个参数传入objc_exception_throw.LLDB提供$arg1.. $argn变量来引用正确的调用约定中的参数,使得打印异常细节变得简单:

(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]
Run Code Online (Sandbox Code Playgroud)

objc_exception_throw在执行这些命令之前,请确保选择调用堆栈中的帧.请参阅WWDC15会话视频中的"高级调试和地址清理程序",以查看在舞台上执行此操作.

过时的信息

如果您使用的是GDB,则引用第一个参数的语法取决于您运行的体系结构的调用约定.如果您在实际的iOS设备上进行调试,则指向该对象的指针将处于注册状态r0.要打印它或向其发送消息,请使用以下简单语法:

(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]
Run Code Online (Sandbox Code Playgroud)

在iPhone模拟器上,所有函数参数都在堆栈上传递,因此语法更加可怕.我可以构建的最短表达式是*(id *)($ebp + 8).为了减少痛苦,我建议使用一个便利变量:

(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]
Run Code Online (Sandbox Code Playgroud)

您还可以$exception通过向断点添加命令列表来触发断点时自动设置objc_exception_throw.

(请注意,在我测试的所有情况下,异常对象在断点发生时也存在于eaxedx寄存器中.但我不确定是否总是如此.)

从以下评论中添加:

lldb中,选择堆栈帧objc_exception_throw,然后输入以下命令:

(lldb) po *(id *)($esp + 4)
Run Code Online (Sandbox Code Playgroud)

  • 这有效!但是,**直到我选择堆栈帧0**才行.(`objc_exception_throw`). (7认同)
  • 怎么会在lldb中这样做?我收到错误"错误:对'id'的引用含糊不清" (6认同)
  • 在设备上,`po $ eax`在模拟器中对我来说是作为`$ r0`的吊坠. (6认同)
  • 目前,在_LLDB_中的`objc_exception_throw`:`po*(id*)($ esp + 4)`中,以下内容适用于序言. (3认同)
  • 你能提供这些信息的来源吗?我想了解更多相关信息 (2认同)

Joã*_*nes 10

在新模拟器(iOS 8,64bit)xcode 6 im在异常帧中使用: objc_exception_throw

po $rax
Run Code Online (Sandbox Code Playgroud)

在32位:

po $eax
Run Code Online (Sandbox Code Playgroud)

什么是rax?

Rax是一个64位寄存器,取代了旧的eax

如何找到所有寄存器?

register read
Run Code Online (Sandbox Code Playgroud)

来源维基百科


Jef*_*eff 5

在撰写本文时,这篇文章是我在Google上获得的最高评价:lldb print exception。因此,我将此答案添加到lldb和x86_64帐户中。

我尝试使用查找异常,但po $eax失败了error: Couldn't materialize struct: Couldn't read eax (materialize)。早期答案中链接文档中描述的其他尝试也失败了。

关键是我必须首先单击objc_exception_throw主线程中的框架。lldb不在该帧中开始。

在我的所有搜索和以下示例中,此博客条目都是第一种以对我有用的方式来解释问题的文章。它更现代,将于2012年8月发布。