compilation gcc et fichiers objets
1 Concepts de base
Compilation Gcc 4 étapes: prétraitement, compilation, assemblage, liaison
Prétraitement (cpp): traitement des fichiers d'en-tête, définitions de macros, compilation conditionnelle, etc .;
compilation (ccl): inspection de code, génération de fichiers d'assemblage .s;
assemblage (as): génération de repositionnables (symboles globaux, fonctions externes, etc.). o Fichier objet;
processus de liaison (ld): combinez tout le code et les données dans un seul fichier, qui peut être chargé en mémoire pour exécution.
1.1 Type de processus de liaison
Liaison à la compilation: liaison vers des bibliothèques statiques et des fichiers objets relocalisables lors du processus de compilation des fichiers exécutables
Liaison au moment du chargement: liaison vers des bibliothèques dynamiques à l'exécution, lorsqu'elles sont chargées en mémoire pour exécution par le chargeur.
Liaison d'exécution: pour les bibliothèques dynamiques, le programme d'application charge dynamiquement les fichiers de bibliothèque, les fonctions associées telles que: dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym. L'interface native Java consiste à lier et à charger dynamiquement la bibliothèque de liens dynamiques générée par la compilation C / C ++ via la liaison d'exécution.
1.2 Format de fichier cible
Fichiers objets déplaçables: fichiers objets .o compilés et assemblés, déplaçables;
fichiers objets exécutables: fichiers objets exécutables binaires, fichiers bin après liaison statique
Fichiers objets partagés: bibliothèque de liens dynamiques
2 Exemple de processus de compilation Gcc
2.1 Exemple de code
Trois fichiers
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 = add (a, b); }
2.2 Prétraitement
2.2.1 main.i
gcc -E main.c -o main.i
génère le fichier main.i après le prétraitement 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 Compiler
2.3.1 main.s
cc1 -m32 main.i -o main.s
génère le fichier d'assemblage main.s
Remarques:
1. Compilez ici avec 32 bits
2. Si la commande prompt est introuvable, la raison est que le répertoire où se trouve cc1 n'est pas dans la variable d'environnement $ PATH. Utilisez des chemins absolus, tels que /usr/lib/gcc/x86_64-linux-gnu/4.8.4/cc1 -m32 main.i -o main.s
3. Le troisième caractère de cc1 est le chiffre 1, pas la lettre 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 Montage et démontage
as --32 -o main.o main.s
génère un fichier objet relocalisable main.o
2.4.1 main.o
Ce fichier n'est pas facile à visualiser directement avec chat, et un tas de caractères déformés sera affiché.
Vous pouvez utiliser objdump pour afficher les options de la commande de désassemblage:
objdump -dx main.o
-d: disassembly
-x: afficher tous les
résultats de la commande d'en- tête sont affichés comme suit:
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 Lien
ld -m elf_i386 -o main main.o add.o
2.6 Résumé des commandes associées
cpp main.c main.i
cc1 main.i -o main.s
comme --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
Remarque: Le chemin de version utilisé par la commande
cc1 /usr/lib/gcc/x86_64-linux-gnu/4.8.4/ cc1
3 Analyse des fichiers exécutables
3.1 Disposition de l'espace fichier ELF exécutable
3.2 Décompilation des fichiers exécutables
objdump -dx main
3.2.1 Informations de base sur les fichiers
main: format de fichier elf32-i386 architecture
principale
: i386, indicateurs 0x00000112:
EXEC_P, HAS_SYMS,
adresse de départ D_PAGED 0x08048094
3.2.2 Informations du tableau des en-têtes de programme
Programme en- tête:
OFF CHARGE PADDR 0x08048000 0x08048000 0x00000000 vaddr align = left 2 12 est
filesz 0x00000120 0x00000120 les drapeaux RX MEMSZ
la charge OFF PADDR 0x08049120 0x08049120 0x00000120 vaddr align = left 2 12 est
filesz 0x00000008 0x00000008 MEMSZ les drapeaux
STACK OFF de vaddr 0x00000000 0x00000000 0x00000000 align = PADDR gauche 2 ** 4.
Filesz 0x00000000 memsz 0x00000000 flags rw-
Description:
Off: Décalage dans le fichier cible
Vadd / paddr: Adresse mémoire
Alignement: Exigences d'alignement
Filesz: Taille du segment dans le fichier cible
Memsz: Taille du segment dans la mémoire Indicateurs:
Droits d'accès à l' exécution
3.2.3 Informations sectorielles
Sections:
Idx Nom Taille VMA LMA File off Algn
0 .text 00000033 08048094 08048094 00000094 2 0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 00000058 080480c8 080480c8 000000c8 2 2
CONTENTS, ALLOC, LOAD DATA, READONLY,
00000008 2. 08049120 08049120 00000120 2 2
CONTENU, ALLOC, LOAD, DATA
3 .comment 0000002b 00000000 00000000 00000128 2 0
CONTENU, LECTURE UNIQUEMENT
3.2.4 Informations sur le tableau des symboles
TABLEAU
DES SYMBOLES : 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.i df ABS 00000000 main.i
00000000 l.i df 00000000 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 main
08049128 g .data 00000000 _edend
0804900001 g .data 00000000 _edend 080490000120 g .data 00000000
_edend 080490000120 g .data 00000004 a
3.2.5 Informations de démontage
Démontage de la section .text:
08048094:
8048094: 55 push% ebp
8048095: 89 e5 mov% esp,% ebp
8048097: 83 e4 f0 et $ 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 appeler 80480ba
80480b4: 89 44 24 1c mov% eax, 0x1c (% esp)
80480b8: c9 quitter
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 ajouter% edx,% eax
80480c5: 5d pop% ebp
80480c6: c3 ret
4 Charger le fichier objet exécutable
4.1 Mappage de la mémoire d'exécution
5 Référence
1. "Compréhension approfondie des systèmes informatiques", [États-Unis] Randal E. Bryant, David R. O'Hallaron
, 3e édition, mars 2019, China Machinery Industry Press,