Riesci a ottenere qualsiasi programma in Linux per stampare una traccia dello stack se segfaults?


20

Se eseguo un programma dalla shell e segfaults:

$ buggy_program
Segmentation fault

Mi dirà, tuttavia, c'è un modo per ottenere programmi per stampare un backtrace, forse eseguendo qualcosa del genere:

$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)

Preferirei anche non usare strace o ltrace per quel tipo di informazioni, in quanto stamperebbero in entrambi i modi ...

Risposte:


25

Potrebbe esserci un modo migliore, ma questo tipo di automatizza.

Inserisci quanto segue ~/backtrace:

backtrace
quit

Inseriscilo in uno script chiamato seg_wrapper.shin una directory nel tuo percorso:

#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
    gdb -q $1 core -x ~/backtrace
fi

Il ulimitcomando rende così il dump del core. "$@"sono gli argomenti forniti allo script, quindi sarebbe il tuo programma e i suoi argomenti. $?contiene lo stato di uscita, 139 sembra essere lo stato di uscita predefinito per la mia macchina per un segfault.

Per gdb, -qmezzi tranquilla (nessun messaggio intro), e -xdice gdbdi eseguire comandi nel file dato ad essa.

uso

Quindi per usarlo dovresti solo:

seg_wrapper.sh ./mycommand and its arguments 

Aggiornare

Puoi anche scrivere un gestore di segnale che faccia questo, vedi questo link .


2
Il tuo link alla soluzione del gestore del segnale è morto - ecco perché le risposte non dovrebbero essere collegate ad altre risorse ...
josch

1
probabilmente vuoi dire "-x dice a gdb di eseguire" invece di "-x dice a gdb di uscire"
josch

19

Mi dispiace venire qui 2 anni dopo ... inciampato mentre cercavo qualcos'altro. Aggiungendo questo per completezza.

1) Mentre penso che la risposta accettata sia ottima, richiede gdb. Il metodo con cui ho familiarità utilizza libSegFault.so.

Se esegui la tua app con

LD_PRELOAD = ... path-to ... / libSegFault.so myapp

Otterresti un rapporto con backtrace, librerie caricate, ecc

2) È catchsegvdisponibile anche uno script wrapper che tenta di utilizzare addr2lineper tradurre gli indirizzi in nome file + numero riga.

Queste sono soluzioni molto più leggere rispetto ai file core o gdb (buono per i sistemi embedded per esempio)


In realtà, LD_PRELOAD=libSegFault.sova bene se si trova nel percorso dl.
Fernando Silveira,

1
@FernandoSilveira ok. Scrivere la risposta in questo modo suggerisce al lettore che dovrebbero controllare qual è quel percorso.
nhed

6

Hai bisogno dell'amico GDB di tutti

gdb <program> [core file]

Dopo aver caricato il tuo corefile, il comando 'backtrace' (può essere abbreviato in bt) ti darà lo stack di chiamate corrente. Se esegui il tuo programma da gdb, puoi impostare punti di interruzione arbitrari ed esaminare il contenuto della memoria, ecc.


C'è un modo per ottenerlo solo per stampare il backtrace ed uscire?
Neil,

5

catchsegv

È stato menzionato in un'altra risposta (ma in nessun modo focalizzato su). È uno strumento utile in bundle con il progetto glibc. Fornirà un backtrace (e altre utili informazioni di debug) solo se un programma effettivamente segfault.

Una buona scrittura esiste qui .

Puoi includerlo nei tuoi script come ritieni opportuno.



2

Ecco una variante leggermente modificata della sceneggiatura di Kyle Brandt. È migliorato nei seguenti modi:

  • non richiede l'interazione manuale se la traccia dello stack è lunga
  • alcuni coredump vengono salvati con il nome del modello principale. Rispettare questa impostazione
  • non richiede un file di comando esplicito che vola in giro per gdb (ne creerà uno temporaneo)
  • attendere i lavori in background

script:

#!/bin/bash
gdbcommandfile=$(tempfile)
usepid=$(cat /proc/sys/kernel/core_uses_pid)
printf "set pagination off\nbacktrace\nquit\n" > $gdbcommandfile
ulimit -c unlimited
"$@"&
pid=$!
wait $!
if [[ $? -eq 139 ]]; then
    if [[ $usepid == 1 ]]; then 
        gdb -q $1 core.$pid -x $gdbcommandfile
    else
        gdb -q $1 core -x $gdbcommandfile
    fi
fi
rm $gdbcommandfile

1
Per una catena di comandi così semplici, vorrei semplicemente usare -exinvece. gdb ... -ex 'set pagination off' -ex backtrace -ex quit
Josh Stone,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.