Meu programa funciona assim:
exe -p param1 -i param2 -o param3
Ele travou e gerou um arquivo de despejo principal core.pid
,.
Eu quero analisar o arquivo de despejo principal
gdb ./exe -p param1 -i param2 -o param3 core.pid
Mas o GDB reconhece os parâmetros do arquivo EXE como entrada do GDB.
Como analiso um arquivo de despejo principal nessa situação?
exe
não é um script de shell (para definir algumas variáveis, etc.) como, por exemplo, ofirefox
Linux?Respostas:
Você pode usar o núcleo com o GDB de várias maneiras, mas passar parâmetros que devem ser passados ao executável para o GDB não é a maneira de usar o arquivo principal. Esse também pode ser o motivo pelo qual você recebeu esse erro. Você pode usar o arquivo principal das seguintes maneiras:
gdb <executable> <core-file>
ougdb <executable> -c <core-file>
ouAo usar o arquivo principal, você não precisa passar argumentos. O cenário de falha é mostrado no GDB (verificado com o GDB versão 7.1 no Ubuntu).
Por exemplo:
Se você deseja passar parâmetros para o executável a ser depurado no GDB, use
--args
.Por exemplo:
As páginas de manual serão úteis para ver outras opções do GDB.
fonte
Uso simples do GDB, para depurar arquivos coredump:
Um arquivo coredump para um "processo" é criado como um arquivo "core.pid".
Depois de entrar no prompt do GDB (na execução do comando acima), digite:
Isso fornecerá as informações da pilha, onde é possível analisar a causa da falha / falha. Outro comando, para os mesmos fins, é:
É o mesmo que acima. Por convenção, ele lista todas as informações da pilha (o que leva ao local da falha).
fonte
Basta pular os parâmetros. O GDB não precisa deles:
fonte
objdump
+gdb
exemplo mínimo executávelTL; DR:
objdump -s core
pode ser usado para despejar memória em massaAgora, para a configuração completa do teste educacional:
main.c
Compile e execute para gerar o núcleo:
Resultado:
O GDB indica a linha exata em que ocorreu a falha de segmentação, que é o que a maioria dos usuários deseja durante a depuração:
então:
o que nos aponta diretamente para a linha de buggy 7.
Os argumentos da CLI são armazenados no arquivo principal e não precisam ser passados novamente
Para responder às perguntas específicas dos argumentos da CLI, vemos que, se alterarmos os argumentos cli, por exemplo, com:
então isso se reflete no bactrace anterior sem nenhuma alteração em nossos comandos:
Então, observe como agora
argc=3
. Portanto, isso deve significar que o arquivo principal armazena essas informações. Suponho que apenas armazene como argumentos demain
, assim como armazena os argumentos de quaisquer outras funções.Isso faz sentido se você considerar que o dump principal deve armazenar toda a memória e o estado do registro do programa e, portanto, possui todas as informações necessárias para determinar o valor dos argumentos da função na pilha atual.
Menos óbvia é como inspecionar as variáveis de ambiente: Como obter variáveis de ambiente de um dump principal As variáveis de ambiente também estão presentes na memória para que o objdump contenha essas informações, mas não tenho certeza de como listar todas elas de uma só vez. , um por um da seguinte forma funcionou nos meus testes:
Análise de Binutils
Usando ferramentas binutils como
readelf
eobjdump
, podemos despejar em massa as informações contidas nocore
arquivo, como o estado da memória.A maioria / tudo isso também deve estar visível no GDB, mas essas ferramentas binutils oferecem uma abordagem mais em massa, conveniente para certos casos de uso, enquanto o GDB é mais conveniente para uma exploração mais interativa.
Primeiro:
nos diz que o
core
arquivo é realmente um arquivo ELF :é por isso que somos capazes de inspecioná-lo mais diretamente com as ferramentas binutils comuns.
Uma rápida olhada no padrão ELF mostra que existe realmente um tipo ELF dedicado a ele:
Informações adicionais sobre o formato podem ser encontradas em:
Então:
fornece algumas dicas sobre a estrutura do arquivo. A memória parece estar contida nos cabeçalhos regulares do programa:
e há mais alguns metadados presentes em uma área de anotações, principalmente
prstatus
o PC :objdump
pode facilmente despejar toda a memória com:que contém:
que corresponde exatamente ao valor stdout em nossa execução.
Isso foi testado no Ubuntu 16.04 amd64, GCC 6.4.0 e binutils 2.26.1.
fonte
No tutorial do depurador GDB do RMS :
Verifique se o arquivo é realmente uma
core
imagem - verifique usandofile
.fonte
Uma abordagem ligeiramente diferente permitirá que você pule completamente o GDB. Se tudo o que você deseja é um backtrace, o utilitário específico do Linux 'catchsegv' captura o SIGSEGV e exibe um backtrace.
fonte
Não importa se o executável tem argumentos ou não. Para executar o GDB em qualquer binário com um arquivo principal gerado, a sintaxe está abaixo.
Deixe-me dar o exemplo abaixo para mais compreensão.
A partir da saída acima, você pode adivinhar algo sobre o núcleo, seja um acesso NULL, SIGABORT, etc.
Esses números de 0 a 10 são os quadros de pilha do GDB. Esses quadros de pilha não são do seu binário. Nos quadros 0 a 10 acima, se você suspeitar de algo errado, selecione esse quadro
Agora, para ver mais detalhes sobre isso:
Para investigar melhor o problema, você pode imprimir os valores de variáveis suspeitos aqui neste momento.
fonte
Basta digitar o comando:
Ou
Não há necessidade de fornecer nenhum argumento de linha de comando. O dump de código gerado devido a um exercício anterior.
fonte
Você pode analisar o arquivo de despejo principal usando o comando "gdb".
fonte