Skip to content

Commit a733374

Browse files
authored
fixes variable rewriter and some Primus Lisp symbolic functions (#1350)
* fixes variable rewriter and some Primus Lisp symbolic functions The variable rewriter was incorrectly setting the mask when a register was modified through its alias. Instead of preserving the bits that are not set it was erasing them. There were also a couple of issues in handling registers and variables in the Primus Lisp lifter. First of all, let bindings were breaching the type system by binding variables to values that have different type. The set function was sometimes mistyping the registers (reminiscent of times when there were no pseudo-registers). * allows macos to fail without canceling all other jobs It fails too often and for random but independent of us reasons.
1 parent 42c2e7a commit a733374

File tree

7 files changed

+82
-19
lines changed

7 files changed

+82
-19
lines changed

.github/workflows/build-dev-repo.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
- 4.08.x
1616

1717
runs-on: ${{ matrix.os }}
18+
continue-on-error: ${{ matrix.os == 'macos-latest'}}
1819

1920
env:
2021
TMPDIR: /tmp

lib/bap_core_theory/bap_core_theory.mli

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,11 @@ module Theory : sig
12961296
(** the slot to store program semantics. *)
12971297
val slot : (program, t) Knowledge.slot
12981298

1299+
(** the value of the effect.
1300+
1301+
Represents the value of side-effectful compuations.
1302+
1303+
@since 2.3.0 *)
12991304
val value : (cls, unit Value.t) Knowledge.slot
13001305

13011306
include Knowledge.Value.S with type t := t
@@ -2041,37 +2046,53 @@ module Theory : sig
20412046
*)
20422047
module Origin : sig
20432048

2044-
(** [] *)
2049+
(** the abstract representation of an aliased register origin. *)
20452050
type ('s,'k) t = ('s,'k) origin
20462051

2047-
(** type index of the *)
2052+
(** the type index of the sub-registers *)
20482053
type sub
2054+
2055+
(** the type index for the super-registers *)
20492056
type sup
20502057

2058+
(** [cast_sub origin] recovers the kind of the origin. *)
20512059
val cast_sub : ('a,unit) t -> ('a,sub) t option
2060+
2061+
(** [cast_sup origin] recovers the kind of the origin. *)
20522062
val cast_sup : ('a,unit) t -> ('a,sup) t option
20532063

20542064

20552065
(** [reg origin] is the base register.
20562066
2057-
The returned value is never an alias itself. *)
2067+
The returned value is never an alias itself, i.e., it is a
2068+
base register. *)
20582069
val reg : ('a,sub) t -> 'a Bitv.t Var.t
20592070

2071+
2072+
(** [is_alias origin] if the the base register has the same size
2073+
and sort as the aliased register. *)
20602074
val is_alias : ('a,sub) t -> bool
20612075

20622076

20632077
(** [hi origin] the inclusive upper bound.
20642078
When an alias is a subset of the [origin] register,
20652079
[hi origin] is the most significant bit of the alias
2066-
register.
2067-
2068-
*)
2080+
register. *)
20692081
val hi : ('a,sub) t -> int
20702082

20712083
(** [lo origin] returns the inclusive upper bound of the origin register
20722084
to which an alias belongs. *)
20732085
val lo : ('a,sub) t -> int
20742086

2087+
2088+
(** [regs origin] returns an ordered list of constituent registers.
2089+
2090+
The registers are sorted in the big endian order, i.e., the
2091+
first element of the list corresponds to the most significant
2092+
part of the base register. This is the same order, in which
2093+
the aliasing was specified, e.g., if the aliasing was defined
2094+
as, [def x [reg hix; reg lox], then [regs] will
2095+
return [hix; lox].*)
20752096
val regs : ('a,sup) t -> 'a Bitv.t Var.t list
20762097

20772098
end

lib/bap_core_theory/bap_core_theory_pass.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ module Desugar(CT : Core) : Core = struct
9797
let open Bitvec.Make(struct
9898
let modulus = Bitvec.modulus dst_len
9999
end) in
100-
let mask = (one lsl int src_len - one) lsl int off in
100+
let mask =
101+
lnot ((one lsl int src_len - one) lsl int off) in
101102
let x = CT.(logand (var dst) (int s mask)) in
102103
let off = int off in
103104
let y = if Bitvec.equal off zero

lib/bap_primus/bap_primus_lisp_semantics.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,6 @@ module Prelude(CT : Theory.Core) = struct
432432
| {data=Var {data={exp=n}}} -> lookup@@var n
433433
| {data=Sym {data=s}} -> sym (KB.Name.unqualified s)
434434
| {data=Ite (cnd,yes,nay)} -> ite cnd yes nay
435-
| {data=Let ({data={exp=n; typ=Type t}},x,y)} -> let_ ~t n x y
436435
| {data=Let ({data={exp=n}},x,y)} -> let_ n x y
437436
| {data=App (Dynamic name,args)} -> app name args
438437
| {data=Seq xs} -> seq_ xs
@@ -545,9 +544,10 @@ module Prelude(CT : Theory.Core) = struct
545544
Scope.lookup v >>= function
546545
| Some v -> eval x >>= assign target ~local:true v
547546
| None -> eval x >>= assign target v
548-
and let_ ?(t=word) v x b =
547+
and let_ v x b =
549548
let* xeff = eval x in
550-
let orig = Theory.Var.define (bits t) (KB.Name.to_string v) in
549+
let s = Theory.Value.sort (res xeff) in
550+
let orig = Theory.Var.define s (KB.Name.to_string v) in
551551
if is_parameter prog orig
552552
then
553553
Env.set orig (res xeff) >>= fun () ->

lib/graphlib/graphlib.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ module Std : sig
11761176
solution is always a lower approximation of a real solution,
11771177
so it is always safe to use it).
11781178
1179-
@param the upper bound to the number of iterations the solver
1179+
@param steps the upper bound to the number of iterations the solver
11801180
can make.
11811181
11821182
@param start the entry node of the graph

plugins/primus_lisp/primus_lisp_main.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,15 @@ module Semantics = struct
320320
sysdatadir / "primus" / "semantics";
321321
]
322322

323+
let check_user_provided paths =
324+
match List.find paths ~f:(Fn.non is_folder) with
325+
| None -> ()
326+
| Some path ->
327+
invalid_argf "unable to load semantics from %S, \
328+
the path must exist and be a folder" path ()
329+
323330
let load_lisp_sources paths =
331+
check_user_provided paths;
324332
let paths = List.filter ~f:is_folder (paths @ default_paths) in
325333
let features = "core"::List.concat_map ~f:collect_features paths in
326334
let paths = paths @ library_paths in

plugins/primus_lisp/primus_lisp_semantic_primitives.ml

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ let export = Primus.Lisp.Type.Spec.[
188188
"get-current-program-counter", unit @-> int,
189189
"(get-current-program-counter) is an alias to (get-program-counter)";
190190

191-
"set-symbol-value", tuple [sym; a] @-> a,
191+
"set-symbol-value", tuple [int; a] @-> a,
192192
"(set-symbol-value S X) sets the value of the symbol S to X.
193193
Returns X";
194194

@@ -198,6 +198,10 @@ let export = Primus.Lisp.Type.Spec.[
198198
"is-symbol", one any @-> bool,
199199
"(is-symbol X) is true if X has a symbolic value.";
200200

201+
"alias-base-register", one int @-> int,
202+
"(alias-base-register x) if X has a symbolic value that is an
203+
aliased register returns the base register";
204+
201205
"cast-low", tuple [int; a] @-> b,
202206
"(cast-low S X) extracts low S bits from X.";
203207

@@ -582,13 +586,40 @@ module Primitives(CT : Theory.Core)(T : Target) = struct
582586
| None -> !!(empty s)
583587
| Some addr -> forget@@const_int s addr
584588

585-
let set_symbol v x =
586-
match KB.Value.get Primus.Lisp.Semantics.symbol v with
587-
| Some name ->
588-
let var = Theory.Var.define (Theory.Value.sort x) name in
589-
CT.set var !!x
589+
let require_symbol v k =
590+
match symbol v with
591+
| Some name -> k name
592+
| None -> illformed "not a symbolic value"
593+
594+
let possibly_register target v =
595+
require_symbol v @@ fun v ->
596+
match Theory.Target.var target v with
597+
| Some v -> !!v
590598
| None ->
591-
illformed "requires a value reified to a variable"
599+
let s = Theory.Bitv.define (Theory.Target.bits target) in
600+
KB.return @@ Theory.Var.forget (Theory.Var.define s v)
601+
602+
let set_symbol t v x =
603+
let* var = possibly_register t v in
604+
let x = KB.Value.refine x (Theory.Var.sort var) in
605+
CT.set var !!x
606+
607+
let alias_base_register target v =
608+
let* r = possibly_register target v in
609+
match Theory.Target.unalias target r with
610+
| None ->
611+
illformed "the register %a is not an alias in %a"
612+
Theory.Var.pp r Theory.Target.pp target
613+
| Some origin -> match Theory.Origin.cast_sub origin with
614+
| None ->
615+
illformed "the aliased register %a is not a subregister"
616+
Theory.Var.pp r
617+
| Some origin ->
618+
let reg = Theory.Origin.reg origin in
619+
let name = Theory.Var.name reg in
620+
forget @@
621+
CT.var reg >>| fun v ->
622+
KB.Value.put Primus.Lisp.Semantics.symbol v (Some name)
592623

593624
let symbol s v =
594625
match KB.Value.get Primus.Lisp.Semantics.symbol v with
@@ -755,9 +786,10 @@ module Primitives(CT : Theory.Core)(T : Target) = struct
755786
| "store-word",_-> data@@store_word t args
756787
| "get-program-counter",[]
757788
| "get-current-program-counter",[] -> pure@@get_pc s lbl
758-
| "set-symbol-value",[sym;x] -> data@@set_symbol sym x
789+
| "set-symbol-value",[sym;x] -> data@@set_symbol t sym x
759790
| "symbol",[x] -> pure@@symbol s x
760791
| "is-symbol", [x] -> pure@@is_symbol x
792+
| "alias-base-register", [x] -> pure@@alias_base_register t x
761793
| "cast-low",xs -> pure@@low xs
762794
| "cast-high",xs -> pure@@high xs
763795
| "cast-signed",xs -> pure@@signed xs

0 commit comments

Comments
 (0)