linux - traductor - ¿Hay alguna manera de hacer que gcc emita código binario sin formato?
tabla de numeros binarios (4)
¿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.
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 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
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.
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 pasar opciones al enlazador directamente con -Wl,<linker option>
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 sintaxis 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 compilar 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 expresar 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.
Puede usar objcopy
para extraer el segmento de texto del archivo .o o del 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