Хорошо, поэтому предположите что моя точка останова в objc_exception_throw
только что инициировал. Я сижу при подсказке отладчика, и я хочу получить еще некоторую информацию об объекте исключения. Где я нахожу его?
Объект исключения передается в качестве первого аргумента 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)