elf debug-symbols disassembly objdump dwarf

elf - ¿Cómo desensamblar una sola función usando objdump?



debug-symbols disassembly (6)

Desarmar una sola función usando Objdump

Tengo dos soluciones:

1. Basado en línea de comandos

Este método funciona perfectamente y también es muy corto. Yo uso objdump con la opción -d y lo canalizo a awk . La salida desensamblada se ve como

000000000000068a <main>: 68a: 55 push %rbp 68b: 48 89 e5 mov %rsp,%rbp 68e: 48 83 ec 20 sub $0x20,%rsp

Una sección o función está separada por una línea vacía. Por lo tanto, cambiar el FS (Seperador de campo) a la nueva línea y el RS (Separador de registros) a dos líneas nuevas le permite buscar fácilmente su función recomendada, ¡ya que es simplemente para encontrar dentro del campo de $ 1!

objdump -d name_of_your_obj_file | awk -F"/n" -v RS="/n/n" ''$1 ~ /main/''

Por supuesto, puede cambiar la función principal a cualquier función que desee.

2. Bash Script

He escrito un pequeño script bash para este tema. Simplemente cópielo y guárdelo como, por ejemplo, un archivo dasm .

#!/bin/bash # Author: abu # Description: puts disassembled objectfile to std-out if [ $# = 2 ]; then sstrg="^[[:xdigit:]]{2,}+.*<$2>:$" objdump -d $1 | awk -v fun=$sstrg -F"/n" -v RS="/n/n" ''$1 ~ /''"$sstrg"''/'' elif [ $# = 1 ]; then objdump -d $1 | awk -F"/n" -v RS="/n/n" ''{ print $1 }'' else echo "You have to add argument(s)" echo "Usage: "$0 " arg1 arg2" echo "Description: print disassembled label to std-out" echo " arg1: name of object file" echo " arg2: name of function to be disassembled" echo " "$0 " arg1 ... print labels and their rel. addresses" fi

Cambie el acceso x e invoqúelo con por ejemplo:

chmod +x dasm ./dasm test main

Esto es mucho más rápido que invocar gdb con un script. Además de usar objdump, ¡las bibliotecas no se cargarán en la memoria y, por lo tanto, serán más seguras!

Tengo un binario instalado en mi sistema y me gustaría ver el desmontaje de una función determinada. Preferiblemente usando objdump , pero otras soluciones también serían aceptables.

De estas preguntas aprendí que podría desmontar parte del código si solo conozco las direcciones de los límites. A partir de esta respuesta , aprendí cómo convertir mis símbolos de depuración divididos en un único archivo.

Pero incluso operando en ese único archivo, e incluso desensamblando todo el código (es decir, sin inicio o detención de la dirección, sino con un parámetro -d para objdump ), todavía no veo ese símbolo en ninguna parte. Lo cual tiene sentido en la medida en que la función en cuestión es estática, por lo que no se exporta. Sin embargo, valgrind informará el nombre de la función, por lo que debe almacenarse en algún lugar.

Mirando los detalles de las secciones de depuración, encuentro ese nombre mencionado en la sección .debug_str , pero no conozco una herramienta que pueda convertir esto en un rango de direcciones.


Completar Bash para ./dasm (ver respuesta arriba). Completar nombres de símbolos. (Versión D lang)

Archivos:

/etc/bash_completion.d/dasm

# bash completion for dasm _dasm() { local cur=${COMP_WORDS[COMP_CWORD]} if [[ $COMP_CWORD -eq 1 ]] ; then # files COMPREPLY=( $( command ls *.o -F 2>/dev/null | grep "^$cur" ) ) elif [[ $COMP_CWORD -eq 2 ]] ; then # functions OBJFILE=${COMP_WORDS[COMP_CWORD-1]} COMPREPLY=( $( command nm --demangle=dlang $OBJFILE | grep " W " | cut -d " " -f 3 | tr "()" " " | grep "$cur" ) ) else COMPREPLY=($(compgen -W "" -- "$cur")); fi } complete -F _dasm dasm


Esto funciona igual que la solución gdb (en el sentido de que desplaza las compensaciones hacia cero), excepto que no es laggy (hace el trabajo en unos 5 ms en mi PC, mientras que la solución gdb tarda unos 150 ms):

objdump_func:

#!/bin/sh # $1 -- function name; rest -- object files fn=$1; shift 1 exec objdump -d "$@" | awk " /^[[:xdigit:]].*<$fn>/,/^/$/ { print /$0 }" | awk -F: -F'' '' ''NR==1 { offset=strtonum("0x"$1); print $0; } NR!=1 { split($0,a,":"); rhs=a[2]; n=strtonum("0x"$1); $1=sprintf("%x", n-offset); printf "%4s:%s/n", $1,rhs }''


Para simplificar el uso de awk para analizar el resultado de objdump en relación con otras respuestas:

objdump -d filename | sed ''/<functionName>:/,/^$/!d''


Sugeriría usar gdb como el enfoque más simple. Incluso puede hacerlo como una línea, como:

gdb -batch -ex ''file /bin/ls'' -ex ''disassemble main''


disassemble/rs para mostrar bytes fuente y raw también

Con este formato, se acerca mucho al objdump -S output:

gdb -batch -ex "file $EXECUTABLE" -ex "disassemble/rs $FUNCTION"

C.A:

#include <assert.h> int myfunc(int i) { i = i + 2; i = i * 2; return i; } int main(void) { assert(myfunc(1) == 6); assert(myfunc(2) == 8); return 0; }

Compilar y desmontar

gcc -std=c99 -O0 -g a.c gdb -batch -ex ''file a.out'' -ex "disassemble/rs myfunc"

Desmontaje:

Dump of assembler code for function main: a.c: 1 int main(void) { 0x00000000004004d6 <+0>: 55 push %rbp 0x00000000004004d7 <+1>: 48 89 e5 mov %rsp,%rbp 2 int i; 3 i = 0; 0x00000000004004da <+4>: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 4 i = i + 2; 0x00000000004004e1 <+11>: 83 45 fc 02 addl $0x2,-0x4(%rbp) 5 i = i * 2; 0x00000000004004e5 <+15>: d1 65 fc shll -0x4(%rbp) 6 return 0; 0x00000000004004e8 <+18>: b8 00 00 00 00 mov $0x0,%eax 7 } 0x00000000004004ed <+23>: 5d pop %rbp 0x00000000004004ee <+24>: c3 retq End of assembler dump.

Probado en Ubuntu 16.04, GDB 7.11.1.

awk soluciones

Imprima el párrafo como se menciona en: https://unix.stackexchange.com/questions/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the-text

objdump -d a.out | awk -v RS= ''/^[[:xdigit:]].*<FUNCTION>/''

Cuando uso -S , no creo que haya una manera a prueba de fallas, ya que los comentarios del código podrían contener cualquier secuencia posible ... Pero lo siguiente funciona casi todo el tiempo:

objdump -S a.out | awk ''/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag''

adaptado de: cómo seleccionar líneas entre dos patrones de marcador que pueden aparecer varias veces con awk / sed

Respuestas de la lista de correo

Hay un hilo de 2010 en la lista de correo que dice que no es posible: https://sourceware.org/ml/binutils/2010-04/msg00445.html

Además de la solución alternativa de gdb propuesta por Tom, también comentan otra (peor) solución de compilar con -ffunction-section que pone una función por sección y luego descarta la sección.

Nicolas Clifton le dio un WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , probablemente porque la solución GDB cubre ese caso de uso.