Source file load.ml
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
open Lem_assert_extra
open Lem_basic_classes
open Lem_bool
open Lem_list
open Lem_maybe
open Lem_num
open Lem_string
open Error
open Elf_dynamic
open Elf_file
open Elf_header
open Elf_interpreted_section
open Elf_memory_image
open Elf_relocation
open Elf_section_header_table
open Elf_symbol_table
open Elf_types_native_uint
open Endianness
open Memory_image
open Missing_pervasives
open Show
open Abi_amd64
open Abi_amd64_relocation
open Abi_mips64
open Abi_mips64_dynamic
open Abi_mips64_relocation
open Abi_cheri_mips64
open Abi_cheri_mips64_capability
open Abi_cheri_mips64_dynamic
open Abi_cheri_mips64_relocation
open Gnu_ext_abi
open Gnu_ext_symbol_versioning
let get_section_at_addr f addr:(elf64_interpreted_section)option=
(if Nat_big_num.equal addr( (Nat_big_num.of_int 0)) then None else
let l = (List.filter (fun sec -> Nat_big_num.greater_equal
addr sec.elf64_section_addr && Nat_big_num.less
addr (Nat_big_num.add sec.elf64_section_addr sec.elf64_section_size)
) f.elf64_file_interpreted_sections) in
(match l with
| [] -> None
| [sec] -> Some sec
| sec::_ -> Some sec
))
let show_section_at_addr f addr:string=
((match get_section_at_addr f addr with
| Some section ->
let offset_in_section = (Nat_big_num.sub_nat addr section.elf64_section_addr) in
"[section at " ^ (section.elf64_section_name_as_string ^ ("+0x" ^ ((hex_string_of_natural offset_in_section) ^ "]")))
| None ->
"[unknown section at 0x" ^ ((hex_string_of_natural addr) ^ "]")
))
type dynamic_symbol = {
dynamic_symbol_name : string;
dynamic_symbol_entry : elf64_symbol_table_entry;
dynamic_symbol_value : Nat_big_num.num;
dynamic_symbol_version : string option;
dynamic_symbol_version_base : bool
}
let find_sym syms name1 version:(dynamic_symbol)option=
(
let matches = (List.filter (fun sym1 -> sym1.dynamic_symbol_name = name1) syms) in
let version_matches = (List.filter (fun sym1 -> (Lem.option_equal (=) sym1.dynamic_symbol_version version)) matches) in
(match version_matches with
| [] ->
(match version with
| Some _ ->
(match matches with
| [sym1] ->
(match sym1.dynamic_symbol_version with
| Some _ -> None
| None -> Some sym1
)
| _ -> None
)
| None ->
(match matches with
| [] -> None
| [sym1] ->
Some sym1
| _ ->
Lem_list.list_find_opt (fun sym1 -> sym1.dynamic_symbol_version_base) matches
)
)
| [sym1] ->
Some sym1
| sym1 :: _ ->
Some sym1
))
let is_data_section sec:bool=
(false
|| ((sec.elf64_section_name_as_string = ".data")
|| ((sec.elf64_section_name_as_string = ".sdata")
|| ((sec.elf64_section_name_as_string = ".sbss")
|| ((sec.elf64_section_name_as_string = ".tdata")
|| ((sec.elf64_section_name_as_string = ".tbss")
|| ((sec.elf64_section_name_as_string = ".dynamic")
|| ((sec.elf64_section_name_as_string = ".data.rel.ro")
|| (sec.elf64_section_name_as_string = ".rld_map")))))))))
let is_unsupported_relocation_type f rel_type1:bool=
(
if Abi_amd64.header_is_amd64 f.elf64_file_header then Nat_big_num.equal
rel_type1 r_x86_64_irelative || (Nat_big_num.equal rel_type1 r_x86_64_tpoff64
|| (Nat_big_num.equal rel_type1 r_x86_64_dtpoff64 || Nat_big_num.equal rel_type1 r_x86_64_dtpmod64))
else if Abi_mips64.header_is_mips64 f.elf64_file_header
|| Abi_cheri_mips64.header_is_cheri_mips64 f.elf64_file_header then Nat_big_num.equal
rel_type1 r_mips_tls_tprel64 || Nat_big_num.equal rel_type1 r_mips_tls_dtpmod64
else
false)
let apply_relocation abi1 f img2 base reloc1 symref_and_reloc_site maybe_sym ignore_data_sections:'abifeature annotated_memory_image=
(let endian = (get_elf64_header_endianness f.elf64_file_header) in
let (rel_type1, _) = (abi1.parse_reloc_info reloc1.elf64_ra_info) in
let offset = (Ml_bindings.nat_big_num_of_uint64 reloc1.elf64_ra_offset) in
let addend = (Nat_big_num.of_int64 reloc1.elf64_ra_addend) in
let addr = (Nat_big_num.add base offset) in
let (is_absolute, applyfn) = (abi1.reloc rel_type1) in
let (width, calcfn) = (applyfn img2 addr symref_and_reloc_site) in
let _ = (prerr_endline ("Relocation of type 0x" ^ ((hex_string_of_natural rel_type1) ^ (" at 0x" ^ ((hex_string_of_natural addr) ^ (" (offset 0x" ^ ((hex_string_of_natural offset) ^ ("), size 0x" ^ ((hex_string_of_natural width) ^ (" in " ^ (show_section_at_addr f offset))))))))))) in
if Nat_big_num.equal rel_type1( (Nat_big_num.of_int 0)) then
let _ = (prerr_endline " Skipping NONE relocation") in
img2
else
let is_in_data_section =
(if ignore_data_sections then
false
else
(match get_section_at_addr f offset with
| Some sec -> is_data_section sec
| None -> false
))
in
if is_in_data_section then
let _ = (prerr_endline " Relocation inside a data section, ignoring") in
img2
else
let maybe_sym_addr = ((match maybe_sym with
| Some sym1 ->
if Nat_big_num.equal (get_elf64_symbol_type sym1.dynamic_symbol_entry) stt_gnu_ifunc then
let _ = (prerr_endline " Symbol is an ifunc") in
None
else
Some sym1.dynamic_symbol_value
| None ->
Some( (Nat_big_num.of_int 0))
)) in
let maybe_sym_addr =
(if is_unsupported_relocation_type f rel_type1 then
let _ = (prerr_endline (" Giving up on this one: unsupported relocation type")) in
None
else
maybe_sym_addr)
in
(match maybe_sym_addr with
| Some sym_addr ->
if header_is_pure_cheri_mips64 f.elf64_file_header
&& Nat_big_num.equal rel_type1 r_mips_cheri_capability then
let cap_bp = (abi_cheri_mips64_write_capability_byte_pattern endian None
None None None (Some( (Nat_big_num.of_int 42))) (Some( (Nat_big_num.of_int 42))) (Some( (Nat_big_num.of_int 42)))) in
let _ = (prerr_endline (" Relocating CHERI capability `" ^ (symref_and_reloc_site.ref.ref_symname ^ "`"))) in
write_memory_image img2 addr cap_bp
else
let existing_bytes = (assert_unwrap_maybe (read_memory_image img2 addr width)) in
let existing_value = (Memory_image.natural_of_byte_list endian existing_bytes) in
let new_value = (calcfn sym_addr addend existing_value) in
let field_bytes = (Memory_image.natural_to_byte_list_padded_to endian width new_value) in
let field_bp = (Lem_list.map (fun b -> Some b) field_bytes) in
let _ = (prerr_endline (" Relocating `" ^ (symref_and_reloc_site.ref.ref_symname ^ ("` (existing=0x" ^ ((hex_string_of_natural existing_value) ^ (" addend=" ^ ((Nat_big_num.to_string addend) ^ (") to 0x" ^ ((hex_string_of_natural new_value) ^ (" (symbol address 0x" ^ ((hex_string_of_natural sym_addr) ^ ")"))))))))))) in
write_memory_image img2 addr field_bp
| None ->
let _ = (prerr_endline (" Masking relocation for `" ^ (symref_and_reloc_site.ref.ref_symname ^ "`"))) in
mask_memory_image img2 addr width
))
let get_sym_ref_version dynsym_scnidx maybe_versym_table sym_name sym_scn sym_idx:(string)option=
(if not (Nat_big_num.equal dynsym_scnidx sym_scn) then None else
(match maybe_versym_table with
| Some versym_table ->
(match get_gnu_ext_interpreted_verneed versym_table sym_idx with
| Success None -> None
| Success (Some vernaux) ->
Some vernaux.gnu_ext_interpreted_vernaux_name
| Fail errmsg ->
(match get_gnu_ext_interpreted_verdef versym_table sym_idx with
| Success (GnuExtInterpretedVerdefVersion verdef) ->
Some verdef.gnu_ext_interpreted_verdef_name
| _ ->
None
)
)
| None ->
None
))
let mask_data_sections f img2:'abifeature annotated_memory_image=
(let data_sections = (List.filter is_data_section f.elf64_file_interpreted_sections) in
List.fold_left (fun img2 sec ->
let _ = (prerr_endline ("Masking " ^ (sec.elf64_section_name_as_string ^ (" at 0x" ^ ((hex_string_of_natural sec.elf64_section_addr) ^ (", size 0x" ^ (hex_string_of_natural sec.elf64_section_size))))))) in
mask_memory_image img2 sec.elf64_section_addr sec.elf64_section_size
) img2 data_sections)
let mask_relocations abi1 f img2:'abifeature annotated_memory_image=
(let all_relocs = (Elf_memory_image.extract_all_relocs "<input file>" f) in
List.fold_left (fun img2 (scn, rel_idx, rel_src_scn, rel) ->
let addr = (Ml_bindings.nat_big_num_of_uint64 rel.elf64_ra_offset) in
let (rel_type1, _) = (abi1.parse_reloc_info rel.elf64_ra_info) in
let (is_absolute, applyfn) = (abi1.reloc rel_type1) in
let (width, calcfn) = (applyfn img2 addr Memory_image.null_symbol_reference_and_reloc_site) in
let _ = (prerr_endline ("Masking relocation of type 0x" ^ ((hex_string_of_natural rel_type1) ^ (" at 0x" ^ ((hex_string_of_natural addr) ^ (", size 0x" ^ ((hex_string_of_natural width) ^ (" in " ^ (show_section_at_addr f addr))))))))) in
mask_memory_image img2 addr width
) img2 all_relocs)
let amd64_address_size : Nat_big_num.num= ( (Nat_big_num.of_int 8))
let init_amd64_pltgot img2 base dyns:'abifeature annotated_memory_image=
(let maybe_pltgot_offset = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Elf_dynamic.dt_pltgot
) dyns) in
(match maybe_pltgot_offset with
| Some (_, Address pltgot_offset) ->
let pltgot_addr = (Nat_big_num.add base (Ml_bindings.nat_big_num_of_uint64 pltgot_offset)) in
let _ = (prerr_endline ("Initializing PLTGOT at 0x" ^ (hex_string_of_natural pltgot_addr))) in
let img2 = (mask_memory_image img2 ( Nat_big_num.add pltgot_addr amd64_address_size) amd64_address_size) in
let img2 = (mask_memory_image img2 ( Nat_big_num.add pltgot_addr (Nat_big_num.mul( (Nat_big_num.of_int 2)) amd64_address_size)) amd64_address_size) in
img2
| None ->
let _ = (prerr_endline ("No DT_PLTGOT in .dynamic, skipping PLTGOT initialization")) in
img2
))
let mips64_address_size : Nat_big_num.num= ( (Nat_big_num.of_int 8))
let rec apply_mips64_local_got_relocations endian img2 base got_entry_addr local_gotno:'abifeature annotated_memory_image*Nat_big_num.num=
(if Nat_big_num.equal local_gotno( (Nat_big_num.of_int 0)) then (img2, got_entry_addr) else
let _ = (prerr_endline ("MIPS local .got relocation at 0x" ^ ((hex_string_of_natural got_entry_addr) ^ (" (remaining: " ^ ((Nat_big_num.to_string local_gotno) ^ ")"))))) in
let width = mips64_address_size in
let existing_bytes = (assert_unwrap_maybe (read_memory_image img2 got_entry_addr width)) in
let existing_value = (Memory_image.natural_of_byte_list endian existing_bytes) in
let new_value = (Nat_big_num.add base existing_value) in
let field_bytes = (Memory_image.natural_to_byte_list_padded_to endian width new_value) in
let field_bp = (Lem_list.map (fun b -> Some b) field_bytes) in
let _ = (prerr_endline (" Relocating MIPS64 local .got entry from 0x" ^ ((hex_string_of_natural existing_value) ^ (" to 0x" ^ (hex_string_of_natural new_value))))) in
let img2 = (write_memory_image img2 got_entry_addr field_bp) in
apply_mips64_local_got_relocations endian img2 base ( Nat_big_num.add got_entry_addr width) ( Nat_big_num.sub_nat local_gotno( (Nat_big_num.of_int 1))))
let rec apply_mips64_global_got_relocations' abi1 f img2 dynsyms syms dynsym_scnidx maybe_versym_table base got_entry_addr (symtabno : Nat_big_num.num) ignore_data_sections:'a annotated_memory_image*Nat_big_num.num=
(if Nat_big_num.equal symtabno( (Nat_big_num.of_int 0)) then (img2, got_entry_addr) else
let endian = (get_elf64_header_endianness f.elf64_file_header) in
(match syms with
| (sym_name, sym_entry, scnidx, symidx) :: syms ->
let ra_info = (Uint64_wrapper.of_bigint Abi_mips64_relocation.r_mips_jump_slot) in
let ra_info = ((match endian with
| Little -> Uint64_wrapper.shift_left ra_info 56
| Big -> ra_info
)) in
let reloc1 = ({
elf64_ra_offset = (Uint64_wrapper.of_bigint ( Nat_big_num.sub_nat got_entry_addr base));
elf64_ra_info = ra_info;
elf64_ra_addend = (Nat_big_num.to_int64( (Nat_big_num.of_int 0)))
}) in
let maybe_sym =
(
if not (sym_name = "") then
let maybe_sym_version = (get_sym_ref_version dynsym_scnidx maybe_versym_table sym_name scnidx symidx) in
let _ = (prerr_endline ("Searching for symbol `" ^ (sym_name ^ ("`, version " ^ (string_of_maybe
instance_Show_Show_string_dict maybe_sym_version))))) in
find_sym dynsyms sym_name maybe_sym_version
else
None)
in
let symref_and_reloc_site = null_symbol_reference_and_reloc_site in
let img2 = (apply_relocation abi1 f img2 base reloc1 symref_and_reloc_site maybe_sym ignore_data_sections) in
apply_mips64_global_got_relocations' abi1 f img2 dynsyms syms dynsym_scnidx maybe_versym_table base ( Nat_big_num.add got_entry_addr mips64_address_size) ( Nat_big_num.sub_nat symtabno( (Nat_big_num.of_int 1))) ignore_data_sections
| _ -> failwith "apply_mips64_global_got_relocations': not enough symbols"
))
let apply_mips64_global_got_relocations abi1 f img2 dynsyms dynsym_scnidx maybe_versym_table base got_entry_addr symtab_addr gotsym symtabno ignore_data_sections:'a annotated_memory_image*Nat_big_num.num=
(let symtab_triples = (mapMaybei (fun scnidx isec1 ->
if Nat_big_num.equal isec1.elf64_section_addr (Ml_bindings.nat_big_num_of_uint64 symtab_addr) then
(match find_elf64_symbols_by_symtab_idx scnidx f with
| Fail _ -> None
| Success triple -> Some triple
)
else
None
) f.elf64_file_interpreted_sections) in
let (syms : (string * elf64_symbol_table_entry * Nat_big_num.num * Nat_big_num.num ) list) =
((match symtab_triples with
| [triple] -> Elf_memory_image.extract_all_symbols triple
| [] -> failwith "apply_mips64_global_got_relocations: no .symtab found"
| _ -> failwith "apply_mips64_global_got_relocations: multiple .symtab sections not supported for MIPS64"
))
in
let syms = (Lem_list.drop (Nat_big_num.to_int gotsym) syms) in
apply_mips64_global_got_relocations' abi1 f img2 dynsyms syms dynsym_scnidx maybe_versym_table base got_entry_addr ( Nat_big_num.sub_nat symtabno gotsym) ignore_data_sections)
let apply_mips64_got_relocations abi1 f img2 dynsyms base dyns dynsym_scnidx maybe_versym_table ignore_data_sections:'a annotated_memory_image=
(let maybe_got_offset = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal tag Elf_dynamic.dt_pltgot) dyns) in
let got_offset = ((match maybe_got_offset with
| Some (_, Address got) -> got
| None -> failwith "apply_mips64_got_relocations: missing DT_PLTGOT in .dynamic"
)) in
let got_addr = (Nat_big_num.add base (Ml_bindings.nat_big_num_of_uint64 got_offset)) in
let got_entry_addr = got_addr in
let maybe_local_gotno = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Abi_mips64_dynamic.abi_mips64_dt_local_gotno
) dyns) in
let (img2, got_entry_addr) = ((match maybe_local_gotno with
| Some (_, Numeric local_gotno) ->
let reserved_num =( (Nat_big_num.of_int 2)) in
let img2 = (mask_memory_image img2 got_entry_addr ( Nat_big_num.mul reserved_num mips64_address_size)) in
let got_entry_addr = (Nat_big_num.add got_addr (Nat_big_num.mul reserved_num mips64_address_size)) in
let local_gotno = (Nat_big_num.sub_nat local_gotno reserved_num) in
let _ = (prerr_endline ("Applying " ^ ((Nat_big_num.to_string local_gotno) ^ " MIPS64 local .got relocations"))) in
let endian = (get_elf64_header_endianness f.elf64_file_header) in
apply_mips64_local_got_relocations endian img2 base got_entry_addr local_gotno
| None ->
let _ = (prerr_endline "Not applying MIPS64 .got relocations: missing DT_LOCAL_GOTNO") in
(img2, got_addr)
)) in
let maybe_symtab_addr = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Elf_dynamic.dt_symtab
) dyns) in
let symtab_addr = ((match maybe_symtab_addr with
| Some (_, Address symtab_addr) -> symtab_addr
| None -> failwith "apply_mips64_got_relocations: missing DT_SYMTAB in .dynamic"
)) in
let maybe_gotsym = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Abi_mips64_dynamic.abi_mips64_dt_gotsym
) dyns) in
let gotsym = ((match maybe_gotsym with
| Some (_, Numeric gotsym) -> gotsym
| None -> failwith "apply_mips64_got_relocations: missing DT_MIPS_GOTSYM in .dynamic"
)) in
let maybe_symtabno = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Abi_mips64_dynamic.abi_mips64_dt_symtabno
) dyns) in
let symtabno = ((match maybe_symtabno with
| Some (_, Numeric symtabno) -> symtabno
| None -> failwith "apply_mips64_got_relocations: missing DT_MIPS_SYMTABNO in .dynamic"
)) in
let (img2, got_entry_addr) = (apply_mips64_global_got_relocations abi1 f img2 dynsyms dynsym_scnidx maybe_versym_table base got_entry_addr symtab_addr gotsym symtabno ignore_data_sections) in
img2)
let apply_cheri_mips64_cap_relocations f img2 base dyns ignore_data_sections:'a annotated_memory_image=
(let maybe_cap_relocs = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Abi_cheri_mips64_dynamic.abi_cheri_dt___caprelocs
) dyns) in
let cap_relocs_addr = ((match maybe_cap_relocs with
| Some (_, Address cap_relocs_addr) -> Ml_bindings.nat_big_num_of_uint64 cap_relocs_addr
| None -> failwith "apply_cheri_mips64_cap_relocations: missing DT_CHERI___CAPRELOCS in .dynamic"
)) in
let maybe_cap_relocssz = (Lem_list.list_find_opt (fun (tag, _) -> Nat_big_num.equal
tag Abi_cheri_mips64_dynamic.abi_cheri_dt___caprelocssz
) dyns) in
let cap_relocssz = ((match maybe_cap_relocssz with
| Some (_, Numeric cap_relocssz) -> cap_relocssz
| None -> failwith "apply_cheri_mips64_cap_relocations: missing DT_CHERI___CAPRELOCSSZ in .dynamic"
)) in
let cap_relocs_bs = ((match read_memory_image_byte_sequence img2 ( Nat_big_num.add base cap_relocs_addr) cap_relocssz with
| Some bs -> bs
| None -> failwith "apply_cheri_mips64_cap_relocations: cannot dereference DT_CHERI___CAPRELOCS"
)) in
let endian = (get_elf64_header_endianness f.elf64_file_header) in
let cap_relocs = ((match read_cheri_mips64_cap_relocs endian cap_relocs_bs with
| Success cap_relocs -> cap_relocs
| Fail errmsg -> failwith errmsg
)) in
let img2 = (List.fold_left (fun img2 reloc1 ->
let is_func = (cheri_mips64_cap_reloc_is_function reloc1) in
let loc = (Ml_bindings.nat_big_num_of_uint64 reloc1.cheri_mips64_cap_reloc_location) in
let obj = (Ml_bindings.nat_big_num_of_uint64 reloc1.cheri_mips64_cap_reloc_object) in
let offset = (Ml_bindings.nat_big_num_of_uint64 reloc1.cheri_mips64_cap_reloc_offset) in
let size2 = (Ml_bindings.nat_big_num_of_uint64 reloc1.cheri_mips64_cap_reloc_size) in
let is_in_data_section =
(if ignore_data_sections then
false
else
(match get_section_at_addr f ( Nat_big_num.sub_nat loc base) with
| Some sec -> is_data_section sec
| None -> false
))
in
if is_in_data_section then
let _ = (prerr_endline ("Skipping __cap_relocs relocation at 0x" ^ ((hex_string_of_natural loc) ^ ": in a data section"))) in
img2
else
let (cursor, cap_base, len) =
(if Nat_big_num.equal obj( (Nat_big_num.of_int 0)) then
( (Nat_big_num.of_int 0), (Nat_big_num.of_int 0), (Nat_big_num.of_int 0))
else
let cursor = (Nat_big_num.add obj offset) in
if is_func then
(cursor, (Nat_big_num.of_int 0), size2)
else
(cursor, obj, size2))
in
let cap_bp = (abi_cheri_mips64_write_capability_byte_pattern endian None
None None None (Some cursor) (Some cap_base) (Some len)) in
let _ = (prerr_endline (
"Applying __cap_relocs relocation at 0x" ^ ((hex_string_of_natural loc)
^ (" in " ^ ((show_section_at_addr f ( Nat_big_num.sub_nat loc base))
^ (" offset=0x" ^ ((hex_string_of_natural offset)
^ (" size=0x" ^ ((hex_string_of_natural size2)
^ (" object=0x" ^ ((hex_string_of_natural obj)
^ (" cursor=0x" ^ ((hex_string_of_natural cursor)
^ (" base=0x" ^ ((hex_string_of_natural cap_base)
^ (" len=0x" ^ ((hex_string_of_natural len)
^ (" is_func=" ^ (string_of_bool is_func)))))))))))))))))
)) in
write_memory_image img2 loc cap_bp
) img2 cap_relocs) in
img2)
let sym_add_verdef sym1 verdef:dynamic_symbol=
(
{
dynamic_symbol_name = (sym1.dynamic_symbol_name);
dynamic_symbol_entry = (sym1.dynamic_symbol_entry);
dynamic_symbol_value = (sym1.dynamic_symbol_value);
dynamic_symbol_version = (Some verdef.gnu_ext_interpreted_verdef_name);
dynamic_symbol_version_base = (Nat_big_num.equal
verdef.gnu_ext_interpreted_verdef_ndx gnu_ext_verdef_base_unspecified
|| Nat_big_num.equal verdef.gnu_ext_interpreted_verdef_ndx gnu_ext_verdef_base_versioned)
})
let f base existing_syms symtab_scnidx maybe_versym_table:((dynamic_symbol)list)error=
(let symtab_scn = (assert_unwrap_maybe (Lem_list.list_index f.elf64_file_interpreted_sections (Nat_big_num.to_int symtab_scnidx))) in bind (find_elf64_symbols_by_symtab_idx symtab_scnidx f) (fun triple ->
let syms = (Elf_memory_image.extract_all_symbols triple) in
let syms = (List.filter (fun (sym_name, sym_entry, scnidx, symidx) ->
let sym_binding = (get_elf64_symbol_binding sym_entry) in
let sym_value = (Ml_bindings.nat_big_num_of_uint64 sym_entry.elf64_st_value) in
( Nat_big_num.equal sym_binding Elf_symbol_table.stb_global || Nat_big_num.equal sym_binding Elf_symbol_table.stb_weak)
&& not (Nat_big_num.equal (Uint32_wrapper.to_bigint sym_entry.elf64_st_shndx)( (Nat_big_num.of_int 0)))
) syms) in
let syms = (Lem_list.map (fun (sym_name, sym_entry, scnidx, symidx) ->
let is_abs = (Nat_big_num.equal (Uint32_wrapper.to_bigint sym_entry.elf64_st_shndx) shn_abs) in
let sym_value =
(if is_abs then
Ml_bindings.nat_big_num_of_uint64 sym_entry.elf64_st_value
else Nat_big_num.add
base (Ml_bindings.nat_big_num_of_uint64 sym_entry.elf64_st_value))
in
let sym1 = ({
dynamic_symbol_name = sym_name;
dynamic_symbol_entry = sym_entry;
dynamic_symbol_value = sym_value;
dynamic_symbol_version = None;
dynamic_symbol_version_base = false
}) in
(sym1, symidx)
) syms) in bind (match maybe_versym_table with
| Some versym_table ->
if List.length versym_table.gnu_ext_interpreted_versym_table_entries < List.length syms then
Error.fail "extract_dynsyms: versym table too short"
else
bind (return ()) (fun () ->
Error.foldM (fun syms (sym1, symidx) -> bind (get_gnu_ext_interpreted_verdef versym_table symidx) (fun verdef_lookup ->
let versioned_sym = ((match verdef_lookup with
| GnuExtInterpretedVerdefVersion verdef ->
sym_add_verdef sym1 verdef
| GnuExtInterpretedVerdefHidden verdef ->
sym_add_verdef sym1 verdef
| _ -> sym1
)) in
return (versioned_sym :: syms))
) [] syms)
| None ->
let syms = (Lem_list.map (fun (sym1, symidx) -> sym1) syms) in
return syms
) (fun syms ->
let syms = (List.fold_left (fun syms sym1 ->
let sym_name = (sym1.dynamic_symbol_name) in
let sym_entry = (sym1.dynamic_symbol_entry) in
let sym_addr = (sym1.dynamic_symbol_value) in
let sym_version = (sym1.dynamic_symbol_version) in
let sym_binding = (get_elf64_symbol_binding sym_entry) in
let _ = (prerr_endline ("Processing symbol `" ^ (sym_name ^ ("`, 0x" ^ ((hex_string_of_natural sym_addr) ^ (", binding=" ^ ((Nat_big_num.to_string sym_binding) ^ (", version=" ^ (string_of_maybe
instance_Show_Show_string_dict sym_version))))))))) in
let maybe_existing = (find_sym existing_syms sym_name None) in
(match maybe_existing with
| Some existing ->
let existing_entry = (existing.dynamic_symbol_entry) in
let existing_addr = (existing.dynamic_symbol_value) in
let existing_version = (existing.dynamic_symbol_version) in
if Nat_big_num.equal (get_elf64_symbol_binding existing_entry) Elf_symbol_table.stb_weak && not (Nat_big_num.equal sym_binding Elf_symbol_table.stb_weak) then
let _ = (prerr_endline ("Overriding weak symbol `" ^ (sym_name ^ ("`, 0x" ^ ((hex_string_of_natural existing_addr) ^ (" -> 0x" ^ (hex_string_of_natural sym_addr))))))) in
sym1 :: syms
else if Nat_big_num.equal (Uint32_wrapper.to_bigint existing_entry.elf64_st_shndx) shn_undef && not (Nat_big_num.equal (Uint32_wrapper.to_bigint sym_entry.elf64_st_shndx)( (Nat_big_num.of_int 0))) then
let _ = (prerr_endline ("Overriding symbol with undefined ndx `" ^ (sym_name ^ ("`, 0x" ^ ((hex_string_of_natural existing_addr) ^ (" -> 0x" ^ (hex_string_of_natural sym_addr))))))) in
sym1 :: syms
else if not ((Lem.option_equal (=) existing_version None)) && (not ((Lem.option_equal (=) sym_version None)) && not ((Lem.option_equal (=) sym_version existing_version))) then
let _ = (prerr_endline ("Adding new version `" ^ ((string_of_maybe
instance_Show_Show_string_dict sym_version) ^ ("` of symbol `" ^ (sym_name ^ ("` (already have: `" ^ ((string_of_maybe
instance_Show_Show_string_dict existing_version) ^ "`)"))))))) in
sym1 :: syms
else
let _ = (prerr_endline ("Multiple definitions of `" ^ (sym_name ^ ("` version " ^ ((string_of_maybe
instance_Show_Show_string_dict sym_version) ^ ", only keeping the first one"))))) in
syms
| None ->
sym1 :: syms
)
) [] syms) in
return syms)))