-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathelf.format.txt
652 lines (589 loc) · 37.1 KB
/
elf.format.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
┏━━━━━━━━━┓
┃ ELF ┃
┗━━━━━━━━━┛
HEADER ==> #<elf.h>
TYPE ==> #Peut être :
# - une shared library
# - un exécutable
# - un core file
# - un [relocatable] objet file
STRUCTURE ==> # - header général :
# - propriétés générales
# - un seul, et au début.
# - Détermine la location de la pht et de la sht.
# - program header table (PHT) :
# - arrays de pointers vers les program headers.
# - program headers :
# - Décrit un segment. Un segment = 1 ou +
# sections liées ensemble. Un segment peut en
# recouper un autre.
# - utilisé lors de l'exécution : quels segments
# charger et comment trouver les infos pour le
# dynamic linking
# - Utilisés seulement par les shared libraries et
# exécutable, mais pas core files ni object
# files (bien que ces premiers en ait)
# - section header table (SHT) :
# - Arrays de pointers vers les section headers.
# - section headers :
# - Décrit une section, bout de data/code machine
# avec un but précis
# - utilisé lors du linking et loading : comment
# résoudre les symboles, et commen regrouper
# plusieurs sections de plusieurs fichiers ELF
# différents
┌────────────────────┐
│ HEADER GENERAL │
└────────────────────┘
SYNTHESE ==> #Voici (l'endianness s'applique sur les groupes d'octets
#c'est-à-dire ceux pas séparés par un |) :
+--------+--------+--------+--------+--------+--------+--------+--------+
| 7f | 45 | 4c | 46 | Bits | Endian | 01 | 00 |
+--------+--------+--------+--------+--------+--------+--------+--------+
Magic numbers (0x7f"elf")
0x00 Invalide Invalide
0x01 32 bits Litl-end
0x02 64 bits Big-end
0x03
0x61
+--------+--------------------------------------------------------------+
| Version| 00000000000000 |
| ABI | |
+--------+--------------------------------------------------------------+
+-----------------+-----------------+-----------------------------------+
| Type | Architecture | 00000001 |
+-----------------+-----------------+-----------------------------------+
0x0000 Invalide
0x0001 Object file
0x0002 Exécutable
0x0003 Shared library x86
0x0004 Core file
0x0028 ARM
0x003e x86_64
+-----------------------------------+-----------------------------------+
|ADR virtuelle de l'entry point | Offset PHT (32 ou 64) |
|(32 bits ou 64 bits selon archit) | |
+-----------------------------------+-----------------------------------+
| Offset SHT (32 ou 64) | Flags CPU |
+-----------------------------------+-----------------------------------+
+-----------------+-----------------+-----------------+-----------------+
| Taille header | Taille 1 entrée | Nb entrées PHT | Taille 1 entrée |
| général | dans PHT | | dans SHT |
+-----------------+-----------------+-----------------+-----------------+
+-----------------+-----------------+
| Nb entrées SHT |Indx de .shstrtab|
| | dans SHT |
+-----------------+-----------------+
TYPEDEFS ==> #N signifie 32 ou 64, selon l'architecture.
#Il y a aussi ces typedefs :
ElfN_Addr #uintN_t (ADR)
ElfN_Off #uintN_t (Offset)
ElfN_Versym #uint16_t (Version)
ElfN_Section #uint16_t (Section index)
ElfN_Byte #UCHAR
ElfN_Half #uint16_t
ElfN_Sword #uint32_t
ElfN_Word #uint32_t
ElfN_Sxword #uint64_t
ElfN_Xword #uint64_t
MACRO ==> #Voici :
EI_NIDENT #16 (taille de e_indent)
HEADER GENERAL ==> #Voici :
ElfN_Ehdr #Struct désignant l'header général. Voici sa structure,
#dans l'ordre :
e_ident #unsigned char[EI_NIDENT]. Informations générales. Des
#macros EI_* désignent l'index de chaque octet (0 à 15).
#Chaque octet doit avoir une valeur == l'une des macros
#ELF* en général.
e_ident[EI_MAG0] #Premier octet du magic number.
#Doit être égal à ELFMAG0 (0x7f)
#EI_MAG0 == 0.
e_ident[EI_MAG1] #Deuxième octet du magic number.
#Doit être égal à ELFMAG1 (0x45, soit 'E')
#EI_MAG0 == 1.
e_ident[EI_MAG2] #Troisième octet du magic number.
#Doit être égal à ELFMAG2 (0x4c, soit 'L')
#EI_MAG0 == 2.
e_ident[EI_MAG3] #Quatrième. octet du magic number.
#Doit être égal à ELFMAG3 (0x46, soit 'F')
#EI_MAG0 == 3.
e_ident[EI_CLASS] #Architecture 32/64 bits. Valeurs :
# - ELFCLASSNONE (0) : architecture invalide
# - ELFCLASS32 (1) : architecture 32 bits
# - ELFCLASS64 (2) : architecture 64 bits
#EI_CLASS == 4.
e_ident[EI_DATA] #Endianness et signedness. Valeurs :
# - ELFDATANONE (0) : endianness inconnue
# - ELFDATA2LSB (1) : little-endian et 2's complement
# - ELFDATA2MSB (2) : big-endian et 2's complement
#EI_DATA == 5.
e_ident[EI_VERSION] #Version d'ELF. Valeurs :
# - EV_NONE (0) : version invalide
# - EV_CURRENT (1) : dernière version
#EI_VERSION == 6.
e_ident[EI_OSABI] #OS et ABI. Valeurs :
# - ELFOSABI_NONE (0x00)
# - ELFOSABI_SYSV (0x00) : SysV, Unix, Linux
# - ELFOSABI_HPUX (0x01) : HP-UX
# - ELFOSABI_NETBSD (0x02)
# - ELFOSABI_LINUX (0x03)
# - ELFOSABI_SOLARIS (0x06)
# - ELFOSABI_AIX (0x07)
# - ELFOSABI_IRIX (0x08)
# - ELFOSABI_FREEBSD (0x0d)
# - ELFOSABI_TRU64 (0x0a)
# - ELFOSABI_MODESTO (0x0b) : Novell Modesto
# - ELFOSABI_OPENBSD (0x0c)
# - ELFOSABI_ARM (0x61)
# - ELFOSABI_STANDALONE (0xff) : embedded
#EI_OSABI == 7.
e_ident[EI_ABIVERSION] #Version de l'ABI (dépend de e_ident[EI_OSABI]).
#EI_ABIVERSION == 8.
e_ident[EI_PAD] #Suite de 0x00 réservés et utilisés donc comme padding.
#EI_PAD == 9.
e_type #Type du fichier (uint16_t). Valeurs :
# - ET_NONE (0) : type inconnu
# - ET_REL (1) : [relocatable] object file
# - ET_EXEC (2) : exécutable
# - ET_DYN (3) : shared library
# - ET_CORE (4) : core file
e_machine #Architecture (CPU) (uint16_t). Valeurs :
# - EM_NONE (0x00) : inconnu
# - EM_M32 (0x01) : AT&T WE32 100
# - EM_SPARC (0x02)
# - EM_386 (0x03) : x86
# - EM_68K (0x04) : Motorola 68000
# - EM_88K (0x05) : Motorola 88000
# - EM_860 (0x07) : Intel 80860
# - EM_MIPS (0x08) : MIPS RS3000, big-endian
# - EM_PARISC (0x0f) : HP/PA
# - EM_SPARC32PLUS (0x12) : SPARC avec intruction set
# enhanced
# - EM_PPC (0x14) : PowerPC 32 bits
# - EM_PPC64 (0x15) : PowerPC 64 bits
# - EM_S390 (0x16)
# - EM_ARM (0x28)
# - EM_SH (0x2a) : SuperH
# - EM_SPARCV9 (0x2b)
# - EM_IA_64 (0x32)
# - EM_X32_64 (0x3e)
# - EM_VAX (0x4b)
e_version #Version du fichier ? (uint32_t). Valeurs : EV_NONE ou
#EV_CURRENT.
e_entry #ADR virtuelle de l'entry point (début du code à
#exécuter, normalement main() en C, ou plus exactement
#une fonction d'introduction, menant ensuite à main())
#(ElfN_Addr). 0 si pas d'entry point.
e_phoff #Offset (octets) de la pht par rapport au début du
#fichier ELF (ElfN_Off). 0 si pas de pht.
e_shoff #Pareil, mais pour la sht
e_flags #Flags du CPU ? (uint32_t)
e_ehsize #Taille (octets) du general header (uint16_t)
e_phentsize #Taille (octets) de la pht (uint16_t)
e_phnum #Nombre d'entrées de la pht (uint16_t). 0 si pas de pht.
e_shentsize #Comme e_phentsize, mais pour la sht.
e_shnum #Comme e_phnum, mais pour la sht.
e_shstrndx #Index de la section name string table (.shstrtab) dans
#la SHT (si aucune, == SHN_UNDEF)
┌─────────┐
│ PHT │
└─────────┘
PHT ==> #Voici :
#Il s'agit d'une array de ElfN_Phdr.
+---------------------------------+(--------------------------------)
| Type | Droit d'accès (64) )
+---------------------------------+(--------------------------------)
0x00 NULL
0x01 LOAD Exécution
0x02 DYNAMIC Ecriture
0x03 INTERP
0X04 NOTE Lecture
0x06 PHDR
0x07 TLS
0x6474e550 GNU_EH_FRAME
0x6474e551 GNU_STACK
0x6474e552 GNU_RELRO
+---------------------------------+---------------------------------+
| Offset fichier (32 ou 64) | Adr virtuelle (32 ou 64) |
+---------------------------------+---------------------------------+
| Adr physique (32 ou 64) | Taille dans fichier (32 ou 64) |
+---------------------------------+---------------------------------+
+---------------------------------+(----------------)+
| Taille dans mémoire (32 ou 64) |Droit d'acces (32)|
+---------------------------------+(----------------)+
+---------------------------------+
| alignement (32 ou 64) |
+---------------------------------+
ElfN_Phdr #Struct désignant un programme header. Dans l'ordre :
p_type #Type (uint32_t). Peut être :
# - PT_NULL (0) : header ignoré
# - PT_LOAD (1) : segment à charger en mémoire
# (inclue en général les autres
# segments) lors exécution. En
# général deux (sauf core files)
# principaux.
# - PT_DYNAMIC (2) : contient .dynamic
# - PT_INTERP (3) : contient .interp
# - PT_NOTE (4) : contient des infos secondaires
# (.note*)
# - PT_SHLIB (5) : jamais utilisé
# - PT_PHDR (6) : la PHT elle-même
# - PT_TLS (7) : contient des data pour les threads
# (.tdata et .tbss)
# - GNU_EH_FRAME (0x6474e550) : contient .eh_frame_hdr
# - GNU_STACK (0x6474e551) : indique droits
# d'exécution du stack, mais ne contient pas de
# sections. Permet d'éviter une attaque par buffer
# overflow en mettant ce segment RW- et non RWE.
# Normalement, automatiquement fait par gcc, sauf
# lorsqu'il (ou nasm) assemble un fichier ASM FILE.S,
# auquel cas il faut rajouter dans ce fichier :
#
#%ifidn __OUTPUT_FORMAT__,elf
#section .note.GNU-stack noalloc noexec nowrite progbits
#%endif
#%ifidn __OUTPUT_FORMAT__,elf32
#section .note.GNU-stack noalloc noexec nowrite progbits
#%endif
#%ifidn __OUTPUT_FORMAT__,elf64
#section .note.GNU-stack noalloc noexec nowrite progbits
#%endif
#
# - GNU_RELRO (0x6474e552) : segment devient read-
# only après relocation
# (utilisé par les
# libraries)
# - PT_LOPROC (0x70000000) et PT_HIPROC (0x7fffffff) :
# valeurs > et < à elles sont réservées
p_offset #Offset du segment depuis début du fichier (ElfN_Off)
p_vaddr #Adresse virtuelle (ElfN_Addr)
p_paddr #Adresse physique (ElfN_Addr)
p_pfilesz #Taille dans le fichier (uintN_t)
p_memsz #Taille dans la mémoire (uintN_t)
p_flags #Droit d'accès flags (uint32_t) (attention : après
#p_type si N == 64), doit être or'd :
# - PF_X (1) : exécution
# - PF_W (2) : écriture
# - PF_R (4) : lecture
p_align #Alignement en mémoire (uintN_t), créant donc un padding
┌─────────┐
│ SHT │
└─────────┘
SHT ==> #Voici :
#Il s'agit d'une array de ElfN_Shdr.
#Elle suit en général .shstrtab (header string table
#section), un array de strings utilisés comme nom pour
#les sections.
#L'élément [0] est une section NULL.
+---------------------------------+---------------------------------+
| Name | Type |
+---------------------------------+---------------------------------+
| Droit d'accès (32 ou 64) | Adresse (32 ou 64) |
+---------------------------------+---------------------------------+
0x01 Exécution
0x02 Ecriture
0X04 Lecture
+---------------------------------+---------------------------------+
| Offset fichier (32 ou 64) | Taille (32 ou 64) |
+---------------------------------+---------------------------------+
| Link | Info |
+---------------------------------+---------------------------------+
| Alignement (32 ou 64) | Entsize (32 ou 64) |
+---------------------------------+---------------------------------+
ElfN_Shdr #Struct désignant une section. Dans l'ordre :
sh_name #Offset du nom dans la section dans .shstrtab (uint32_t)
sh_type #Type (uint32_t). Peut être :
# - A FAIRE
sh_flags #Droit d'accès et flags (uintN_t), doit être or'd :
# - SHF_WRITE (0x1) : écriture possible
# - SHF_ALLOC (0x2) : la section sera chargée en
# mémoire. Pas le cas par
# exemple des sections de
# debuggage, des symboles,
# etc.
# - SHF_EXECINSTR (0x4) : la section contient du
# code exécutable
# - SHF_MERGE (0x10) : peut être merged ?? (vient
# souvent avec SHF_STRINGS)
# - SHF_STRINGS (0x20) : contient des strings
# - SHF_INFO_LINK (0x40) : ???
# - SHF_LINK_ORDER (0x80) : preserve order after
# combining ???
# - SHF_GROUP (0x200) : membre d'un groupe ???
# - SHF_TLS (0x400) : contient des data propres
# aux threads
# - SHF_X86_64_LARGE (0x10000000) : pour x86_64,
# section pouvant contenir
# plus de 2Go
# - SHF_X86_64_UNWIND (0x70000001) : pour x86_64,
# .eh_frame
sh_addr #Adresse (ElfN_Addr)
sh_offset #Offset du segment depuis début du fichier (ElfN_Off)
sh_size #Taille (uintN_t)
sh_link #Section header table index link ?? (uint32_t)
sh_info #Extra info, dépend du type ?? (uint32_t)
sh_addralign #Alignement en mémoire (uintN_t), créant donc un padding
sh_entsize #Si section est une array, taille de chaque entrée
#(uintN_t)
┌──────┐
│ │
└──────┘
A NOTER ==> #L'offset dans le fichier ELF semble égale à la
#virtual adress & 0x00000fff. Ex : 0x8048340 ==> 0x340
#Les sections sont les plus petites unités. Elles se
#suivent les unes après les autres.
#Un segment comprend une ou plusieurs sections. Un
#segment peut en recouper un autre (en général cibler
#une sous-partie d'un autre segment).
Exemple de fichier ELF (pour exécutable ; ! signifie indispensable, [] pour pas courant):
SECTIONS SEGMENTS FLAG ALIGN TAILLE SECT_TYPE FLAGS ALIGN LK ES INF
vide 0 NULL
---+
!ELF header(pas sec.)| 52|64 rien ?
!PHT |] [PHDR] R E 4 32 rien ?
.interp |] INTERP R 1 0x13 PROGBITS A 1
.note.ABI-tag |-+ R 4 0x20 NOTE A 4
| | NOTE
| |
!.note.gnu.build-id |-+ 0x24 NOTE A 4
.hash | HASH A 4 5-6 4
.gnu.hash | GNU_HASH A 4 5-6 4
.dynsym | DYNSYM A 4 6-7 10 1
.dynstr | STRTAB A 1
petit vide |
.gnu.version | VERSYM A 2 5-6 2
.gnu.version_r | # VERNEED A 4 6-7 1-10
.rel.dyn | LOAD R E 0x1000 # REL A 4 5-6 8
.rel.got | # REL A 4 5-6 8 20
.rel.bss | # REL A 4 5-6 8 24
.rel.plt | REL A 4 5-6 8 12|13
.init | 0x30 PROGBITS AX 4
.plt | PROGBITS AX 4 4
!.text | PROGBITS AX 16
.fini | 0x1c PROGBITS AX 4
!.rodata | PROGBITS A 4|8|16|32
[.eh_frame_hdr] |] GNU_EH_FRAME R 4 PROGBITS A 4
.eh_frame | PROGBITS A 4
[.gcc_except_table] | PROGBITS A 1
---+
[.tdata] ---+--+ R 4 0x04 NOBITS A WT 4
[.tbss] |--+ TLS R 4 0x04 NOBITS A WT 4
|
.ctors |--+ # PROGBITS A W 4
.dtors | | [GNU_RELRO] R 1 # PROGBITS A W 4
.jcr | | 0x04 PROGBITS A W 4
[.data.rel.ro] | | # PROGBITS A W 4|8|16|32
.dynamic | |] DYNAMIC RW 4 # DYNAMIC A W 4 6-7 8
.got |--+ # PROGBITS A W 4 4
.got.plt | PROGBITS A W 4 4
!.data | LOAD RW 0x1000 PROGBITS A W 4|8|16|32
!.bss | NOBITS A W 4|8|16|32
---+
aucune section ] GNU_STACK RW 4 0
Jamais chargées en mémoire en runtime :
- utilisé pour le debuggage :
[.comment] ? PROGBITS MS 1 1 pas courant car stripped ?
[.debug_aranges] ? PROGBITS 1
[.debug_pubnames] ? PROGBITS 1
[.debug_info] ? PROGBITS 1
[.debug_abbrev] ? PROGBITS 1
[.debug_line] ? PROGBITS 1
[.debug_str] ? PROGBITS MS 1 1
[.debug_loc] ? PROGBITS 1
[.debug_macinfo] ? PROGBITS 1
[.gnu_debuglink] ? PROGBITS 1
[.shstrtab] ? STRTAB 1 pas courant car stripped ?
- utilisé pour le loading :
!SHT (pas de section)
[.symtab] ? SYMTAB 4 37 10 53 pas courant car stripped ?
[.strtab] ? STRTAB 1 pas courant car stripped ?
------------
.interp : section désignant le loader (c-string) à utiliser pour loader les shared libraries needed, en général "/lib/ld-linux.so.?" pour x86 et "/lib64/ld-linux-x86-64.so.2" pour x86_64
.note.ABI-tag :
.note.gnu.build-id :
.hash : hash table "historique", non utilisée (seulement backward compatibility)
.gnu.hash : hash table des symboles
.dynsym : Contient type des valeurs d'une array utilisée par le loader pour la relocation
.dynstr : Contient valeurs (strings, entiers et adresses) de cet array
.gnu.version :
.gnu.version_r :
.rel.dyn :
.rel.got :
.rel.bss :
.rel.plt :
.init : fonction exécutée au début, invoque main() ensuite
.plt : PLT (procedure linkage table)
.text : main(), et procédure appelées par lui.
.fini : fonction exécutée à la fin
.rodata :
- comme .data, mais celles const
- aussi les STR_LIT passées en argument.
.eh_frame_hdr : frame unwind info (Exception Handling)
.eh_frame :
.gcc_except_table :
---------------
.tdata :
.tbss :
.ctors :
.dtors :
.jcr :
.data.rel.ro :
.dynamic :
.got : GOT
.got.plt : GOT.PLT
.data : data globales initialisées
.bss :
- data globales non-initialisées
- en général ce sont des pointeurs (dont les buffers et les pointeurs devant être alloués dynamiquement), car les autres sont "optimized out" par le compiler
- prend de la place en mémoire, mais pas dans le fichier ELF
-------------
.comment :
.debug_aranges :
.debug_pubnames :
.debug_info :
.debug_abbrev :
.debug_line :
.debug_str :
.debug_loc :
.debug_macinfo :
.gnu_debuglink :
.shstrtab : array des strings étant le nom des sections
.symtab : array d'informations sur chaque symbole (dont leur index dans .strtab)
.strtab : array des strings étant le nom des symboles
_______________________________
Trois arrays de noms de symboles
- .shstrtab : array de noms des sections (première section est null)
- .strtab (première valeur est null string)
- .dynstr (première et dernière value sont null string)
- ne se recoupent pas : différence entre les deux dernières ???
Deux arrays de valeurs et types de symboles (ElfN_Sym) :
- .symtab :
- première partie (terminée par un null ElfN_Sym), correspondant avec .shstrtab
- pas de st_name ; st_value == adresse de la section link-time ; st_size == 0 ; STT_SECTION ; STV_DEFAULT ; index du nom dans la .shstrtab
- seconde partie, correspondant avec .strtab
- .dynsym, correspondant avec .dynstr
ElfN_Sym #Représente un symbole.
#.symtab et .dynsym sont des arrays de ElfN_Sym.
#Dans l'ordre (32 bits ; st_value et st_size sont à la
#fin si 64 bits) :
st_name #(uint32_t), offset du nom du symbole dans la string
#symbol table correspondante (.strtab pour .symtab,
#.dynstr pour .dynsym)
st_value #(ElfN_Addr) Valeur du symbole (adresse link-time)
st_size #(uintN_t) Taille du symbole (si pas connu link-time, == 0)
st_info #(UCHAR_VAL) Type ou binding.
#Type :
# - STT_NOTYPE (0) : type indéfini
# - STT_OBJECT (1) : data object
# - STT_COMMON (5) : common data object
# - STT_TLS (6) : thread-local data object
# - STT_FUNC (2) : fonction / code exécutable
# - STT_SECTION (3) : section (en général STB_LOCAL)
# - STT_FILE (4) : fichier (en général STB_LOCAL)
#Binding :
# - STB_LOCAL (0x00) : local au fichier
# - STB_GLOBAL (0x10) : global
# - STB_WEAK (0x20) : weak symbol (comme global, mais global peuvent les remplacer)
st_other #(UCHAR_VAL) Symbol visibility :
# - STV_DEFAULT (0) :
# - STV_INTERNAL (1) :
# - STV_HIDDEN (2) :
# - STV_PROTECTED (3) :
st_shndx #(uint16_t) Index de la section utilisant ce symbole dans la SHT. Valeurs spéciales :
# - SHN_UNDEF (0) : section indéfinie
# - SHN_ABS (0xfff1) : pas de sections (par exemple pour les STT_FILE)
Autres arrays de symboles values (ElfN_Rel[a]) :
- .rel.plt : array d'éléments de deux octets (une adresse + un type "info")
- .rel.dyn : même chose
ElfN_Rel #Désigne la relocation d'un symbole (sans addend). Membres : cf ElfN_Rel
ElfN_Rela #Désigne la relocation d'un symbole (sans addend). Membres :
r_offset #(ElfN_Addr)
r_info #(uintN_t) donne à la fois (or'd) symbol table index, et relocation à appliquer.
#Relocation :
# - R_386_NONE (0) : pas de relocation
# - R_386_32 (1) : direct
# - R_386_PC32 (2) : PC relative
# - R_386_GOT32 (3) : GOT entry
# - R_386_PLT32 (4) : PLT address
# - R_386_COPY (5) : copy symbol at runtime
# - R_386_GLOB_DAT (6) : relocation crée une GOT entry
# - R_386_JMP_SLOT (7) : relocation crée une PLT entry
# - RELATIVE (8) : adjust by program base
# - R_386_GOTOFF (9) : offset to GOT
# - R_386_GOTPC (10) : PC relative offset to GOT
r_addend #(intN_t) (ElfN_Rela uniquement)
.dynamic : indique shared libraries needed, offset GOT, etc. (array d'élement de deux octets, ElfN_Dyn)
ElfN_Dyn #
d_tag #(ElfN_Sword) :
# - DT_NULL (0) : fin de .dynamic
# - DT_NEEDED (1) : needed library (String table offset)
# - DT_PLTRELSZ (2) : Size in bytes of PLT relocs
# - DT_PLTGOT (3) : Address of PLT and/or GOT
# - DT_HASH (4) : Address of symbol hash table
# - DT_STRTAB (5) : Address of string table
# - DT_SYMTAB (6) : Address of symbol table
# - DT_RELA (7) : Address of Rela relocs table
# - DT_RELASZ (8) : Size in bytes of Rela table
# - DT_RELAENT (9) : Size in bytes of a Rela table entry
# - DT_STRSZ (10) : Size in bytes of string table
# - DT_SYMENT (11) : Size in bytes of a symbol table entry
# - DT_INIT (12) : Address of the initialization function
# - DT_FINI (13) : Address of the termination function
# - DT_SONAME (14) : String table offset to name of shared object
# - DT_RPATH (15) : String table offset to library search path (dep‐ recated)
# - DT_SYMBOLIC (16) : Alert linker to search this shared object before the executable for symbols
# - DT_REL (17) : Address of Rel relocs table
# - DT_RELSZ (18) : Size in bytes of Rel table
# - DT_RELENT (19) : Size in bytes of a Rel table entry
# - DT_PLTREL (20) : Type of reloc the PLT refers (Rela or Rel)
# - DT_DEBUG (21) : Undefined use for debugging
# - DT_TEXTREL (22) : Absence of this indicates no relocs should apply to a nonwritable segment
# - DT_JMPREL (23) : Address of reloc entries solely for the PLT
# - DT_BIND_NOW (24) : Instruct dynamic linker to process all relocs before transferring control to the executable
# - DT_RUNPATH (29) : String table offset to library search path
d_un #Union de d_val et d_ptr, valeur du d_tag (ou bien une valeur (d_val) ou une virtual adress (d_ptr))
d_val #(ElfN_Word)
d_ptr #(ElfN_Addr)
_DYNAMIC[] #Array des ElfN_Dyn du fichier ELF.
.got : la GOT
.got.plt : les entrées PLT pour la GOT
.plt : la PLT
_______________________________
core files : un semble de segments LOAD (pas de sections, ni se SHT), alignement 0x1000, flags RE ou RWE, qui se suivent, avec tailles % 0x1000 + 1 segment NOTE (contenant signal ayant causé crash, pending & held signals, PID, PPID, UID, niceness, user & system time, valeurs des registres (dont $eip)). Un grand mystère.
object files : pas de segments, ni de PHT. Seuls sont présents :
- .text, mais avec juste le code assemblé, sans toutes les fonctions d'enrobage ajoutées autour après linking
- .data / .data1
- .bss
- [[.eh_frame]]
- .comment
- .shstrtab
- .symtab
- .strtab
- souvent des .debug*
- plein de .rela.debug.* couplé avec .debug.* (s'il y en a) + .rela.text
Le reste (différence avec un exécutable) est sûrement ajouté par le linker
shared object files :
- segments : pas de INTERP
- sections :
- pas de :
- .interp
- .note.ABI-tag
- pas de main()
- mappage virtual adresses != exécutable
Lors de l'éxécution d'un exécutable, les segments sont loaded, .bss est zeroed, puis le control est passé à ld.so
ld charge les segments des shared objects needed, en commençant par libc.so, et "update the link map, perform relocations"
Et les segments utilisés des shared objects (libraries) sont ensuite rajoutés après lors du runtime + finalement le heap + un vide + le stack (qui descend) + argv et arge
Le stack a toujours l'air d'avoir l'adresse virtuelle 0xbfffffff
Chargement en mémoire de l'exécutable :
- un ensemble de 3 (ou +) memory segment pour chaque shared object (library) needed
- un memory segment pour chaque segments LOAD (le premier RX, le deuxième R), le tout commençant à 0x8048000. Il y a parfois un memory segment vide (sans R, ni W ni X) entre les deux : étrange.
- .data et .bss semblent aussi avoir chacun leur memory segment (RW) à part ensuite. .bss semble ne pas avoir de mem segment quand aucun .bss n'est en fait utilisé (même si au moins 8 octets seront alloués après .data pour un mini .bss inutile) ????
- puis un memory segment pour le heap (si besoin de un)
- puis un autre mem segment pour le stack : vide (pouvant être occupé par stack), puis stack (descendant, avec au top : argc, argv (argv[0] étant le program name) + arge, argv et arge étant des char*[], elles se terminent par un '\00000000')
- parfois des memory segments de 64Ko ou + (RWX) s'insèrenet entre deux libs... étrange
Memory segment = 1 ou plusieurs pages.
On peut exécuter un fichier ASM sans utiliser un driver en C :
- après assemblage, on a juste un fichier objet, pour le rendre exécutable : ld FICHIER.o
- ld s'attend à ce que l'entry point soit _start() (ce qui est fait avec gcc automatiquement), donc la fonction principale du fichier principale doit être _start
- la fonction principale doit faire un clean exit, c'est-à-dire appeler sys_exit()
- ld directement, sans la "case gcc", n'ajoute pas toutes les sections comme .init, .fini, .got, etc. Les seules sections présentes sont celles définies, au minimum .text, et ensuite peut-être .data ou .bss. Du coup, le fichier est vraiment moins gros (mais les sections ajoutées par gcc sont utiles !) .shstrtab, .symtab et .strtab sont cependant rajoutés.