Refactored, process table now loaded centrally.
[virt-mem.git] / ps / virt_ps.ml
index a9bcf1f..5c53dbf 100644 (file)
@@ -25,77 +25,48 @@ open Virt_mem_types
 
 open Kernel_task_struct
 
-let run debug (image, ksymmap, utsname) =
-  try
-    let { domname = domname } = image in
-
-    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
-
-    if not (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
-    );
-
-    let task_struct_size = task_struct_size kernel_version in
-
-    let init_task, init_task_addr =
-      let init_task_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 init_task =
-       get_task_struct kernel_version image.mem init_task_addr in
-      init_task, init_task_addr in
-
-    (* Starting at init_task, navigate through the linked list of
-     * tasks (through tasks.next).  Grab each task_struct as we go.
-     *)
-    let tasks, image =
-      let rec loop image acc task =
-       let next = task.task_struct_tasks'next in
-       if next <> init_task_addr then (
-         let mapped =
-           Virt_mem_mmap.is_mapped_range image.mem next task_struct_size in
-         let image =
-           if not mapped then load_memory image next task_struct_size
-           else image in
-         let task = get_task_struct kernel_version image.mem next in
-         let task = {
-           task with
-             task_struct_comm = truncate_c_string task.task_struct_comm
-         } in
-         let acc = task :: acc in
-         loop image acc task
-       ) else
-         acc, image
-      in
-      loop image [] init_task 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 "  PID STAT COMMAND\n";
-
-    List.iter (
-      fun task ->
-       printf "%5Ld      %s\n" task.task_struct_pid task.task_struct_comm
-    ) tasks
-
-  with Exit -> ()
+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
+
+  (* 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
+
+  (* 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 "  PID STAT COMMAND\n";
+
+  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