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
open Arch_decl
open PrintCommon
open Prog
open Utils
open PrintASM
let global_datas_label = "glob_data"
let pp_syscall (o : _ Syscall_t.syscall_t) =
match o with
| Syscall_t.RandomBytes _ -> "__jasmin_syscall_randombytes__"
let local_label_prefix () = if is_target_system_macos () then "L" else ".L"
let string_of_label name p =
Format.asprintf "%s%s$%a" (local_label_prefix ()) (escape name) Z.pp_print (Conv.z_of_pos p)
let pp_remote_label (fn, lbl) =
string_of_label fn.fn_name lbl
let mangle x =
if is_target_system_macos () then
Format.asprintf "_%s" x
else x
let string_of_glob occurrences x =
Hash.modify_def (-1) x.v_name Stdlib.Int.succ occurrences;
let count = Hash.find occurrences x.v_name in
let suffix = if count > 0 then Format.asprintf "$%d" count else "" in
Format.asprintf "G$%s%s" (escape x.v_name) suffix
let format_glob_data globs names =
let occurrences = Hash.create 42 in
let names =
List.map (fun ((x, _), p) -> (Conv.var_of_cvar x, Conv.z_of_cz p)) names
in
let init = [], [] in
let close (bytes, acc) = if bytes = [] then acc else Bytes (List.rev bytes) :: acc in
let push b (bytes, acc) = (b :: bytes, acc) in
let add_label x s = ([], Label x :: close s) in
let finish s = s |> close |> List.rev in
List.fold_lefti (fun s i b ->
let b = Z.format "%3i" (Conv.z_unsigned_of_word U8 b) in
match List.find (fun (_, p) -> Z.equal (Z.of_int i) p) names with
| exception Not_found -> s |> push b
| x, _ -> s |> add_label (string_of_glob occurrences x) |> push b
) init globs
|> finish
let hash_to_string (to_string : 'a -> string) =
let tbl = Hashtbl.create 17 in
fun r ->
try Hashtbl.find tbl r
with Not_found ->
let s = to_string r in
Hashtbl.add tbl r s;
s
let pp_imm imm_pre imm = Format.asprintf "%s%s" imm_pre (Z.to_string imm)
let pp_rip_address p : string =
Format.asprintf "%s+%a" global_datas_label Z.pp_print (Conv.z_of_int32 p)
let pp_register arch = hash_to_string arch.toS_r.to_string
type parsed_reg_address = {
base : string;
displacement : string option;
offset : string option;
scale : string option;
}
let parse_reg_address (arch : ('a, 'b, 'c, 'd, 'e) arch_decl) addr =
match addr.ad_base with
| None -> failwith (Format.asprintf "TODO_RISC: pp_reg_address")
| Some r ->
let base = pp_register arch r in
let displacement = Conv.z_of_word (arch_pd arch) addr.ad_disp in
let displacement =
if Z.equal displacement Z.zero then None
else Some (Z.to_string displacement)
in
let offset = Option.map (pp_register arch) addr.ad_offset in
let scale = Conv.z_of_nat addr.ad_scale in
let scale =
if Z.equal scale Z.zero then None else Some (Z.to_string scale)
in
{ base; displacement; offset; scale }
let pp_reg_address (arch : ('a, 'b, 'c, 'd, 'e) arch_decl) addr =
let addr = parse_reg_address arch addr in
let base = addr.base in
let pp_opt op fmt os =
match os with
| None -> ()
| Some s -> Format.fprintf fmt " %s %s" op s in
let pp_off fmt (offset, scale) =
if offset <> None then
Format.fprintf fmt "%a%a" (pp_opt "+") offset (pp_opt "<<") scale
in
Format.asprintf "%s%a%a" base (pp_opt "+") addr.displacement pp_off (addr.offset, addr.scale)
let pp_address (arch : ('a, 'b, 'c, 'd, 'e) arch_decl) = function
| Areg ra -> pp_reg_address arch ra
| Arip r -> pp_rip_address r
let declassify_mem (arch : ('a, 'b, 'c, 'd, 'e) arch_decl) len a =
let s = Format.sprintf "declassify_mem %s [%s]" (Z.to_string (Conv.z_of_cz len)) (pp_address arch a) in
[Comment s]
let declassify_val pp_asm_arg_ty lty a =
let sa = pp_asm_arg_ty lty a in
let s = Format.sprintf "declassify_val %s %s" (PrintCommon.string_of_ltype lty) sa in
[Comment s]