Tenho um binário instalado em meu sistema e gostaria de ver a desmontagem de uma determinada função. De preferência usando objdump
, mas outras soluções também seriam aceitáveis.
Com essas perguntas , aprendi que posso desmontar parte do código se apenas souber os endereços de limite. Com essa resposta , aprendi como transformar meus símbolos de depuração de divisão de volta em um único arquivo.
Mas mesmo operando naquele único arquivo, e até mesmo desmontando todo o código (ou seja, sem endereço de início ou parada, mas -d
parâmetro simples para objdump
), ainda não vejo esse símbolo em lugar nenhum. O que faz sentido na medida em que a função em questão é estática, portanto, não é exportada. No entanto, valgrind
relatará o nome da função, portanto, ele deve ser armazenado em algum lugar.
Olhando os detalhes das seções de depuração, encontro esse nome mencionado na .debug_str
seção, mas não conheço uma ferramenta que possa transformar isso em um intervalo de endereços.
static
, ela pode ser embutida pelo compilador em seus sites de chamada. Isso pode significar que pode não haver nenhuma função para desmontar, por si só . Se você puder localizar símbolos para outras funções, mas não para a função que está procurando, esta é uma forte dica de que a função foi incorporada. Valgrind ainda pode fazer referência à função pré-embutida original porque as informações de depuração do arquivo ELF armazenam de onde cada instrução individual se originou, mesmo se as instruções forem movidas para outro lugar.addr2line
aceitará PCs / IPs destdin
e imprimirá suas linhas de código-fonte correspondentes. Da mesma forma,objdump -l
irá misturar o objdump com linhas de origem; embora para código altamente otimizado com inlining pesado, os resultados de qualquer programa nem sempre são particularmente úteis.Respostas:
Eu sugeriria usar gdb como a abordagem mais simples. Você pode até fazer uma linha, como:
fonte
-ex 'command'
não está dentroman gdb
!? Mas na verdade está listado na documentação do gdb . Também para outros, coisas como/bin/ls
podem ser removidas, então se esse comando exato não exibir nada, tente outro objeto! Também pode especificar arquivo / objeto como argumento de bareword; por exemplo,gdb -batch -ex 'disassemble main' /bin/ls
gdb /bin/ls -batch -ex 'disassemble main'
também funcionacolumn -ts$'\t'
para filtrar a saída GDB, terá os bytes brutos e as colunas de origem bem alinhados. Além disso,-ex 'set disassembly-flavor intel'
antes de outros-ex
s resultarão na sintaxe de montagem da Intel.disassemble fn
usando o método acima. Mas parece que quando há várias funções com o mesmo nome no arquivo binário, apenas uma é desmontada. É possível desmontar todos eles ou devo desmontá-los com base no endereço bruto?gdb
disassemble/rs
para mostrar os bytes originais e brutos tambémCom este formato, fica muito próximo da
objdump -S
saída:main.c
Compilar e desmontar
Desmontagem:
Testado em Ubuntu 16.04, GDB 7.11.1.
objdump + soluções alternativas do awk
Imprima o parágrafo conforme mencionado em: /unix/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the -texto
por exemplo:
dá apenas:
Ao usar
-S
, acho que não há uma maneira à prova de falhas, pois os comentários do código podem conter qualquer sequência possível ... Mas o seguinte funciona quase o tempo todo:adaptado de: Como selecionar linhas entre dois padrões de marcadores que podem ocorrer várias vezes com awk / sed
Respostas da lista de discussão
Há um tópico de 2010 na lista de discussão que diz que não é possível: https://sourceware.org/ml/binutils/2010-04/msg00445.html
Além da
gdb
solução alternativa proposta por Tom, eles também comentam sobre outra (pior) solução alternativa de compilar, com a-ffunction-section
qual coloca uma função por seção e, em seguida, despeja a seção.Nicolas Clifton deu a ele um WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , provavelmente porque a solução alternativa GDB cobre esse caso de uso.
fonte
Desmonte uma única função usando Objdump
Tenho duas soluções:
1. Baseado em linha de comando
Este método funciona perfeitamente e mais simples. Eu uso objdump com o -d bandeira e tubulação -lo através de awk . A saída desmontada parece
Para começar, começo com a descrição da saída do objdump. Uma seção ou função é separada por uma linha vazia. Portanto, alterar o FS (Separador de campo) para nova linha e o RS (Separador de registro) para duas vezes de nova linha permite que você pesquise facilmente a função recomendada, já que é simplesmente encontrar dentro do campo $ 1!
Claro que você pode substituir main por qualquer outra função que gostaria de imprimir.
2. Bash Script
Eu escrevi um pequeno script bash para esse problema. Cole e copie e salve como, por exemplo um arquivo dasm .
Mudar o x-access e invoque-o com, por exemplo:
Isso é muito mais rápido do que invocar gdb com um script. Além da maneira como o objdump não carrega as bibliotecas na memória, é mais seguro!
Vitaly Fadeev programou um preenchimento automático para este script, que é realmente um recurso interessante e acelera a digitação.
O script pode ser encontrado aqui .
fonte
objdump
ougdb
é mais rápido. Para um binário enorme (libxul.so do Firefox)objdump
demora uma eternidade, cancelei depois de uma hora, enquantogdb
leva menos de um minuto.Se você tiver um binutils muito recente (2.32+), isso é muito simples.
Passar
--disassemble=SYMBOL
para objdump desmontará apenas a função especificada. Não há necessidade de passar o endereço inicial e o endereço final.O objdump do LLVM também tem uma opção semelhante (
--disassemble-symbols
).fonte
Para simplificar o uso de awk para analisar a saída de objdump em relação a outras respostas:
fonte
Isso funciona exatamente como a solução gdb (no sentido de que muda os deslocamentos para zero), exceto que não é lento (faz o trabalho em cerca de 5ms no meu PC, enquanto a solução gdb leva cerca de 150ms):
objdump_func:
fonte
awk
faz) era a única função no arquivo de objeto, ou seja, mesmo se a função começar em, digamos0x2d
, o segundo awk a deslocará para0x00
(subtraindo0x2d
do endereço de cada instrução), o que é útil porque o código assembly geralmente faz referências relativas ao início da função e se a função começa em 0, você não precisa fazer as subtrações em sua cabeça. O código awk poderia ser melhor, mas pelo menos ele faz o trabalho e é bastante eficiente.-ffunction-sections
é uma maneira mais fácil de garantir que cada função comece em 0.Conclusão Bash para
./dasm
Nomes de símbolos completos para esta solução (versão D lang):
dasm test
e pressionandoTabTab , você obterá uma lista de todas as funções.dasm test m
e pressionando TabTab todas as funções, começando com m serão mostradas, ou no caso de existir apenas uma função, ela será completada automaticamente.Arquivo
/etc/bash_completion.d/dasm
:fonte