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

发布于 2024-09-11 10:44:17 字数 81 浏览 13 评论 0原文

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

OK, so imagine that my breakpoint in objc_exception_throw has just triggered. I'm sitting at the debugger prompt, and I want to get some more information about the exception object. Where do I find it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

碍人泪离人颜 2024-09-18 10:44:17

异常对象作为第一个参数传递给 objc_exception_throw 。 LLDB 提供了 $arg1..$argn 变量来引用正确调用约定中的参数,从而可以轻松打印异常详细信息:

(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]

确保选择 在执行这些命令之前,调用堆栈中的 objc_exception_throw 帧。请参阅 WWDC15 会议视频中的“高级调试和地址清理器”,了解在舞台上执行的操作。

过时的信息

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

(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]

在 iPhone 模拟器上,所有函数参数都在堆栈上传递,因此语法要糟糕得多。我可以构造的最短表达式是 *(id *)($ebp + 8)。为了让事情不那么痛苦,我建议使用一个方便的变量:

(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]

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

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

从下面的评论中添加:

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

(lldb) po *(id *)($esp + 4)

The exception object is passed in as the first argument to objc_exception_throw. LLDB provides $arg1..$argn variables to refer to arguments in the correct calling convention, making it simple to print the exception details:

(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]

Make sure to select the objc_exception_throw frame in the call stack before executing these commands. See the "Advanced Debugging and the Address Sanitizer" in the WWDC15 session videos to see this performed on stage.

Outdated Information

If you're on GDB, the syntax to refer to the first argument depends on the calling conventions of the architecture you're running on. If you're debugging on an actual iOS device, the pointer to the object is in register r0. To print it or send messages to it, use the following simple syntax:

(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]

On the iPhone Simulator, all function arguments are passed on the stack, so the syntax is considerably more horrible. The shortest expression I could construct that gets to it is *(id *)($ebp + 8). To make things less painful, I suggest using a convenience variable:

(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]

You can also set $exception automatically whenever the breakpoint is triggered by adding a command list to the objc_exception_throw breakpoint.

(Note that in all cases I tested, the exception object was also present in the eax and edx registers at the time the breakpoint hit. I'm not sure that'll always be the case, though.)

Added from comment below:

In lldb, select the stack frame for objc_exception_throw and then enter this command:

(lldb) po *(id *)($esp + 4)
月亮坠入山谷 2024-09-18 10:44:17

在新的模拟器(iOS 8,64位)xcode 6上,我在异常框架中使用:objc_exception_throw

po $rax

in 32bit:

po $eax

什么是rax?

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

如何查找所有寄存器?

register read

来源维基百科

on new simulators (iOS 8, 64bit) xcode 6 im using in the exception frame: objc_exception_throw

po $rax

in 32bit:

po $eax

What is rax?

Rax is a 64bits register that replaces the old eax

How to find all the registers?

register read

Source wikipedia

悸初 2024-09-18 10:44:17

在撰写本文时,这篇文章是我在 Google 上的热门搜索:lldb 打印异常。因此,我添加这个答案是为了考虑 lldb 和 x86_64。

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

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

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

At the time of this writing, this post is my top Google hit for: lldb print exception. Thus, I am adding this answer to account for lldb and x86_64.

My attempts to find the exception using po $eax failed with error: Couldn't materialize struct: Couldn't read eax (materialize). Other attempts described in linked documents from earlier answers also failed.

The key was I had to first click on the objc_exception_throw frame in my main thread. lldb does not start off in that frame.

In all my searching and following examples, this blog entry was the first to explain things in a way that worked for me. It is more modern, being posted in Aug 2012.

遗弃M 2024-09-18 10:44:17

如果您有 catch 语句,请在其中放置一个断点,然后您可以在该点检查异常对象。

如果您没有 catch 语句,请继续。

您将在终端中收到如下消息:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“* -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]:尝试从以下位置插入 nil 对象

但是,您可能正在寻找一种方法来检查它而不继续,因为当应用程序终止时您将丢失良好的堆栈跟踪。

为此,听起来 Fnord 的答案是最好的,但我无法让它在 LLDB 中工作。

If you have a catch statement, put a breakpoint in there and you can inspect the exception object at that point.

If you don't have a catch statement, continue.

You'll get a message in your terminal like this:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'

However, you're probably looking for a way to inspect it without continuing since you'll lose your nice stack trace when the application is terminated.

For that it sounds like Fnord's answer is best, but I wasn't able to get it working in LLDB.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文