Skip to content

Commit c100c28

Browse files
authored
makes the ABI processors usable programmatically (#1529)
Publishes several functions that make it easier to apply the ABI processors. Also, fixes the naming scheme for the abi processors that stopped to be unique, after we switched to the real ABI names. We now use the target name for the name of the ABI.
1 parent 7e3d406 commit c100c28

File tree

5 files changed

+144
-113
lines changed

5 files changed

+144
-113
lines changed

lib/bap_c/bap_c_abi.ml

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
open Core_kernel[@@warning "-D"]
2+
open Bap_core_theory
23
open Bap.Std
34
open Bap_c_type
45
open Monads.Std
@@ -184,10 +185,43 @@ let create_arg size i intent name t (data,exp) sub =
184185
let arg = Term.set_attr arg Attrs.layout layout in
185186
arg
186187

187-
let registry = Hashtbl.create (module String)
188-
let register name abi = Hashtbl.set registry ~key:name ~data:abi
188+
189+
190+
let models = Hashtbl.create (module Theory.Target)
191+
192+
let register_model target model =
193+
if Hashtbl.mem models target
194+
then invalid_argf "A data model for target %s is already set"
195+
(Theory.Target.to_string target) ();
196+
Hashtbl.add_exn models target (model :> Bap_c_size.base)
197+
198+
let model target = match Hashtbl.find models target with
199+
| Some m -> m
200+
| None -> if Theory.Target.bits target = 32
201+
then new Bap_c_size.base `LP32
202+
else new Bap_c_size.base `LP64
203+
204+
let registry = Hashtbl.create (module Theory.Target)
205+
206+
let register name abi =
207+
let target = match Theory.Target.lookup ~package:"bap" name with
208+
| Some t -> t
209+
| None -> invalid_argf
210+
"The name of the abi should be a valid name. Got %s. \
211+
See `bap list targets` for the list valid names" name () in
212+
Hashtbl.add registry ~key:target ~data:abi |> function
213+
| `Ok -> ()
214+
| `Duplicate ->
215+
invalid_argf "The processor for ABI %s is already registered. \
216+
Please pick a unique name" name ()
189217
let register_abi = register
190-
let get_processor name = Hashtbl.find registry name
218+
219+
let get_processor name =
220+
match Theory.Target.lookup ~package:"bap" name with
221+
| None -> None
222+
| Some t -> Hashtbl.find registry t
223+
224+
let lookup = Hashtbl.find registry
191225

192226

193227
let get_prototype gamma name = match gamma name with
@@ -212,6 +246,40 @@ let get_prototype gamma name = match gamma name with
212246
}
213247
}
214248

249+
250+
let apply_args abi size attrs t sub =
251+
let t = decay_arrays t in
252+
match abi.insert_args sub attrs t with
253+
| None -> sub
254+
| Some {return; hidden; params} ->
255+
let params = List.mapi params ~f:(fun i a -> i,a) in
256+
List.map2 params t.Bap_c_type.Proto.args ~f:(fun (i,a) (n,t) ->
257+
create_arg size i (arg_intent t) n t a sub) |>
258+
function
259+
| Unequal_lengths ->
260+
error "The ABI processor generated an incorrect number of \
261+
argument terms for the subroutine %s: %d <> %d"
262+
(Sub.name sub)
263+
(List.length params)
264+
(List.length t.args);
265+
sub
266+
| Ok args ->
267+
let ret = match return with
268+
| None -> []
269+
| Some ret ->
270+
let t = t.Bap_c_type.Proto.return in
271+
[create_arg size 0 Out "result" t ret sub] in
272+
let hid = List.mapi hidden ~f:(fun i (t,a) ->
273+
let n = "hidden" ^ if i = 0 then "" else Int.to_string i in
274+
create_arg size 0 Both n t a sub) in
275+
List.fold (args@hid@ret) ~init:sub ~f:(Term.append arg_t)
276+
277+
let apply abi size attrs t sub =
278+
let sub = apply_args abi size attrs t sub in
279+
let sub = Term.set_attr sub Attrs.proto t in
280+
let sub = List.fold_right ~init:sub attrs ~f:Bap_c_attr.apply in
281+
abi.apply_attrs attrs sub
282+
215283
let create_api_processor size abi : Bap_api.t =
216284
let stage1 gamma = object(self)
217285
inherit Term.mapper as super
@@ -225,40 +293,7 @@ let create_api_processor size abi : Bap_api.t =
225293
else
226294
let name = Sub.name sub in
227295
let {Bap_c_type.Spec.t; attrs} = get_prototype gamma name in
228-
let sub = self#apply_args sub attrs t in
229-
let sub = Term.set_attr sub Attrs.proto t in
230-
let sub = List.fold_right ~init:sub attrs ~f:Bap_c_attr.apply in
231-
abi.apply_attrs attrs sub
232-
233-
234-
method private apply_args sub attrs t =
235-
let t = decay_arrays t in
236-
match abi.insert_args sub attrs t with
237-
| None ->
238-
super#map_sub sub
239-
| Some {return; hidden; params} ->
240-
let params = List.mapi params ~f:(fun i a -> i,a) in
241-
List.map2 params t.Bap_c_type.Proto.args ~f:(fun (i,a) (n,t) ->
242-
create_arg size i (arg_intent t) n t a sub) |>
243-
function
244-
| Unequal_lengths ->
245-
error "The ABI processor generated an incorrect number of \
246-
argument terms for the subroutine %s: %d <> %d"
247-
(Sub.name sub)
248-
(List.length params)
249-
(List.length t.args);
250-
sub
251-
| Ok args ->
252-
let ret = match return with
253-
| None -> []
254-
| Some ret ->
255-
let t = t.Bap_c_type.Proto.return in
256-
[create_arg size 0 Out "result" t ret sub] in
257-
let hid = List.mapi hidden ~f:(fun i (t,a) ->
258-
let n = "hidden" ^ if i = 0 then "" else Int.to_string i in
259-
create_arg size 0 Both n t a sub) in
260-
List.fold (args@hid@ret) ~init:sub ~f:(Term.append arg_t)
261-
296+
apply abi size attrs t sub
262297
end in
263298
let module Api = struct
264299
let language = "c"
@@ -780,15 +815,14 @@ module Arg = struct
780815

781816
let install target ruler pass =
782817
let open Bap_core_theory in
783-
let abi = Theory.Target.abi target in
784-
let abi_name = Format.asprintf "%s"
785-
(KB.Name.unqualified (Theory.Abi.name abi)) in
818+
let abi_name = KB.Name.unqualified (Theory.Target.name target) in
786819
let abi_processor = {
787820
apply_attrs = (fun _ x -> x);
788821
insert_args = fun _ attrs proto ->
789822
reify target ruler (pass attrs proto)
790823
} in
791824
register_abi abi_name abi_processor;
825+
register_model target ruler;
792826
Bap_abi.register_pass @@ fun proj ->
793827
if Theory.Target.equal (Project.target proj) target
794828
then begin

lib/bap_c/bap_c_abi.mli

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@ val data : #Bap_c_size.base -> Bap_c_type.t -> Bap_c_data.t
8484
val layout : #Bap_c_size.base -> Bap_c_type.t -> Bap_c_data.layout
8585

8686

87+
(** [model target] returns the data model for the given target.
88+
89+
@since 2.5.0 *)
90+
val model : Theory.Target.t -> Bap_c_size.base
91+
92+
93+
(** [apply processor attrs proto sub] applies the abi processor to the
94+
subroutine [sub].
95+
96+
The function inserts arguments and attaches appropriate arguments
97+
to the function and its subterms, such as strores the type of each
98+
argument, the provided C attributes, stores the prototype, computes
99+
and attaches data layouts, etc.
100+
101+
@since 2.5.0 *)
102+
val apply : t -> #Bap_c_size.base -> attr list -> proto -> sub term -> sub term
103+
104+
87105
(** [arg_intent t] infers argument intention based on its C type. If
88106
an argument is passed by value, i.e., it is a c basic type, then
89107
it is an input argument. If an argument is a reference, but not a
@@ -95,12 +113,25 @@ val layout : #Bap_c_size.base -> Bap_c_type.t -> Bap_c_data.layout
95113
val arg_intent : Bap_c_type.t -> intent
96114

97115
(** [register name t] registers an abi processor [t] named [name] that
98-
may be used by subroutines in this project.*)
116+
may be used by subroutines in this project.
117+
118+
@after 2.5.0 fails if there is already a processor for the given [name].
119+
@after 2.5.0 the abi name should be a valid target name.
120+
*)
99121
val register : string -> t -> unit
122+
[@@deprecated "[since 2022-07] use the Arg module"]
100123

101124
(** [get_processor name] is used to access an abi processor with its
102125
name.*)
103126
val get_processor : string -> t option
127+
[@@deprecated "[since 2022-07] use [lookup]"]
128+
129+
130+
(** [lookup t] the abi processor associated with the target [t].
131+
132+
@since 2.5.0
133+
*)
134+
val lookup : Theory.Target.t -> t option
104135

105136

106137
(** An abstraction of a stack, commonly used in C compilers. *)
@@ -403,10 +434,10 @@ module Arg : sig
403434
[arena] is empty; or if some other argument is already passed
404435
via memory.
405436
406-
@since 2.5.0 accepts the [rev] parameter.
407-
@since 2.5.0 accepts the [limit] parameter.
437+
@after 2.5.0 accepts the [rev] parameter.
438+
@after 2.5.0 accepts the [limit] parameter.
408439
409-
@since 2.5.0 passes as much as possible (up to the limit) of the
440+
@after 2.5.0 passes as much as possible (up to the limit) of the
410441
object via registers.
411442
412443
@before 2.5.0 was passing at most one word via registers.

lib/x86_cpu/x86_target.ml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -544,14 +544,14 @@ module Abi = struct
544544

545545
let calling_conventions = [
546546
(* 16-bit ABI *)
547-
[i286], [
547+
i286, [
548548
Abi.cdecl, cdecl16;
549549
Abi.pascal, pascal16;
550550
Abi.fortran, pascal16;
551551
];
552552

553553
(* 32-bit ABI *)
554-
[i386; i486; i586; i686], [
554+
i386, [
555555
Abi.sysv, cdecl;
556556
Abi.cdecl, cdecl;
557557
Abi.pascal, pascal;
@@ -561,7 +561,7 @@ module Abi = struct
561561
];
562562

563563
(* 64-bit ABI *)
564-
[amd64], [
564+
amd64, [
565565
Abi.ms, ms64;
566566
Abi.sysv, sysv;
567567
]
@@ -579,9 +579,8 @@ module Abi = struct
579579
]
580580

581581
let install_calling_conventions () =
582-
List.iter calling_conventions ~f:(fun (targets,args) ->
583-
List.cartesian_product targets args |>
584-
List.iter ~f:(fun (parent,(abi,install)) ->
582+
List.iter calling_conventions ~f:(fun (parent,abis) ->
583+
List.iter abis ~f:(fun (abi,install) ->
585584
Theory.Target.filter ~parent ~abi () |>
586585
List.iter ~f:(fun t ->
587586
if Theory.Target.bits t = Theory.Target.bits parent

plugins/arm/arm_gnueabi.ml

Lines changed: 28 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
open Core_kernel[@@warning "-D"]
22
open Bap.Std
33
open Bap_c.Std
4-
5-
include Self()
4+
open Bap_core_theory
5+
6+
module Arg = C.Abi.Arg
7+
open Arg.Language
8+
9+
let data model = object(self)
10+
inherit C.Size.base model
11+
method! enum elts =
12+
if Int64.(C.Size.max_enum_elt elts < (1L lsl 32))
13+
then self#integer `uint
14+
else self#integer `ulong_long
15+
method! real = function
16+
| `float -> `r32
17+
| `double | `long_double -> `r64
18+
end
619

720
module Aapcs32 = struct
8-
open Bap_core_theory
9-
open Bap_c.Std
10-
open Bap.Std
11-
12-
module Arg = C.Abi.Arg
13-
open Arg.Language
14-
15-
let model = object(self)
16-
inherit C.Size.base `ILP32
17-
method! enum elts =
18-
if Int64.(C.Size.max_enum_elt elts < (1L lsl 32))
19-
then self#integer `uint
20-
else self#integer `ulong_long
21-
method! real = function
22-
| `float -> `r32
23-
| `double | `long_double -> `r64
24-
end
2521

2622
let define t =
27-
install t model @@ fun describe ->
23+
install t (data `ILP32) @@ fun describe ->
2824
let* iargs = Arg.Arena.iargs t in
2925
let* irets = Arg.Arena.irets t in
3026
let rev = Theory.Endianness.(Theory.Target.endianness t = le) in
@@ -44,41 +40,15 @@ module Aapcs32 = struct
4440
Arg.memory
4541
];
4642
]
47-
48-
let supported_abis = Theory.Abi.[unknown; gnueabi; eabi]
49-
let is_our_abi abi = List.exists supported_abis ~f:(Theory.Abi.equal abi)
50-
51-
52-
let install () =
53-
Theory.Target.family Arm_target.parent |>
54-
List.iter ~f:(fun t ->
55-
if Theory.Target.bits t = 32 &&
56-
is_our_abi (Theory.Target.abi t)
57-
then define t)
5843
end
5944

60-
6145
module Aapcs64 = struct
62-
open Bap_core_theory
63-
open Bap_c.Std
64-
open Bap.Std
65-
66-
let name = "aapcs64"
67-
68-
module Arg = C.Abi.Arg
69-
open Arg.Language
70-
71-
let data_model t =
72-
let bits = Theory.Target.bits t in
73-
new C.Size.base (if bits = 32 then `ILP32 else `LP64)
74-
7546
let is_composite t =
7647
C.Type.(is_structure t || is_union t)
7748

7849
let define t =
79-
let model = data_model t in
50+
let model = data `LP64 in
8051
let rev = Theory.Endianness.(Theory.Target.endianness t = le) in
81-
8252
install t model @@ fun describe ->
8353
let* iargs = Arg.Arena.iargs t in
8454
let* irets = Arg.Arena.irets t in
@@ -126,20 +96,17 @@ module Aapcs64 = struct
12696
]
12797
]
12898
]
129-
130-
let is_our_abi abi = List.exists ~f:(Theory.Abi.equal abi) Theory.Abi.[
131-
unknown; gnu; eabi;
132-
]
133-
134-
let install () =
135-
Theory.Target.family Arm_target.parent |>
136-
List.iter ~f:(fun t ->
137-
if Theory.Target.bits t = 64 && is_our_abi (Theory.Target.abi t)
138-
then define t)
139-
140-
14199
end
142100

101+
let is_our_abi abi = List.exists ~f:(Theory.Abi.equal abi) Theory.Abi.[
102+
unknown; gnu; eabi; gnueabi;
103+
]
104+
143105
let setup () =
144-
Aapcs32.install ();
145-
Aapcs64.install ();
106+
Theory.Target.family Arm_target.parent |>
107+
List.iter ~f:(fun t ->
108+
if is_our_abi (Theory.Target.abi t)
109+
then match Theory.Target.bits t with
110+
| 64 -> Aapcs64.define t
111+
| 32 -> Aapcs32.define t
112+
| _ -> ())

plugins/arm/arm_main.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ let () = Bap_main.Extension.declare ~doc @@ fun ctxt ->
4747
let backend = ctxt-->backend in
4848
let features = List.concat (ctxt-->features) in
4949
Arm_target.load ~features ?backend ?interworking ();
50+
Arm_gnueabi.setup ();
5051
List.iter all_of_arms ~f:(fun arch ->
51-
register_target (arch :> arch) (module ARM);
52-
Arm_gnueabi.setup ());
52+
register_target (arch :> arch) (module ARM));
5353
Ok ()

0 commit comments

Comments
 (0)