Tengo un binario instalado en mi sistema y me gustaría ver el desmontaje de una función determinada. Preferiblemente usar objdump
, pero también serían aceptables otras soluciones.
De estas preguntas aprendí que podría desensamblar parte del código si solo conociera las direcciones de los límites. A partir de esta respuesta , aprendí cómo convertir mis símbolos de depuración divididos nuevamente en un solo archivo.
Pero incluso operando en ese único archivo, e incluso desensamblando todo el código (es decir, sin dirección de inicio o parada, pero -d
parámetro simple para objdump
), todavía no veo ese símbolo en ninguna parte. Lo que 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 .debug_str
sección, pero no conozco una herramienta que pueda convertir esto en un rango de direcciones.
static
, el compilador podría incluirla en sus sitios de llamada. Esto puede significar que es posible que no haya ninguna función para desmontar, per se . Si puede detectar símbolos para otras funciones, pero no la función que está buscando, esto es un fuerte indicio de que la función se ha incluido. Valgrind aún puede hacer referencia a la función original preincluida porque la información de depuración del archivo ELF almacena el origen de cada instrucción individual, incluso si las instrucciones se mueven a otro lugar.addr2line
aceptará PC / IP destdin
e imprimirá sus líneas de código fuente correspondientes. Del mismo modo,objdump -l
mezclará el objdump con las líneas fuente; aunque para el código altamente optimizado con mucha inserción, los resultados de ambos programas no siempre son particularmente útiles.Respuestas:
Sugeriría usar gdb como el enfoque más simple. Incluso puedes hacerlo como una sola línea, como:
fuente
-ex 'command'
no está enman gdb
!? Pero, de hecho, aparece en la documentación de gdb . También para otros, cosas como/bin/ls
podrían ser eliminadas, así que si ese comando exacto no muestra nada, ¡pruebe con otro objeto! También puede especificar archivo / objeto como argumento de palabra simple; por ejemplo,gdb -batch -ex 'disassemble main' /bin/ls
gdb /bin/ls -batch -ex 'disassemble main'
también funcionacolumn -ts$'\t'
para filtrar la salida de GDB, tendrá los bytes sin procesar y las columnas de origen bien alineadas. Además,-ex 'set disassembly-flavor intel'
antes de que otros-ex
s resulten en sintaxis de ensamblaje Intel.disassemble fn
usando el método anterior. Pero parece que cuando hay varias funciones con el mismo nombre en el archivo binario, solo se desmonta una. ¿Es posible desmontarlos todos o debería desmontarlos según la dirección sin procesar?gdb
disassemble/rs
para mostrar también los bytes de origen y sin procesarCon este formato, se acerca mucho a la
objdump -S
salida:C Principal
Compilar y desmontar
Desmontaje:
Probado en Ubuntu 16.04, GDB 7.11.1.
objdump + awk soluciones alternativas
Imprima el párrafo como se menciona en: /unix/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the -texto
p.ej:
da solo:
Cuando se usa
-S
, no creo que haya una forma 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:adaptado de: Cómo seleccionar líneas entre dos patrones de marcador que pueden ocurrir 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
gdb
solución alternativa propuesta por Tom, también comentan sobre otra solución (peor) de compilación con la-ffunction-section
que se coloca una función por sección y luego se descarga la sección.Nicolas Clifton le dio un WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , probablemente porque la solución alternativa de GDB cubre ese caso de uso.
fuente
Desmontar una sola función usando Objdump
Tengo dos soluciones:
1. Basado en línea de comandos
Este método funciona perfectamente y además es simple. Yo uso objdump con la -d bandera y el tubo a través de awk . La salida desmontada parece
Para empezar, empiezo con la descripción de la salida objdump. Una sección o función está separada por una línea vacía. Por lo tanto, cambiar el FS (Separador de campo) a una nueva línea y el RS (Separador de registros) a dos veces una nueva línea le permite buscar fácilmente la función recomendada, ¡ya que es simplemente buscar dentro del campo $ 1!
Por supuesto, puede reemplazar main con cualquier otra función que le gustaría imprimir.
2. Bash Script
He escrito un pequeño script bash para este problema. Péguelo , cópielo y guárdelo como, por ejemplo, un archivo dasm .
Cambie el acceso x e invocalo con, por ejemplo:
Esto es mucho más rápido que invocar gdb con un script. Además, el uso de objdump no cargará las bibliotecas en la memoria y, por lo tanto, es más seguro.
Vitaly Fadeev programó un autocompletado para este script, que es realmente una característica agradable y acelera la escritura.
El guión se puede encontrar aquí .
fuente
objdump
ogdb
es más rápido. Para un binario enorme (libxul.so de Firefox)objdump
tarda una eternidad, lo cancelé después de una hora, mientras quegdb
tarda menos de un minuto.Para simplificar el uso de awk para analizar la salida de objdump en relación con otras respuestas:
fuente
Esto funciona igual que la solución gdb (en el sentido de que desplaza las compensaciones hacia cero), excepto que no tiene retrasos (hace el trabajo en aproximadamente 5 ms en mi PC, mientras que la solución gdb tarda aproximadamente 150 ms):
objdump_func:
fuente
awk
) fuera la única función en el archivo de objeto, es decir, incluso si la función comienza en, digamos0x2d
, el segundo awk la desplazará hacia0x00
(restando0x2d
de la dirección de cada instrucción), lo cual es útil porque el código ensamblador a menudo hace referencias relativas al inicio de la función y si la función comienza en 0, no tiene que hacer las restas en su cabeza. El código awk podría ser mejor, pero al menos hace el trabajo y es bastante eficiente.-ffunction-sections
es una forma más fácil de asegurarse de que cada función comience en 0.Si tiene un binutils muy reciente (2.32+), esto es muy simple.
Pasar
--disassemble=SYMBOL
a objdump desensamblará solo la función especificada. No es necesario pasar la dirección de inicio y la dirección final.LLVM objdump también tiene una opción similar (
--disassemble-symbols
).fuente
Finalización de golpe para
./dasm
Nombres de símbolos completos para esta solución (versión D lang):
dasm test
y luego presionar TabTab, obtendrá una lista de todas las funciones.dasm test m
y luego presionar , se mostrarán TabTab todas las funciones que comienzan con m , o en caso de que solo exista una función, se completará automáticamente.Archivo
/etc/bash_completion.d/dasm
:fuente