GCC est un compilateur imposant. Avoir un compilateur légé est chose aisée : on peut penser à nasm. Seulement, la création des fichier ELF passe toujours par LD. Le problème de LD c'est qu'il fait partie de l'environnement de développement standard qui lui-même dépend de libc6/glibc2... et libc6/glibc2 est une librairie trop lourde pour être utilisable sur les petits systèmes.

Mais il existe une solution qui vous permettra de créer des fichiers ELF sans même passer par un lieur. L'avantage de cette solution et qu'elle vous permet de créer des véritable fichiers ELF sous un environnement restreint, et vous permettra même, le fin-du-fin, de faire de la cross-compilation, c'est à dire de créer sous Windows des binaires ELF destinés à fonctionner sous Linux.

Ceci, je l'espère, rendra service à tous/toutes ceux/celles qui travail sur des adaptation de Linux (petit PCs, système embarqué à peu de frais, etc).

Vous pourrez conculter un exposé détaillé de la question ici : Création de fichier ELF pour Linux, sans utiliser de lieur.

La solution passe par l'utilisation de deux pattern au choix. Vous utiliserez le premier pour les applications nécessitant un segement de code ainsi qu'un segment de données en lecture/écriture. Le second pattern sera à utiliser pour les applications ne nécessitant qu'un segement de code (notez que les donnée en lecture seule pourront être placées dans le segment de code).

Sans plus tarder, allons droit au but, voici les deux patterns éditable :

elf-with-data.asm
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
; (hint:tabulation size is 3)
; (date-dd-mm-yyyy:03/01/2007)
 
; Creating a fully functional ELF file without even GNU/ld
; ---------------------------------------------------------
; 
; This a pattern file which allow you to create ELF executable without
; even a linker in hands. This is useful for custom installation with
; low resource, such as old PC. Indeed, the usual way is to use GNU/ld,
; but unfortunatly, ld rely on glibc, which is very-very hugh en
; outrageously resource consuming.
;
; You can use it with nasm (the syntax used here is the one of nasm).
; A static version of nasm if very light (between 150 and 200KB). So
; with a static version of e3 (which is no more than 13KB), and
; a few text files documentations about syscalls and some other good
; stuff, you can have a real developpement environement under less
; than the quarter of an 1.44M floppy disk.
;
; Please visit http://www.les-ziboux.rasama.org/elf-without-ld.html
; for updates. In the futur, I will mirror a very small static version
; of nasm (102KB), a static version of e3, and some useful texte
; documentation.
;
; You can use this pattern in any project... it is not mandatory, but this
; would be very nice of you to put this url on top of your product sources :
; http://www.les-ziboux.rasama.org/elf-without-ld.html
; Thank you :)
;
; To use this pattern, just edit the place between the BEGIN and END mark,
; both in code and data segment.
;
; If you code only adress read-only data, then you can use the other
; "elf-simple.asm", beceause is there are only read-only datas, it is
; best to put them in code segment.
;
; Finaly you have to compile your code with "nasm -f bin [-O2] yourcode.asm"
; (the -O parameter is optional, alghtough often requited because of
; short-jumps and some stuff like that).
 
; This file is full of comments... you may remove them after reading ;)
;
; Comments are welcome : les-ziboux@rasama.org (fr/en)
; You wanna learn Arabic ? -> http://www.les-ziboux.rasama.org (fr)
 
cpu 386
bits 32
 
org 0x08048000 ; Linux applications are loaded at this virtual address.
 
; === Header ================================================================
 
elf_header:
.start
   db 0x7F, "ELF"          ; ELF signature                 -- constant
   db 1                    ; Architecture(1)               -- 1 = 32 bits
   db 1                    ; Data enconding                -- 1 = LSB-First
   db 1                    ; File version                  -- 1 = v1
   db 0,0,0,0,0,0,0,0,0    ; 9 bytes padding               -- should be zero
   dw 2                    ; Type                          -- 2 = executable
   dw 3                    ; Architecture(2)               -- 3 = i386
   dd 1                    ; ELF Version                   -- 1 = ELF-v1
   dd _start               ; Entry point adress in memory  -- virtual adress
   dd segments_table - $$  ; Segments table offset in file
   dd 0                    ; Sections table offset in file -- 0 = none)
   dd 0                    ; File's flags
   dw elf_header.size      ; ELF Header's size
   dw 32                   ; Segments table entries's size
   dw 2                    ; Number of segment descriptors
   dw 0                    ; Sections table entries's size -- 0 = none
   dw 0                    ; Number of sections descriptor -- 0 = none
   dw 0                    ; String table index            -- 0 = none
.size equ $ - .start
 
segments_table:
 
code_segment_descriptor:
.start:
   dd 1                    ; Type            -- 1 = loadable into memory
   dd 0                    ; Offset in file  -- include ELF header and table
   dd $$                   ; Virtual address in memory
   dd 0                    ; Physical adress -- 0 = no physical address
   dd code_size            ; Size in file
   dd code_size            ; Size in memory
   dd 5                    ; Permission flags -- 0x4 + 0x1 = read and execute
   dd 0x4                  ; Alignment in memory (and in file)
.size equ $ - .start
 
data_segment_descriptor:
.start:
   dd 1                    ; Type -- 1 = loadable into memory
   dd _data - $$           ; Offset in file
   dd _data                ; Virtual adress in memory
   dd 0                    ; Physical adress -- 0 = no physical address
   dd data_size            ; Size in file
   dd data_size            ; Size in memory
   dd 6                    ; Permission flags -- 0x4 + 0x2 = read and write
   dd 0x4                  ; Alignment in memory (and in file)
.size equ $ - .start
 
; === Code ==================================================================
 
_code :
 
_start: ; You can move the start label where-ever you want in code segment.
 
   ; ----- BEGIN of your code -----
 
   ; Here is a sample code which simply say good bye and terminate.
   ; It give an example of usage of both code segment and data
   ; segment. Although this example does write to data segment,
   ; the data segment is still fully writable. Note that read-only
   ; datas can also reside in code segment (you should use
   ; the pattern "elf-simple.asm" for this purpose).
   ; You can put your own code between the BEGIN and END mark.
   ; Do not modify something else, unless you're sure about what
   ; you are playing with.
 
   mov  eax, 4                ; function id for sys_write
   mov  ebx, 1                ; descriptor of standard output
   mov  ecx, message          ; offset of bytes to write
   mov  edx, message.length   ; number of bytes to write
   int  0x80                  ; syscall
 
   mov  eax, 1                ; function id for sys_exit
   mov  ebx, 0                ; return code from the program (0 mean Ok)
   int  0x80                  ; syscall
 
   ; ----- END of your code -----
 
align 4
code_size equ $ - $$
 
; === Data ==================================================================
 
align 4
_data:
 
   ; ----- BEGIN of your datas -----
 
   ; This is a simple data example. This data segment is writable.
   ; Note that you can put read-only data in the code segment. If you
   ; only have read-only data, and no writable data in you application,
   ; then putting them in code segmet, avoid the creation of a data
   ; segment, reducing a bit the size of the executable. For this
   ; purpose, use the other patten name "elf-simple.asm".
   ; You can put your own datas between the BEGIN and END mark.
   ; Do not modify something else, unless you're sure about what
   ; you are playing with.
 
message:
   db "Bye, Au-revoir, Ma'a as-salama, Bisbald ... :)", 10
.length equ $ - message
 
   ; ----- END of your datas -----
 
align 4
data_size equ $ - _data
La deuxième version du pattern, pour les applications qui ne nécessite rien de plus qu'un simple segment de code.

elf-simple.asm
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
 
; (hint:tabulation size is 3)
; (date-dd-mm-yyyy:03/01/2007)
 
; Creating a fully functional ELF file without even GNU/ld
; ---------------------------------------------------------
;
; There are no explanations here : read "elf-with-data.asm" for
; informations on usage and copyright.
;
; Compile: nasm -f bin [-O2] yourcode.asm
; Updates : http://www.les-ziboux.rasama.org/elf-without-ld.html
; Comments are welcome : les-ziboux@rasama.org (fr/en)
; You wanna learn Arabic ? -> http://www.les-ziboux.rasama.org (fr)
 
cpu 386
bits 32
 
org 0x08048000 ; Linux applications are loaded at this virtual address.
 
; === Header ================================================================
 
elf_header:
.start
   db 0x7F, "ELF"          ; ELF signature                 -- constant
   db 1                    ; Architecture(1)               -- 1 = 32 bits
   db 1                    ; Data enconding                -- 1 = LSB-First
   db 1                    ; File version                  -- 1 = v1
   db 0,0,0,0,0,0,0,0,0    ; 9 bytes padding               -- should be zero
   dw 2                    ; Type                          -- 2 = executable
   dw 3                    ; Architecture(2)               -- 3 = i386
   dd 1                    ; ELF Version                   -- 1 = ELF-v1
   dd _start               ; Entry point adress in memory  -- virtual adress
   dd segments_table - $$  ; Segments table offset in file
   dd 0                    ; Sections table offset in file -- 0 = none)
   dd 0                    ; File's flags
   dw elf_header.size      ; ELF Header's size
   dw 32                   ; Segments table entries's size
   dw 1                    ; Number of segment descriptors -- just one (code)
   dw 0                    ; Sections table entries's size -- 0 = none
   dw 0                    ; Number of sections descriptor -- 0 = none
   dw 0                    ; String table index            -- 0 = none
.size equ $ - .start
 
segments_table:
 
code_segment_descriptor:
.start:
   dd 1                    ; Type            -- 1 = loadable into memory
   dd 0                    ; Offset in file  -- include ELF header and table
   dd $$                   ; Virtual address in memory
   dd 0                    ; Physical adress -- 0 = no physical address
   dd code_size            ; Size in file
   dd code_size            ; Size in memory
   dd 5                    ; Permission flags -- 0x4 + 0x1 = read and execute
   dd 0x4                  ; Alignment in memory (and in file)
.size equ $ - .start
 
; === Code ==================================================================
 
_code :
 
_start: ; You can move the start label where-ever you want in code segment.
 
   ; ----- BEGIN of your code -----
 
   ; Here is a sample code which simply cleanly terminate :P
 
   mov  eax, 1                ; function id for sys_exit
   mov  ebx, 0                ; return code from the program (0 mean Ok)
   int  0x80                  ; syscall
 
   ; ----- END of your code -----
 
   ; You may have read-only data here as well ;)
 
align 4
code_size equ $ - $$