Skip to content

Commit db7b112

Browse files
authored
BAP 2.0.0 release (candidate) (#1017)
* BAP 2.0.0 release (candidate) Polishes documentation as well as fixes the theory declaration function. And finally bumps the version to 2.0.0. Whle revising the documentation I've noticed that the interface of theory declaration is not allowing references to other theories as it isn't wrapped in the knowledge monad as it should be. I fixed it, but immediately fell into the trap of a recursive instantiation. Indeed, a theory may require itself as a base, which will lead to an infinite recursion and runtime failure. Since it is so easy to fall into this trap, the implementation has to be robust enough and either forbid this, with an appropriate error message, or allow it, with an appropriate semantics. We chose the latter, since our theories are domains we have a sane semantics for recursive theories (well, this is what denotational semantics was invented on the first hand). We employed the same technique for recursive module instantiation as OCaml does, i.e., first initialize the theory with an empty structure, then overwrite it with the result. * updates testsuites commit
1 parent 77252ca commit db7b112

File tree

11 files changed

+277
-258
lines changed

11 files changed

+277
-258
lines changed

lib/bap_byteweight/bap_byteweight.mli

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(** Byteweight library.
22
3-
Byteweight is a function start identification mechanism [[1]]. This
3+
Byteweight is a function start identification algorithm [[1]]. This
44
library provides a functorized implementation.
55
66
An auxiliary {!Bap_byteweight_signatures} library provides an
@@ -13,7 +13,6 @@
1313
23rd USENIX Security Symposium (USENIX Security 14). 2014.
1414
v}
1515
*)
16-
1716
open Bap.Std
1817

1918

lib/bap_core_theory/bap_core_theory.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module Theory = struct
5353
module type Trans = Bap_core_theory_definition.Trans
5454
module type Core = Bap_core_theory_definition.Core
5555

56+
type core = (module Core)
5657
module Basic = struct
5758
module Empty : Basic = Bap_core_theory_empty.Core
5859
module Make = Bap_core_theory_basic.Make

lib/bap_core_theory/bap_core_theory.mli

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -264,21 +264,21 @@
264264
["constant-tracker"] analysis:
265265
266266
{[
267-
let () = Theory.declare "my-constant-tracker" (module struct
268-
include (val Theory.require "constant-tracker")
269-
270-
(* probably a bad example, but we all do this :) *)
271-
let add x y =
272-
printf "add is called!\n%!";
273-
add x y
267+
let () =
268+
Theory.declare "my-constant-tracker"
269+
Theory.instance ~require:["bap.std:constant-tracker"] >>=
270+
Theory.require >>|
271+
fun (module Base) : Theory.core -> (module struct
272+
include Base
273+
let add x y =
274+
printf "add is called!\n%!";
275+
add x y
274276
end
275277
]}
276278
277-
278279
The real analysis should store it results either in the knowledge
279280
base or directly in denotations of the terms (or in both places).
280281
281-
282282
{2 Instantiating a theory}
283283
284284
To use a theory we need to instantiate it. In the previous section
@@ -310,15 +310,18 @@
310310
specified context. For example,
311311
312312
{[
313-
module Theory = (val Theory.instance ()
314-
~context:["arm"; "arm-gnueabi"]
315-
~requires:[
316-
"variable-recovery";
317-
"stack-frame-analysis";
318-
"structural-analysis";
319-
"floating-point";
320-
"bap.std:bil-semantics";
321-
])
313+
314+
Theory.instance ()
315+
~context:["arm"; "arm-gnueabi"]
316+
~requires:[
317+
"variable-recovery";
318+
"stack-frame-analysis";
319+
"structural-analysis";
320+
"floating-point";
321+
"bap.std:bil-semantics"
322+
] >>=
323+
Theory.require >>= fun (module Theory) ->
324+
322325
]}
323326
324327
In the example above, theories that are specific to ARM
@@ -329,9 +332,11 @@
329332
explicitly, the [bap.std:bil-semantics], to ensure that each term
330333
has a BIL denotation.
331334
332-
[1]: http://okmij.org/ftp/tagless-final/JFP.pdf
333-
[2]: http://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
334-
[3]: http://okmij.org/ftp/tagless-final/course/optimizations.html
335+
References:
336+
337+
- [1]: http://okmij.org/ftp/tagless-final/JFP.pdf
338+
- [2]: http://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
339+
- [3]: http://okmij.org/ftp/tagless-final/course/optimizations.html
335340
336341
337342
{2 Parsing binary code}
@@ -1997,6 +2002,10 @@ module Theory : sig
19972002
end
19982003

19992004

2005+
(** a type abbreviation for the core theory module type. *)
2006+
type core = (module Core)
2007+
2008+
20002009
(** The Basic Theory.
20012010
20022011
Implements the empty basic theory and provides a module for
@@ -2049,7 +2058,9 @@ module Theory : sig
20492058
?context:string list ->
20502059
?provides:string list ->
20512060
?package:string ->
2052-
name:string -> (module Core) -> unit
2061+
name:string ->
2062+
(module Core) knowledge ->
2063+
unit
20532064

20542065
(** [instance ()] creates an instance of the Core Theory.
20552066

lib/bap_core_theory/bap_core_theory_manager.ml

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type 'a theory = {
2121
}
2222

2323
type core = (module Core)
24-
let known_theories : (Name.t, core theory) Hashtbl.t =
24+
let known_theories : (Name.t, core knowledge theory) Hashtbl.t =
2525
Hashtbl.create (module Name)
2626

2727
let features = Set.of_list (module String)
@@ -312,7 +312,6 @@ let slot = Knowledge.Class.property theory "instance" domain
312312
~desc:"The theory structure"
313313

314314

315-
316315
let str_ctxt () ctxt =
317316
List.to_string (Set.to_list ctxt) ~f:ident
318317

@@ -321,11 +320,10 @@ module Theory = (val Knowledge.Object.derive theory)
321320
let theories () =
322321
let init = Map.empty (module Theory) in
323322
Hashtbl.to_alist known_theories |>
324-
Knowledge.List.fold ~init ~f:(fun theories (name,structure) ->
323+
Knowledge.List.fold ~init ~f:(fun theories (name,def) ->
325324
Knowledge.Symbol.intern (Name.unqualified name) theory
326325
~package:(Name.package name) >>| fun name ->
327-
Map.add_exn theories name structure)
328-
326+
Map.add_exn theories name def)
329327

330328
let is_applicable ~provided ~requires =
331329
Set.for_all requires ~f:(Set.mem provided)
@@ -350,44 +348,75 @@ let refine ?(context=[]) ?requires theories =
350348
is_applicable ~provided ~requires &&
351349
is_required ~required ~provides)
352350

353-
let new_theory ?context ?requires () =
354-
theories () >>| Map.data >>| refine ?context ?requires >>= function
355-
| [] -> Knowledge.return Empty.theory
356-
| [t] -> Knowledge.return t
357-
| theories ->
358-
Knowledge.return @@
359-
(List.reduce_balanced_exn theories ~f:merge)
360-
361351
let theory_for_id id =
362352
let sym = sprintf "'%s" @@
363353
List.to_string (Set.to_list id) ~f:Name.show in
364354
Knowledge.Symbol.intern sym theory
365355
~package:"core-theory-internal"
366356

357+
let is_instantiated id =
358+
Knowledge.collect slot id >>| fun t ->
359+
not t.is_empty
360+
361+
362+
(* On instantiation of recursive modules.
363+
364+
We employ the same techinique as OCaml does [1].
365+
When a module is instantiated we create an instance
366+
of this module with an empty structure, so that if
367+
a module creates an instance of itself during instantiation,
368+
it will not enter an infinite recursion but will get the
369+
empty denotation. Our merge operator, which will be called,
370+
by the provide operator after the final instance is created,
371+
will notice that the initial structure is ordered strictly
372+
before the new one (because we used the Empty.name for it),
373+
thus it will drop it from the final structure.
374+
375+
[1]: Leroy, Xavier."A proposal for recursive modules in Objective
376+
Caml." Available from the author’s website (2003).
377+
*)
378+
let instantiate t =
379+
theory_for_id t.id >>= fun id ->
380+
is_instantiated id >>= function
381+
| true -> Knowledge.return id
382+
| false ->
383+
Knowledge.provide slot id {
384+
Empty.theory with is_empty = false
385+
} >>= fun () ->
386+
t.structure >>= fun structure ->
387+
Knowledge.provide slot id {t with structure} >>| fun () ->
388+
id
389+
367390
let instance ?context ?requires () =
368391
theories () >>| Map.data >>| refine ?context ?requires >>= function
369392
| [] -> theory_for_id Empty.theory.id
370-
| [t] -> theory_for_id t.id
393+
| [t] ->
394+
instantiate t
371395
| theories ->
372396
List.fold theories ~init:(Set.empty (module Name)) ~f:(fun names t ->
373397
Set.union names t.id) |>
374398
theory_for_id >>= fun id ->
375-
let theory = List.reduce_balanced_exn theories ~f:merge in
376-
Knowledge.provide slot id theory >>| fun () ->
377-
id
399+
is_instantiated id >>= function
400+
| true -> Knowledge.return id
401+
| false ->
402+
Knowledge.List.map theories
403+
~f:(instantiate >=> Knowledge.collect slot) >>|
404+
List.reduce_balanced_exn ~f:merge >>=
405+
Knowledge.provide slot id >>| fun () ->
406+
id
378407

379408
let require name =
380409
let open Knowledge.Syntax in
381410
theories () >>= fun theories ->
382411
match Map.find theories name with
383-
| Some t -> Knowledge.return t.structure
412+
| Some t -> t.structure
384413
| None -> Knowledge.collect slot name >>| fun t ->
385414
t.structure
386415

387416

388417
module Documentation = struct
389418
module Theory = struct
390-
type t = Name.t * core theory
419+
type t = Name.t * core knowledge theory
391420

392421
let (-) xs name = Set.remove xs (Name.show name)
393422

lib/bap_core_theory/bap_core_theory_manager.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ val declare :
77
?context:string list ->
88
?provides:string list ->
99
?package:string ->
10-
name:string -> (module Core) -> unit
10+
name:string ->
11+
(module Core) knowledge ->
12+
unit
1113

1214
val instance :
1315
?context:string list ->

0 commit comments

Comments
 (0)