2011-01-22 14 views

risposta

10

MODIFICA: la mia risposta originale non verrà stampata da un thread arbitrario. Da allora ho scritto un corretta attuazione nel mio progetto gestione dei crash: https://github.com/kstenerud/KSCrash

In particolare, questi file:

con qualche aiuto da:

Quello che fate è:

  • fare una nuova struttura di contesto della macchina (_STRUCT_MCONTEXT)
  • Fill nel suo stato dello stack mediante thread_get_state()
  • Prendi il contatore di programma (first stack trace entry) e frame pointer (tutto il resto)
  • Passare attraverso il frame stack puntato dal puntatore del frame e memorizzare tutte le istruzioni a indirizzi in un buffer per un uso successivo.

Si noti che è necessario mettere in pausa la discussione prima di eseguire questa operazione oppure è possibile ottenere risultati imprevedibili.

lo stack frame è pieno di strutture che contiene due puntatori:

  • Puntatore al livello successivo sulla pila
  • indirizzo di istruzioni

quindi è necessario tenerne conto quando percorrendo il fotogramma per compilare la traccia dello stack. C'è anche la possibilità di uno stack corrotto, che porta a un puntatore cattivo, che farà crashare il tuo programma. È possibile aggirare questo copiando la memoria usando vm_read_overwrite(), che prima chiede al kernel se ha accesso alla memoria, quindi non si blocca.

Una volta ottenuta la traccia dello stack, è sufficiente richiamare backtrace() su di esso come normale (il gestore di crash deve essere async-safe in modo da implementare il proprio metodo backtrace, ma in casi normali backtrace() va bene) .

+0

Si noti che è necessario sospendere il thread mentre si sta leggendo il suo stack. – Albert

+0

Inoltre, sei sicuro che funzioni? Usa '__builtin_frame_address', che riguarda sempre il ** thread ** corrente. – Albert

+0

Quindi risulta che non funziona (stampa una traccia dello stack, ma non mi sono reso conto che stava stampando dal thread corrente). Ho del nuovo codice che funziona come previsto, ma non è ancora pronto per il rilascio. Pubblicherò un aggiornamento una volta pronto. – Karl

3

Ecco un modo più sicuro per ottenere il callstack da un altro thread: Implementation e some background information. Usa la gestione del segnale e genera un gestore di segnale nel thread di destinazione. Ha anche il vantaggio che è più multipiattaforma della tua soluzione, cioè dovrebbe funzionare ovunque tu abbia <signal.h> e <execinfo.h>.

Per la stampa, è possibile utilizzare backtrace_symbols come si fa nel proprio suggerimento. Ma potresti essere interessato a una versione estesa di questo come implementato here.Utilizza libbfd (da binutils; la versione recente funziona anche principalmente su MacOSX, vedi here per una piccola limitazione che potrebbe non essere rilevante per te) per leggere le informazioni di debug e per aggiungere numero di riga e altre informazioni (ricade anche su dladdr se tutto il resto fallisce, questo è ciò che sta facendo backtrace_symbols).

Problemi correlati