Você pode obter qualquer programa no Linux para imprimir um rastreio de pilha se ele for segfaults?

18

Se eu executar um programa a partir do shell e segfaults:

$ buggy_program
Segmentation fault

Ele me dirá, no entanto, se existe uma maneira de obter programas para imprimir um backtrace, talvez executando algo como isto:

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

Eu também prefiro não usar strace ou ltrace para esse tipo de informação, pois eles serão impressos de qualquer maneira ...

    
por Neil 02.09.2009 / 21:09

6 respostas

24

Pode haver uma maneira melhor, mas isso automatiza isso.

Coloque o seguinte em ~/backtrace :

backtrace
quit

Coloque isso em um script chamado seg_wrapper.sh em um diretório em seu caminho:

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

O comando ulimit faz com que o núcleo seja descartado. "$@" são os argumentos dados ao script, portanto, seria seu programa e seus argumentos. $? detém o status de saída, 139 parece ser o status de saída padrão da minha máquina para um segfault.

Para gdb , -q significa silêncio (sem mensagem de introdução) e -x indica gdb para executar comandos no arquivo fornecido a ele.

Uso

Então, para usá-lo, você apenas faria:

seg_wrapper.sh ./mycommand and its arguments 

Atualizar

Você também pode escrever um manipulador de sinal que faça isso, veja este link .

    
por 02.09.2009 / 21:52
15

Desculpe entrar aqui 2 anos depois ... tropeçou enquanto procurava por outra coisa. Adicionando isso para completar.

1) Embora eu ache que a resposta aceita é ótima, requer gdb. O método que eu estou familiarizado usa libSegFault.so.

Se você executar seu aplicativo com

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

Você receberia um relatório com backtrace, libs carregadas, etc.

2) Também está disponível um script de wrapper catchsegv que tentaria usar addr2line para converter endereços em nome de arquivo + número de linha.

Estas são soluções muito mais leves que os arquivos principais ou o gdb (bom para sistemas embarcados, por exemplo)

    
por 22.01.2012 / 21:49
6

Você precisa do GDB de amigos de todos

gdb <program> [core file]

Depois de carregar seu corefile, o comando 'backtrace' (pode ser abreviado para bt) fornecerá a pilha de chamadas atual. Se você rodar seu programa dentro do gdb, você pode definir pontos de interrupção arbitrários e examinar o conteúdo da memória, etc.

    
por 02.09.2009 / 21:15
5

catchsegv

Foi mencionado em outra resposta (mas não focado de maneira alguma). É uma ferramenta útil junto com o projeto glibc. Ele irá fornecer um backtrace (e outras informações de depuração úteis) somente se um programa realmente segfault.

Um bom artigo existe aqui .

Você pode incluí-lo em seus próprios scripts como achar melhor.

    
por 22.09.2016 / 08:14
3

O Ubuntu (como um projeto) usa o Apport para fazer isso. Você pode ver como eles fizeram isso.

link

    
por 22.02.2011 / 23:34
2

Aqui está uma variante ligeiramente modificada do script de Kyle Brandt. Ele é aprimorado das seguintes maneiras:

  • não requer interação manual se o rastreio da pilha for longo
  • alguns coredumps são salvos com o nome padrão core., respeite essa configuração
  • não requer um arquivo de comando explícito voando pelo gdb (ele criará um arquivo temporário)
  • aguarde trabalhos em segundo plano

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
    
por 13.01.2016 / 17:37