Estou depurando usando core dumps, e observe que o gdb precisa que você forneça o executável e o core dump. Por que é isso? Se o core dump contiver toda a memória que o processo usa, o executável não está contido no core dump? Talvez não haja garantia de que todo o exe seja carregado na memória (os executáveis individuais geralmente não são tão grandes assim) ou talvez o dump do núcleo não contenha toda a memória relevante, afinal? É para os símbolos (talvez eles não sejam carregados na memória normalmente)?
11
Respostas:
O core dump é apenas o dump da pegada de memória de seus programas; se você souber onde estava tudo, poderá usá-lo.
Você usa o executável porque explica onde (em termos de endereços lógicos) as coisas estão localizadas na memória, ou seja, o arquivo principal.
Se você usar um comando,
objdump
ele fará o dump dos metadados sobre o objeto executável que você está investigando. Usando um objeto executável chamado a.out como exemplo.objdump -h a.out
despeja apenas as informações do cabeçalho, você verá seções nomeadas, por exemplo. .data ou .bss ou .text (há muito mais). Eles informam ao carregador do kernel onde, no objeto, várias seções podem ser encontradas e onde, no espaço de endereço do processo, a seção deve ser carregada e, para algumas seções (por exemplo, .data .text), o que deve ser carregado. (a seção .bss não contém nenhum dado no arquivo, mas se refere à quantidade de memória a ser reservada no processo para dados não inicializados, é preenchida com zeros).O layout do arquivo de objeto executável está em conformidade com um ELF padrão.
objdump -x a.out
- despeja tudoSe o objeto executável ainda contiver suas tabelas de símbolos (ele não foi retirado -
man strip
e você costumava-g
gerar geração de depuração paragcc
assumir a compilação da fonte de CA), poderá examinar o conteúdo principal por nomes de símbolos, por exemplo, se você tivesse uma variável / buffer chamado inputLine no seu código-fonte, você pode usar esse nomegdb
para examinar seu conteúdo. isto égdb
, saberia o deslocamento desde o início do segmento de dados inicializado de seus programas onde o inputLine inicia e o tamanho dessa variável.Leitura adicional Artigo 1 , Artigo 2 e para a especificação Executable and Linking Format (ELF) .
Atualizar após o comentário @mirabilos abaixo.
Mas se usar a tabela de símbolos como em
Produz
e depois não usar a tabela de símbolos e examinar o endereço diretamente em,
Produz
Examinei a memória diretamente sem usar a tabela de símbolos no segundo comando.
Vejo também que a resposta de @ user580082 adiciona mais explicações e fará uma votação positiva.
fonte
O arquivo principal é uma captura instantânea da imagem da pilha, mapeamentos de memória e registros no momento do encerramento do processo. O conteúdo pode ser manipulado conforme fornecido na página principal do manual . Por padrão, mapeamentos privados, mapeamentos compartilhados e informações de cabeçalho ELF são despejados no arquivo principal.
Chegando à sua pergunta , o motivo pelo qual o gdb requer executável é que ele não simula a execução. Ao ler e interpretar as instruções binárias, como o valgrind, ele se torna o pai do processo, a fim de controlar o comportamento do processo durante a execução. Tempo. Ele usa o arquivo principal para determinar os mapeamentos de memória e o estado do processo do processador durante a falha.
No Linux, os processos pai podem obter informações adicionais sobre seus filhos, em particular a capacidade de rastreá-los, permitindo que o depurador acesse informações de baixo nível do processo, como ler / gravar sua memória, registros, alterar os mapeamentos de sinais, interromper sua execução etc.
Você entenderá o requisito do executável, apesar de ter o arquivo principal mais uma vez depois de ler como funciona qualquer depurador.
fonte
(além de outras boas respostas)
Nos modernos sistemas Linux (e em muitos sistemas Unix), as informações de depuração (incluindo metadados sobre os tipos de símbolos, localização do código-fonte, tipo de variáveis, etc etc ....) estão no formato DWARF e ficam dentro do executável do ELF ( ou bibliotecas compartilhadas ELF) quando compiladas com alguma
-g
opção. Eu recomendo compilar programas para serem depurados-g3 -O0
e, talvez,-fno-inline
se estiver usando um GCC recente ; no entanto, com o GCC você pode até compilar informações de otimização e depuração, por exemplo, com-O2 -g1
, embora as informações de depuração possam, nesse caso, ser um pouco "imprecisas" (isso pode ajudar um pouco a capturar alguns Heisenbugs impertinentes ).É bastante sensato evitar colocar essas informações nos arquivos principais , porque você pode ter muitos arquivos principais diferentes (imagine um software amplamente usado com muitos usuários fazendo relatórios de erros, a maioria deles com um
core
despejo) para o mesmo executável. Os arquivos core (5) também são despejados pelo kernel, que não deve se importar com a existência de seções DWARF nos executáveis elf (5) (porque essas seções não são mapeadas no espaço de endereço virtual do processo com falha que despejou o núcleo em algum sinal ( 7) ). Existe até a possibilidade de colocar as informações de depuração em arquivos separados (fora do executável).BTW, GDB pode ser dolorosamente usado para descarregar um core debug para executáveis sem qualquer informação de depuração. Mas você praticamente depura no nível do código da máquina (não no nível simbólico fornecido pelas linguagens de programação e seus compiladores).
fonte