compilación gcc y archivos de objeto
1 Conceptos básicos
Compilación gcc 4 etapas: preprocesamiento, compilación, ensamblaje, vinculación
Preprocesamiento (cpp): procesamiento de archivos de cabecera, definiciones de macros, compilación condicional, etc .;
compilación (ccl): inspección de código, generación de archivos ensamblados .s;
ensamblado (as): generación de símbolos relocables (globales, funciones externas, etc.). o Archivo objeto;
proceso de enlace (ld): Combina todos los códigos y datos en un solo archivo, que se puede cargar en la memoria para su ejecución.
1.1 Tipo de proceso de enlace
Vinculación en tiempo de compilación: vinculación a bibliotecas estáticas y archivos de objetos reubicables durante el proceso de compilación de archivos ejecutables
Vinculación en tiempo de carga: vinculación a bibliotecas dinámicas en tiempo de ejecución, cuando se cargan en la memoria para su ejecución por el cargador.
Vinculación en tiempo de ejecución: para bibliotecas dinámicas, el programa de aplicación carga dinámicamente archivos de biblioteca, funciones relacionadas como dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym. La interfaz nativa de Java sirve para vincular y cargar dinámicamente la biblioteca de vínculos dinámicos generada por la compilación C / C ++ a través de la vinculación en tiempo de ejecución.
1.2 Formato de archivo de destino
Archivos de objeto reubicables: archivos de objeto .o compilados y ensamblados, reubicables;
archivos de objeto ejecutables: archivos de objeto ejecutables binarios, archivos bin después de la vinculación estática
Archivos de objetos compartidos: biblioteca de vínculos dinámicos
2 ejemplo de proceso de compilación de Gcc
2.1 Código de muestra
Tres archivos
add.h file content:
int add (int a, int b);
add.c file content:
int add (int a, int b)
{ return a + b; } main.c file content: #include " add.h " int a = 1; int b = 2;
int main ()
{ int res = agregar (a, b); }
2.2 Pretratamiento
2.2.1 main.i
gcc -E main.c -o main.i
genera el archivo main.i después de preprocesar main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
# 1 "add.h" 1
int add(int a,int b);
# 2 "main.c" 2
int a = 1;
int b = 2;
int main()
{
int res=add(a,b);
}
2.2.2 add.i
# 1 "add.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "add.c"
int add(int a,int b)
{
return a+b;
}
2.3 Compilar
2.3.1 main.s
cc1 -m32 main.i -o main.s
genera un archivo de ensamblaje main.s
Observaciones:
1. Compile aquí con 32 bits
2. Si no se puede encontrar el comando de línea, la razón es que el directorio donde se encuentra cc1 no está en la variable de entorno $ PATH. Utilice rutas absolutas, como /usr/lib/gcc/x86_64-linux-gnu/4.8.4/cc1 -m32 main.i -o main.s
3. El tercer carácter de cc1 es el número 1, no la letra l
.file "main.i"
.globl a
.data
.align 4
.type a, @object
.size a, 4
a:
.long 1
.globl b
.align 4
.type b, @object
.size b, 4
b:
.long 2
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl b(%rip), %edx
movl a(%rip), %eax
movl %edx, %esi
movl %eax, %edi
call add
movl %eax, -4(%rbp)
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4"
.section .note.GNU-stack,"",@progbits
2.3.2 add.s
.file "add.i"
.text
.globl add
.type add, @function
add:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size add, .-add
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4"
.section .note.GNU-stack,"",@progbits
2.4 Montaje y desmontaje
como --32 -o main.o main.s
genera un archivo de objeto reubicable main.o
2.4.1 main.o
Este archivo no es fácil de ver directamente con cat, y se mostrarán un montón de caracteres confusos.
Puede usar objdump para ver las opciones del comando de desmontaje:
objdump -dx main.o
-d: desensamblaje
-x: mostrar todos los
resultados del comando de encabezado se muestran de la siguiente manera:
main.o: file format elf32-i386
main.o
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000026 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 00000000 00000000 0000005c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000064 2**0
ALLOC
3 .comment 0000002c 00000000 00000000 00000064 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 00000090 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 00000000 00000000 00000090 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
00000000 l df *ABS* 00000000 main.i
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .eh_frame 00000000 .eh_frame
00000000 l d .comment 00000000 .comment
00000000 g O .data 00000004 a
00000004 g O .data 00000004 b
00000000 g F .text 00000026 main
00000000 *UND* 00000000 add
Disassembly of section .text:
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: 8b 15 00 00 00 00 mov 0x0,%edx
b: R_386_32 b
f: a1 00 00 00 00 mov 0x0,%eax
10: R_386_32 a
14: 89 54 24 04 mov %edx,0x4(%esp)
18: 89 04 24 mov %eax,(%esp)
1b: e8 fc ff ff ff call 1c <main+0x1c>
1c: R_386_PC32 add
20: 89 44 24 1c mov %eax,0x1c(%esp)
24: c9 leave
25: c3 ret
2.4.2 add.o
main.o: file format elf32-i386
main.o
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000026 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 00000000 00000000 0000005c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000064 2**0
ALLOC
3 .comment 0000002c 00000000 00000000 00000064 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 00000090 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 00000000 00000000 00000090 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
00000000 l df *ABS* 00000000 main.i
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .eh_frame 00000000 .eh_frame
00000000 l d .comment 00000000 .comment
00000000 g O .data 00000004 a
00000004 g O .data 00000004 b
00000000 g F .text 00000026 main
00000000 *UND* 00000000 add
Disassembly of section .text:
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 20 sub $0x20,%esp
9: 8b 15 00 00 00 00 mov 0x0,%edx
b: R_386_32 b
f: a1 00 00 00 00 mov 0x0,%eax
10: R_386_32 a
14: 89 54 24 04 mov %edx,0x4(%esp)
18: 89 04 24 mov %eax,(%esp)
1b: e8 fc ff ff ff call 1c <main+0x1c>
1c: R_386_PC32 add
20: 89 44 24 1c mov %eax,0x1c(%esp)
24: c9 leave
25: c3 ret
2.5 Enlace
ld -m elf_i386 -o main main.o add.o
2.6 Resumen de comandos relacionados
cpp main.c main.i
cc1 main.i -o main.s
como --32 -o main.o main.s
objdump -dx main.o> main.o.txt
cpp add.c add.i /usr/lib/gcc/x86_64-linux-gnu/4.8.4/cc1
-m32 add.i -o add.s
as --32 -o add.o add.s
objdump -dx add.o> add.o.txt
链接 :
ld -m elf_i386 -o main main.o add.o
Observación: la ruta de la versión utilizada por el comando
cc1 /usr/lib/gcc/x86_64-linux-gnu/4.8.4/ cc1
3 Análisis de archivos ejecutables
3.1 Disposición del espacio de archivos ELF ejecutable
3.2 Descompilación de archivos ejecutables
objdump -dx principal
3.2.1 Información básica del archivo
main: formato de archivo elf32-i386 arquitectura
principal
: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
dirección de inicio 0x08048094
3.2.2 Información de la tabla de encabezado del programa
Programa Header:
la PADDR LOAD OFF 0x08048000 0x08048000 0x00000000 vaddr align = left 2 12 es
filesz 0x00000120 0x00000120 las banderas RX MEMSZ
la carga de PADDR 0x08049120 0x08049120 0x00000120 vaddr align = left 2 12 es
filesz 0x00000008 0x00000008 MEMSZ las banderas rw-
STACK OFF vaddr 0x00000000 0x00000000 0x00000000 align = PADDR izquierda 2 ** 4.
Filesz 0x00000000 memsz 0x00000000 flags rw-
Descripción:
Off: Offset en el archivo de destino
Vadd / paddr: Dirección de memoria
Alinear: Requisitos de alineación
Filesz: Tamaño de segmento en el archivo de destino
Memsz: Tamaño de segmento en la memoria
Flags: Derechos de acceso en tiempo de ejecución
3.2.3 Información por segmentos
Secciones:
Idx Nombre Tamaño VMA LMA Archivo desactivado Algn
0 .text 00000033 08048094 08048094 00000094 2 0
CONTENIDO, ASIGNAR, CARGAR, SOLO LECTURA, CÓDIGO
1 .eh_frame 00000058 080480c8 080480c8 000000c8 2 2
CONTENIDO, ASIGNAR, CARGAR, SÓLO LECTURA 0000 DATOS
. 08049120 08049120 00000120 2 2
CONTENIDO, ASIGNACIÓN, CARGA, DATOS
3 .comentario 0000002b 00000000 00000000 00000128 2 0
CONTENIDO, SOLO LECTURA
3.2.4 Información de la tabla de símbolos
Símbolo de la tabla:
08048094 ld .text 00000000 .text
080480c8 ld .eh_frame 00000000 .eh_frame
08049120 ld .data 00000000 .data
00000000 ld .comment 00000000 .comment
00000000 l df ABS 00000000 main.i
00000000 l df ABS 00000000 Add.I
00000000 l df ABS 00000000
08049124 g O .data 00000004 b
080480ba g F .text 0000000d add
00000000 UND 00000000 _start
08049128 g .data 00000000 __bss_start
08048094 g F .text 00000026 principal
08049128 g .data 00000000 _edata
08049128 g .data 00000000 _edata
08049128 g .data 00000000 _edata . 00000004 a
3.2.5 Información de desmontaje
Desmontaje de la sección .text:
08048094:
8048094: 55 push% ebp
8048095: 89 e5 mov% esp,% ebp
8048097: 83 e4 f0 y $ 0xfffffff0,% esp
804809a: 83 ec 20 sub $ 0x20,% esp
804809d: 8b 15 24 91 04 08 mov 0x8049124 ,% edx
80480a3: a1 20 91 04 08 mov 0x8049120,% eax
80480a8: 89 54 24 04 mov% edx, 0x4 (% esp)
80480ac: 89 04 24 mov% eax, (% esp)
80480af: e8 06 00 00 00 llamar 80480ba
80480b4: 89 44 24 1c mov% eax, 0x1c (% esp)
80480b8: c9 dejar
80480b9: c3 ret
080480ba:
80480ba: 55 push% ebp
80480bb: 89 e5 mov% esp,% ebp
80480bd: 8b 45 0c mov 0xc (% ebp),% eax
80480c0: 8b 55 08 mov 0x8 (% ebp),% edx
80480c3: 01 d0 agregar% edx,% eax
80480c5: 5d pop% ebp
80480c6: c3 ret
4 Cargar archivo de objeto ejecutable
4.1 Mapeo de memoria en tiempo de ejecución
5 Referencia
1. "Comprensión en profundidad de los sistemas informáticos", [Estados Unidos] Randal E. Bryant, David R. O'Hallaron
, tercera edición, marzo de 2019, China Machinery Industry Press,