Объект исключения передается в качестве первого аргумента 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 Simulator все аргументы функции передаются в стек, поэтому синтаксис значительно более ужасен.Самое короткое выражение, которое я смог построить, это *(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)