Skip to content

Commit a4981a2

Browse files
authored
switches to FrontC.4.x adds the preprocessing option (#1314)
* switches to FrontC.4.x adds the preprocessing option Since FrontC.4.x supports new types from C99+ we had to update BAP as well, both its representation of the C types as well as the parsing procedure. We also added an option (disabled by default) to apply preprocessing (with an ability to specify the path to it) since FrontC.4.1+ is much more robust and is capable of chewing linux system headers. * adds the FrontC constraint
1 parent 2540853 commit a4981a2

File tree

5 files changed

+53
-25
lines changed

5 files changed

+53
-25
lines changed

lib/bap_c/bap_c_size.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type bits = Int.t
1212
class base (m : model) = object(self)
1313
method integer (t : integer) : size =
1414
match m,t with
15-
| _,#char -> `r8
15+
| _,(`bool|#char) -> `r8
1616
| _,#short -> `r16
1717
| `LP32,#cint -> `r16
1818
| (`ILP32|`LLP64|`LP64),#cint -> `r32

lib/bap_c/bap_c_type.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type signed =
3737
[@@deriving bin_io,compare,sexp,enumerate]
3838

3939
type unsigned =
40-
[`uchar | `ushort | `uint | `ulong | `ulong_long]
40+
[`bool | `uchar | `ushort | `uint | `ulong | `ulong_long]
4141
[@@deriving bin_io,compare,sexp,enumerate]
4242

4343
type enum =

oasis/frontc-parser

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ Library frontc_parser_plugin
88
Path: plugins/frontc_parser
99
FindlibName: bap-plugin-frontc_parser
1010
CompiledObject: best
11-
BuildDepends: bap, bap-c, FrontC, core_kernel, ppx_bap
11+
BuildDepends: bap, bap-c, FrontC, core_kernel, ppx_bap, core_kernel.caml_unix
1212
InternalModules: Frontc_parser_main
1313
XMETAExtraLines: tags="api,c,parser"

opam/opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ depends: [
1717
"core_kernel" {>= "v0.14" & < "v0.15"}
1818
"ezjsonm"
1919
"fileutils"
20-
"FrontC"
20+
"FrontC" {>= "4.1" & < "4.2"}
2121
"oasis" {build & >= "0.4.10"}
2222
"ounit" {build}
2323
"ocamlgraph" {>= "1.8.6"}

plugins/frontc_parser/frontc_parser_main.ml

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ let () = Config.manpage [
1414
`P "$(b,bap-api)(3), $(b,bap-c)(3), $(b,bap-plugin-api)(1)"
1515
]
1616

17+
1718
let int size sign : C.Type.basic = match size,sign with
1819
| (NO_SIZE,(NO_SIGN|SIGNED)) -> `sint
1920
| (SHORT,(NO_SIGN|SIGNED)) -> `sshort
@@ -73,7 +74,7 @@ let name_groups : name_group list -> 'a list =
7374
List.map ns ~f:(fun (n,t,attrs,_) -> n,t,attrs))
7475

7576
let single_names : single_name list -> 'a list =
76-
List.map ~f:(fun (_,s,(n,t,attrs,_)) -> n,t,attrs)
77+
List.map ~f:(fun (_,_,(n,t,attrs,_)) -> n,t,attrs)
7778

7879
let rec gnu_attr = function
7980
| GNU_NONE -> None
@@ -83,7 +84,8 @@ let rec gnu_attr = function
8384
| GNU_ID s -> Some C.Type.Attr.{name = s; args = []}
8485
| GNU_CST _
8586
| GNU_EXTENSION
86-
| GNU_INLINE -> None
87+
| GNU_INLINE
88+
| GNU_TYPE_ARG _ -> None
8789
and gnu_attrs_args = List.filter_map ~f:(function
8890
| GNU_ID s
8991
| GNU_CST
@@ -142,11 +144,16 @@ type tag = {
142144

143145
let ctype gamma {lookup} t =
144146
let rec ctype : base_type -> C.Type.t = function
145-
| NO_TYPE | TYPE_LINE _ | OLD_PROTO _ | BITFIELD _ | VOID -> `Void
147+
| NO_TYPE | TYPE_LINE _ | OLD_PROTO _ | BITFIELD _
148+
| BUILTIN_TYPE _ | VOID -> `Void
149+
| BOOL -> basic `bool
146150
| CHAR sign -> basic @@ char sign
147151
| INT (size,sign) -> basic @@ int size sign
148152
| FLOAT _ -> basic @@ `float
149153
| DOUBLE long -> basic @@ if long then `long_double else `double
154+
| COMPLEX_FLOAT -> basic `cfloat
155+
| COMPLEX_DOUBLE -> basic `cdouble
156+
| COMPLEX_LONG_DOUBLE -> basic `clong_double
150157
| PTR t -> pointer @@ ctype t
151158
| RESTRICT_PTR t -> restrict @@ ctype t
152159
| ARRAY (et,ice) -> array (size ice) @@ ctype et
@@ -161,7 +168,7 @@ let ctype gamma {lookup} t =
161168
| CONST t -> qualify const @@ ctype t
162169
| VOLATILE t -> qualify volatile @@ ctype t
163170
| GNU_TYPE (a,t) -> with_attrs (gnu_attrs a) @@ ctype t
164-
and enum_items tag =
171+
and enum_items _ =
165172
List.map ~f:(fun (name,exp) -> match exp with
166173
| CONSTANT (CONST_INT x) ->
167174
name, Option.try_with (fun () -> Int64.of_string x)
@@ -200,7 +207,7 @@ let parse (size : C.Size.base) parse lexbuf =
200207
let tags = String.Table.create () in
201208
let gamma name = match Hashtbl.find env name with
202209
| Some t -> t
203-
| None -> invalid_argf "unbound type %s" name () in
210+
| None -> `Void in
204211
let lookup what name = match Hashtbl.find tags name with
205212
| Some t -> t
206213
| None -> what name [] in
@@ -231,19 +238,40 @@ let parse (size : C.Size.base) parse lexbuf =
231238
Hashtbl.map_inplace env ~f:resolve;
232239
Hashtbl.to_alist env
233240

234-
let parser size name =
235-
In_channel.with_file name ~f:(fun input ->
236-
let open Clexer in
237-
init {
238-
!current_handle with
239-
h_in_channel = input;
240-
h_file_name = name;
241-
h_out_channel = stderr;
242-
};
243-
init_lexicon ();
244-
let lexbuf = Lexing.from_function (get_buffer current_handle) in
245-
let parser = Cparser.file initial in
246-
try Ok (parse size parser lexbuf) with exn ->
247-
Or_error.of_exn exn)
248-
249-
let () = Config.when_ready @@ fun _ -> C.Parser.provide parser
241+
exception Cpp_failed
242+
243+
let with_file cpp name f =
244+
match cpp with
245+
| None -> In_channel.with_file name ~f
246+
| Some cpp ->
247+
let cmd = sprintf "%s %S" cpp name in
248+
let input = Caml_unix.open_process_in cmd in
249+
protect ~f:(fun () -> f input)
250+
~finally:(fun () ->
251+
match Caml_unix.close_process_in input with
252+
| WEXITED 0 -> ()
253+
| _ -> raise Cpp_failed)
254+
255+
let parser cpp size name =
256+
with_file cpp name @@ fun input ->
257+
let open Clexer in
258+
init {
259+
!current_handle with
260+
h_in_channel = input;
261+
h_file_name = name;
262+
h_out_channel = stderr;
263+
};
264+
init_lexicon ();
265+
let lexbuf = Lexing.from_function (get_buffer current_handle) in
266+
let parser = Cparser.file initial in
267+
try Ok (parse size parser lexbuf) with exn ->
268+
Or_error.of_exn exn
269+
270+
let cpp = Config.param Config.(some string)
271+
~as_flag:(Some "cpp")
272+
~doc:"Preprocess headers with the specified preprocessor."
273+
"preprocess"
274+
~synonyms:["pp"]
275+
276+
let () = Config.when_ready @@ fun {get} ->
277+
C.Parser.provide (parser (get cpp))

0 commit comments

Comments
 (0)