Prints the process table, yay.
[virt-mem.git] / ps / virt_ps.ml
1 (* Memory info for virtual domains.
2    (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *)
19
20 open Printf
21
22 open Virt_mem_gettext.Gettext
23 open Virt_mem_utils
24 open Virt_mem_types
25
26
27 let run debug (image, ksymmap, utsname) =
28   try
29     let { domname = domname } = image in
30
31     let kernel_version =
32       match utsname with
33       | None ->
34           eprintf (f_"%s: could not guess kernel version\n") domname;
35           raise Exit
36       | Some { kernel_release = v } -> v in
37
38     if not (Kernel_task_struct.known kernel_version) then (
39       eprintf (f_"%s: %s: unknown kernel version
40 Try a newer version of virt-mem, or if the guest is not from a
41 supported Linux distribution, see this page about adding support:
42   http://et.redhat.com/~rjones/virt-mem/faq.html\n") domname kernel_version;
43       raise Exit
44     );
45
46     let task_struct_size = Kernel_task_struct.size kernel_version in
47
48     let init_task, init_task_addr =
49       let init_task_addr =
50         try Ksymmap.find "init_task" ksymmap
51         with Not_found ->
52           eprintf (f_"%s: could not find init_task in kernel image\n") domname;
53           raise Exit in
54       let addr =
55         (Virt_mem_mmap.unsafe_typed_addr_of_addr init_task_addr :
56            [ `task_struct ] Virt_mem_mmap.typed_addr) in
57       let init_task = Kernel_task_struct.get kernel_version image.mem addr in
58       init_task, init_task_addr in
59
60     (* Starting at init_task, navigate through the linked list of
61      * tasks (through tasks.next).  Grab each task_struct as we go.
62      *)
63     let tasks, image =
64       let rec loop image acc task =
65         let next = task.Kernel_task_struct.tasks'next in
66         let next_addr = Virt_mem_mmap.unsafe_addr_of_typed_addr next in
67         if next_addr <> init_task_addr then (
68           let mapped =
69             Virt_mem_mmap.is_mapped_range image.mem
70               next_addr task_struct_size in
71           let image =
72             if not mapped then load_memory image next_addr task_struct_size
73             else image in
74           let task = Kernel_task_struct.get kernel_version image.mem next in
75           let acc = task :: acc in
76           loop image acc task
77         ) else
78           acc, image
79       in
80       loop image [] init_task in
81
82     List.iter (
83       fun task ->
84         printf "%S\n" task.Kernel_task_struct.comm
85     ) tasks
86
87   with
88   | Exit -> ()
89
90 let summary = s_"list processes in virtual machine"
91 let description = s_"\
92 virt-ps prints a process listing for virtual machines running under
93 libvirt."
94
95 let () = Virt_mem.register "ps" summary description ~run