Extracted kernel structures for device addressing in ifconfig.
[virt-mem.git] / dmesg / virt_dmesg.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 open Virt_mem_mmap
26
27 let run debug { domname = domname; mem = mem } { ksyms = ksyms } =
28   let ksyms = Option.get ksyms in
29   try
30     (* I don't know why but this symbol doesn't exist in 2.6.9
31      * even in kallsyms.  Hence this won't work with that kernel.
32      * It's possible we can fall back to memory scanning. XXX
33      *)
34     let log_buf = Ksymmap.find "log_buf" ksyms in
35     let log_buf = follow_pointer mem log_buf in
36     let log_buf_len = Ksymmap.find "log_buf_len" ksyms in
37     let log_buf_len = Int64.of_int32 (get_C_int mem log_buf_len) in
38     (*  let log_start = Ksymmap.find "log_start" ksyms in
39         let log_start = get_C_long mem log_start in *)
40     let log_end = Ksymmap.find "log_end" ksyms in
41     let log_end = get_C_long mem log_end in
42     (*  let con_start = Ksymmap.find "con_start" ksyms in
43         let con_start = get_C_long mem con_start in *)
44     let logged_chars = Ksymmap.find "logged_chars" ksyms in
45     let logged_chars = get_C_long mem logged_chars in
46
47     (* This is basically the same algorithm from printk.c:do_syslog
48      * type=3, translated into OCaml.  Unlike the kernel version
49      * however we don't copy the buffer backwards.
50      *)
51     let get_log_buf idx =
52       let addr = log_buf +^ (idx &^ (log_buf_len -^ 1L)) in
53       Char.chr (get_byte mem addr)
54     in
55
56     let count = log_buf_len in
57     let count = if count > logged_chars then logged_chars else count in
58     let limit = log_end in
59
60     let rec loop i =
61       if i >= 0L then (
62         let j = limit-^1L-^i in
63         if j +^ log_buf_len >= log_end then (
64           let c = get_log_buf j in
65           printf "%c" c;
66           loop (i-^1L)
67         )
68       )
69     in
70     loop (count-^1L)
71   with
72     Not_found ->
73       eprintf (f_"%s: could not find kernel log buffer in kernel image\n")
74         domname
75
76 let summary = s_"display kernel messages"
77 let description = s_"\
78 virt-dmesg prints the kernel messages for virtual machines running
79 under libvirt.  The output is similar to the ordinary dmesg command
80 run inside the virtual machine."
81
82 let () = Virt_mem.register "dmesg" summary description ~needs_ksyms:true ~run