Xcode / LLDB: как получить информацию об исключении, которое только что было вызвано?


хорошо, так что представьте, что моя точка останова в objc_exception_throw только что вызвал. Я сижу в приглашении отладчика, и я хочу получить дополнительную информацию об объекте исключения. Где я могу его найти?

4 76

4 ответа:

объект исключения передается в качестве первого аргумента objc_exception_throw. Символы отладки обеспечивает $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]

вы также можете установить $exception автоматически всякий раз, когда точка останова запускается путем добавления списка команд в objc_exception_throw точка останова.

(обратите внимание, что во всех случаях я тестировал, объект исключения также присутствовал в eax и edx регистрирует момент останова удар. Хотя я не уверен, что так будет всегда.)

добавлено из комментария ниже:

на lldb выберите кадр стека для objc_exception_throw и затем введите следующую команду:

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

на новых симуляторах (iOS 8, 64bit) Xcode 6 im использует в кадре исключения:objc_exception_throw

po $rax

в 32 бит:

po $eax

что такое rax?

Rax-это 64-битный регистр, который заменяет старый eax

как найти все регистры?

register read

Источник wikipedia

на момент написания этой статьи этот пост является моим лучшим хитом Google для: исключение печати lldb. Таким образом, я добавляю этот ответ к учетной записи lldb и x86_64.

мои попытки найти исключение с помощью po $eax не с error: Couldn't materialize struct: Couldn't read eax (materialize). Другие попытки, описанные в связанных документах из предыдущих ответов, также потерпели неудачу.

ключ был я должен был сначала нажать на objc_exception_throw кадр в моем главном потоке. lldb не начинается в этом рамка.

во всех моих поисках и следующих примерах,эта запись в блоге был первым, чтобы объяснить вещи таким образом, что работал для меня. Это более современный, будучи размещены в августе 2012 года.

Если у вас есть оператор catch, поместите туда точку останова, и вы можете проверить объект исключения в этой точке.

Если у вас нет оператора catch, продолжайте.

вы получите сообщение в вашем терминале, как это:

завершение приложения из-за неперехваченного исключения 'NSInvalidArgumentException', причина: '* - [__NSPlaceholderDictionary initWithObjects:forKeys: count:]: попытка вставить нулевой объект из объекты[0]'

, вы, вероятно, ищете способ проверить его без продолжения, так как вы потеряете свою хорошую трассировку стека, когда приложение будет завершено.

для этого похоже, что ответ Fnord лучше всего, но я не смог заставить его работать в LLDB.