@@ -127,6 +127,7 @@ let linear_of_stmt ?addr return insn stmt : linear list =
127
127
Label finish :: [] in
128
128
linearize stmt
129
129
130
+
130
131
let lift_insn ?addr fall init insn =
131
132
List. fold (Insn. bil insn) ~init ~f: (fun init stmt ->
132
133
List. fold (linear_of_stmt ?addr fall insn stmt) ~init
@@ -152,8 +153,39 @@ let is_conditional_jump jmp =
152
153
Insn. (may affect_control_flow) jmp &&
153
154
has_jump_under_condition (Insn. bil jmp)
154
155
155
- let blk cfg block : blk term list =
156
- let fall_label = label_of_fall cfg block in
156
+ let has_called block addr =
157
+ let finder =
158
+ object inherit [unit ] Stmt. finder
159
+ method! enter_jmp e r =
160
+ match e with
161
+ | Bil. Int a when Addr. (a = addr) -> r.return (Some () )
162
+ | _ -> r
163
+ end in
164
+ Bil. exists finder (Insn. bil (Block. terminator block))
165
+
166
+ let fall_of_symtab symtab block =
167
+ Option. (
168
+ symtab >> = fun symtab ->
169
+ match Symtab. enum_calls symtab (Block. addr block) with
170
+ | [] -> None
171
+ | calls ->
172
+ List. find_map calls
173
+ ~f: (fun (n ,e ) -> Option. some_if (e = `Fall ) n) >> = fun name ->
174
+ Symtab. find_by_name symtab name >> = fun (_ ,entry ,_ ) ->
175
+ Option. some_if Block. (block <> entry) entry >> = fun callee ->
176
+ let addr = Block. addr callee in
177
+ Option. some_if (not (has_called block addr)) () >> = fun () ->
178
+ let bldr = Ir_blk.Builder. create () in
179
+ let call = Call. create ~target: (Label. indirect Bil. (int addr)) () in
180
+ let () = Ir_blk.Builder. add_jmp bldr (Ir_jmp. create_call call) in
181
+ Some (Ir_blk.Builder. result bldr))
182
+
183
+ let blk ?symtab cfg block : blk term list =
184
+ let fall_to_fn = fall_of_symtab symtab block in
185
+ let fall_label =
186
+ match label_of_fall cfg block, fall_to_fn with
187
+ | None , Some b -> Some (Label. direct (Term. tid b))
188
+ | fall_label ,_ -> fall_label in
157
189
List. fold (Block. insns block) ~init: ([] ,Ir_blk.Builder. create () )
158
190
~f: (fun init (mem ,insn ) ->
159
191
let addr = Memory. min_addr mem in
@@ -167,7 +199,10 @@ let blk cfg block : blk term list =
167
199
| Some dst -> Some (`Jmp (Ir_jmp. create_goto dst)) in
168
200
Option. iter fall ~f: (Ir_blk.Builder. add_elt b);
169
201
let b = Ir_blk.Builder. result b in
170
- List. rev (b::bs) |> function
202
+ let blocks = match fall_to_fn with
203
+ | None -> b :: bs
204
+ | Some b' -> b' :: b :: bs in
205
+ List. rev blocks |> function
171
206
| [] -> assert false
172
207
| b ::bs -> Term. set_attr b address (Block. addr block) :: bs
173
208
@@ -214,14 +249,14 @@ let remove_false_jmps blk =
214
249
215
250
let unbound _ = true
216
251
217
- let lift_sub entry cfg =
252
+ let lift_sub ? symtab entry cfg =
218
253
let addrs = Addr.Table. create () in
219
254
let recons acc b =
220
255
let addr = Block. addr b in
221
- let blks = blk cfg b in
256
+ let blks = blk ?symtab cfg b in
222
257
Option. iter (List. hd blks) ~f: (fun blk ->
223
258
Hashtbl. add_exn addrs ~key: addr ~data: (Term. tid blk));
224
- acc @ blks in
259
+ acc @ blks in
225
260
let blocks = Graphlib. reverse_postorder_traverse
226
261
(module Cfg ) ~start: entry cfg in
227
262
let blks = Seq. fold blocks ~init: [] ~f: recons in
@@ -248,23 +283,23 @@ let indirect_target jmp =
248
283
let is_indirect_call jmp = Option. is_some (indirect_target jmp)
249
284
250
285
let with_address t ~f ~default =
251
- match Term. get_attr t address with
252
- | None -> default
253
- | Some a -> f a
286
+ Option. value_map ~default ~f (Term. get_attr t address)
254
287
255
- let find_call_name symtab blk =
256
- with_address blk ~default: None ~f: (Symtab. find_call_name symtab)
288
+ let with_address_opt t ~f ~default =
289
+ let g a = Option. value (f a) ~default in
290
+ with_address t ~f: g ~default
257
291
258
292
let update_unresolved symtab unresolved exts sub =
259
293
let iter cls t ~f = Term. to_sequence cls t |> Seq. iter ~f in
260
294
let symbol_exists name =
261
295
Option. is_some (Symtab. find_by_name symtab name) in
262
296
let is_known a = Option. is_some (Symtab. find_by_start symtab a) in
263
297
let is_unknown name = not (symbol_exists name) in
264
- let add_external name =
265
- Hashtbl. update exts name ~f: (function
266
- | None -> create_synthetic name
267
- | Some x -> x) in
298
+ let add_external (name ,_ ) =
299
+ if is_unknown name then
300
+ Hashtbl. update exts name ~f: (function
301
+ | None -> create_synthetic name
302
+ | Some x -> x) in
268
303
iter blk_t sub ~f: (fun blk ->
269
304
iter jmp_t blk ~f: (fun jmp ->
270
305
match indirect_target jmp with
@@ -273,24 +308,24 @@ let update_unresolved symtab unresolved exts sub =
273
308
| _ ->
274
309
with_address blk ~default: () ~f: (fun addr ->
275
310
Hash_set. add unresolved addr;
276
- match Symtab. find_call_name symtab addr with
277
- | Some name when is_unknown name -> add_external name
278
- | _ -> () )))
311
+ Symtab. enum_calls symtab addr |>
312
+ List. iter ~f: add_external)))
279
313
280
314
let resolve_indirect symtab exts blk jmp =
281
315
let update_target tar =
316
+ Option. some @@
282
317
match Ir_jmp. kind jmp with
283
318
| Call c -> Ir_jmp. with_kind jmp (Call (Call. with_target c tar))
284
319
| _ -> jmp in
285
- match find_call_name symtab blk with
286
- | None -> jmp
287
- | Some name ->
320
+ let resolve_name (name ,_ ) =
288
321
match Symtab. find_by_name symtab name with
289
322
| Some (_ ,b ,_ ) -> update_target (Indirect (Int (Block. addr b)))
290
- | None ->
291
- match Hashtbl. find exts name with
323
+ | _ -> match Hashtbl. find exts name with
292
324
| Some s -> update_target (Direct (Term. tid s))
293
- | None -> jmp
325
+ | None -> None in
326
+ with_address_opt blk ~default: jmp ~f: (fun addr ->
327
+ Symtab. enum_calls symtab addr |>
328
+ List. find_map ~f: resolve_name)
294
329
295
330
let program symtab =
296
331
let b = Ir_program.Builder. create () in
@@ -299,7 +334,7 @@ let program symtab =
299
334
let unresolved = Addr.Hash_set. create () in
300
335
Seq. iter (Symtab. to_sequence symtab) ~f: (fun (name ,entry ,cfg ) ->
301
336
let addr = Block. addr entry in
302
- let sub = lift_sub entry cfg in
337
+ let sub = lift_sub ~symtab entry cfg in
303
338
Ir_program.Builder. add_sub b (Ir_sub. with_name sub name);
304
339
Tid. set_name (Term. tid sub) name;
305
340
Hashtbl. add_exn addrs ~key: addr ~data: (Term. tid sub);
@@ -318,7 +353,8 @@ let program symtab =
318
353
else j in
319
354
resolve_jmp ~local: false addrs j)))
320
355
321
- let sub = lift_sub
356
+ let sub = lift_sub ?symtab:None
357
+ let blk = blk ?symtab:None
322
358
323
359
let insn insn =
324
360
lift_insn None ([] , Ir_blk.Builder. create () ) insn |>
0 commit comments