Xcode / LLDB: ¿Cómo obtener información sobre una excepción que se acaba de lanzar?


OK, así que imagina que mi punto de interrupción en objc_exception_throw acaba de dispararse. Estoy sentado en el indicador del depurador, y quiero obtener más información sobre el objeto de excepción. ¿Dónde lo encuentro?

Author: Karoy Lorentey, 2010-07-25

4 answers

El objeto exception se pasa como primer argumento a objc_exception_throw. LLDB proporciona $arg1..$argn variables para referirse a los argumentos en la convención de llamada correcta, por lo que es fácil imprimir los detalles de la excepción:

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

Asegúrese de seleccionar el marco objc_exception_throw en la pila de llamadas antes de ejecutar estos comandos. Vea el "Depuración avanzada y el Desinfectante de direcciones" en los videos de la sesión WWDC15 para ver esto realizado en el escenario.

Anticuado Información

Si está en GDB, la sintaxis para referirse al primer argumento depende de las convenciones de llamada de la arquitectura en la que se está ejecutando. Si está depurando en un dispositivo iOS real, el puntero al objeto está en register r0. Para imprimirlo o enviarle mensajes, utilice la siguiente sintaxis simple:

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

En el Simulador de iPhone, todos los argumentos de función se pasan a la pila, por lo que la sintaxis es considerablemente más horrible. La expresión más corta que pude la construcción que llega a ella es *(id *)($ebp + 8). Para hacer las cosas menos dolorosas, sugiero usar una variable de conveniencia:

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

También puede establecer $exception automáticamente cada vez que se active el punto de interrupción agregando una lista de comandos al punto de interrupción objc_exception_throw.

(Tenga en cuenta que en todos los casos que probé, el objeto de excepción también estaba presente en los registros eax y edx en el momento en que se alcanzó el punto de interrupción. Aunque no estoy seguro de que siempre sea así.)

Añadido desde el comentario abajo:

En lldb , seleccione el marco de pila para objc_exception_throw y luego ingrese este comando:

(lldb) po *(id *)($esp + 4)
 149
Author: Karoy Lorentey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-12 16:18:10

En nuevos simuladores (iOS 8, 64bit) xcode 6 im usando en el marco de excepción: objc_exception_throw

po $rax

En 32bit:

po $eax

¿Qué es rax?

Rax es un registro de 64 bits que reemplaza al antiguo eax

Cómo encontrar todos los registros?

register read

Fuente wikipedia

 10
Author: João Nunes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-23 07:35:58

En el momento de escribir esto, este post es mi principal éxito de Google para: excepción de impresión lldb. Por lo tanto, estoy agregando esta respuesta para dar cuenta de lldb y x86_64.

Mis intentos de encontrar la excepción usando po $eax fallaron con error: Couldn't materialize struct: Couldn't read eax (materialize). Otros intentos descritos en documentos vinculados de respuestas anteriores también fallaron.

La clave era que primero tenía que hacer clic en el marco objc_exception_throw en mi hilo principal. lldb no comienza en ese marco.

En toda mi búsqueda y seguimiento ejemplos, esta entrada del blog fue la primera en explicar las cosas de una manera que funcionó para mí. Es más moderno, siendo publicado en agosto de 2012.

 4
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-10 19:37:20

Si tiene una instrucción catch, coloque un punto de interrupción allí y puede inspeccionar el objeto de excepción en ese punto.

Si no tiene una declaración de captura, continúe.

Recibirá un mensaje en su terminal como este:

Terminación de la aplicación debido a la excepción no capturada 'NSInvalidArgumentException', razón: '* -[__NSPlaceholderDictionary initWithObjects:forKeys: count:]: intenta insertar un objeto nil desde objetos [0] '

Sin embargo , usted es probablemente buscando una manera de inspeccionarlo sin continuar, ya que perderá su buen seguimiento de pila cuando se termine la aplicación.

Para eso parece que la respuesta de Fnord es la mejor, pero no pude hacerlo funcionar en LLDB.

 0
Author: funroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-15 11:20:47