From 45845eeeff9ccbd4cbda63d6deaa9a29ab1abb05 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 1 Jan 1970 00:00:00 +0000 Subject: [PATCH] Script to generate the parsing code from kernel database. --- HACKING | 5 ++ configure.ac | 1 + extract/README | 6 ++ extract/codegen/Makefile.in | 46 ++++++++++++ extract/codegen/kerneldb_to_parser.ml | 129 ++++++++++++++++++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 extract/codegen/Makefile.in create mode 100644 extract/codegen/kerneldb_to_parser.ml diff --git a/HACKING b/HACKING index 26e5ffe..a9b1b71 100644 --- a/HACKING +++ b/HACKING @@ -34,6 +34,11 @@ extract/ subdirectories here correspond to the different Linux distributions and methods of getting at their kernels. +extract/codegen/ + + - Tools to turn the kernel database into generated code which parses + the kernel structures. + General structure of lib/virt_mem.ml ------------------------------------ diff --git a/configure.ac b/configure.ac index 336a672..c045865 100644 --- a/configure.ac +++ b/configure.ac @@ -157,5 +157,6 @@ AC_CONFIG_FILES([Makefile mem/Makefile po/Makefile extract/fedora-koji/Makefile + extract/codegen/Makefile ]) AC_OUTPUT diff --git a/extract/README b/extract/README index f19fc7c..06d6636 100644 --- a/extract/README +++ b/extract/README @@ -5,3 +5,9 @@ and extracting the information we need from them. fedora-koji/ - For recent Fedora kernels built at http://koji.fedoraproject.org/ + + +codegen/ + + - This contains tools which turn the kernels database (in ../kernels/) + into parsing code. diff --git a/extract/codegen/Makefile.in b/extract/codegen/Makefile.in new file mode 100644 index 0000000..4643f13 --- /dev/null +++ b/extract/codegen/Makefile.in @@ -0,0 +1,46 @@ +# virt-mem +# @configure_input@ +# 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 + +PACKAGE = @PACKAGE_NAME@ +VERSION = @PACKAGE_VERSION@ + +INSTALL = @INSTALL@ +MKDIR_P = @MKDIR_P@ +bindir = @bindir@ + +OCAMLCPACKAGES = -package extlib,pcre + +OCAMLCFLAGS = @OCAMLCFLAGS@ +OCAMLCLIBS = -linkpkg + +OCAMLOPTFLAGS = @OCAMLOPTFLAGS@ +OCAMLOPTPACKAGES = $(OCAMLCPACKAGES) +OCAMLOPTLIBS = -linkpkg + +TARGETS = kerneldb-to-parser.opt + +OBJS = kerneldb_to_parser.cmo +XOBJS = $(OBJS:.cmo=.cmx) + +all: $(TARGETS) + +kerneldb-to-parser.opt: $(XOBJS) + ocamlfind ocamlopt \ + $(OCAMLOPTFLAGS) $(OCAMLOPTPACKAGES) $(OCAMLOPTLIBS) $(XOBJS) -o $@ + +include ../../Make.rules \ No newline at end of file diff --git a/extract/codegen/kerneldb_to_parser.ml b/extract/codegen/kerneldb_to_parser.ml new file mode 100644 index 0000000..6b64786 --- /dev/null +++ b/extract/codegen/kerneldb_to_parser.ml @@ -0,0 +1,129 @@ +(* Memory info for virtual domains. + (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc. + http://libvirt.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*) + +(* This program takes the kernel database (in kernels/ in toplevel + directory) and generates parsing code for the various structures + in the kernel that we are interested in. + + The output programs -- *.ml, *.mli files of generated code -- go + into lib/ at the toplevel, eg. lib/kernel_task_struct.ml + + The stuff at the top of this file determine what structures + and fields we try to parse. +*) + +let what = [ + "task_struct", ( + "struct task_struct", + [ "state"; "prio"; "normal_prio"; "static_prio"; "tasks"; "comm"] + ); +] + +open ExtList +open ExtString +open Printf + +let (//) = Filename.concat + +let () = + let args = Array.to_list Sys.argv in + + let kernelsdir, outputdir = + match args with + | [_;kd;od] -> kd,od + | _ -> + let arg0 = Filename.basename Sys.executable_name in + eprintf "%s - Turn kernels database into code modules. + +Usage: + %s + +Example (from toplevel of virt-mem source tree): + %s kernels/ lib/ +" arg0 arg0 arg0; + exit 2 in + + (* Get the *.info files from the kernels database. *) + let infos = Sys.readdir kernelsdir in + let infos = Array.to_list infos in + let infos = List.filter (fun name -> String.ends_with name ".info") infos in + let infos = List.map ((//) kernelsdir) infos in + + (* Regular expressions. We really really should use ocaml-mikmatch ... *) + let re_oldformat = Pcre.regexp "^RPM: \\d+: \\(build \\d+\\) ([-\\w]+) ([\\w.]+) ([\\w.]+) \\(.*?\\) (\\w+)" in + let re_keyvalue = Pcre.regexp "^(\\w+): (.*)" in + + (* Parse in the *.info files. These have historically had a few different + * formats that we need to support. + *) + let infos = List.map ( + fun filename -> + (* Get the basename (for getting the .data file later on). *) + let basename = Filename.chop_suffix filename ".info" in + + let chan = open_in filename in + let line = input_line chan in + + let name, version = + if Pcre.pmatch ~rex:re_oldformat line then ( + (* If the file starts with "RPM: \d+: ..." then it's the original + * format. Everything in one line. + *) + let subs = Pcre.exec ~rex:re_oldformat line in + let name = Pcre.get_substring subs 1 in + let version = Pcre.get_substring subs 2 in + let release = Pcre.get_substring subs 3 in + let arch = Pcre.get_substring subs 4 in + close_in chan; + name, sprintf "%s-%s.%s" version release arch + ) else ( + (* New-style "key: value" entries, up to end of file or the first + * blank line. + *) + let name, version, release, arch = + ref "", ref "", ref "", ref "" in + let rec loop line = + try + let subs = Pcre.exec ~rex:re_keyvalue line in + let key = Pcre.get_substring subs 1 in + let value = Pcre.get_substring subs 2 in + if key = "Name" then name := value + else if key = "Version" then version := value + else if key = "Release" then release := value + else if key = "Architecture" then arch := value; + let line = input_line chan in + loop line + with + Not_found | End_of_file -> + close_in chan + in + loop line; + let name, version, release, arch = + !name, !version, !release, !arch in + if name = "" || version = "" || release = "" || arch = "" then + failwith (sprintf "%s: missing Name, Version, Release or Architecture key" filename); + name, sprintf "%s-%s.%s" version release arch + ) in + + printf "%s -> %s, %s\n" basename name version; + + (basename, name, version) + ) infos in + + () -- 1.8.3.1