Skip to content

Commit 79fd1a2

Browse files
bmourad01bmourad01
and
bmourad01
authored
Fixes the stub resolver tests (#1564)
* Fixes the stub resolver tests * Preserves transitivity * Drop `bap-relation` Co-authored-by: bmourad01 <[email protected]>
1 parent ce84c26 commit 79fd1a2

File tree

3 files changed

+96
-91
lines changed

3 files changed

+96
-91
lines changed

oasis/stub-resolver

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Library bap-plugin-stub_resolver
77
Path: plugins/stub_resolver/
88
BuildDepends: bap, bap-abi, bap-knowledge, bap-core-theory, core_kernel,
99
bitvec, bitvec-order, bitvec-sexp,
10-
bap-main, ppx_bap, ogre
10+
bap-main, ppx_bap, ogre, graphlib, regular
1111
FindlibName: bap-plugin-stub_resolver
1212
CompiledObject: best
1313
Modules: Stub_resolver

plugins/stub_resolver/stub_resolver.ml

+78-85
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,30 @@ open Core_kernel[@@warning "-D"]
22
open Bap.Std
33
open Bap_core_theory
44
open Bap_knowledge
5+
open Graphlib.Std
6+
open Regular.Std
57

68
include Self ()
79
let package = "bap"
810

911
open KB.Syntax
1012

11-
type groups = int Tid.Map.t
12-
type names = String.Set.t Int.Map.t
13+
module Regular_string = struct
14+
type t = string
15+
include Regular.Make(struct
16+
include String
17+
let module_name = Some "String"
18+
let version = "2.6.0"
19+
end)
20+
end
21+
22+
module G = Graphlib.Make(Regular_string)(Unit)
1323

1424
type state = {
15-
groups : groups;
16-
names : names;
17-
next : int;
18-
stubs : Tid.Set.t;
19-
units : Theory.Unit.t Tid.Map.t;
25+
graph : G.t;
26+
names : Tid.Set.t String.Map.t;
27+
stubs : Tid.Set.t;
28+
units : Theory.Unit.t Tid.Map.t;
2029
}
2130

2231
module Class = struct
@@ -39,11 +48,10 @@ module Class = struct
3948
end
4049

4150
let empty = {
42-
groups = Map.empty (module Tid);
43-
names = Map.empty (module Int);
44-
units = Map.empty (module Tid);
45-
stubs = Set.empty (module Tid);
46-
next = 0;
51+
graph = G.empty;
52+
names = String.Map.empty;
53+
stubs = Tid.Set.empty;
54+
units = Tid.Map.empty;
4755
}
4856

4957
let in_file file f =
@@ -83,84 +91,69 @@ let update_units t sub =
8391
!!{t with units = Map.add_exn t.units tid unit}
8492
| None -> !!t
8593

86-
let find_groups names aliases =
87-
Map.fold names ~init:[]
88-
~f:(fun ~key:group ~data:aliases' groups ->
89-
if Set.(is_empty @@ inter aliases aliases')
90-
then groups
91-
else group :: groups)
92-
93-
let unite_names t groups =
94-
List.fold groups ~init:(Set.empty (module String))
95-
~f:(fun als id ->
96-
Set.union als (Map.find_exn t.names id))
97-
98-
let pick_representative = function
99-
| [] -> assert false
100-
| groups ->
101-
Option.value_exn (List.min_elt groups ~compare:Int.compare)
102-
103-
104-
let redirect t ~from ~to_ =
105-
Map.map t.groups ~f:(fun id ->
106-
if List.mem from id ~equal:Int.equal
107-
then to_
108-
else id)
109-
110-
let add t sub =
94+
let should_link aliases ~link_only ~no_link =
95+
Set.(is_empty @@ inter aliases no_link) && begin
96+
Set.is_empty link_only ||
97+
not Set.(is_empty @@ inter aliases link_only)
98+
end
99+
100+
let update_graph t name aliases =
101+
let n = G.Node.create name in
102+
let init = G.Node.insert n t.graph in
103+
let graph = Set.fold aliases ~init ~f:(fun g alias ->
104+
if String.(name <> alias) then
105+
let a = G.Node.create alias in
106+
let x = G.Edge.create n a () in
107+
let y = G.Edge.create a n () in
108+
G.Edge.(insert x (insert y g))
109+
else g) in
110+
{t with graph}
111+
112+
let update_names t sub ~link_only ~no_link =
113+
aliases_of_sub sub >>| fun aliases ->
114+
if should_link aliases ~link_only ~no_link then
115+
let tid = Term.tid sub in
116+
let names = Set.fold aliases ~init:t.names ~f:(fun m a ->
117+
Map.update m a ~f:(function
118+
| None -> Tid.Set.singleton tid
119+
| Some s -> Set.add s tid)) in
120+
update_graph {t with names} (Sub.name sub) aliases
121+
else t
122+
123+
let add t sub ~link_only ~no_link =
111124
update_stubs t sub >>= fun t ->
112125
update_units t sub >>= fun t ->
113-
aliases_of_sub sub >>| fun aliases ->
114-
match find_groups t.names aliases with
115-
| [] ->
116-
let groups = Map.add_exn t.groups (Term.tid sub) t.next in
117-
let names = Map.add_exn t.names t.next aliases in
118-
{t with groups; names; next = t.next + 1}
119-
| [id] ->
120-
let groups = Map.add_exn t.groups (Term.tid sub) id in
121-
let names = Map.update t.names id ~f:(function
122-
| None -> assert false
123-
| Some als' -> Set.union aliases als') in
124-
{t with names; groups}
125-
| groups ->
126-
let grp = pick_representative groups in
127-
let aliases = Set.union aliases (unite_names t groups) in
128-
let names = List.fold groups ~init:t.names ~f:Map.remove in
129-
let names = Map.add_exn names ~key:grp ~data:aliases in
130-
let groups = redirect t ~from:groups ~to_:grp in
131-
{t with names; groups}
132-
133-
let collect_by_group_id stubs groups =
134-
Map.fold groups ~init:Int.Map.empty
135-
~f:(fun ~key:tid ~data:id xs ->
136-
Map.update xs id ~f:(function
137-
| None -> [tid]
138-
| Some tids -> tid :: tids)) |>
139-
Map.map ~f:(List.partition_tf ~f:(Set.mem stubs))
140-
141-
let unambiguous_pairs names xs ~link_only ~no_link =
142-
let should_link id names =
143-
let names = Map.find_exn names id in
144-
Set.(is_empty @@ inter names no_link) && begin
145-
Set.is_empty link_only ||
146-
not Set.(is_empty @@ inter names link_only)
147-
end in
148-
let add y pairs x = Map.add_exn pairs x y in
149-
Map.fold xs ~init:(Map.empty (module Tid))
150-
~f:(fun ~key:id ~data:(stubs, impls) init ->
151-
match impls with
152-
| [y] when should_link id names ->
153-
List.fold stubs ~init ~f:(add y)
154-
| _ -> init)
155-
156-
let find_pairs t ~link_only ~no_link =
157-
unambiguous_pairs t.names ~link_only ~no_link @@
158-
collect_by_group_id t.stubs t.groups
126+
update_names t sub ~link_only ~no_link
127+
128+
let partition_group t group =
129+
Group.enum group |>
130+
Seq.fold ~init:Tid.Set.empty ~f:(fun default name ->
131+
Map.find t.names name |>
132+
Option.value_map ~default ~f:(Set.union default)) |>
133+
Set.partition_tf ~f:(Set.mem t.stubs)
134+
135+
let find_pairs t =
136+
let pp = Group.pp String.pp in
137+
Graphlib.strong_components (module G) t.graph |>
138+
Partition.groups |> Seq.fold ~init:Tid.Map.empty ~f:(fun init group ->
139+
let stubs, reals = partition_group t group in
140+
match Set.length reals with
141+
| 1 ->
142+
let impl = Set.min_elt_exn reals in
143+
Set.fold stubs ~init ~f:(fun links stub ->
144+
Map.add_exn links stub impl)
145+
| 0 ->
146+
info "no implementations found in group %a" pp group;
147+
init
148+
| n ->
149+
info "ambiguous implementations (%d) found in group %a" n pp group;
150+
init)
159151

160152
let resolve prog ~link_only ~no_link =
153+
let f = add ~link_only ~no_link in
161154
Term.to_sequence sub_t prog |>
162-
Knowledge.Seq.fold ~init:empty ~f:add >>| fun state ->
163-
state, find_pairs state ~link_only ~no_link
155+
Knowledge.Seq.fold ~init:empty ~f >>| fun state ->
156+
state, find_pairs state
164157

165158
let label_name x =
166159
KB.collect Theory.Label.name x >>| function

plugins/stub_resolver/stub_resolver_tests.ml

+17-5
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,19 @@ let suite = "stub-resolver" >::: [
177177
real "h0" ["h1"; "h2"];
178178
stub "h1" [];
179179
stub "h2" [];
180-
] ~expected:[];
180+
] ~expected:[
181+
"h1", "h0";
182+
"h2", "h0";
183+
];
181184

182185
test "ambiguous stubs" [
183186
real "i0" [];
184187
stub "i1" ["i0"];
185188
stub "i2" ["i0"];
186-
] ~expected:[];
189+
] ~expected:[
190+
"i1", "i0";
191+
"i2", "i0";
192+
];
187193

188194
test "crossreference" [
189195
real "j0" ["j1"];
@@ -210,7 +216,9 @@ let suite = "stub-resolver" >::: [
210216
real "m6" ["m5"; "m9"];
211217
real "m9" ["m10"];
212218
stub "m10" [];
213-
] ~expected:["m0", "m1"; ];
219+
] ~expected:[
220+
"m0", "m1";
221+
];
214222

215223
test "several intersections 2" [
216224
stub "n0" ["n1"; "n2"; "n3"];
@@ -220,14 +228,18 @@ let suite = "stub-resolver" >::: [
220228
real "n6" [];
221229
stub "n7" ["n6"];
222230
real "n8" ["n1"; "n5"]
223-
] ~expected:["n7", "n6" ];
231+
] ~expected:["n7", "n6"];
224232

225233
test "several intersections 3" [
226234
stub "p0" ["p1"; "p2"; "p3"];
227235
stub "p4" ["p5"; "p6"; "p7"];
228236
real "p5" [];
229237
stub "p6" ["p8"; "p9"; "p10"; "p4"];
230238
real "p11" ["p12"; "p13"; "p1"];
231-
] ~expected:["p0", "p11" ];
239+
] ~expected:[
240+
"p0", "p11";
241+
"p4", "p5";
242+
"p6", "p5";
243+
];
232244

233245
]

0 commit comments

Comments
 (0)