¿Hay alguna manera de hacer que gcc emita código binario sin formato?

¿Hay un conjunto de opciones de línea de comandos que convenzan a gcc para producir un archivo binario plano a partir de un archivo fuente independiente? Por ejemplo, supongamos que los contenidos de foo.c son

static int f(int x) { int y = x*x; return y+2; } 

Sin referencias externas, nada para exportar al enlazador. Me gustaría obtener un archivo pequeño con solo las instrucciones de la máquina para esta función, sin ninguna otra decoración. Algo así como un archivo .COM (DOS) excepto el modo protegido de 32 bits.

Probar esto:

 $ cc -c test.c $ objcopy -O binary test.o binfile 

Puedes asegurarte de que sea correcto con objdump :

 $ objdump -d test.o test.o: file format pe-i386 Disassembly of section .text: 00000000 <_f>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 8b 45 08 mov 0x8(%ebp),%eax 9: 0f af 45 08 imul 0x8(%ebp),%eax d: 89 45 fc mov %eax,-0x4(%ebp) 10: 8b 45 fc mov -0x4(%ebp),%eax 13: 83 c0 02 add $0x2,%eax 16: c9 leave 17: c3 ret 

Y compare con el archivo binario:

 $ hexdump -C binfile 00000000 55 89 e5 83 ec 04 8b 45 08 0f af 45 08 89 45 fc |U......E...E..E.| 00000010 8b 45 fc 83 c0 02 c9 c3 |.E......| 00000018 

Puede usar objcopy para extraer el segmento de texto del archivo .o o del archivo a.out.

 $ cat qc f() {} $ cc -S -O qc $ cat qs .file "qc" .text .globl f .type f, @function f: pushl %ebp movl %esp, %ebp popl %ebp ret .size f, .-f .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" .section .note.GNU-stack,"",@progbits $ cc -c -O qc $ objcopy -O binary qo q.bin $ od -X q.bin 0000000 5de58955 000000c3 0000005 $ objdump -d qo qo: file format elf32-i386 Disassembly of section .text: 00000000 : 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 5d pop %ebp 4: c3 ret 

Las otras respuestas son definitivamente el camino a seguir. Sin embargo, tuve que especificar argumentos de línea de comandos adicionales para objcopy para que mi salida fuera la esperada. Tenga en cuenta que estoy desarrollando código de 32 bits en una máquina de 64 bits, de ahí el argumento -m32 . Además, me gusta mejor la syntax de ensamblaje de intel, por lo que también lo verás en los argumentos.

 $ cat test.c int main() { return 0; } $ gcc -nostdinc -m32 -masm=intel -Wall -c test.c -o test.o $ objdump --disassemble --disassembler-options intel test.o test.o: file format elf32-i386 Disassembly of section .text: 00000000 
: 0: 55 push ebp 1: 89 e5 mov ebp,esp 3: b8 00 00 00 00 mov eax,0x0 8: 5d pop ebp 9: c3 ret

Ok, aquí es donde tuve que especificar que específicamente solo quería la sección .text:

 $ objcopy --only-section=.text --output-target binary test.o test.bin $ hexdump -C test.bin 00000000 55 89 e5 b8 00 00 00 00 5d c3 |U.......].| 0000000a 

Me tomó aproximadamente 2 horas de lectura y probar diferentes opciones antes de darme cuenta de esto. Esperemos que esto le ahorre a alguien más ese momento.

Puede pasar opciones al enlazador directamente con -Wl,

La documentación relevante se copia debajo del man gcc

-Wl, opción
Pase la opción como una opción al vinculador. Si la opción contiene comas, se divide en múltiples opciones en las comas. Puede usar esta syntax para pasar un argumento a la opción. Por ejemplo, -Wl, -Map, output.map pasa -Map output.map al enlazador. Cuando usa el enlazador GNU, también puede obtener el mismo efecto con -Wl, -Map = output.map.

Por lo tanto, al comstackr con gcc, si pasa -Wl,--oformat=binary , generará un archivo binario en lugar del formato elf. Donde --oformat=binary le dice a ld que genere un archivo binario.

Esto elimina la necesidad de objcopy separado.

Tenga en cuenta que --oformat=binary se puede express como OUTPUT_FORMAT("binary") dentro de un script del enlazador . Si desea trabajar con binarios planos, existe una gran posibilidad de que se beneficie del alto nivel de control que ofrecen los scripts del enlazador.

    Intereting Posts