Me dijeron que usara un desensamblador. ¿ gcc
Tiene algo incorporado? ¿Cuál es la forma más sencilla de hacer esto?
c++
linux
assembly
executable
disassembly
Error de sintaxis
fuente
fuente
Respuestas:
No creo que
gcc
tenga una bandera, ya que es principalmente un compilador, pero otra de las herramientas de desarrollo GNU sí.objdump
toma una bandera-d
/--disassemble
:El desmontaje se ve así:
080483b4 <main>: 80483b4: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483b8: 83 e4 f0 and $0xfffffff0,%esp 80483bb: ff 71 fc pushl -0x4(%ecx) 80483be: 55 push %ebp 80483bf: 89 e5 mov %esp,%ebp 80483c1: 51 push %ecx 80483c2: b8 00 00 00 00 mov $0x0,%eax 80483c7: 59 pop %ecx 80483c8: 5d pop %ebp 80483c9: 8d 61 fc lea -0x4(%ecx),%esp 80483cc: c3 ret 80483cd: 90 nop 80483ce: 90 nop 80483cf: 90 nop
fuente
objdump -Mintel -d
. O el desensamblador objconv de Agner Fog es el mejor que he probado hasta ahora (vea mi respuesta). Agregar etiquetas numeradas a los objetivos de las ramas es realmente agradable.objdump -drwC -Mintel
.-r
muestra las reubicaciones de la tabla de símbolos.-C
exige nombres C ++.-W
evita enrollar la línea para instrucciones largas. Si lo usa a menudo, esto es muy práctico:alias disas='objdump -drwC -Mintel'
.-S
para mostrar el código fuente mezclado con el desmontaje. (Como se señaló en otra respuesta .)Una alternativa interesante a objdump es gdb. No es necesario ejecutar el binario o tener debuginfo.
$ gdb -q ./a.out Reading symbols from ./a.out...(no debugging symbols found)...done. (gdb) info functions All defined functions: Non-debugging symbols: 0x00000000004003a8 _init 0x00000000004003e0 __libc_start_main@plt 0x00000000004003f0 __gmon_start__@plt 0x0000000000400400 _start 0x0000000000400430 deregister_tm_clones 0x0000000000400460 register_tm_clones 0x00000000004004a0 __do_global_dtors_aux 0x00000000004004c0 frame_dummy 0x00000000004004f0 fce 0x00000000004004fb main 0x0000000000400510 __libc_csu_init 0x0000000000400580 __libc_csu_fini 0x0000000000400584 _fini (gdb) disassemble main Dump of assembler code for function main: 0x00000000004004fb <+0>: push %rbp 0x00000000004004fc <+1>: mov %rsp,%rbp 0x00000000004004ff <+4>: sub $0x10,%rsp 0x0000000000400503 <+8>: callq 0x4004f0 <fce> 0x0000000000400508 <+13>: mov %eax,-0x4(%rbp) 0x000000000040050b <+16>: mov -0x4(%rbp),%eax 0x000000000040050e <+19>: leaveq 0x000000000040050f <+20>: retq End of assembler dump. (gdb) disassemble fce Dump of assembler code for function fce: 0x00000000004004f0 <+0>: push %rbp 0x00000000004004f1 <+1>: mov %rsp,%rbp 0x00000000004004f4 <+4>: mov $0x2a,%eax 0x00000000004004f9 <+9>: pop %rbp 0x00000000004004fa <+10>: retq End of assembler dump. (gdb)
Con información de depuración completa, es aún mejor.
(gdb) disassemble /m main Dump of assembler code for function main: 9 { 0x00000000004004fb <+0>: push %rbp 0x00000000004004fc <+1>: mov %rsp,%rbp 0x00000000004004ff <+4>: sub $0x10,%rsp 10 int x = fce (); 0x0000000000400503 <+8>: callq 0x4004f0 <fce> 0x0000000000400508 <+13>: mov %eax,-0x4(%rbp) 11 return x; 0x000000000040050b <+16>: mov -0x4(%rbp),%eax 12 } 0x000000000040050e <+19>: leaveq 0x000000000040050f <+20>: retq End of assembler dump. (gdb)
objdump tiene una opción similar (-S)
fuente
Esta respuesta es específica para x86. Herramientas portátiles que pueden desmontar AArch64, MIPS o cualquier código de máquina que incluya
objdump
yllvm-objdump
.Desensamblador de Agner Fog ,
objconv
es bastante agradable. Agregará comentarios a la salida de desmontaje por problemas de rendimiento (como el temido bloqueo de LCP de instrucciones con constantes inmediatas de 16 bits, por ejemplo).objconv -fyasm a.out /dev/stdout | less
(No reconoce
-
como abreviatura de stdout y, por defecto, la salida a un archivo de nombre similar al archivo de entrada, con.asm
tachuelas).También agrega destinos de rama al código. Otros desensambladores generalmente desensamblan las instrucciones de salto con solo un destino numérico, y no colocan ningún marcador en un objetivo de rama para ayudarlo a encontrar la parte superior de los bucles, etc.
También indica los NOP con más claridad que otros desensambladores (dejando claro cuándo hay relleno, en lugar de desensamblarlo como una instrucción más).
Es de código abierto y fácil de compilar para Linux. Puede desmontarse en sintaxis NASM, YASM, MASM o GNU (AT&T).
Salida de muestra:
; Filling space: 0FH ; Filler type: Multi-byte NOP ; db 0FH, 1FH, 44H, 00H, 00H, 66H, 2EH, 0FH ; db 1FH, 84H, 00H, 00H, 00H, 00H, 00H ALIGN 16 foo: ; Function begin cmp rdi, 1 ; 00400620 _ 48: 83. FF, 01 jbe ?_026 ; 00400624 _ 0F 86, 00000084 mov r11d, 1 ; 0040062A _ 41: BB, 00000001 ?_020: mov r8, r11 ; 00400630 _ 4D: 89. D8 imul r8, r11 ; 00400633 _ 4D: 0F AF. C3 add r8, rdi ; 00400637 _ 49: 01. F8 cmp r8, 3 ; 0040063A _ 49: 83. F8, 03 jbe ?_029 ; 0040063E _ 0F 86, 00000097 mov esi, 1 ; 00400644 _ BE, 00000001 ; Filling space: 7H ; Filler type: Multi-byte NOP ; db 0FH, 1FH, 80H, 00H, 00H, 00H, 00H ALIGN 8 ?_021: add rsi, rsi ; 00400650 _ 48: 01. F6 mov rax, rsi ; 00400653 _ 48: 89. F0 imul rax, rsi ; 00400656 _ 48: 0F AF. C6 shl rax, 2 ; 0040065A _ 48: C1. E0, 02 cmp r8, rax ; 0040065E _ 49: 39. C0 jnc ?_021 ; 00400661 _ 73, ED lea rcx, [rsi+rsi] ; 00400663 _ 48: 8D. 0C 36 ...
Tenga en cuenta que esta salida está lista para volver a ensamblarse en un archivo de objeto, por lo que puede modificar el código en el nivel de fuente de asm, en lugar de con un editor hexadecimal en el código de máquina. (Por lo tanto, no está limitado a mantener las cosas del mismo tamaño). Sin cambios, el resultado debería ser casi idéntico. Sin embargo, puede que no lo sea, ya que el desmontaje de cosas como
(from /lib/x86_64-linux-gnu/libc.so.6) SECTION .plt align=16 execute ; section number 11, code ?_00001:; Local function push qword [rel ?_37996] ; 0001F420 _ FF. 35, 003A4BE2(rel) jmp near [rel ?_37997] ; 0001F426 _ FF. 25, 003A4BE4(rel) ... ALIGN 8 ?_00002:jmp near [rel ?_37998] ; 0001F430 _ FF. 25, 003A4BE2(rel) ; Note: Immediate operand could be made smaller by sign extension push 11 ; 0001F436 _ 68, 0000000B ; Note: Immediate operand could be made smaller by sign extension jmp ?_00001 ; 0001F43B _ E9, FFFFFFE0
no tiene nada en la fuente para asegurarse de que se ensambla con la codificación más larga que deja espacio para reubicaciones para reescribirlo con un desplazamiento de 32 bits.
Si no desea instalarlo objconv, GNU binutils
objdump -Mintel -d
es muy útil y ya estará instalado si tiene una configuración gcc normal de Linux.fuente
también está ndisasm, que tiene algunas peculiaridades, pero puede ser más útil si usa nasm. Estoy de acuerdo con Michael Mrozek en que objdump es probablemente lo mejor.
[más adelante] es posible que también desee ver la ciasdis de Albert van der Horst: http://home.hccnet.nl/awmvan.der.horst/forthassembler.html . Puede ser difícil de entender, pero tiene algunas características interesantes que probablemente no encontrará en ningún otro lugar.
fuente
Utilice IDA Pro y el Decompiler .
fuente
Puede que la AOD le resulte útil. Es un desensamblador basado en web que admite toneladas de arquitecturas.
http://onlinedisassembler.com/
fuente
ht editor puede desensamblar binarios en muchos formatos. Es similar a Hiew, pero de código abierto.
Para desmontar, abra un binario, luego presione F6 y luego seleccione elf / image.
fuente
Puede acercarse bastante (pero no puro) a generar un ensamblaje que se volverá a ensamblar, si eso es lo que pretende hacer, utilizando este truco de tubería bastante tosco y tediosamente largo (reemplace / bin / bash con el archivo que desea desensamblar y bash.S con lo que pretendes enviar la salida):
objdump --no-show-raw-insn -Matt,att-mnemonic -Dz /bin/bash | grep -v "file format" | grep -v "(bad)" | sed '1,4d' | cut -d' ' -f2- | cut -d '<' -f2 | tr -d '>' | cut -f2- | sed -e "s/of\ section/#Disassembly\ of\ section/" | grep -v "\.\.\." > bash.S
Sin embargo, tenga en cuenta cuánto tiempo es esto. Realmente desearía que hubiera una forma mejor (o, para el caso, un desensamblador capaz de generar código que un ensamblador reconocerá), pero desafortunadamente no la hay.
fuente
Digamos que tienes:
#include <iostream> double foo(double x) { asm("# MyTag BEGIN"); // <- asm comment, // used later to locate piece of code double y = 2 * x + 1; asm("# MyTag END"); return y; } int main() { std::cout << foo(2); }
Para obtener el código ensamblador usando gcc, puede hacer lo siguiente:
g++ prog.cpp -c -S -o - -masm=intel | c++filt | grep -vE '\s+\.'
c++filt
símbolos de demandagrep -vE '\s+\.'
elimina alguna información inútilAhora, si desea visualizar la parte etiquetada, simplemente use:
g++ prog.cpp -c -S -o - -masm=intel | c++filt | grep -vE '\s+\.' | grep "MyTag BEGIN" -A 20
Con mi computadora obtengo:
# MyTag BEGIN # 0 "" 2 #NO_APP movsd xmm0, QWORD PTR -24[rbp] movapd xmm1, xmm0 addsd xmm1, xmm0 addsd xmm0, xmm1 movsd QWORD PTR -8[rbp], xmm0 #APP # 9 "poub.cpp" 1 # MyTag END # 0 "" 2 #NO_APP movsd xmm0, QWORD PTR -8[rbp] pop rbp ret .LFE1814: main: .LFB1815: push rbp mov rbp, rsp
Un enfoque más amigable es usar: Compiler Explorer
fuente
-O0
asm.