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") name);
+
+ let start_t = gettimeofday () in
(* Read the kernel memory.
* Maximum 64K can be read over remote connections.
in
loop 0;
+ if debug then (
+ let end_t = gettimeofday () in
+ eprintf "timing: downloading kernel took %f seconds\n%!"
+ (end_t -. start_t)
+ );
+
(* Map the virtual memory. *)
let mem = MMap.of_string str !def_text_addr in
(* Searching for <NUL>string<NUL> *)
let common_ksyms_nul = List.map (sprintf "\000%s\000") common_ksyms in
+ let start_t = gettimeofday () in
+
(* Search for these strings in the memory image. *)
let ksym_strings = List.map (MMap.find_all mem) common_ksyms_nul in
let ksym_strings = List.concat ksym_strings in
(* Adjust found addresses to start of the string (skip <NUL>). *)
let ksym_strings = List.map Int64.succ ksym_strings in
+ if debug then (
+ let end_t = gettimeofday () in
+ eprintf "timing: searching for common_ksyms took %f seconds\n%!"
+ (end_t -. start_t)
+ );
+
+ let start_t = gettimeofday () in
+
(* For any we found, try to look up the symbol table
* base addr and size.
*)
let ksymtabs = List.filter (fun (_, size) -> size > 64L) ksymtabs in
if debug then (
- printf "%s: candidate symbol tables at:\n" name;
+ eprintf "%s: candidate symbol tables at:\n" name;
List.iter (
fun (addr, size) ->
- printf "\t%Lx\t%Lx\t%!" addr size;
- printf "first symbol: %s\n%!"
+ eprintf "\t%Lx\t%Lx\t%!" addr size;
+ eprintf "first symbol: %s\n%!"
(MMap.get_string mem
(MMap.follow_pointer mem
(MMap.succ_long mem addr)))
| (_, (ksymtab_addr, ksymtab_size)) :: _ ->
if debug then
- printf
+ eprintf
"%s: Kernel symbol table found at %Lx, size %Lx bytes\n%!"
name ksymtab_addr ksymtab_size;
lookup_ksym
in
+ if debug then (
+ let end_t = gettimeofday () in
+ eprintf "timing: searching for ordinary ksyms took %f seconds\n%!"
+ (end_t -. start_t)
+ );
+
+ let start_t = gettimeofday () in
+
(* Now try to find the /proc/kallsyms table. This is in an odd
* compressed format (but not a very successful compression
* format). However if it exists we know that it will contain
* If found, jump backwards by length and check all addresses.
*)
if debug then
- printf "%s: testing candidate kallsyms at %Lx\n" name addr;
+ eprintf "%s: testing candidate kallsyms at %Lx\n" name addr;
let rec loop addr =
let addrp = MMap.follow_pointer mem addr in
if MMap.is_mapped mem addrp then
(* ok! *)
let names_addr = MMap.succ_long mem end_addr in
if debug then
- printf "%s: candidate kallsyms found at %Lx (names_addr at %Lx, num_entries %d)\n"
+ eprintf "%s: candidate kallsyms found at %Lx (names_addr at %Lx, num_entries %d)\n"
name start_addr names_addr num_entries;
Some (start_addr, num_entries, names_addr)
in
let names_addr = names_addr +^ Int64.of_int len +^ 2L in
let sym_value = MMap.follow_pointer mem start_addr in
let start_addr = MMap.succ_long mem start_addr in
- (*printf "%S -> %Lx\n" name sym_value;*)
+ (*eprintf "%S -> %Lx\n" name sym_value;*)
names := (name, sym_value) :: !names;
loop names_addr start_addr (num-1)
)
) ksym_addrs in
if debug then (
- printf "%s: candidate kallsyms at:\n" name;
+ eprintf "%s: candidate kallsyms at:\n" name;
List.iter (
function
| (start_addr, num_entries, names_addr, Uncompressed _) ->
- printf "\t%Lx %d entries names_addr=%Lx old-style\n%!"
+ eprintf "\t%Lx %d entries names_addr=%Lx old-style\n%!"
start_addr num_entries names_addr
| (start_addr, num_entries, names_addr,
Compressed (_, markers_addr)) ->
- printf "\t%Lx %d entries names_addr=%Lx markers_addr=%Lx\n%!"
+ eprintf "\t%Lx %d entries names_addr=%Lx markers_addr=%Lx\n%!"
start_addr num_entries names_addr markers_addr
) kallsymtabs
);
*)
(*let typ = name.[0] in*)
let name = String.sub name 1 (String.length name - 1) in
- (*printf "%S -> %Lx\n" name sym_value;*)
+ (*eprintf "%S -> %Lx\n" name sym_value;*)
Some (name, sym_value)
) compressed_names in
lookup_ksym in
+ if debug then (
+ let end_t = gettimeofday () in
+ eprintf "timing: searching for kallsyms took %f seconds\n%!"
+ (end_t -. start_t)
+ );
+
(* Just wrap the lookup_ksym call in something which prints
* the query when debug is set.
*)
let lookup_ksym sym =
try
let value = lookup_ksym sym in
- printf "lookup_ksym %S = %Lx\n%!" sym value;
+ eprintf "lookup_ksym %S = %Lx\n%!" sym value;
value
with Not_found ->
- printf "lookup_ksym %S failed\n%!" sym;
+ eprintf "lookup_ksym %S failed\n%!" sym;
raise Not_found
in
lookup_ksym
if addr &^ 7L <> 0L then
invalid_arg "add_file: mapping address must be aligned to 8 bytes";
let size = String.length str in
- (* Use Bigarray.Array1. XXX We should just use the string. *)
+ (* Copy the string data to a Bigarray. *)
let arr = Array1.create char c_layout size in
for i = 0 to size-1 do
Array1.set arr i (String.unsafe_get str i)
in
loop mappings
+(* The following functions are actually written in C
+ * because memmem(3) is likely to be much faster than anything
+ * we could write in OCaml.
+ *
+ * Also OCaml bigarrays are specifically designed to be accessed
+ * easily from C:
+ * http://caml.inria.fr/pub/docs/manual-ocaml/manual043.html
+ *)
+(*
(* Array+offset = string? *)
let string_at arr offset str strlen =
let j = ref offset in
loop ()
)
else Some start
+*)
+external _find_in :
+ int -> int -> string -> (char,int8_unsigned_elt,c_layout) Array1.t ->
+ int option = "virt_mem_mmap_find_in"
(* Generic find function. *)
let _find t start align str =
--- /dev/null
+/* 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.
+
+ This contains hand-coded C functions written for speed.
+*/
+
+#include <config.h>
+
+#include <string.h>
+
+#include <caml/config.h>
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+#include <caml/bigarray.h>
+
+CAMLprim value
+virt_mem_mmap_find_in (value startv, value alignv, value strv, value arrv)
+{
+ CAMLparam4 (startv, alignv, strv, arrv);
+ CAMLlocal2 (rv, vv);
+ long start = Long_val (startv); /* Start offset for search. */
+ long align = Long_val (alignv); /* Alignment for search. */
+ char *str = String_val (strv); /* String to search for. */
+ int strlen = caml_string_length (strv);
+ void *data = Data_bigarray_val (arrv); /* Data in bigarray. */
+ int datalen = Bigarray_val(arrv)->dim[0]; /* Total length of bigarray. */
+ long i, r = -1;
+ void *p;
+
+ /* memmem is a GNU extension. Note that we cannot use strstr because
+ * OCaml strings may contain NULs, and in this case it is very likely
+ * that it does contain NULs.
+ */
+#ifdef HAVE_MEMMEM
+ if (align == 1) {
+ p = memmem (data+start, datalen-start, str, strlen);
+ r = p ? p-data : -1;
+ goto ret;
+ }
+#endif
+
+ p = data+start;
+ for (i = start; i < datalen-strlen; i += align) {
+ if (memcmp (p, str, strlen) == 0) {
+ r = p-data;
+ goto ret;
+ }
+ p += align;
+ }
+
+ ret:
+ if (r == -1)
+ rv = Val_int (0); /* None */
+ else {
+ vv = Val_long (r); /* Some r */
+ rv = caml_alloc (1, 0);
+ Store_field (rv, 0, vv);
+ }
+
+ CAMLreturn (rv);
+}