@@ -39,6 +39,182 @@ let memory_slot = KB.Class.property Theory.Unit.cls "unit-memory"
39
39
~desc: " annotated memory regions of the unit"
40
40
Memmap. domain
41
41
42
+ module Symbols = struct
43
+ open KB.Let
44
+ open KB.Syntax
45
+
46
+ module Addr = struct
47
+ include Bitvec
48
+ include Bitvec_order
49
+ include Bitvec_binprot. Functions
50
+ include Bitvec_sexp. Functions
51
+ end
52
+
53
+ type table = {
54
+ roots : Set .M (Addr ).t;
55
+ names : string Map .M (Addr ).t;
56
+ aliases : Set .M (String ).t Map .M (Addr ).t;
57
+ } [@@ deriving compare , equal , bin_io , sexp ]
58
+
59
+ let empty = {
60
+ roots = Set. empty (module Addr );
61
+ names = Map. empty (module Addr );
62
+ aliases = Map. empty (module Addr );
63
+ }
64
+
65
+ let slot = KB.Class. property Theory.Unit. cls
66
+ ~package: " bap" " symbol-table"
67
+ ~persistent: (KB.Persistent. of_binable (module struct
68
+ type t = table [@@ deriving bin_io ]
69
+ end )) @@
70
+ KB.Domain. flat ~empty ~equal: equal_table " symbols"
71
+
72
+ let is_ident s =
73
+ String. length s > 0 &&
74
+ (Char. is_alpha s.[0 ] || Char. equal s.[0 ] '_' ) &&
75
+ String. for_all s ~f: (fun c -> Char. is_alphanum c ||
76
+ Char. equal c '_' )
77
+
78
+ let from_spec t =
79
+ let collect fld = Ogre. collect Ogre.Query. (select @@ from fld) in
80
+ let open Ogre.Let in
81
+ let to_addr =
82
+ let m = Bitvec. modulus (Theory.Target. code_addr_size t) in
83
+ let n = Theory.Target. code_alignment t / Theory.Target. byte t in
84
+ let mask = Int64. (lnot (of_int n - 1L )) in
85
+ fun x ->
86
+ let x = Int64. (x land mask) in
87
+ Bitvec. (int64 x mod m) in
88
+ let add_alias aliases addr alias = Map. update aliases addr ~f: (function
89
+ | None -> Set. singleton (module String ) alias
90
+ | Some names -> Set. add names alias) in
91
+ let pp_comma ppf () = Format. pp_print_string ppf " , " in
92
+ let pp_addrs =
93
+ Format. pp_print_list ~pp_sep: pp_comma Bitvec. pp
94
+ and pp_names =
95
+ Format. pp_print_list ~pp_sep: pp_comma Format. pp_print_string in
96
+ let * roots =
97
+ let + roots =
98
+ let * starts = collect Image.Scheme. code_start in
99
+ let * values = collect Image.Scheme. symbol_value in
100
+ let + entry = Ogre. request Image.Scheme. entry_point in
101
+ let roots = Seq. append starts (Seq. map ~f: fst values) in
102
+ match entry with
103
+ | None -> roots
104
+ | Some entry -> Seq. cons entry roots in
105
+ Seq. fold roots ~init: (Set. empty (module Bitvec_order ))
106
+ ~f: (fun xs x -> Set. add xs (to_addr x)) in
107
+ let + named_symbols = collect Image.Scheme. named_symbol in
108
+ let init = Bap_relation. empty Bitvec. compare String. compare in
109
+ Seq. fold named_symbols ~init ~f: (fun rel (data ,name ) ->
110
+ let addr = to_addr data in
111
+ if Set. mem roots addr && is_ident name
112
+ then Bap_relation. add rel (to_addr data) name
113
+ else rel) |> fun rel ->
114
+ Bap_relation. matching rel {empty with roots}
115
+ ~saturated: (fun k v t -> {
116
+ t with names = Map. add_exn t.names k v
117
+ })
118
+ ~unmatched: (fun reason t -> {
119
+ t with aliases = match reason with
120
+ | Non_injective_fwd (addrs ,name ) ->
121
+ info " the symbol %s has ambiguous addresses: %a@\n "
122
+ name pp_addrs addrs;
123
+ List. fold addrs ~init: t.aliases ~f: (fun aliases addr ->
124
+ add_alias aliases addr name)
125
+ | Non_injective_bwd (names ,addr ) ->
126
+ info " the symbol at %a has ambiguous names: %a@\n "
127
+ Bitvec. pp addr pp_names names;
128
+ List. fold names ~init: t.aliases ~f: (fun aliases name ->
129
+ add_alias aliases addr name)
130
+ })
131
+
132
+ let build_table t spec = match Ogre. eval (from_spec t) spec with
133
+ | Ok x -> x
134
+ | Error err ->
135
+ invalid_argf " Malformed ogre specification: %s"
136
+ (Error. to_string_hum err) ()
137
+
138
+ let collect_inputs from obj f =
139
+ KB. collect Theory.Label. unit obj >> =? fun unit ->
140
+ KB. collect Theory.Label. addr obj >> =? fun addr ->
141
+ let + data = KB. collect from unit in
142
+ f data addr
143
+
144
+ let promised_table : unit =
145
+ KB. promise slot @@ fun unit ->
146
+ let * t = KB. collect Theory.Unit. target unit in
147
+ let + s = KB. collect Image.Spec. slot unit in
148
+ build_table t s
149
+
150
+ let promised_roots : unit =
151
+ KB.Rule. (begin
152
+ declare " provides roots" |>
153
+ require Image.Spec. slot |>
154
+ provide Theory.Label. is_subroutine |>
155
+ comment " computes roots from spec" ;
156
+ end );
157
+ KB. promise Theory.Label. is_subroutine @@ fun obj ->
158
+ collect_inputs slot obj @@ fun {roots} addr ->
159
+ Option. some_if (Set. mem roots addr) true
160
+
161
+
162
+ let names_agent = KB.Agent. register
163
+ ~package: " bap" " specification-provider"
164
+ ~desc: " provides names obtained from the image specification."
165
+
166
+ let promised_names : unit =
167
+ KB.Rule. (begin
168
+ declare " provides names" |>
169
+ require Image.Spec. slot |>
170
+ provide Theory.Label. possible_name |>
171
+ comment " computes symbol names from spec" ;
172
+ end );
173
+ KB. propose names_agent Theory.Label. possible_name @@ fun obj ->
174
+ collect_inputs slot obj @@ fun {names} addr ->
175
+ Map. find names addr
176
+
177
+
178
+ let promised_aliases : unit =
179
+ KB.Rule. (begin
180
+ declare " provides aliases" |>
181
+ require Image.Spec. slot |>
182
+ provide Theory.Label. possible_name |>
183
+ comment " computes symbol aliases (names) from spec" ;
184
+ end );
185
+ KB. promise Theory.Label. aliases @@ fun obj ->
186
+ let * unit = KB. collect Theory.Label. unit obj in
187
+ let * addr = KB. collect Theory.Label. addr obj in
188
+ match unit ,addr with
189
+ | None ,_ |_ ,None -> KB. return (Set. empty (module String ))
190
+ | Some unit , Some addr ->
191
+ let + {aliases} = KB. collect slot unit in
192
+ match Map. find aliases addr with
193
+ | None -> Set. empty (module String )
194
+ | Some aliases -> aliases
195
+
196
+ let gossiper = KB.Agent. register
197
+ ~package: " bap" " symbols-gossiper"
198
+ ~desc: " propses an alias as a possible name"
199
+ ~reliability: KB.Agent. unreliable
200
+
201
+ let gossiped_aliases : unit =
202
+ KB.Rule. (begin
203
+ declare " provides aliases as names" |>
204
+ require Image.Spec. slot |>
205
+ provide Theory.Label. possible_name |>
206
+ comment " uses aliases as an unreliable source of symbol names" ;
207
+ end );
208
+ KB. propose gossiper Theory.Label. possible_name @@ fun obj ->
209
+ let + aliases = KB. collect Theory.Label. aliases obj in
210
+ match Set. find aliases ~f: is_ident with
211
+ | None -> Set. max_elt aliases
212
+ | ident -> ident
213
+ end
214
+
215
+
216
+
217
+
42
218
let with_filename spec target _code memory path f =
43
219
let open KB.Syntax in
44
220
let width = Theory.Target. code_addr_size target in
@@ -237,27 +413,11 @@ module Input = struct
237
413
target = compute_target ?target (Image. spec img);
238
414
}
239
415
240
- let symtab_agent =
241
- let reliability = KB.Agent. authorative in
242
- KB.Agent. register " symtab"
243
- ~reliability
244
- ~desc: " extracts symbols from symbol tables"
245
- ~package: " bap"
246
-
247
- let provide_image file image =
248
- let image_symbols = Symbolizer. (set_path (of_image image) file) in
249
- let image_roots = Rooter. (set_path (of_image image) file) in
250
- info " providing rooter and symbolizer from image of %a"
251
- Sexp. pp_hum ([% sexp_of : string option ] (Image. filename image));
252
- Symbolizer. provide symtab_agent image_symbols;
253
- Rooter. provide image_roots
254
-
255
416
let of_image ?target ?loader filename =
256
417
Image. create ?backend:loader filename >> | fun (img ,warns ) ->
257
418
List. iter warns ~f: (fun e -> warning " %a" Error. pp e);
258
419
let spec = Image. spec img in
259
420
Signal. send Info. got_img img;
260
- provide_image filename img;
261
421
let finish proj = {
262
422
proj with
263
423
storage = Dict. set proj.storage Image. specification spec;
0 commit comments