From 909f573d797eee83641263fbfe9c42417185ec26 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 10 Jun 2008 21:50:48 +0000 Subject: [PATCH] Started to copy the import tool from libunbin. --- Makefile.in | 12 +++ README | 6 +- cil-tools/.depend | 2 + cil-tools/Makefile.in | 82 ++++++++++++++++++++ cil-tools/bitmatch-import-prefix.h | 9 +++ cil-tools/bitmatch_import_c.ml | 150 +++++++++++++++++++++++++++++++++++++ cil-tools/ext3.c | 24 ++++++ configure.ac | 8 +- 8 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 cil-tools/.depend create mode 100644 cil-tools/Makefile.in create mode 100644 cil-tools/bitmatch-import-prefix.h create mode 100644 cil-tools/bitmatch_import_c.ml create mode 100644 cil-tools/ext3.c diff --git a/Makefile.in b/Makefile.in index ff5945b..b535b7a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -32,11 +32,17 @@ OCAMLOPTPACKAGES = OCAMLDOCFLAGS = -html -sort +SUBDIRS = +ifneq ($(pkg_cil),no) +SUBDIRS += cil-tools +endif + EXAMPLES = $(patsubst %.ml,%,$(wildcard examples/*.ml)) TESTS = $(patsubst %.ml,%,$(wildcard tests/*.ml)) all: bitmatch.cma bitmatch.cmxa pa_bitmatch.cmo + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done bitmatch.cma: bitmatch_types.cmo bitmatch_config.cmo bitmatch.cmo $(OCAMLFIND) ocamlc -a -o $@ $^ @@ -62,6 +68,7 @@ test: pa_bitmatch.cmo bitmatch.cma $$f; \ if [ $$? -ne 0 ]; then exit 1; fi; \ done + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done examples: pa_bitmatch.cmo bitmatch.cma @for f in $(EXAMPLES); do \ @@ -70,6 +77,7 @@ examples: pa_bitmatch.cmo bitmatch.cma -package unix -linkpkg -I . bitmatch.cma $$f.ml -o $$f; \ if [ $$? -ne 0 ]; then exit 1; fi; \ done + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done print-tests: pa_bitmatch.cmo @for f in $(TESTS); do \ @@ -92,11 +100,13 @@ clean: rm -f core *~ *.cmi *.cmo *.cmx *.cma *.cmxa *.a *.o rm -f tests/*~ tests/*.cmi tests/*.cmo $(TESTS) rm -f examples/*~ examples/*.cmi examples/*.cmo $(EXAMPLES) + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done distclean: clean rm -rf autom4te.cache rm -f config.log config.status rm -f config.h Makefile META bitmatch_config.ml + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done # Documentation. @@ -113,6 +123,7 @@ install: ocamlfind install bitmatch META *.mli *.cmx *.cma *.cmxa *.a \ bitmatch.cmi \ pa_bitmatch.cmo + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done # Standard rules. @@ -124,6 +135,7 @@ install: $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) $(OCAMLOPTPACKAGES) -c $< depend: .depend + @for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done .depend: bitmatch.ml bitmatch.mli rm -f .depend diff --git a/README b/README index e6da02d..d0c8b13 100644 --- a/README +++ b/README @@ -3,7 +3,11 @@ License: LGPLv2+ with OCaml linking exception. Please see the html subdirectory for developer documentation. -The only dependencies are OCaml >= 3.10.0, camlp4, ocamldoc, and findlib. +The only requirements are OCaml >= 3.10.0, camlp4, ocamldoc, and findlib. + +If you optionally have CIL (http://cil.sourceforge.net/) installed +then there are some nice extra tools for converting C header files +into matchable OCaml structures. To build: diff --git a/cil-tools/.depend b/cil-tools/.depend new file mode 100644 index 0000000..20be473 --- /dev/null +++ b/cil-tools/.depend @@ -0,0 +1,2 @@ +bitmatch_import_c.cmo: ../bitmatch.cmi +bitmatch_import_c.cmx: ../bitmatch.cmx diff --git a/cil-tools/Makefile.in b/cil-tools/Makefile.in new file mode 100644 index 0000000..c66dd21 --- /dev/null +++ b/cil-tools/Makefile.in @@ -0,0 +1,82 @@ +# Bitmatch syntax extension. +# Copyright (C) 2008 Red Hat Inc., Richard W.M. Jones +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# $Id: Makefile.in 81 2008-05-21 09:59:21Z richard.wm.jones $ + +PACKAGE = @PACKAGE_NAME@ +VERSION = @PACKAGE_VERSION@ + +OCAMLFIND = @OCAMLFIND@ +OCAMLMKLIB = @OCAMLMKLIB@ +OCAMLDOC = @OCAMLDOC@ +INSTALL = @INSTALL@ + +OCAMLCFLAGS = -g +OCAMLCPACKAGES = -package unix,str,extlib,cil -I .. +OCAMLCLIBS = $(OCAMLCPACKAGES) -linkpkg ../bitmatch.cma +OCAMLOPTFLAGS = +OCAMLOPTPACKAGES = $(OCAMLCPACKAGES) +OCAMLOPTLIBS = $(OCAMLOPTPACKAGES) -linkpkg ../bitmatch.cmxa + +OCAMLDOCFLAGS = -html -sort + +all: bitmatch-import-c bitmatch-import-c.opt + +bitmatch-import-c: bitmatch_import_c.cmo + $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) $(OCAMLCLIBS) $< -o $@ + +bitmatch-import-c.opt: bitmatch_import_c.cmx + $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) $(OCAMLOPTLIBS) $< -o $@ + +test: + +examples: + +# Clean. + +clean: + rm -f core *~ *.cmi *.cmo *.cmx *.cma *.cmxa *.a *.o + +distclean: clean + +# Install. + +install: + +# Standard rules. + +.mli.cmi: + $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) $(OCAMLCPACKAGES) -c $< +.ml.cmo: + $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) $(OCAMLCPACKAGES) -c $< +.ml.cmx: + $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) $(OCAMLOPTPACKAGES) -c $< + +depend: .depend + +.depend: $(wildcard *.ml) $(wildcard *.mli) + rm -f .depend + $(OCAMLFIND) ocamldep $(OCAMLCPACKAGES) $^ > $@ + +ifeq ($(wildcard .depend),.depend) +include .depend +endif + +.PHONY: depend dist check-manifest dpkg doc \ + print-examples print-tests examples test + +.SUFFIXES: .cmo .cmi .cmx .ml .mli .mll diff --git a/cil-tools/bitmatch-import-prefix.h b/cil-tools/bitmatch-import-prefix.h new file mode 100644 index 0000000..d7f769a --- /dev/null +++ b/cil-tools/bitmatch-import-prefix.h @@ -0,0 +1,9 @@ +/* This file is automagically prefixed to all .ubd files + * and provides some macros that we need for CIL. + */ + +#define BITMATCH_IMPORT(name) __bitmatch_import_##name +#define BITMATCH_CONSTANT_STRING(name,val) \ + char *__bitmatch_constant_##name = val +#define BITMATCH_CONSTANT_INT32(name,val) \ + int __bitmatch_constant_##name = val diff --git a/cil-tools/bitmatch_import_c.ml b/cil-tools/bitmatch_import_c.ml new file mode 100644 index 0000000..7587fc4 --- /dev/null +++ b/cil-tools/bitmatch_import_c.ml @@ -0,0 +1,150 @@ +(* Import a C header file. + * Copyright (C) 2008 Red Hat Inc., Richard W.M. Jones + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id$ + *) + +open Printf +open ExtList +open ExtString +open Cil + +let () = + (* Parse command line arguments. *) + let debug = ref false in + let save_temps = ref false in + let version () = + printf "bitmatch-import-c %s" Bitmatch.version; + exit 1 + in + + let argspec = Arg.align [ + "--debug", Arg.Set debug, + " Debug messages"; + "-save-temps", Arg.Set save_temps, + " Save temporary files"; + "--version", Arg.Unit version, + " Display version and exit"; + ] in + + let input_file = ref None in + let anon_fun str = + match !input_file with + | None -> input_file := Some str + | Some _ -> + eprintf "bitmatch-import-c: only give a single input file\n"; + exit 1 + in + let usage_msg = "\ + +bitmatch-import-c: Import C structures and constants and + generate bitmatching functions from them. Please see the + manual page bitmatch-import-c(1) for more information. + +OPTIONS" in + + Arg.parse argspec anon_fun usage_msg; + + let debug = !debug in + let save_temps = !save_temps in + let input_file = + match !input_file with + | Some f -> f + | None -> + eprintf "bitmatch-import-c: no input file specified\n"; + exit 1 in + + (* Grab the file and pass it to the preprocessor, and then read the + * C code into memory using CIL. + *) + msvcMode := false; + Cil.initCIL (); + + (* XXX Unavoidable tmp exploit here. Fix? *) + let tmp, delete_tmp = + if not save_temps then ( + let tmp = Filename.temp_file (Filename.temp_dir_name) ".i" in + tmp, fun () -> try Unix.unlink tmp with Unix.Unix_error _ -> () + ) else ( + let tmp = Filename.chop_extension input_file ^ ".i" in + tmp, fun () -> (* -save-temps, so do nothing *) () + ) in + + let cmd = + sprintf "cpp -include bitmatch-import-prefix.h %s > %s" + (Filename.quote input_file) (Filename.quote tmp) in + if debug then prerr_endline cmd; + if Sys.command cmd <> 0 then ( + eprintf "%s: command failed\n" cmd; + delete_tmp (); + exit 1 + ); + + (* Why does Frontc.parse return a continuation ...? *) + let file = (Frontc.parse tmp) () in + delete_tmp (); + + (* Find out which structures, #defines, etc. are to be imported. + * (cf. the macros in bitmatch-import-prefix.h) + *) + let constants = + List.filter_map ( + function + | GVar ({vname = vname; vtype = vtype}, + { init = Some (SingleInit vinit) }, + loc) + when String.starts_with vname "__bitmatch_constant_" -> + let vname = String.sub vname 20 (String.length vname - 20) in + + (* Do constant folding on the initializer and then calculate + * its compile-time value. + *) + let vinit = + match isInteger (constFold true vinit) with + | Some i -> i + | None -> + Errormsg.error + "%a: non-constant initializer: %a" d_loc loc d_exp vinit; + -1L in + + Some (vname, vinit, loc) + | _ -> None + ) file.globals in + let structs = + List.filter_map ( + function + | GType ({tname = tname; ttype = ttype}, loc) + when String.starts_with tname "__bitmatch_import_" -> + let tname = String.sub tname 18 (String.length tname - 18) in + Some (tname, ttype, loc) + | _ -> None + ) file.globals in + + if !Errormsg.hadErrors then exit 1; + + (* If debugging, print out the imports. *) + if debug then ( + List.iter ( + fun (vname, vinit, loc) -> + Errormsg.log "%a: import %s as constant 0x%LX\n" d_loc loc vname vinit; + ) constants; + List.iter ( + fun (tname, ttype, loc) -> + Errormsg.log "%a: import %s as %a\n" d_loc loc tname d_type ttype; + ) structs; + ); + diff --git a/cil-tools/ext3.c b/cil-tools/ext3.c new file mode 100644 index 0000000..ba35518 --- /dev/null +++ b/cil-tools/ext3.c @@ -0,0 +1,24 @@ +/* This is an example import file, showing how to import the ext3 + * superblock automatically from Linux header files. + * + * Use: bitmatch-import-c ext3.c + * + * Tip: Add the --debug flag to that command line to see what's going on. + */ + +/* These are required by Linux in order to get the little/big-endian + * notations present in the Linux kernel header files. Any other + * defines needed can go here. + */ +#define __CHECKER__ 1 +#define __CHECK_ENDIAN__ 1 + +/* Include files necessary to get the structure(s) and constant(s) we're + * interested in. + */ +#include +#include + +/* This tells the importer program what structures and constants to import. */ +typedef struct ext3_super_block BITMATCH_IMPORT(ext3_super_block); +BITMATCH_CONSTANT_INT32 (ext3_super_magic, EXT3_SUPER_MAGIC); diff --git a/configure.ac b/configure.ac index ab88542..a964a9e 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ test "x$U" != "x" && AC_MSG_ERROR(Compiler not ANSI compliant) AC_PROG_CC_C_O -dnl Check for endianness. +dnl Check for native endianness. AC_C_BIGENDIAN( [NATIVEENDIAN=BigEndian], [NATIVEENDIAN=LittleEndian], @@ -51,7 +51,11 @@ if test "x$CAMLP4OF" = "xno"; then AC_MSG_ERROR([You must have camlp4 installed]) fi +dnl Check for CIL (optional) +AC_CHECK_OCAML_PKG(cil) +AC_SUBST(pkg_cil) + dnl Produce output files. AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([Makefile META bitmatch_config.ml]) +AC_CONFIG_FILES([Makefile META bitmatch_config.ml cil-tools/Makefile]) AC_OUTPUT -- 1.8.3.1