lib/virt_mem_mmap.mli
lib/virt_mem_mmap_c.c
lib/virt_mem_types.ml
+lib/virt_mem_types.mli
lib/virt_mem_utils.ml
lib/virt_mem_utsname.ml
lib/virt_mem_utsname.mli
datarootdir = @datarootdir@
mandir = @mandir@
-OCAMLDOCFLAGS = -html -sort -package bitstring,extlib -I lib
+OCAMLDOCFLAGS = -html -sort -package bitstring,extlib,libvirt -I lib
OCAMLDOC = @OCAMLDOC@
OCAMLDOCFILES = lib/virt_mem_utils.ml \
lib/virt_mem_mmap.mli \
- lib/virt_mem_types.ml \
+ lib/virt_mem_types.mli \
lib/virt_mem_ksyms.mli \
lib/virt_mem_kallsyms.mli \
lib/virt_mem_utsname.mli \
-virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
+virt_dmesg.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmi \
../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_types
open Virt_mem_mmap
-let run debug (_, name, arch, mem, lookup_ksym, _) =
+let run debug ({ domname = domname; mem = mem }, ksymmap, _) =
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 = Ksymmap.find "log_buf" ksymmap in
let log_buf = follow_pointer mem log_buf in
- let log_buf_len = lookup_ksym "log_buf_len" in
+ let log_buf_len = Ksymmap.find "log_buf_len" ksymmap 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 = Ksymmap.find "log_start" ksymmap in
let log_start = get_C_long mem log_start in *)
- let log_end = lookup_ksym "log_end" in
+ let log_end = Ksymmap.find "log_end" ksymmap in
let log_end = get_C_long mem log_end in
- (* let con_start = lookup_ksym "con_start" in
+ (* let con_start = Ksymmap.find "con_start" ksymmap in
let con_start = get_C_long mem con_start in *)
- let logged_chars = lookup_ksym "logged_chars" in
+ let logged_chars = Ksymmap.find "logged_chars" ksymmap in
let logged_chars = get_C_long mem logged_chars in
(* This is basically the same algorithm from printk.c:do_syslog
with
Not_found ->
eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
- name
+ domname
let summary = s_"display kernel messages"
let description = s_"\
-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_kallsyms.cmi: virt_mem_types.cmi
+virt_mem_ksyms.cmi: virt_mem_types.cmi
+virt_mem.cmi: virt_mem_types.cmi
virt_mem_mmap.cmi: virt_mem_utils.cmo
-virt_mem_utsname.cmi: virt_mem_types.cmo
+virt_mem_types.cmi: virt_mem_utils.cmo virt_mem_mmap.cmi
+virt_mem_utsname.cmi: virt_mem_types.cmi
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_capture.cmx: virt_mem_gettext.cmx virt_mem.cmx
-virt_mem_kallsyms.cmo: virt_mem_utils.cmo virt_mem_types.cmo \
+virt_mem_capture.cmo: virt_mem_types.cmi virt_mem_gettext.cmo virt_mem.cmi
+virt_mem_capture.cmx: virt_mem_types.cmx virt_mem_gettext.cmx virt_mem.cmx
+virt_mem_kallsyms.cmo: virt_mem_utils.cmo virt_mem_types.cmi \
virt_mem_mmap.cmi virt_mem_ksyms.cmi virt_mem_gettext.cmo \
virt_mem_kallsyms.cmi
virt_mem_kallsyms.cmx: virt_mem_utils.cmx virt_mem_types.cmx \
virt_mem_mmap.cmx virt_mem_ksyms.cmx virt_mem_gettext.cmx \
virt_mem_kallsyms.cmi
-virt_mem_ksyms.cmo: virt_mem_utils.cmo virt_mem_types.cmo virt_mem_mmap.cmi \
+virt_mem_ksyms.cmo: virt_mem_utils.cmo virt_mem_types.cmi 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_utsname.cmi virt_mem_utils.cmo \
- virt_mem_types.cmo virt_mem_mmap.cmi virt_mem_ksyms.cmi \
+ virt_mem_types.cmi 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_types.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi virt_mem_types.cmi
+virt_mem_types.cmx: virt_mem_utils.cmx virt_mem_mmap.cmx virt_mem_types.cmi
+virt_mem_utsname.cmo: virt_mem_utils.cmo virt_mem_types.cmi 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
List.map (
fun (dom, _) ->
- let id = D.get_id dom in
- let name = D.get_name dom in
+ let domname = D.get_name dom in
let wordsize =
match !def_wordsize with
| None ->
failwith
(sprintf (f_"%s: use -W to define word size for this image")
- name);
+ domname);
| Some ws -> ws in
let endian =
match !def_endian with
| None ->
failwith
(sprintf (f_"%s: use -E to define endianness for this image")
- name);
+ domname);
| Some e -> e in
let arch =
| Some I386 -> I386 | Some X86_64 -> X86_64
| _ ->
failwith
- (sprintf (f_"%s: use -A to define architecture (i386/x86-64 only) for this image") name) in
+ (sprintf (f_"%s: use -A to define architecture (i386/x86-64 only) for this image") domname) in
if !def_text_addr = 0L then
failwith
- (sprintf (f_"%s: use -T to define kernel load address for this image") name);
+ (sprintf (f_"%s: use -T to define kernel load address for this image") domname);
let start_t = gettimeofday () in
let mem = Virt_mem_mmap.set_wordsize mem wordsize in
let mem = Virt_mem_mmap.set_endian mem endian in
- ((Some id, name, arch, mem) : image0)
+ { dom = Some dom; domname = domname; mem = mem; arch = arch }
) xmls
) else (
(* One or more -t options passed. *)
let mem = Virt_mem_mmap.set_wordsize mem wordsize in
let mem = Virt_mem_mmap.set_endian mem endian in
- ((None, filename, arch, mem) : image0)
+ { dom = None; domname = filename; mem = mem; arch = arch }
) testimages
) in
(* Look for kallsyms: *)
let image = Virt_mem_kallsyms.find_kallsyms debug image in
+(*
(* Finally, just wrap the lookup_ksym call in something
* which prints the query when debug is set.
*)
(domid, name, arch, mem, lookup_ksym)
else
image in
+*)
image
) images in
open Printf
open ExtString
+module D = Libvirt.Domain
+
+open Virt_mem_types
open Virt_mem_gettext.Gettext
(* This will contain what is passed by the user as '-o' option. *)
* is the domain ID (if known) or a mangled domain name.
*)
List.iter (
- fun ((domid, domname, _, _) as image) ->
+ fun ({ dom = dom; domname = domname } as image) ->
let filename =
!output_filename ^ "." ^
- match domid with
- | Some id -> string_of_int id
+ match dom with
+ | Some dom -> string_of_int (D.get_id dom)
| None ->
let f = function
| ('a'..'z'|'A'..'Z'|'0'..'9'|'_' as c) -> String.make 1 c
save_image image filename
) images
-and save_image (_, domname, arch, mem) filename =
+and save_image { domname = domname } filename =
assert false;
let chan = open_out filename in
| Compressed of (string * Virt_mem_mmap.addr) list * Virt_mem_mmap.addr
| Uncompressed of (string * Virt_mem_mmap.addr) list
-let find_kallsyms debug (domid, name, arch, mem, lookup_ksym) =
+let find_kallsyms debug (({ domname = domname; mem = mem } as image), ksymmap) =
let start_t = gettimeofday () in
(* Now try to find the /proc/kallsyms table. This is in an odd
* more useful than the basic list of exports.
*)
let ksym_addrs = List.filter_map (
- fun ksym -> try Some (lookup_ksym ksym) with Not_found -> None
+ fun ksym -> try Some (Ksymmap.find ksym ksymmap) with Not_found -> None
) Virt_mem_ksyms.common_ksyms in
(* Search for those kernel addresses in the image. We're looking
* If found, jump backwards by length and check all addresses.
*)
if debug then
- eprintf "%s: testing candidate kallsyms at %Lx\n" name addr;
+ eprintf "%s: testing candidate kallsyms at %Lx\n" domname addr;
let rec loop addr =
let addrp = Virt_mem_mmap.follow_pointer mem addr in
if Virt_mem_mmap.is_mapped mem addrp then
let names_addr = Virt_mem_mmap.succ_long mem end_addr in
if debug then
eprintf "%s: candidate kallsyms found at %Lx (names_addr at %Lx, num_entries %d)\n"
- name start_addr names_addr num_entries;
+ domname start_addr names_addr num_entries;
Some (start_addr, num_entries, names_addr)
in
loop2 start_addr
) ksym_addrs in
if debug then (
- eprintf "%s: candidate kallsyms at:\n" name;
+ eprintf "%s: candidate kallsyms at:\n" domname;
List.iter (
function
| (start_addr, num_entries, names_addr, Uncompressed _) ->
(* Vote for the most popular symbol table candidate and
* enhance the function for looking up ksyms.
*)
- let lookup_ksym =
+ let ksymmap =
let freqs = frequency kallsymtabs in
match freqs with
| [] ->
- (* Can't find any kallsymtabs, just return the lookup_ksym
- * function generated previously from the exported symbols.
+ (* Can't find any kallsymtabs, just return the ksymmap
+ * map generated previously from the exported symbols.
*)
- lookup_ksym
+ ksymmap
| (_, (_, _, _, Uncompressed names)) :: _ ->
- let lookup_ksym name =
- try (* first look it up in kallsyms table. *)
- List.assoc name names
- with Not_found -> (* try the old exports table instead *)
- lookup_ksym name
+ let rec loop ksymmap = function
+ | (name, value) :: names ->
+ loop (Ksymmap.add name value ksymmap) names
+ | [] -> ksymmap
in
- lookup_ksym
+ loop ksymmap names
| (_, (start_addr, num_entries, names_addr,
Compressed (compressed_names, markers_addr))) :: _ ->
Some (name, sym_value)
) compressed_names in
- let lookup_ksym name =
- try (* first look it up in kallsyms table. *)
- List.assoc name names
- with Not_found -> (* try the old exports table instead *)
- lookup_ksym name
+ let rec loop ksymmap = function
+ | (name, value) :: names ->
+ loop (Ksymmap.add name value ksymmap) names
+ | [] -> ksymmap
in
-
- lookup_ksym in
+ loop ksymmap names in
if debug then (
let end_t = gettimeofday () in
(end_t -. start_t)
);
- ((domid, name, arch, mem, lookup_ksym) : image1)
+ ((image, ksymmap) : image1)
"schedule"; (* scheduler entry point *)
]
-let find_kernel_symbols debug (domid, name, arch, mem) =
+let find_kernel_symbols debug ({ mem = mem; domname = domname } as image) =
(* Searching for <NUL>string<NUL> *)
let common_ksyms_nul = List.map (sprintf "\000%s\000") common_ksyms in
let ksymtabs = List.filter (fun (_, size) -> size > 64L) ksymtabs in
if debug then (
- eprintf "%s: candidate symbol tables at:\n" name;
+ eprintf "%s: candidate symbol tables at:\n" domname;
List.iter (
fun (addr, size) ->
eprintf "\t%Lx\t%Lx\t%!" addr size;
(* Vote for the most popular symbol table candidate and from this
* generate a function to look up ksyms.
*)
- let lookup_ksym =
+ let ksymmap =
let freqs = frequency ksymtabs in
match freqs with
| [] ->
- eprintf (f_"%s: cannot find start of kernel symbol table\n") name;
- (fun _ -> raise Not_found)
+ eprintf (f_"%s: cannot find start of kernel symbol table\n") domname;
+ Ksymmap.empty
| (_, (ksymtab_addr, ksymtab_size)) :: _ ->
if debug then
eprintf
"%s: Kernel symbol table found at %Lx, size %Lx bytes\n%!"
- name ksymtab_addr ksymtab_size;
+ domname ksymtab_addr ksymtab_size;
(* Load the whole symbol table as a bitstring. *)
let ksymtab =
(Virt_mem_mmap.get_bytes mem ksymtab_addr
(Int64.to_int ksymtab_size)) in
- (* Function to look up an address in the symbol table. *)
- let lookup_ksym sym =
+ (* Construct kernel symbol map. *)
+ let ksymmap =
let bits = bits_of_wordsize (Virt_mem_mmap.get_wordsize mem) in
let e = Virt_mem_mmap.get_endian mem in
- let rec loop bs =
+ let rec loop ksymmap bs =
bitmatch bs with
| { value : bits : endian(e);
- name_ptr : bits : endian(e) }
- when Virt_mem_mmap.get_string mem name_ptr = sym ->
- value
- | { _ : bits : endian(e);
- _ : bits : endian(e);
+ name_ptr : bits : endian(e);
bs : -1 : bitstring } ->
- loop bs
- | { _ } -> raise Not_found
+ let name = Virt_mem_mmap.get_string mem name_ptr in
+ let ksymmap = Ksymmap.add name value ksymmap in
+ loop ksymmap bs
+ | { _ } ->
+ ksymmap
in
- loop ksymtab
- in
+ loop Ksymmap.empty ksymtab in
- lookup_ksym
+ ksymmap
in
if debug then (
(end_t -. start_t)
);
- ((domid, name, arch, mem, lookup_ksym) : image1)
+ ((image, ksymmap) : image1)
Common types.
*)
-(** A kernel image. *)
-type image0 =
- 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. *)
-
-(** A kernel symbol. *)
+module D = Libvirt.Domain
+
+open Virt_mem_mmap
+
type ksym = string
-(** A kernel image, after finding kernel symbols. *)
+module Ksymmap = Map.Make (String)
+
+type image0 = {
+ dom : Libvirt.ro D.t option;
+ domname : string;
+ arch : Virt_mem_utils.architecture;
+ mem : ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t;
+}
+
type image1 =
- 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. *)
+ image0
+ * addr Ksymmap.t
-(** 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. *)
+ image0
+ * addr Ksymmap.t
+ * utsname option
and utsname = {
kernel_name : string;
--- /dev/null
+(** Common types. *)
+(* 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.
+
+ Common types.
+ *)
+
+type ksym = string
+ (** A kernel symbol. *)
+
+module Ksymmap : sig
+ type key = String.t
+ type 'a t = 'a Map.Make(String).t
+ val empty : 'a t
+ val is_empty : 'a t -> bool
+ val add : key -> 'a -> 'a t -> 'a t
+ val find : key -> 'a t -> 'a
+ val remove : key -> 'a t -> 'a t
+ val mem : key -> 'a t -> bool
+ val iter : (key -> 'a -> unit) -> 'a t -> unit
+ val map : ('a -> 'b) -> 'a t -> 'b t
+ val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t
+ val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+ val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
+ val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
+end
+ (** A map of kernel symbols to addresses. *)
+
+type utsname = {
+ kernel_name : string;
+ nodename : string;
+ kernel_release : string;
+ kernel_version : string;
+ machine : string;
+ domainname : string;
+}
+ (** Kernel version, from utsname structure in the kernel. *)
+
+type image0 = {
+ dom : Libvirt.ro Libvirt.Domain.t option; (** Domain, if known. *)
+ domname : string; (** Domain name. *)
+ arch : Virt_mem_utils.architecture; (** Architecture, eg. i386. *)
+ mem : ([`Wordsize], [`Endian], [`HasMapping]) Virt_mem_mmap.t;
+ (** Memory map. *)
+}
+ (** A basic kernel image. *)
+
+type image1 =
+ image0
+ * Virt_mem_mmap.addr Ksymmap.t (* Kernel symbol map. *)
+ (** A kernel image, after finding kernel symbols. *)
+
+type image2 =
+ image0
+ * Virt_mem_mmap.addr Ksymmap.t (* Kernel symbol map. *)
+ * utsname option (* Kernel version, etc., if found. *)
+ (** A kernel image, after finding kernel version (like 'uname'). *)
| { _ } ->
None
-let find_utsname debug (domid, name, arch, mem, lookup_ksym) =
+let find_utsname debug ({ domname = name; mem = mem } as image, ksymmap) =
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 addr = Ksymmap.find "init_uts_ns" ksymmap in
let bs = Bitstring.bitstring_of_string (get_bytes mem addr (65*6+4)) in
(bitmatch bs with
* http://lxr.linux.no/linux-bk+v2.6.9/include/linux/utsname.h#L24
*)
try
- let addr = lookup_ksym "system_utsname" in
+ let addr = Ksymmap.find "system_utsname" ksymmap in
let bits =
Bitstring.bitstring_of_string (get_bytes mem addr (65*6)) in
Not_found ->
eprintf (f_"%s: could not find utsname in kernel image\n") name
in
- (domid, name, arch, mem, lookup_ksym, utsname)
+ (image, ksymmap, utsname)
-virt_ps.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_mmap.cmi \
- ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi
-virt_ps.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_mmap.cmx \
- ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx
+virt_ps.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmi \
+ ../lib/virt_mem_mmap.cmi ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi
+virt_ps.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
(* The implementation of 'ps' has gone through a number of complete
get_task_struct ~i:0 addr accum
(* This is the directed search function. *)
-let search debug mem lookup_ksym =
+let search debug mem ksymmap =
let ws = get_wordsize mem in
let ws = match ws with W32 -> 32 | W64 -> 64 in
let e = get_endian mem in
let wse = ws, e in
let init_task =
- try lookup_ksym "init_task"
+ try Ksymmap.find "init_task" ksymmap
with Not_found ->
- eprintf "virt-ps: lookup_ksym of init_task failed\n";
+ eprintf "virt-ps: cannot find kernel symbol 'init_task'\n";
exit 1 in
let accum = Accum.empty in
let ts = loop 0 0 in
()
-let run debug (_, _, _, mem, lookup_ksym, _) =
- search debug mem lookup_ksym
+let run debug ({ mem = mem }, ksymmap, _) =
+ search debug mem ksymmap
let summary = s_"list processes in virtual machine"
let description = s_"\
-virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmo \
+virt_uname.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmi \
../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi
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_utils
open Virt_mem_types
-let run debug (_, name, _, _, _, utsname) =
+let run debug ({ domname = domname }, _, utsname) =
match utsname with
| Some u ->
printf "%s: %s %s %s %s %s %s\n"
- name
+ domname
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
+ eprintf (f_"%s: no system_utsname in kernel image\n") domname
let summary = s_"uname command for virtual machines"
let description = s_"\