2010-07-25 10 views
70

OK, quindi immagina che il mio punto di interruzione in objc_exception_throw sia appena stato attivato. Sono seduto al prompt del debugger e desidero ottenere ulteriori informazioni sull'oggetto exception. Dove lo trovo?Xcode/LLDB: come ottenere informazioni su un'eccezione appena lanciata?

+0

Non è nella console? – Steve

+2

Ricorda, l'eccezione è stata appena sollevata, la sua descrizione non è stata ancora stampata sulla console. –

+0

Dai un'occhiata a questa domanda: http://stackoverflow.com/questions/711650/ –

risposta

138

L'oggetto eccezione viene passato come primo argomento a objc_exception_throw. LLDB fornisce $arg1 .. $argn variabili per fare riferimento ad argomenti nella convenzione di chiamata corretta, rendendo semplice per stampare i dettagli di eccezione:

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

assicurarsi di selezionare il frame objc_exception_throw nello stack di chiamate prima di eseguire questi comandi. Vedi "Advanced Debugging and the Address Sanitizer" nei video della sessione WWDC15 per vederlo eseguito sul palco.

informazioni obsolete

Se siete in GDB, la sintassi per fare riferimento al primo argomento dipende dalle convenzioni di chiamata dell'architettura si sta eseguendo su. Se esegui il debug su un dispositivo iOS reale, il puntatore all'oggetto si trova nel registro r0. Per stampare o inviare messaggi ad esso, utilizzare la seguente sintassi semplice:

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

Su iPhone Simulator, tutti gli argomenti della funzione sono passati sullo stack, per cui la sintassi è molto più orribile. L'espressione più corta che potrei costruire per arrivarci è *(id *)($ebp + 8). Per rendere le cose meno doloroso, io suggerisco di usare una variabile convenienza:

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

è anche possibile impostare $exception automaticamente ogni volta che il punto di interruzione viene attivato con l'aggiunta di un elenco di comando al objc_exception_throw punto di interruzione.

(Si noti che in tutti i casi che ho provato, l'oggetto eccezione era presente anche nelle eax e edx registri al momento il punto di interruzione ha colpito. Non sono sicuro che sarà sempre il caso, però.)

Aggiunto da commento qui sotto:

In lldb, selezionare lo stack frame per objc_exception_throw e quindi immettere questo comando:

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

Come si farebbe questo in lldb? Ho un errore "Errore: il riferimento a" id "è ambiguo" – offex

+2

puoi fornire la fonte di queste informazioni? Mi piacerebbe saperne di più a riguardo –

+0

Le convenzioni di chiamata iOS/ARM sono documentate nella [Guida alle chiamate della funzione ABI iOS] (http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference .pdf), che si basa su [Procedure Call Standard per ARM Architecture ABI] (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0042e/index.html). IOS Simulator utilizza le [convenzioni di chiamata OS X su 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

Al momento della stesura di questo post, questo è il mio migliore hit di Google per: lldb print exception. Quindi, sto aggiungendo questa risposta per conto di lldb e x86_64.

I miei tentativi di trovare l'eccezione utilizzando po $eax fallito con error: Couldn't materialize struct: Couldn't read eax (materialize). Anche altri tentativi descritti in documenti collegati da precedenti risposte fallirono.

La chiave era che dovevo prima fare clic sul frame objc_exception_throw nella mia discussione principale. lldb non si avvia in quella cornice.

In tutti i miei esempi di ricerca e seguenti, this blog entry è stato il primo a spiegare le cose in un modo che ha funzionato per me. È più moderno, pubblicato nell'agosto 2012.

0

Se si dispone di un'istruzione catch, inserire un punto di interruzione e controllare l'oggetto eccezione in quel punto.

Se non si dispone di un estratto conto, continuare.

Otterrete un messaggio nel vostro terminale come questo:

terminazione app a causa di eccezione non identificata 'NSInvalidArgumentException', la ragione: '* - [__ NSPlaceholderDictionary initWithObjects: forKeys: COUNT:]: tentare di inserire nil object from objects [0] '

Tuttavia,, probabilmente stai cercando un modo per ispezionarlo senza continuare poiché perderai la tua bella traccia di stack quando l'applicazione viene terminata.

Per questo sembra che la risposta di Fnord sia la migliore, ma non sono riuscito a farlo funzionare in LLDB.

10

nuovi simulatori (IOS 8, 64 bit) xcode 6 im utilizzando nel telaio eccezione: objc_exception_throw

po $rax 

a 32 bit:

po $eax 

cosa è rax?

Rax è un 64bit registrare che sostituisce il vecchio eax

come trovare tutti i registri?

register read 

Source wikipedia

+0

Hmm ... In Xcode 6.1, sto ricevendo: (lldb) po $ rax errore: Impossibile materializzarsi: couldn' t leggere il valore di registro rax Errored out in Execute, could not PreparareToExecuteJITExpression – bradheintz

+0

simulatore o dispositivo @bradheintz? ho provato questo con 6.0.1 –

+0

Puoi indicare fornire un link alla tua fonte per questo? Grazie! –

Problemi correlati