From 643e58b5e26c18f2cfc1c7b9aa676cb44feee847 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 1 Jan 1970 00:00:00 +0000
Subject: [PATCH] Bring kernel version checking (utsname) into the central
 process.

---
 Makefile.in              |  1 +
 dmesg/.depend            |  8 ++---
 dmesg/virt_dmesg.ml      | 88 ++++++++++++++++++++++-----------------------
 lib/.depend              | 17 +++++----
 lib/Makefile.in          |  1 +
 lib/virt_mem.ml          | 36 ++++++++++++-------
 lib/virt_mem.mli         |  7 ++--
 lib/virt_mem_types.ml    | 18 ++++++++++
 lib/virt_mem_utsname.ml  | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/virt_mem_utsname.mli | 22 ++++++++++++
 ps/virt_ps.ml            |  7 ++--
 uname/.depend            |  4 +--
 uname/virt_uname.ml      | 77 ++++++---------------------------------
 13 files changed, 237 insertions(+), 142 deletions(-)
 create mode 100644 lib/virt_mem_utsname.ml
 create mode 100644 lib/virt_mem_utsname.mli

diff --git a/Makefile.in b/Makefile.in
index 62e2fed..02cb91c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -31,6 +31,7 @@ OCAMLDOCFILES	= lib/virt_mem_utils.ml \
 		  lib/virt_mem_types.ml \
 		  lib/virt_mem_ksyms.mli \
 		  lib/virt_mem_kallsyms.mli \
+		  lib/virt_mem_utsname.mli \
 		  lib/virt_mem.mli
 
 HAVE_PERLDOC    = @HAVE_PERLDOC@
diff --git a/dmesg/.depend b/dmesg/.depend
index 6c94cb9..89da6ef 100644
--- a/dmesg/.depend
+++ b/dmesg/.depend
@@ -1,4 +1,4 @@
-virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_mmap.cmi \
-    ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
-virt_dmesg.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_mmap.cmx \
-    ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
+virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
+    ../lib/virt_mem_mmap.cmi ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
+virt_dmesg.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
+    ../lib/virt_mem_mmap.cmx ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
diff --git a/dmesg/virt_dmesg.ml b/dmesg/virt_dmesg.ml
index dd41d26..1886a92 100644
--- a/dmesg/virt_dmesg.ml
+++ b/dmesg/virt_dmesg.ml
@@ -21,58 +21,56 @@ open Printf
 
 open Virt_mem_gettext.Gettext
 open Virt_mem_utils
+open Virt_mem_types
 open Virt_mem_mmap
 
-let run debug images =
-  List.iter (
-    fun (_, name, arch, mem, lookup_ksym) ->
-      try
-	(* I don't know why but this symbol doesn't exist in 2.6.9
-	 * even in kallsyms.  Hence this won't work with that kernel.
-	 * It's possible we can fall back to memory scanning. XXX
-	 *)
-	let log_buf = lookup_ksym "log_buf" in
-	let log_buf = follow_pointer mem log_buf in
-	let log_buf_len = lookup_ksym "log_buf_len" in
-	let log_buf_len = Int64.of_int32 (get_C_int mem log_buf_len) in
-(*	let log_start = lookup_ksym "log_start" in
+let run debug (_, name, arch, mem, lookup_ksym, _) =
+  try
+    (* I don't know why but this symbol doesn't exist in 2.6.9
+     * even in kallsyms.  Hence this won't work with that kernel.
+     * It's possible we can fall back to memory scanning. XXX
+     *)
+    let log_buf = lookup_ksym "log_buf" in
+    let log_buf = follow_pointer mem log_buf in
+    let log_buf_len = lookup_ksym "log_buf_len" in
+    let log_buf_len = Int64.of_int32 (get_C_int mem log_buf_len) in
+    (*	let log_start = lookup_ksym "log_start" in
 	let log_start = get_C_long mem log_start in *)
-	let log_end = lookup_ksym "log_end" in
-	let log_end = get_C_long mem log_end in
-(*	let con_start = lookup_ksym "con_start" in
+    let log_end = lookup_ksym "log_end" in
+    let log_end = get_C_long mem log_end in
+    (*	let con_start = lookup_ksym "con_start" in
 	let con_start = get_C_long mem con_start in *)
-	let logged_chars = lookup_ksym "logged_chars" in
-	let logged_chars = get_C_long mem logged_chars in
+    let logged_chars = lookup_ksym "logged_chars" in
+    let logged_chars = get_C_long mem logged_chars in
 
-	(* This is basically the same algorithm from printk.c:do_syslog
-	 * type=3, translated into OCaml.  Unlike the kernel version
-	 * however we don't copy the buffer backwards.
-	 *)
-	let get_log_buf idx =
-	  let addr = log_buf +^ (idx &^ (log_buf_len -^ 1L)) in
-	  Char.chr (get_byte mem addr)
-	in
+    (* This is basically the same algorithm from printk.c:do_syslog
+     * type=3, translated into OCaml.  Unlike the kernel version
+     * however we don't copy the buffer backwards.
+     *)
+    let get_log_buf idx =
+      let addr = log_buf +^ (idx &^ (log_buf_len -^ 1L)) in
+      Char.chr (get_byte mem addr)
+    in
 
-	let count = log_buf_len in
-	let count = if count > logged_chars then logged_chars else count in
-	let limit = log_end in
+    let count = log_buf_len in
+    let count = if count > logged_chars then logged_chars else count in
+    let limit = log_end in
 
-	let rec loop i =
-	  if i >= 0L then (
-	    let j = limit-^1L-^i in
-	    if j +^ log_buf_len >= log_end then (
-	      let c = get_log_buf j in
-	      printf "%c" c;
-	      loop (i-^1L)
-	    )
-	  )
-	in
-	loop (count-^1L)
-      with
-	Not_found ->
-	  eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
-	    name
-  ) images
+    let rec loop i =
+      if i >= 0L then (
+	let j = limit-^1L-^i in
+	if j +^ log_buf_len >= log_end then (
+	  let c = get_log_buf j in
+	  printf "%c" c;
+	  loop (i-^1L)
+	)
+      )
+    in
+    loop (count-^1L)
+  with
+    Not_found ->
+      eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
+	name
 
 let summary = s_"display kernel messages"
 let description = s_"\
diff --git a/lib/.depend b/lib/.depend
index 6eb3e7f..bb77a91 100644
--- a/lib/.depend
+++ b/lib/.depend
@@ -2,6 +2,7 @@ virt_mem_kallsyms.cmi: virt_mem_types.cmo
 virt_mem_ksyms.cmi: virt_mem_types.cmo 
 virt_mem.cmi: virt_mem_types.cmo 
 virt_mem_mmap.cmi: virt_mem_utils.cmo 
+virt_mem_utsname.cmi: virt_mem_types.cmo 
 test_mmap.cmo: virt_mem_mmap.cmi 
 test_mmap.cmx: virt_mem_mmap.cmx 
 virt_mem_capture.cmo: virt_mem_gettext.cmo virt_mem.cmi 
@@ -16,13 +17,17 @@ virt_mem_ksyms.cmo: virt_mem_utils.cmo virt_mem_types.cmo virt_mem_mmap.cmi \
     virt_mem_gettext.cmo virt_mem_ksyms.cmi 
 virt_mem_ksyms.cmx: virt_mem_utils.cmx virt_mem_types.cmx virt_mem_mmap.cmx \
     virt_mem_gettext.cmx virt_mem_ksyms.cmi 
-virt_mem.cmo: virt_mem_version.cmo virt_mem_utils.cmo virt_mem_types.cmo \
-    virt_mem_mmap.cmi virt_mem_ksyms.cmi virt_mem_kallsyms.cmi \
-    virt_mem_gettext.cmo virt_mem.cmi 
-virt_mem.cmx: virt_mem_version.cmx virt_mem_utils.cmx virt_mem_types.cmx \
-    virt_mem_mmap.cmx virt_mem_ksyms.cmx virt_mem_kallsyms.cmx \
-    virt_mem_gettext.cmx virt_mem.cmi 
+virt_mem.cmo: virt_mem_version.cmo virt_mem_utsname.cmi virt_mem_utils.cmo \
+    virt_mem_types.cmo virt_mem_mmap.cmi virt_mem_ksyms.cmi \
+    virt_mem_kallsyms.cmi virt_mem_gettext.cmo virt_mem.cmi 
+virt_mem.cmx: virt_mem_version.cmx virt_mem_utsname.cmx virt_mem_utils.cmx \
+    virt_mem_types.cmx virt_mem_mmap.cmx virt_mem_ksyms.cmx \
+    virt_mem_kallsyms.cmx virt_mem_gettext.cmx virt_mem.cmi 
 virt_mem_mmap.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_mmap.cmx: virt_mem_utils.cmx virt_mem_mmap.cmi 
 virt_mem_types.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_types.cmx: virt_mem_utils.cmx virt_mem_mmap.cmx 
+virt_mem_utsname.cmo: virt_mem_utils.cmo virt_mem_types.cmo virt_mem_mmap.cmi \
+    virt_mem_gettext.cmo virt_mem_utsname.cmi 
+virt_mem_utsname.cmx: virt_mem_utils.cmx virt_mem_types.cmx virt_mem_mmap.cmx \
+    virt_mem_gettext.cmx virt_mem_utsname.cmi 
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 2edc175..9b41e68 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -53,6 +53,7 @@ OBJS		= virt_mem_gettext.cmo \
 		  virt_mem_types.cmo \
 		  virt_mem_ksyms.cmo \
 		  virt_mem_kallsyms.cmo \
+		  virt_mem_utsname.cmo \
 		  virt_mem.cmo \
 		  virt_mem_capture.cmo
 XOBJS		= $(OBJS:%.cmo=%.cmx)
diff --git a/lib/virt_mem.ml b/lib/virt_mem.ml
index 0a956f1..03b0d1e 100644
--- a/lib/virt_mem.ml
+++ b/lib/virt_mem.ml
@@ -44,11 +44,11 @@ let tools = ref []
 
 (* Registration function used by the tools. *)
 let register ?(external_cmd = true) ?(extra_args = [])
-    ?argcheck ?beforeksyms ?run
+    ?argcheck ?beforeksyms ?beforeutsname ?run
     name summary description =
   tools :=
     (name, (name, summary, description, external_cmd, extra_args,
-	    argcheck, beforeksyms, run))
+	    argcheck, beforeksyms, beforeutsname, run))
   :: !tools
 
 (* Main program, called from mem/virt_mem_main.ml when all the
@@ -106,7 +106,7 @@ let main () =
     match tool with
     | None ->				(* Generic usage message. *)
 	let tools = List.map (
-	  fun (name, (_, summary, _, external_cmd, _, _, _, _)) ->
+	  fun (name, (_, summary, _, external_cmd, _, _, _, _, _)) ->
 	    if external_cmd then "virt-"^name, summary
 	    else                 "virt-mem "^name, summary
 	) tools in
@@ -133,7 +133,7 @@ To display extra help for a single tool, do:
 Options:") tools
 
                                         (* Tool-specific usage message. *)
-    | Some (name, summary, description, external_cmd, _, _, _, _) ->
+    | Some (name, summary, description, external_cmd, _, _, _, _, _) ->
 	let cmd =
 	  if external_cmd then "virt-" ^ name else "virt-mem " ^ name in
 
@@ -219,7 +219,7 @@ Options:") cmd summary description in
   let argspec =
     let extra_args = match tool with
       | None -> []
-      | Some (_, _, _, _, extra_args, _, _, _) -> extra_args in
+      | Some (_, _, _, _, extra_args, _, _, _, _) -> extra_args in
     let argspec = [
       "-A", Arg.String set_architecture,
         "arch " ^ s_"Set kernel architecture, endianness and word size";
@@ -270,7 +270,7 @@ Options:") cmd summary description in
    * or the user didn't give us a valid tool (eg. "virt-mem foobar").
    * Detect that final case now and give an error.
    *)
-  let name, _, _, _, _, argcheck, beforeksyms, run =
+  let name, _, _, _, _, argcheck, beforeksyms,  beforeutsname, run =
     match tool with
     | Some t -> t
     | None ->
@@ -469,16 +469,15 @@ Use 'virt-mem --help' for more help or read the manual page virt-mem(1)");
    | Some beforeksyms -> beforeksyms debug images
   );
 
-  (* If there is no run function, then there is no point continuing
-   * with the rest of the program (kernel symbol analysis) ...
+  (* If there are no more callback functions, then there is no point
+   * continuing with the rest of the program (kernel symbol analysis) ...
    *)
-  if run = None then exit 0;
+  if beforeutsname = None && run = None then exit 0;
 
   (* Do the kernel symbol analysis. *)
   let images =
     List.map (
       fun image ->
-
 	(* Look for ordinary kernel symbols: *)
 	let image = Virt_mem_ksyms.find_kernel_symbols debug image in
 	(* Look for kallsyms: *)
@@ -506,9 +505,22 @@ Use 'virt-mem --help' for more help or read the manual page virt-mem(1)");
 	image
     ) images in
 
+  (* Before utsname analysis. *)
+  (match beforeutsname with
+   | None -> ()
+   | Some beforeutsname -> List.iter (beforeutsname debug) images
+  );
+
+  (* If there are no more callback functions, then there is no point
+   * continuing with the rest of the program (kernel version analysis) ...
+   *)
+  if run = None then exit 0;
+
+  (* Get the kernel version (utsname analysis). *)
+  let images = List.map (Virt_mem_utsname.find_utsname debug) images in
+
   (* Run the tool's main function. *)
   (match run with
    | None -> ()
-   | Some run ->
-       run debug images
+   | Some run -> List.iter (run debug) images
   )
diff --git a/lib/virt_mem.mli b/lib/virt_mem.mli
index eae488e..c807365 100644
--- a/lib/virt_mem.mli
+++ b/lib/virt_mem.mli
@@ -23,7 +23,8 @@ val register :
   ?extra_args:(Arg.key * Arg.spec * Arg.doc) list ->
   ?argcheck:(bool -> unit) ->
   ?beforeksyms:(bool -> Virt_mem_types.image0 list -> unit) ->
-  ?run:(bool -> Virt_mem_types.image1 list -> unit) ->
+  ?beforeutsname:(bool -> Virt_mem_types.image1 -> unit) ->
+  ?run:(bool -> Virt_mem_types.image2 -> unit) ->
   string -> string -> Arg.usage_msg ->
   unit
   (** Tools register themselves with this call.
@@ -39,7 +40,9 @@ val register :
       on [extra_args]),
       - [?beforeksyms] called after images are loaded and before
       kernel symbols are analyzed,
-      - [?run] called after kernel symbols have been analyzed
+      - [?beforeutsname] called after kernel symbols are analyzed
+      and before the kernel version is detected
+      - [?run] called after everything
       (almost all tools supply this callback function).
 
       Pass [~external_cmd:false] if this tool doesn't have an
diff --git a/lib/virt_mem_types.ml b/lib/virt_mem_types.ml
index 2f8b329..34f3fe7 100644
--- a/lib/virt_mem_types.ml
+++ b/lib/virt_mem_types.ml
@@ -37,3 +37,21 @@ type image1 =
     * Virt_mem_utils.architecture	(* Architecture, eg. i386. *)
     * ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t (* Memory map. *)
     * (ksym -> Virt_mem_mmap.addr)	(* Kernel symbol lookup function. *)
+
+(** A kernel image, after finding kernel version (like 'uname'). *)
+type image2 =
+    int option				(* Domain ID, if known. *)
+    * string				(* Domain name. *)
+    * Virt_mem_utils.architecture	(* Architecture, eg. i386. *)
+    * ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t (* Memory map. *)
+    * (ksym -> Virt_mem_mmap.addr)	(* Kernel symbol lookup function. *)
+    * utsname option			(* Kernel version, etc., if known. *)
+
+and utsname = {
+  kernel_name : string;
+  nodename : string;
+  kernel_release : string;
+  kernel_version : string;
+  machine : string;
+  domainname : string;
+}
diff --git a/lib/virt_mem_utsname.ml b/lib/virt_mem_utsname.ml
new file mode 100644
index 0000000..61a2b37
--- /dev/null
+++ b/lib/virt_mem_utsname.ml
@@ -0,0 +1,93 @@
+(* Memory info command 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.
+ *)
+
+open Printf
+
+open Virt_mem_gettext.Gettext
+open Virt_mem_utils
+open Virt_mem_types
+open Virt_mem_mmap
+
+(* Truncate an OCaml string at the first ASCII NUL character, ie. as
+ * if it were a C string.
+ *)
+let truncate str =
+  try
+    let i = String.index str '\000' in
+    String.sub str 0 i
+  with
+    Not_found -> str
+
+let parse_utsname bits =
+  (* Expect the first (sysname) field to always be "Linux", which is
+   * also a good way to tell if we're synchronized to the right bit of
+   * memory.
+   *)
+  bitmatch bits with
+  | { "Linux\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" : 65*8 : string;
+      nodename : 65*8 : string;
+      release : 65*8 : string;
+      version : 65*8 : string;
+      machine : 65*8 : string;
+      domainname : 65*8 : string } ->
+      Some {
+	kernel_name = "Linux";
+	nodename = truncate nodename;
+	kernel_release = truncate release;
+	kernel_version = truncate version;
+	machine = truncate machine;
+	domainname = truncate domainname
+      }
+  | { _ } ->
+      None
+
+let find_utsname debug (domid, name, arch, mem, lookup_ksym) =
+  let utsname =
+    (* In Linux 2.6.25, the symbol is init_uts_ns.
+     * http://lxr.linux.no/linux/init/version.c
+     *)
+    try
+      let addr = lookup_ksym "init_uts_ns" in
+
+      let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
+      (bitmatch bs with
+       | { _ : 32 : int;	      (* the kref, atomic_t, always 32 bits *)
+	   new_utsname : -1 : bitstring } ->
+	   parse_utsname new_utsname
+       | { _ } ->
+	   if debug then
+	     eprintf (f_"%s: unexpected init_uts_ns in kernel image\n") name;
+	   None
+      )
+    with
+      Not_found ->
+	(* In Linux 2.6.9, the symbol is system_utsname.
+	 * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
+	 *)
+	try
+	  let addr = lookup_ksym "system_utsname" in
+
+	  let bits =
+	    Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
+	  parse_utsname bits
+	    with
+	      Not_found ->
+		eprintf (f_"%s: could not find utsname in kernel image\n") name
+  in
+  (domid, name, arch, mem, lookup_ksym, utsname)
diff --git a/lib/virt_mem_utsname.mli b/lib/virt_mem_utsname.mli
new file mode 100644
index 0000000..7b62d42
--- /dev/null
+++ b/lib/virt_mem_utsname.mli
@@ -0,0 +1,22 @@
+(** Get system utsname (like 'uname') from kernel. *)
+(* Memory info command 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.
+ *)
+
+val find_utsname : bool -> Virt_mem_types.image1 -> Virt_mem_types.image2
+(** Find the system utsname structure. *)
diff --git a/ps/virt_ps.ml b/ps/virt_ps.ml
index d18ff48..df876ba 100644
--- a/ps/virt_ps.ml
+++ b/ps/virt_ps.ml
@@ -222,11 +222,8 @@ let search debug mem lookup_ksym =
   let ts = loop 0 0 in
   ()
 
-let run debug images =
-  List.iter (
-    fun (domid, domname, arch, mem, lookup_ksym) ->
-      search debug mem lookup_ksym
-  ) images
+let run debug (_, _, _, mem, lookup_ksym, _) =
+  search debug mem lookup_ksym
 
 let summary = s_"list processes in virtual machine"
 let description = s_"\
diff --git a/uname/.depend b/uname/.depend
index 8738997..dbdac15 100644
--- a/uname/.depend
+++ b/uname/.depend
@@ -1,4 +1,4 @@
-virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_mmap.cmi \
+virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
     ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
-virt_uname.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_mmap.cmx \
+virt_uname.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
     ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
diff --git a/uname/virt_uname.ml b/uname/virt_uname.ml
index 6004bb8..981f0ee 100644
--- a/uname/virt_uname.ml
+++ b/uname/virt_uname.ml
@@ -21,72 +21,17 @@ open Printf
 
 open Virt_mem_gettext.Gettext
 open Virt_mem_utils
-open Virt_mem_mmap
-
-let run debug images =
-  (* Print new_utsname structure from bitstring. *)
-  let print_new_utsname name bs =
-    (* Truncate an OCaml string at the first ASCII NUL character, ie. as
-     * if it were a C string.
-     *)
-    let truncate str =
-      try
-	let i = String.index str '\000' in
-	String.sub str 0 i
-      with
-	Not_found -> str
-    in
-    (* Expect the first (sysname) field to always be "Linux", which is
-     * also a good way to tell if we're synchronized to the right bit of
-     * memory.
-     *)
-    bitmatch bs with
-    | { "Linux\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" : 65*8 : string;
-	nodename : 65*8 : string;
-	release : 65*8 : string;
-	version : 65*8 : string;
-	machine : 65*8 : string;
-	domainname : 65*8 : string } ->
-	printf "%s: Linux %s %s %s %s %s\n"
-	  name
-	  (truncate nodename) (truncate release)
-	  (truncate version) (truncate machine) (truncate domainname)
-    | { _ } ->
-	eprintf (f_"%s: unexpected system_utsname in kernel image\n")
-	  name
-  in
-
-  List.iter (
-    fun (_, name, arch, mem, lookup_ksym) ->
-      (* In Linux 2.6.25, the symbol is init_uts_ns.
-       * http://lxr.linux.no/linux/init/version.c
-       *)
-      try
-	let addr = lookup_ksym "init_uts_ns" in
-
-	let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
-	(bitmatch bs with
-	 | { _ : 32 : int;		(* the kref, atomic_t, always 32 bits *)
-	     new_utsname : -1 : bitstring } ->
-	     print_new_utsname name new_utsname
-	 | { _ } ->
-	     eprintf (f_"%s: unexpected init_uts_ns in kernel image\n")
-	       name)
-      with
-	Not_found ->
-	  (* In Linux 2.6.9, the symbol is system_utsname.
-	   * http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
-	   *)
-	  try
-	    let addr = lookup_ksym "system_utsname" in
-
-	    let bs =
-	      Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
-	    print_new_utsname name bs
-	  with
-	    Not_found ->
-	      eprintf (f_"%s: could not find utsname in kernel image\n") name
-  ) images
+open Virt_mem_types
+
+let run debug (_, name, _, _, _, utsname) =
+  match utsname with
+  | Some u ->
+      printf "%s: %s %s %s %s %s %s\n"
+	name
+	u.kernel_name u.nodename u.kernel_release
+	u.kernel_version u.machine u.domainname
+  | None ->
+      eprintf (f_"%s: no system_utsname in kernel image\n") name
 
 let summary = s_"uname command for virtual machines"
 let description = s_"\
-- 
1.8.3.1