Traduções: English - Português (Brasil) - Русский
Contents
Como obter um backtrace significativo
Esta página tentará explicar como obter um backtrace de depuração significativo de uma falha reproduzível no programa. Neste exemplo, instalaremos o pacote com símbolos de depuração para "hello" ou, se não estiver disponível, reconstrua e instale o pacote "hello" para manter as informações de depuração.
Para referência, um "#" no início de uma linha significa que o que vem a seguir é um comando que deve ser executado como root (ou sudo). Um "$" no início significa que o que vem a seguir é um comando que deve ser executado como seu(sua) usuário(a) normal. Um "(gdb)" no início significa que você deve digitar o restante da linha de comando no prompt do gdb (GNU Debugger).
# apt install gdb
Instalando os símbolos de depuração
Verifique se você tem o pacote AutomaticDebugPackages listado em seu SourcesList:
deb http://deb.debian.org/debian-debug/ $RELEASE-debug main # for security updates deb http://deb.debian.org/debian-debug/ $RELEASE-proposed-updates-debug main
Então, dependendo da sua versão, pode se parecer com isso:
deb http://deb.debian.org/debian-debug/ buster-debug main # for security updates deb http://deb.debian.org/debian-debug/ buster-proposed-updates-debug main
Outras possibilidades são:
deb http://deb.debian.org/debian-debug/ testing-debug main deb http://deb.debian.org/debian-debug/ unstable-debug main deb http://deb.debian.org/debian-debug/ experimental-debug main
Se você estiver usando o Debian buster ou posterior, instale debian-goodies e execute o script find-dbgsym-packages para descobrir quais pacotes do dbgsym instalar:
$ find-dbgsym-packages /usr/bin/hello hello-dbgsym
Caso contrário, para ver se o pacote que você está tentando depurar inclui um pacote -dbgsym ou -dbg (por exemplo, para o pacote fonte hello, um pacote ello-dbgsym ou hello-dbg existe), procure-o no seu gerenciador de pacotes. Na linha de comando, você pode usar o seguinte comando:
$ apt-cache search hello dbg p hello-dbgsym - Debug symbols for hello
Se esse também não tiver seu pacote de depuração, você pode tentar reconstruir o pacote, conforme explicado na próxima seção.
Se um pacote apropriado for encontrado, você poderá instalar o pacote de depuração apropriado e pular o processo de reconstrução nas instruções a seguir e seguir diretamente para a execução do gdb.
# apt install hello-dbgsym
Reconstruindo o pacote que você está depurando
Você pode pular esta seção se conseguir instalar os pacotes de símbolos de depuração necessários na seção anterior.
Instale os pacotes básicos de desenvolvimento e as dependências de compilação para o pacote que queremos reconstruir. Observe que você pode pular a parte de reconstrução e ir direto para o gdb, mas é improvável que você obtenha um backtrace útil (se a linha build-dep falhar, verifique se você possui linhas deb-src em apt sources).
# apt install build-essential fakeroot gdb # apt build-dep hello
- Faça o download e reconstrua nosso pacote da fonte, mantendo os símbolos de depuração:
$ DEB_BUILD_OPTIONS="nostrip noopt" apt -b source hello
- Instale nossos pacotes recém-construídos. Pode haver vários pacotes .deb gerados, portanto, instale apenas os que você deseja. Neste exemplo, o .deb gerado foi chamado hello_2.1.1-4_amd64.deb:
# apt install ./hello_2.1.1-4_amd64.deb
- Você pode garantir que os binários instalados no seu .deb tenham símbolos de depuração com o comando "file" ou com o próprio gdb (veja abaixo):
$ file /usr/bin/hello # a saída deve conter "not stripped"
Executando o gdb
Modo em lote
Para incluir um backtrace em um relatório de bug, você pode executar este comando e tentar reproduzir sua falha:
$ gdb -batch -n -ex 'set pagination off' -ex run -ex bt -ex 'bt full' -ex 'thread apply all bt full' --args hello
Interativamente
Use este método se precisar executar interativamente o gdb.
Execute seu programa como apresentado a seguir, substituindo "[--args]" com quaisquer argumentos com os quais você deseje executar programa:
$ gdb hello ... gdb loads ... (gdb) set pagination 0 (gdb) run [--args] ... hello loads...
- Em seguida, tente reproduzir sua falha. Se você tiver sorte, ocorrerá uma falha e você voltará ao prompt do gdb.
- Se você não tiver tanta sorte em fazer o programa travar, mas somente congelar, ainda poderá receber o prompt do gdb pressionando CTRL-C no terminal que está executando o gdb.
Neste ponto, você pode executar:
(gdb) bt
- Você obterá muita saída, que poderá copiar e colar em um e-mail de acompanhamento de relatório de bug ou em outra ferramenta de relatório de bug.
Quando você tiver terminado com o gdb, você pode simplesmente executar:
(gdb) quit
Se o problema parece estar em uma biblioteca importante, como libc6, xlibs ou libgtk2.0-0, instale o pacote -dbg apropriado (por exemplo, libc6-dbg no caso da libc6) e execute o programa problemático novamente no gdb.
Frequentemente, você verá um backtrace em que uma ou mais das principais linhas estão em malloc() ou g_malloc(). Quando isso acontece, é provável que seu backtrace não seja muito útil. A maneira mais fácil de encontrar algumas informações úteis é definir a variável de ambiente MALLOC_CHECK_ como um valor de 2. Você pode fazer isso enquanto executa o gdb fazendo isso:
$ MALLOC_CHECK_=2 gdb hello
Comandos avançados do gdb
Se o programa para o qual você quer obter o backtrace trabalha em multithread, convém obter um backtrace para todos as threads:
(gdb) thread apply all bt
Outra coisa que é bastante útil relatar é quais variáveis foram definidas localmente em cada ponto da pilha:
(gdb) bt full
Convém relatar a saída da combinação das opções anteriores:
(gdb) thread apply all bt full
E se essa é uma saída muito irrelevante, convém manter apenas algumas chamadas, como as 10 principais:
(gdb) thread apply all bt full 10
Se você está com um backtrace grande, pode registrar a saída gdb em um arquivo (o padrão é gdb.txt):
(gdb) set logging on
Para verificar se você possui símbolos de depuração no seu executável:
$ gdb (gdb) symbol-file /usr/bin/hello # Você deveria ver algo como isso: Reading symbols from /usr/bin/hello ... done Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) # Você _não_ deveria ver Reading symbols from /usr/bin/hello... (no debugging symbols found)...done
Depurando erros no X
Se um programa GTK recebeu um erro X; ou seja, você vê uma mensagem na forma:
The program 'preview1' received an X Window System error.
Então você pode tentar executar o programa com --sync e interromper a função gdk_x_error para obter um retorno, assim:
(gdb) break gdk_x_error (gdb) run --sync
Despejo do núcleo
Para um programa que travou, um arquivo de despejo do núcleo pode ser usado para avaliar a situação post-mortem do estado do programa no momento da travamento. Você pode verificar a limitação de recursos, incluindo o tamanho máximo dos arquivos do núcleo criados, digitando "ulimit" no prompt do shell. Você pode definir o tamanho do arquivo do núcleo como ilimitado usando "ulimit -c unlimited" e/ou com outros arquivos de configuração (/etc/security/limits.conf, /usr/lib/sysctl.d/50-coredump.conf e arquivos de serviço do systemd).
A local do arquivo de despejo principal é especificado por /proc/sys/kernel/core_pattern. Se o pacote systemd-coredump estiver instalado no systemd, pode parecer com:
|/lib/systemd/systemd-coredump ...
Em seguida, o arquivo de despejo do núcleo compactado pelo lz4 é gerado em /var/lib/systemd/coredump após um travamento. Você pode obter informações sobre esse arquivo de núcleo compactado com:
$ coredumpctl info -1
Você pode usar esse arquivo de núcleo compactado com gdb da seguinte maneira:
$ coredumpctl gdb -1
Veja mais:
systemd-coredump(1) e coredumpctl(1)
gdb(1) e gcore(1)
core(5), coredump.conf(5), sysctl(8) e sysctl.d(5)
https://www.freedesktop.org/software/systemd/man/systemd-coredump.html (em inglês)
core-dump-handler é um pacote virtual fornecido por corekeeper, minicoredumper, systemd-coredump
Outros links úteis
Depurando o servidor Xorg (em inglês)
Página de backtrace do Ubuntu (em inglês)
Depurando o GNOME Shell (em inglês)
Interpretando a saída do kernel no travamento de um processo (em inglês)