@@ -6,7 +6,7 @@ open Monads.Std
66include Self ()
77
88module Attrs = Bap_c_term_attributes
9-
9+ module Data = Bap_c_data
1010type ctype = t
1111
1212let is_const p = p.Spec. qualifier.Qualifier. const
@@ -40,7 +40,7 @@ type error = [
4040] [@@ deriving sexp_of ]
4141
4242let sexp_of_exp exp = Sexp. Atom (Exp. to_string exp)
43- type param = Bap_c_data .t * exp [@@ deriving sexp ]
43+ type param = Data .t * exp [@@ deriving sexp ]
4444
4545type args = {
4646 return : param option ;
@@ -58,33 +58,96 @@ exception Failed of error [@@deriving sexp_of]
5858let fail x = raise (Failed x)
5959
6060let data (size : #Bap_c_size.base ) (t : Bap_c_type.t ) =
61- let open Bap_c_data in
61+ let open Data in
62+ let sizeof t = match size#bits t with
63+ | None -> Size. in_bits size#pointer
64+ | Some s -> s in
65+ let padding pad : Data.t =
66+ match Size. of_int_opt pad with
67+ | Some pad -> Imm (pad,Set [] )
68+ | None ->
69+ let data : Data.t = Imm (`r8 ,Set [] ) in
70+ Seq (List. init (pad/ 8 ) ~f: (Fn. const data)) in
6271 let rec data = function
6372 | `Void -> Seq []
6473 | `Basic {Spec. t} -> Imm (size#basic t, Top )
6574 | `Pointer {Spec. t} -> Ptr (data t)
6675 | `Array {Spec. t ={Array. element =t ; size =None } } -> Ptr (data t)
6776 | `Array {Spec. t ={Array. element =t ; size =Some n } } ->
68- let et = data t in
69- Ptr (Seq (List. init n ~f: (fun _ -> et)))
77+ Ptr (Seq (List. init n ~f: (Fn. const (data t))))
7078 | `Structure {Spec. t ={Compound. fields =fs } } ->
71- let _,ss =
72- List. fold fs ~init: (0 ,[] ) ~f: (fun (off ,seq ) (_ ,t ) ->
73- let off' = match size#bits t with
74- | None -> off + Size. in_bits size#pointer (* or assert false *)
75- | Some sz -> off + sz in
76- match size#padding t off with
77- | None -> off', data t :: seq
78- | Some pad -> off, data t :: Imm (pad,Set [] ) :: seq) in
79+ List. fold fs ~init: (0 ,0 ,[] ) ~f: (fun (off ,total ,seq ) (_ ,t ) ->
80+ let fsize = sizeof t in
81+ let pad = Bap_c_size. padding (size#alignment t) off in
82+ off + fsize + pad, total + fsize + pad, match pad with
83+ | 0 -> data t :: seq
84+ | _ -> data t :: padding pad :: seq) |> fun (_ ,total ,ss ) ->
85+ let fullsize = sizeof t in
86+ let pad = max 0 (fullsize - total) in
87+ let ss = if pad = 0 then ss else padding (fullsize- total) :: ss in
7988 Seq (List. rev ss)
80- | `Union {Spec. t =_ } ->
81- let sz = match size#bits t with
82- | None -> Size. in_bits size#pointer
83- | Some sz -> sz in
84- Seq (List. init (sz/ 8 ) ~f: (fun _ -> Imm (`r8 ,Set [] )))
89+ | `Union _ ->
90+ let sz = sizeof t in
91+ Seq (List. init (sz/ 8 ) ~f: (fun _ -> Imm (`r8 ,Top )))
8592 | `Function _ -> Ptr (Imm ((size#pointer :> size ),Top )) in
8693 data t
8794
95+ let layout (size : #Bap_c_size.base ) (t : Bap_c_type.t ) =
96+ let open Data in
97+ let sizeof t = match size#bits t with
98+ | None -> Size. in_bits size#pointer
99+ | Some s -> s in
100+ let imm size obj : Data.layout = {layout= Imm (size,obj)}
101+ and ptr {layout =data } : Data.layout = {layout= Ptr data}
102+ and seq layouts : Data.layout = {
103+ layout = Seq (List. map layouts ~f: (fun {layout} -> layout))
104+ } in
105+ let padding pad : Data.layout = imm pad Undef in
106+ let rec layout t : Data.layout = match t with
107+ | `Void -> imm 8 Undef
108+ | `Basic {Spec. t} -> imm (Size. in_bits (size#basic t)) (Basic t)
109+ | `Pointer {Spec. t} -> ptr (layout t)
110+ | `Array {Spec. t ={Array. element =t ; size =None } } -> ptr (layout t)
111+ | `Array {Spec. t ={Array. element =t ; size =Some n } } ->
112+ ptr (seq (List. init n ~f: (Fn. const (layout t))))
113+ | `Structure {Spec. t ={Compound. fields =fs } } ->
114+ List. fold fs ~init: (0 ,0 ,[] ) ~f: (fun (off ,total ,seq ) (name ,t ) ->
115+ let fsize = sizeof t in
116+ let pad = Bap_c_size. padding (size#alignment t) off in
117+ off + fsize + pad, total + fsize + pad,
118+ imm fsize (Field (name,layout t)) ::
119+ match pad with
120+ | 0 -> seq
121+ | _ -> padding pad :: seq) |> fun (_ ,total ,ss ) ->
122+ let fullsize = sizeof t in
123+ let pad = max 0 (fullsize - total) in
124+ let ss = if pad = 0 then ss else padding (fullsize- total) :: ss in
125+ seq (List. rev ss)
126+ | `Union {Spec. t ={Compound. fields =fs } } ->
127+ let total = sizeof t in
128+ let variants = List. map fs ~f: (fun (name ,t ) ->
129+ let fsize = sizeof t in
130+ let pad = max 0 (total - fsize) in
131+ let field = imm fsize @@ Field (name, layout t) in
132+ match pad with
133+ | 0 -> field
134+ | _ -> seq [field; padding pad]) in
135+ imm total (Union variants)
136+ | `Function _ -> ptr (imm (Size. in_bits (size#pointer)) Undef ) in
137+ layout t
138+
139+ let rec size_of_data size : Data.t -> int = function
140+ | Imm (size ,_ ) -> Size. in_bits size
141+ | Seq xs -> List. sum (module Int ) ~f: (size_of_data size) xs
142+ | Ptr _ -> Size. in_bits (size#pointer)
143+
144+ let rec size_of_layout size : Data.layout -> int =
145+ fun {layout} -> size_of_datum size layout
146+ and size_of_datum size : _ Data.datum -> int = function
147+ | Imm (size ,_ ) -> size
148+ | Seq xs -> List. sum (module Int ) ~f: (size_of_datum size) xs
149+ | Ptr _ -> Size. in_bits (size#pointer)
150+
88151let array_to_pointer (t : ctype ) : ctype =
89152 match t with
90153 | `Array ({t ={element} } as s ) -> `Pointer {s with t = element}
@@ -109,12 +172,18 @@ let create_arg size i intent name t (data,exp) sub =
109172 let ltyp = match size#bits t with
110173 | None -> Type. imm (Size. in_bits size#pointer)
111174 | Some m -> Type. imm m in
175+ let layout = match data with
176+ | Data. Ptr _ ->
177+ if Bap_c_type. is_pointer t then layout size t
178+ else layout size (Bap_c_type. pointer t)
179+ | _ -> layout size t in
112180 let rtyp = Type. infer_exn exp in
113181 let name = if String. is_empty name then sprintf " arg%d" (i+ 1 ) else name in
114182 let var = Var. create (Sub. name sub ^ " _" ^ name) ltyp in
115183 let arg = Arg. create ~intent var @@ coerce ltyp rtyp exp in
116184 let arg = Term. set_attr arg Attrs. data data in
117185 let arg = Term. set_attr arg Attrs. t t in
186+ let arg = Term. set_attr arg Attrs. layout layout in
118187 arg
119188
120189let registry = Hashtbl. create (module String )
@@ -242,7 +311,7 @@ module Arg = struct
242311 module C = struct
243312 module Size = Bap_c_size
244313 module Type = Bap_c_type
245- module Data = Bap_c_data
314+ module Data = Data
246315 end
247316
248317 module Stack : sig
0 commit comments