@@ -2,21 +2,30 @@ open Core_kernel[@@warning "-D"]
2
2
open Bap.Std
3
3
open Bap_core_theory
4
4
open Bap_knowledge
5
+ open Graphlib.Std
6
+ open Regular.Std
5
7
6
8
include Self ()
7
9
let package = " bap"
8
10
9
11
open KB.Syntax
10
12
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 )
13
23
14
24
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 ;
20
29
}
21
30
22
31
module Class = struct
@@ -39,11 +48,10 @@ module Class = struct
39
48
end
40
49
41
50
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;
47
55
}
48
56
49
57
let in_file file f =
@@ -83,84 +91,69 @@ let update_units t sub =
83
91
!! {t with units = Map. add_exn t.units tid unit }
84
92
| None -> !! t
85
93
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 =
111
124
update_stubs t sub >> = fun t ->
112
125
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)
159
151
160
152
let resolve prog ~link_only ~no_link =
153
+ let f = add ~link_only ~no_link in
161
154
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
164
157
165
158
let label_name x =
166
159
KB. collect Theory.Label. name x >> | function
0 commit comments