it-swarm-pt.tech

Usando o gdb para converter endereços em linhas

Eu tenho um rastreamento de pilha gerado por um aplicativo despojado que se parece com isso:

 *** Check failure stack trace: ***
    @     0x7f0e442d392d  (unknown)
    @     0x7f0e442d7b1f  (unknown)
    @     0x7f0e442d7067  (unknown)
    @     0x7f0e442d801d  (unknown)
    @     0x7f0e457c55e6  (unknown)
    @     0x7f0e457c5696  (unknown)
    @           0x4e8765  (unknown)
    @           0x4a8b43  (unknown)
    @     0x7f0e43197ced  (unknown)
    @           0x4a6889  (unknown)

E eu tenho uma versão sem strip do executável e de todas as suas bibliotecas (compiladas com informações de depuração). Mas como posso traduzir o endereço em arquivos e números de linha?

Aqui está o que eu tentei:

gdb
set solib-absolute-prefix /path/to/non-stripped/edition/of/root/filesystem/sysroot/
file /path/to/non-stripped/edition/of/root/filesystem/sysroot/usr/bin/my-buggy-app
info line *0x7f0e457c5696

Quando digito o comando file, ele carrega apenas símbolos do arquivo, nem todas as bibliotecas usadas. Existe uma maneira de fazer isso?

O comando "linha de informação" diz:

Nenhuma informação de número de linha disponível para o endereço 0x7f0e442d801d

O que eu assumo é porque o endereço está em uma das bibliotecas compartilhadas, mas como posso saber em qual delas?

32
Allan

Mas como posso traduzir o endereço em arquivos e números de linha?

Para o executável principal (endereços como 0x4e8765) faça isso:

addr2line -e /path/to/non-stripped/.../my-buggy-app \
    0x4a6889 0x4a8b43 0x4e8765

Na verdade, convém subtrair 5 (comprimento usual da instrução CALL) de todos os endereços acima.

Para os endereços nas bibliotecas compartilhadas, você precisa saber o endereço de carregamento da biblioteca.

Se seu aplicativo produziu um arquivo core, então (gdb) info shared lhe dirá onde as bibliotecas foram carregadas.

Se você não obteve um arquivo principal e o aplicativo não imprimiu o mapeamento necessário,

  • você deve corrigir o aplicativo para que imprima essas informações (o rastreamento da pilha é praticamente inútil sem ele) e
  • você ainda pode adivinhar: veja o código no executável em 0x4e8760 - deve ser uma instrução CALL para alguma função. Agora descubra em qual biblioteca essa função está e encontre seu endereço na biblioteca (via nm). Se você tiver sorte, esse endereço está próximo de 0xNc56NN. Agora você pode adivinhar o endereço de carregamento de qualquer biblioteca que esteja em 0x7f0e457NNNNNN. Repita para 0x7f0e457c55e1, e você pode descobrir o endereço de carregamento da biblioteca em 0x7f0e442dNNNN.
31
Employed Russian

De acordo com o OP, o comando no GDB para encontrar a linha de código fonte de um endereço é:

info line *0x10045740

Editar: Substituído "símbolo de informação 0x10045740", que não funcionará sob certas condições (obrigado @ Thomasa88).

32
whitey04