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
|
open Endianness
open Error
let decimal_string_of_int64 e =
let i = Int64.to_int e in
string_of_int i
;;
let hex_string_of_int64 (e : Int64.t) : string =
let i = Int64.to_int e in
Printf.sprintf "0x%x" i
;;
let partition_bitstring size bitstring =
Bitstring.takebits size bitstring, Bitstring.dropbits size bitstring
;;
let acquire_bitstring path_to_target =
try
let bitstring = Bitstring.bitstring_of_file path_to_target in
return bitstring
with _ ->
Fail ("acquire_bitstring: cannot open file" ^ path_to_target)
(** Unsigned char type *)
let read_unsigned_char_le bs rest =
bitmatch bs with
| { unsigned : 8 : littleendian } -> return (Uint32.of_int unsigned, rest)
| { _ } -> Fail "read_unsigned_char_le"
;;
let read_unsigned_char_be bs rest =
bitmatch bs with
| { unsigned : 8 : bigendian } -> return (Uint32.of_int unsigned, rest)
| { _ } -> Fail "read_unsigned_char_be"
;;
let read_unsigned_char endian bs =
let cut, rest = partition_bitstring 8 bs in
match endian with
| Little -> read_unsigned_char_le cut rest
| Big -> read_unsigned_char_be cut rest
;;
(** ELF address type:
* 4 byte unsigned type on 32-bit architectures.
* 8 byte unsigned type on 64-bit architectures.
*)
let read_elf32_addr_le bs rest =
bitmatch bs with
| { addr : 32 : littleendian } -> return (Uint32.of_int32 addr, rest)
| { _ } -> Fail "read_elf32_addr_le"
;;
let read_elf32_addr_be bs rest =
bitmatch bs with
| { addr : 32 : bigendian } -> return (Uint32.of_int32 addr, rest)
| { _ } -> Fail "read_elf32_addr_be"
;;
let read_elf32_addr endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf32_addr_le cut rest
| Big -> read_elf32_addr_be cut rest
;;
let read_elf64_addr_le bs rest =
bitmatch bs with
| { addr : 64 : littleendian } -> return (Uint64.of_int64 addr, rest)
| { _ } -> Fail "read_elf64_addr_le"
;;
let read_elf64_addr_be bs rest =
bitmatch bs with
| { addr : 64 : bigendian } -> return (Uint64.of_int64 addr, rest)
| { _ } -> Fail "read_elf64_addr_be"
;;
let read_elf64_addr endian bs =
let cut, rest = partition_bitstring 64 bs in
match endian with
| Little -> read_elf64_addr_le cut rest
| Big -> read_elf64_addr_be cut rest
;;
(** ELF offset type:
* 4 byte unsigned type on 32-bit architectures.
* 8 byte unsigned type on 64-bit architectures.
*)
let read_elf32_off_le bs rest =
bitmatch bs with
| { off : 32 : littleendian } -> return (Uint32.of_int32 off, rest)
| { _ } -> Fail "read_elf32_off_le"
;;
let read_elf32_off_be bs rest =
bitmatch bs with
| { off : 32 : bigendian } -> return (Uint32.of_int32 off, rest)
| { _ } -> Fail "read_elf32_off_be"
;;
let read_elf32_off endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf32_off_le cut rest
| Big -> read_elf32_off_be cut rest
;;
let read_elf64_off_le bs rest =
bitmatch bs with
| { off : 64 : littleendian } -> return (Uint64.of_int64 off, rest)
| { _ } -> Fail "read_elf64_off_le"
;;
let read_elf64_off_be bs rest =
bitmatch bs with
| { off : 64: bigendian } -> return (Uint64.of_int64 off, rest)
| { _ } -> Fail "read_elf64_off_be"
;;
let read_elf64_off endian bs =
let cut, rest = partition_bitstring 64 bs in
match endian with
| Little -> read_elf64_off_le cut rest
| Big -> read_elf64_off_be cut rest
;;
(** ELF half word type:
* 2 byte unsigned type on 32-bit architectures.
* 2 byte unsigned type on 64-bit architecutres.
*)
let read_elf32_half_le bs rest =
bitmatch bs with
| { half : 16 : littleendian } -> return (Uint32.of_int half, rest)
| { _ } -> Fail "read_elf32_half_le"
;;
let read_elf32_half_be bs rest =
bitmatch bs with
| { half : 16 : bigendian } -> return (Uint32.of_int half, rest)
| { _ } -> Fail "read_elf32_half_be"
;;
let read_elf32_half endian bs =
let cut, rest = partition_bitstring 16 bs in
match endian with
| Little -> read_elf32_half_le cut rest
| Big -> read_elf32_half_be cut rest
;;
let read_elf64_half_le bs rest =
bitmatch bs with
| { half : 16 : littleendian } -> return (Uint32.of_int half, rest)
| { _ } -> Fail "read_elf64_half_le"
;;
let read_elf64_half_be bs rest =
bitmatch bs with
| { half : 16 : bigendian } -> return (Uint32.of_int half, rest)
| { _ } -> Fail "read_elf64_half_be"
;;
let read_elf64_half endian bs =
let cut, rest = partition_bitstring 16 bs in
match endian with
| Little -> read_elf64_half_le cut rest
| Big -> read_elf64_half_be cut rest
;;
(** ELF word type:
* 4 byte unsigned type on 32-bit architectures.
* 4 byte unsigned type on 32-bit architectures.
*)
let read_elf32_word_le bs rest =
bitmatch bs with
| { word : 32 : littleendian } -> return (Uint32.of_int32 word, rest)
| { _ } -> Fail "read_elf32_word_le"
;;
let read_elf32_word_be bs rest =
bitmatch bs with
| { word : 32 : bigendian } -> return (Uint32.of_int32 word, rest)
| { _ } -> Fail "read_elf32_word_be"
;;
let read_elf32_word endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf32_word_le cut rest
| Big -> read_elf32_word_be cut rest
;;
let read_elf64_word_le bs rest =
bitmatch bs with
| { word : 32 : littleendian } -> return (Uint32.of_int32 word, rest)
| { _ } -> Fail "read_elf64_word_le"
;;
let read_elf64_word_be bs rest =
bitmatch bs with
| { word : 32 : bigendian } -> return (Uint32.of_int32 word, rest)
| { _ } -> Fail "read_elf64_word_be"
;;
let read_elf64_word endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf64_word_le cut rest
| Big -> read_elf64_word_be cut rest
;;
(** ELF signed word type:
* 4 byte signed type on 32-bit architectures
* 4 byte signed type on 64-bit architectures
*)
let read_elf32_sword_le bs rest =
bitmatch bs with
| { word : 32 : littleendian } -> return (word, rest)
| { _ } -> Fail "read_elf32_sword_le"
;;
let read_elf32_sword_be bs rest =
bitmatch bs with
| { word : 32 : bigendian } -> return (word, rest)
| { _ } -> Fail "read_elf32_sword_be"
;;
let read_elf32_sword endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf32_sword_le cut rest
| Big -> read_elf32_sword_be cut rest
;;
let read_elf64_sword_le bs rest =
bitmatch bs with
| { word : 32 : littleendian } -> return (word, rest)
| { _ } -> Fail "read_elf64_sword_le"
;;
let read_elf64_sword_be bs rest =
bitmatch bs with
| { word : 32 : bigendian } -> return (word, rest)
| { _ } -> Fail "read_elf64_sword_be"
;;
let read_elf64_sword endian bs =
let cut, rest = partition_bitstring 32 bs in
match endian with
| Little -> read_elf64_sword_le cut rest
| Big -> read_elf64_sword_be cut rest
;;
(** ELF extra wide word type:
* 8 byte unsigned type on 64-bit architectures.
*)
let read_elf64_xword_le bs rest =
bitmatch bs with
| { addr : 64 : littleendian } -> return (Uint64.of_int64 addr, rest)
| { _ } -> Fail "read_elf64_xword_le"
;;
let read_elf64_xword_be bs rest =
bitmatch bs with
| { addr : 64 : bigendian } -> return (Uint64.of_int64 addr, rest)
| { _ } -> Fail "read_elf64_xword_be"
;;
let read_elf64_xword endian bs =
let cut, rest = partition_bitstring 64 bs in
match endian with
| Little -> read_elf64_xword_le cut rest
| Big -> read_elf64_xword_be cut rest
;;
(** ELF signed extra wide word type:
* 8 byte signed type on 64-bit architectures.
*)
let read_elf64_sxword_le bs rest =
bitmatch bs with
| { addr : 64 : littleendian } -> return (addr, rest)
| { _ } -> Fail "read_elf64_sxword_le"
;;
let read_elf64_sxword_be bs rest =
bitmatch bs with
| { addr : 64 : bigendian } -> return (addr, rest)
| { _ } -> Fail "read_elf64_sxword_be"
;;
let read_elf64_sxword endian bs =
let cut, rest = partition_bitstring 64 bs in
match endian with
| Little -> read_elf64_sxword_le cut rest
| Big -> read_elf64_sxword_be cut rest
;;
(** Misc. string operations. *)
let split_string_on_char strings c =
let enum = BatString.enum strings in
let groups = BatEnum.group (fun char -> char <> c) enum in
let enums = BatEnum.map BatString.of_enum groups in
BatList.of_enum enums
;;
let string_suffix index str =
if index < 0 || index > String.length str then
None
else
try
Some (String.sub str index (String.length str - index))
with
| _ -> None
;;
|