2009-10-30 9 views
28

¿Existe un conjunto de opciones de línea de comandos que convenzan a gcc para que produzca un archivo binario plano a partir de un archivo fuente independiente? Por ejemplo, supongamos que el contenido de foo.c son¿Hay alguna manera de hacer que gcc emita código binario sin formato?

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

No hay referencias externas, nada que 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.

+1

Dos respuestas finas enviadas al mismo tiempo. No sé cuál dar la marca de verificación. –

+0

Puede considerar aceptar una [respuesta más reciente] (http://stackoverflow.com/a/23502466/1483676) que responde directamente a su pregunta (compilador puro/respuesta del enlazador). – cubuspl42

Respuesta

30

Trate de hacer esto:

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

Puede asegurarse de que es correcta 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 comparar 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 
+1

Tuve que incluir '-j .text' como parámetro en' objcopy' para obtener el resultado correcto. – SpellingD

+0

¿Por qué? ¿Qué pasó cuando no lo hiciste? –

+0

Copió la sección incorrecta (no .text) del archivo .o. Versión: 'GNU objcopy versión 2.22.52.0.1-10.fc17 20120131' – SpellingD

15

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

$ cat q.c 
f() {} 
$ cc -S -O q.c 
$ cat q.s 
     .file "q.c" 
     .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 q.c 
$ objcopy -O binary q.o q.bin 
$ od -X q.bin 
0000000 5de58955 000000c3 
0000005 
$ objdump -d q.o 
q.o:  file format elf32-i386 
Disassembly of section .text: 
00000000 <f>: 
    0: 55      push %ebp 
    1: 89 e5     mov %esp,%ebp 
    3: 5d      pop %ebp 
    4: c3      ret  
+1

Pareces haber perdido el enlace. –

+0

Reparado, gracias .... – DigitalRoss

11

El otro las 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 sintaxis 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 <main>: 
    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  

autorización, aquí es donde tuve que especificar que me específicamente sólo 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ó cerca de 2 horas de lectura y probar diferentes opciones antes de que me di cuenta de esto. Esperemos que esto le ahorre a alguien más ese momento.

9

Puede pasar opciones al enlazador directamente con -Wl,<linker option>

La documentación correspondiente se copia a continuación de la man gcc

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

Al compilar con gcc, si pasa -Wl,--oformat=binary generará un archivo binario en lugar del formato elf. Donde --oformat=binary dice ld para generar un archivo binario.

Esto elimina la necesidad de objcopy por separado.

Tenga en cuenta que --oformat=binary se puede expresar como OUTPUT_FORMAT("binary") dentro de un linker script.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.

+0

En realidad, esta es la única respuesta válida aquí ... Diría que otras son soluciones aceptables. – cubuspl42

+0

Para referencia futura: la solución '--oformat = binary' parece emitir código incorrecto de máquina en algunos casos * o * No estoy al tanto de algo, pero si por casualidad encuentra algún comportamiento extraño de símbolos externos, intente 'objcopy' solución. – cubuspl42

Cuestiones relacionadas