+ match loop addr with
+ | None -> None
+ | Some (start_addr, num_entries, names_addr) ->
+ (* As an additional verification, check the list of
+ * kallsyms_names.
+ *)
+ try
+ (* If the first byte is '\000' and is followed by a
+ * C identifier, then this is old-school list of
+ * symbols with prefix compression as in 2.6.9.
+ * Otherwise Huffman-compressed kallsyms as in
+ * 2.6.25.
+ *)
+ if MMap.get_byte mem names_addr = 0 &&
+ MMap.is_C_identifier mem (names_addr+^1L) then (
+ let names = ref [] in
+ let prev = ref "" in
+ let rec loop names_addr start_addr num =
+ if num > 0 then (
+ let prefix = MMap.get_byte mem names_addr in
+ let prefix = String.sub !prev 0 prefix in
+ let name = MMap.get_string mem (names_addr+^1L) in
+ let len = String.length name in
+ let name = prefix ^ name in
+ prev := name;
+ 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
+ (*eprintf "%S -> %Lx\n" name sym_value;*)
+ names := (name, sym_value) :: !names;
+ loop names_addr start_addr (num-1)
+ )
+ in
+ loop names_addr start_addr num_entries;
+ let names = List.rev !names in
+
+ Some (start_addr, num_entries, names_addr,
+ Uncompressed names)
+ )
+ else ( (* new-style "compressed" names. *)
+ let compressed_names = ref [] in
+ let rec loop names_addr start_addr num =
+ if num > 0 then (
+ let len = MMap.get_byte mem names_addr in
+ let name = MMap.get_bytes mem (names_addr+^1L) len in
+ let names_addr = names_addr +^ Int64.of_int len +^ 1L in
+ let sym_value = MMap.follow_pointer mem start_addr in
+ let start_addr = MMap.succ_long mem start_addr in
+ compressed_names :=
+ (name, sym_value) :: !compressed_names;
+ loop names_addr start_addr (num-1)
+ ) else
+ names_addr
+ in
+ let markers_addr = loop names_addr start_addr num_entries in
+ let markers_addr = MMap.align mem markers_addr in
+ let compressed_names = List.rev !compressed_names in
+
+ Some (start_addr, num_entries, names_addr,
+ Compressed (compressed_names, markers_addr))
+ )
+ with
+ Invalid_argument _ -> None (* bad names list *)
+ ) ksym_addrs in
+
+ if debug then (
+ eprintf "%s: candidate kallsyms at:\n" name;
+ List.iter (
+ function
+ | (start_addr, num_entries, names_addr, Uncompressed _) ->
+ 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)) ->
+ eprintf "\t%Lx %d entries names_addr=%Lx markers_addr=%Lx\n%!"
+ start_addr num_entries names_addr markers_addr
+ ) kallsymtabs
+ );
+
+ (* Vote for the most popular symbol table candidate and
+ * enhance the function for looking up ksyms.
+ *)
+ let lookup_ksym =
+ let freqs = frequency kallsymtabs in
+ match freqs with
+ | [] ->
+ (* Can't find any kallsymtabs, just return the lookup_ksym
+ * function generated previously from the exported symbols.
+ *)
+ lookup_ksym
+
+ | (_, (_, _, _, Uncompressed names)) :: _ ->
+ let lookup_ksym name =
+ try (* first look it up in kallsyms table. *)
+ List.assoc name names
+ with Not_found -> (* try the old exports table instead *)
+ lookup_ksym name
+ in
+ lookup_ksym
+
+ | (_, (start_addr, num_entries, names_addr,
+ Compressed (compressed_names, markers_addr))) :: _ ->
+ (* Skip the markers and look for the token table. *)
+ let num_markers = Int64.of_int ((num_entries + 255) / 256) in
+ let marker_size =
+ Int64.of_int (bytes_of_wordsize (MMap.get_wordsize mem)) in
+ let tokens_addr = markers_addr +^ marker_size *^ num_markers in
+
+ (* Now read out the compression tokens, which are just
+ * 256 ASCIIZ strings that map bytes in the compression
+ * names to substrings.
+ *)
+ let tokens = Array.make 256 "" in
+ let rec loop i addr =
+ if i < 256 then (
+ let str = MMap.get_string mem addr in
+ let len = String.length str in
+ let addr = addr +^ Int64.of_int (len+1) in
+ tokens.(i) <- str;
+ loop (i+1) addr
+ )
+ in
+ loop 0 tokens_addr;
+
+ (* Expand the compressed names using the tokens. *)
+ let names = List.filter_map (
+ fun (name, sym_value) ->
+ let f c = tokens.(Char.code c) in
+ let name = String.replace_chars f name in
+ (* First character in uncompressed output is the symbol
+ * type, eg. 'T'/'t' for text etc.
+ *)
+ (* NOTE: Symbol names are NOT unique
+ * (eg. 'con_start' is both a function and data in
+ * some kernels). XXX We need to handle this situation
+ * better.
+ *)
+ (*let typ = name.[0] in*)
+ let name = String.sub name 1 (String.length name - 1) in
+ (*eprintf "%S -> %Lx\n" name sym_value;*)
+ Some (name, sym_value)
+ ) compressed_names in
+
+ let lookup_ksym name =
+ try (* first look it up in kallsyms table. *)
+ List.assoc name names
+ with Not_found -> (* try the old exports table instead *)
+ lookup_ksym name
+ in