2012-02-09 20 views
6

Ho bisogno di stampare la traccia dello stack da un gestore di segnale dell'applicazione C++ multi-threaded a 64 bit in esecuzione su Linux. Sebbene abbia trovato diversi esempi di codice, nessuno di essi viene compilato. Il mio punto di blocco è ottenere l'indirizzo del chiamante (il punto in cui il segnale è stato generato) dalla struttura ucontext_t. Tutte le informazioni che sono riuscito a trovare, indicano il registro EIP come ucontext.gregs [REG_EIP] o ucontext.eip. Sembra che entrambi siano specifici per x86. Ho bisogno di un codice conforme a 64 bit per CPU Intel e AMD. Qualcuno può aiutare?Stampa traccia dello stack da un gestore di segnale

+0

Non mi sorprenderebbe se non fosse possibile farlo. Hai provato a farlo su 32 bit? Inoltre, quale distro? –

+0

In 64 bit il registro è RIP. Abbastanza sicuro che sarà lì da qualche parte. –

+0

È Red Hat 4.1.2-50. Non può essere un'applicazione a 32 bit poiché lavoriamo con grandi aree di memoria fino a 60+ GB – GMichael

risposta

1

Il solito modo di ottenere una traccia dello stack è quello di prendere l'indirizzo di una variabile locale , quindi aggiungere un po 'numero magico ad esso, a seconda di come il compilatore genera codice (che può dipendere dalle opzioni di ottimizzazione utilizzati per compilare il codice) e tornare da lì. Tutto molto sistema dipendente, ma fattibile se sai cosa stai facendo.

Se questo funziona in un gestore di segnale è un'altra domanda. Io non sono a conoscenza della piattaforma che descrivi, ma molti sistemi installano uno stack separato per i gestori di segnale, senza alcun collegamento allo stack interrotto nella memoria accessibile all'utente.

+0

Vuoi dire che non ci sono collegamenti allo stack interrotto? –

+0

@wood_brian Non nella memoria accessibile all'utente. (Il sistema operativo ovviamente mantiene le informazioni in qualche modo.) –

+0

Hai scritto un'interruzione statica. Pensavo intendessi uno stack interrotto. –

4

c'è una funzione glibc backtrace. La pagina man riporta un esempio della chiamata:

#define SIZE 100 
void myfunc3(void) { 
     int j, nptrs; 

     void *buffer[100]; 
     char **strings; 

     nptrs = backtrace(buffer, SIZE); 
     printf("backtrace() returned %d addresses\n", nptrs); 

     /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 
      would produce similar output to the following: */ 

     strings = backtrace_symbols(buffer, nptrs); 
     if (strings == NULL) { 
      perror("backtrace_symbols"); 
      exit(EXIT_FAILURE); 
     } 

     for (j = 0; j < nptrs; j++) 
      printf("%s\n", strings[j]); 

     free(strings); 
    } 

Vedere la pagina man per più contesto.

è difficile dire se questo è davvero garantito per funzionare da un gestore di segnale, dal momento che Posix elenca solo alcune funzioni rientranti che sono garantite per funzionare. Ricorda: un gestore di segnale può essere chiamato mentre il resto del processo è nel bel mezzo di una chiamata malloc.

Il mio indovinare è che questo di solito funziona, ma potrebbe non riuscire di volta in volta. Per il debug questo può essere abbastanza buono.

Problemi correlati