2010-07-25 5 views
70

OK, así que imagina que mi punto de interrupción en objc_exception_throw acaba de activarse. Estoy sentado en el indicador del depurador, y quiero obtener más información sobre el objeto de excepción. ¿Donde lo encuentro?Xcode/LLDB: ¿Cómo obtener información sobre una excepción que acaba de lanzarse?

+0

No está en la consola? – Steve

+2

Recuerde, la excepción acaba de aparecer, su descripción aún no se ha impreso en la consola. –

+0

Echa un vistazo a esta pregunta: http://stackoverflow.com/questions/711650/ –

Respuesta

138

El objeto de excepción se pasa como primer argumento a objc_exception_throw. LLDB ofrece $arg1 .. $argn variables para referirse a los argumentos de la convención de llamada correcta, por lo que es fácil de 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. Consulte "Depuración avanzada y el desinfectante de direcciones" en los videos de la sesión WWDC15 para ver esto en el escenario.

información obsoleta

Si estás en el BGF, la sintaxis para referirse al primer argumento depende de las convenciones de llamada de la arquitectura se está ejecutando en. Si está depurando en un dispositivo iOS real, el puntero al objeto está en el registro r0. Para imprimir o enviar mensajes a ella, utilice la siguiente sintaxis sencilla:

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

En el iPhone Simulator, todos los argumentos de la función se pasan en la pila, por lo que la sintaxis es mucho más horrible. La expresión más corta que pude construir es *(id *)($ebp + 8). Para hacer las cosas menos dolorosa, se sugiere emplear 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 siempre que el punto de interrupción se activa mediante la adición de una lista de comandos a la objc_exception_throw punto de interrupción.

(Tenga en cuenta que en todos los casos que he probado, el objeto de excepción también estaba presente en el eax y edx registros en el momento del punto de interrupción golpeó. No estoy seguro de que siempre va a ser el caso, sin embargo.)

Añadido a partir de comentarios a continuación:

En LLDB, seleccione el marco de pila para objc_exception_throw e introduzca este comando:

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

¿Cómo se podría hacer esto en lldb? Aparece un error "error: la referencia a 'id' es ambigua" – offex

+2

¿Puedes proporcionar la fuente de esta información? me gustaría leer más al respecto –

+0

Las convenciones de llamadas iOS/ARM están documentadas en la [Guía de llamadas a la función ABI de iOS] (http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference .pdf), que se basa en [Procedimiento de llamada estándar para ARM Architecture ABI] (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0042e/index.html) El simulador de iOS usa las [convenciones de llamada de OS X en x86] (http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4). –

3

En el momento de escribir esto, esta publicación es mi principal éxito de Google para: lldb print exception. Por lo tanto, estoy agregando esta respuesta a la cuenta para lldb y x86_64.

Mis intentos de encontrar la excepción con po $eax han fallado 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 fue que tuve que hacer clic primero en el marco objc_exception_throw en mi hilo principal. lldb no comienza en ese marco.

En todos mis ejemplos de búsqueda y siguientes, this blog entry fue el primero en explicar las cosas de una manera que funcionó para mí. Es más moderno, publicado en agosto de 2012.

0

Si tiene una declaración catch, ponga un punto de interrupción allí y podrá inspeccionar el objeto de excepción en ese punto.

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

Usted obtendrá un mensaje en el terminal de la siguiente manera:

Terminación de aplicación debido a excepción no detectada 'NSInvalidArgumentException', razón: '* - [__ NSPlaceholderDictionary initWithObjects: forKeys: Count:]: intento de insertar nil objeto de objetos [0] '

Sin embargo,, probablemente esté buscando una forma de inspeccionarlo sin continuar, ya que perderá su buen rastro de pila al finalizar la aplicación.

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

10

en nuevos simuladores (iOS 8, 64 bits) Xcode 6 im utilizando en el marco de excepción: objc_exception_throw

po $rax 

en 32 bits:

po $eax 

¿Cuál es rax?

Rax es un 64bits registro que sustituye a la antigua eax

¿Cómo encontrar todos los registros?

register read 

Source wikipedia

+0

Hmm ... En Xcode 6.1, obtengo: (lldb) po $ rax error: No se pudo materializar: couldn' t leer el valor de registrar rax Errored out en Execute, could not PrepareToExecuteJITExpression – bradheintz

+0

@bradheintz simulator or device? Intenté esto con 6.0.1 –

+0

¿Puedes indicarme un enlace a tu fuente para eso? ¡Gracias! –

Cuestiones relacionadas