open Virt_mem_utils
open Virt_mem_types
+open Kernel_task_struct
-let run debug ({ domname = domname; mem = mem }, ksymmap, utsname) =
- try
- let kernel_version =
- match utsname with
- | None ->
- eprintf (f_"%s: could not guess kernel version\n") domname;
- raise Exit
- | Some { kernel_release = v } -> v in
+let run debug { domname = domname; mem = mem }
+ { utsname = utsname; tasks = tasks } =
+ let utsname = Option.get utsname in
+ let kernel_version = utsname.kernel_release in
+ let init_task_addr = Option.get tasks in
- if not (Kernel_task_struct.known kernel_version) then (
- eprintf (f_"%s: %s: unknown kernel version
-Try a newer version of virt-mem, or if the guest is not from a
-supported Linux distribution, see this page about adding support:
- http://et.redhat.com/~rjones/virt-mem/faq.html\n") domname kernel_version;
- raise Exit
- );
+ (* Starting at init_task, navigate through the linked list of
+ * tasks (through tasks.next). The main program has already made
+ * sure these are mapped into memory.
+ *)
+ let tasks =
+ let rec loop acc task =
+ let next = task.task_struct_tasks'next in
+ if next <> init_task_addr then (
+ let task = get_task_struct kernel_version mem next in
+ let task = {
+ task with
+ task_struct_comm = truncate_c_string task.task_struct_comm
+ } in
+ let acc = task :: acc in
+ loop acc task
+ ) else
+ acc
+ in
+ loop [] (get_task_struct kernel_version mem init_task_addr) in
- let init_task =
- let addr =
- try Ksymmap.find "init_task" ksymmap
- with Not_found ->
- eprintf (f_"%s: could not find init_task in kernel image\n") domname;
- raise Exit in
- let addr =
- (Virt_mem_mmap.unsafe_typed_addr_of_addr addr :
- [ `task_struct ] Virt_mem_mmap.typed_addr) in
- Kernel_task_struct.get kernel_version mem addr in
+ (* Sort tasks by PID. *)
+ let cmp { task_struct_pid = p1 } { task_struct_pid = p2 } = compare p1 p2 in
+ let tasks = List.sort cmp tasks in
- printf "comm = %S prio = %Ld state = %Ld static_prio = %Ld tasks'next = %Lx\n"
- init_task.Kernel_task_struct.comm
- init_task.Kernel_task_struct.prio
- init_task.Kernel_task_struct.state
- init_task.Kernel_task_struct.static_prio
- (Virt_mem_mmap.unsafe_addr_of_typed_addr init_task.Kernel_task_struct.tasks'next);
+ printf " PID STAT COMMAND\n";
- with Exit -> ()
+ List.iter (
+ fun task ->
+ printf "%5Ld %s\n" task.task_struct_pid task.task_struct_comm
+ ) tasks
let summary = s_"list processes in virtual machine"
let description = s_"\
virt-ps prints a process listing for virtual machines running under
libvirt."
-let () = Virt_mem.register "ps" summary description ~run
+let () =
+ Virt_mem.register "ps" summary description
+ ~needs_utsname:true ~needs_tasks:true ~run