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
|
(* This is a module to spit simple ELF
object files that can afterwards be
linked to build an application.
*)
let hash s =
(* The ELF hash function. *)
let open Int64 in (* I doubt this is necessary... *)
let rec f p h =
if p = String.length s then to_int h else
let h = shift_left h 4 in
let h = add h (of_int (int_of_char s.[p])) in
let g = logand h (of_int 0xf0000000) in
let h = logxor h (shift_right g 24) in
f (p+1) (logand h (of_int 0x0fffffff)) in
f 0 (of_int 0)
let le n x =
(* Make a string of bytes in little endian convention. *)
let b = Bytes.create n in
let rec f i x =
if i = n then () else
let d = char_of_int (x land 0xff) in
Bytes.set b i d;
f (i+1) (x lsr 8) in
f 0 x; Bytes.to_string b
let stt_NOTYPE = 0
let stt_OBJECT = 1
let stt_FUNC = 2
let stb_LOCAL = 0
let stb_GLOBAL = 16
let stb_WEAK = 32
let sht_NULL = le 4 0
let sht_PROGBITS = le 4 1
let sht_SYMTAB = le 4 2
let sht_STRTAB = le 4 3
let sht_RELA = le 4 4
let sht_NOTE = le 4 7
let sht_NOBITS = le 4 8
let shf_WRITE = 1
let shf_ALLOC = 2
let shf_EXECINSTR = 4
let barebones_elf oc fn text =
let header = String.concat ""
[ "\x7fELF" (* e_ident, magic *)
; "\x02" (* e_ident, ELFCLASS64 *)
; "\x01" (* e_ident, ELFDATA2LSB *)
; "\x01" (* e_indent, EV_CURRENT *)
; "\x00" (* e_ident, ELFOSABI_SYSV *)
; "\x00" (* e_ident, ABI version *)
; "\x00\x00\x00\x00\x00\x00\x00" (* e_ident, padding *)
; "\x01\x00" (* e_type, ET_REL *)
; "\x3e\x00" (* e_machine, EM_X86_64 *)
; "\x01\x00\x00\x00" (* e_version, EV_CURRENT *)
; "\x00\x00\x00\x00\x00\x00\x00\x00" (* e_entry, unused *)
; "\x00\x00\x00\x00\x00\x00\x00\x00" (* e_phoff, unused *)
; "\x40\x00\x00\x00\x00\x00\x00\x00" (* e_shoff, 64 *)
; "\x00\x00\x00\x00" (* e_flags, 0 *)
; "\x40\x00" (* e_hsize, 64 *)
; "\x00\x00" (* e_phentsize, 0 *)
; "\x00\x00" (* e_phnum, 0 *)
; "\x40\x00" (* e_shentsize, 64 *)
; "\x07\x00" (* e_shnum, 7 *)
; "\x06\x00" (* e_shstrndx, 6 *)
] in
(* We will use the following section organization.
1- .text PROGBITS
2- .data PROGBITS
3- .bss NOBITS
4- .rela RELA
5- .symtab SYMTAB
6- .strtab STRTAB
*)
let adds s x = (String.length s, s ^ x ^ "\x00") in
(* section names *)
let textstr, strtab = adds "\x00" ".text" in
let datastr, strtab = adds strtab ".data" in
let bssstr , strtab = adds strtab ".bss" in
let relastr, strtab = adds strtab ".rela" in
let symtstr, strtab = adds strtab ".symt" in
let strtstr, strtab = adds strtab ".strt" in
(* function names *)
let fnstr, strtab = adds strtab fn in
let symtab = String.concat ""
[ le 0x18 0 (* first symbol is reserved *)
; le 4 fnstr (* st_name *)
; le 1 (stt_FUNC lor stb_GLOBAL) (* st_info *)
; "\x00" (* st_other *)
; le 2 1 (* st_shndx, .text *)
; le 8 0 (* st_value, offset in .text section *)
; le 8 (String.length text) (* st_size *)
] in
let textoff = 64 + 7 * 64 in
let txtlen, txtpad =
let l = String.length text in
let p = (l + 7) land 7 in
(l, p) in
let dataoff = textoff + txtlen + txtpad in
let bssoff = dataoff + 0 in
let relaoff = bssoff + 0 in
let symtoff = relaoff + 0 in
let strtoff = symtoff + String.length symtab in
let sh = String.concat ""
[ le 64 0 (* first section header is reserved *)
(* .text *)
; le 4 textstr (* sh_name *)
; sht_PROGBITS (* sh_type *)
; le 8 (shf_ALLOC lor shf_EXECINSTR) (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 textoff (* sh_offset *)
; le 8 txtlen (* sh_size *)
; le 4 0 (* sh_link *)
; le 4 0 (* sh_info *)
; le 8 1 (* sh_addralign *)
; le 8 0 (* sh_entsize *)
(* .data *)
; le 4 datastr (* sh_name *)
; sht_PROGBITS (* sh_type *)
; le 8 (shf_ALLOC lor shf_WRITE) (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 dataoff (* sh_offset *)
; le 8 0 (* sh_size *)
; le 4 0 (* sh_link *)
; le 4 0 (* sh_info *)
; le 8 1 (* sh_addralign *)
; le 8 0 (* sh_entsize *)
(* .bss *)
; le 4 bssstr (* sh_name *)
; sht_NOBITS (* sh_type *)
; le 8 (shf_ALLOC lor shf_WRITE) (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 bssoff (* sh_offset *)
; le 8 0 (* sh_size *)
; le 4 0 (* sh_link *)
; le 4 0 (* sh_info *)
; le 8 1 (* sh_addralign *)
; le 8 0 (* sh_entsize *)
(* .rela *)
; le 4 relastr (* sh_name *)
; sht_RELA (* sh_type *)
; le 8 0 (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 relaoff (* sh_offset *)
; le 8 0 (* sh_size *)
; le 4 5 (* sh_link, symtab index *)
; le 4 1 (* sh_info, text section *)
; le 8 1 (* sh_addralign *)
; le 8 0x18 (* sh_entsize *)
(* .symtab *)
; le 4 symtstr (* sh_name *)
; sht_SYMTAB (* sh_type *)
; le 8 0 (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 symtoff (* sh_offset *)
; le 8 (String.length symtab) (* sh_size *)
; le 4 6 (* sh_link, strtab index *)
; le 4 1 (* sh_info, first non-local symbol *)
; le 8 1 (* sh_addralign *)
; le 8 0x18 (* sh_entsize *)
(* .strtab *)
; le 4 strtstr (* sh_name *)
; sht_STRTAB (* sh_type *)
; le 8 0 (* sh_flags *)
; le 8 0 (* sh_addr *)
; le 8 strtoff (* sh_offset *)
; le 8 (String.length strtab) (* sh_size *)
; le 4 0 (* sh_link *)
; le 4 0 (* sh_info *)
; le 8 1 (* sh_addralign *)
; le 8 0x18 (* sh_entsize *)
] in
List.iter (output_string oc)
[ header
; sh
; text; String.make txtpad '\x90'
; symtab
; strtab
]
(*
let _ =
let oc = open_out "test.o" in
let text = String.concat ""
[ "\xb8\x2a\x00\x00\x00" (* mov 42, %eax *)
; "\xc3" (* retq *)
] in
barebones_elf oc "main" text
*)
|