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@
-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
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_"\
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
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
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)
(* 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
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
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
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";
* 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 ->
| 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: *)
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
)
?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.
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
* 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;
+}
--- /dev/null
+(* 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)
--- /dev/null
+(** 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. *)
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_"\
-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
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_"\