"Fossies" - the Fresh Open Source Software Archive

Member "virt-dmesg-0.3.0/src/ksyms.ml" (25 May 2011, 6041 Bytes) of package /linux/privat/old/virt-dmesg-0.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Objective Caml source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 (* virt-dmesg
    2  * (C) Copyright 2008-2011 Red Hat Inc.
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17  *)
   18 
   19 open Printf
   20 
   21 open Utils
   22 
   23 (* Look for ordinary symbol table.
   24  *
   25  * The ordinary symbol table is defined as:
   26  * struct kernel_symbol {
   27  *   unsigned long value;
   28  *   const char *name;  -------> points to string somewhere else
   29  * } symbols[];
   30  *
   31  * What we do is look for some likely symbols (ie. the strings,
   32  * common_ksyms).  Then (since we know the address of those strings)
   33  * we look for something which is plausibly a symbol table, searching
   34  * forwards and backwards to find the ends of it.  This gives us, for
   35  * each likely symbol found, a corresponding potential symbol table.
   36  * Then we take a vote for the most frequently occurring symbol table
   37  * and use that.
   38  *)
   39 
   40 (* Look for some common entries in the exported symbol table and
   41  * from that find the symbol table itself.  These are just
   42  * supposed to be symbols which are very likely to be present
   43  * in any Linux kernel, although we only need one of them to be
   44  * present to find the symbol table.
   45  *
   46  * NB. Must not be __initdata, must be in EXPORT_SYMBOL.
   47  *)
   48 let common_ksyms = [
   49   "init_task";                          (* first task_struct *)
   50   "root_mountflags";                    (* flags for mounting root fs *)
   51   "init_uts_ns";                        (* uname strings *)
   52   "nr_cpu_ids";
   53   "speedstep_get_freqs";
   54   "hpet_register_irq_handler";
   55   "tty_put_char";
   56   "driver_find";
   57   "scsi_register_driver";
   58   "phy_register_fixup";
   59   "input_register_handler";
   60   "save_processor_state";
   61 ]
   62 
   63 let search_ksyms k =
   64   let sym_addrs : (string * int64) list =
   65     List.concat (
   66       List.map (
   67         fun symbol ->
   68           let addrs = Kernel.find_all k (sprintf "\000%s\000" symbol) in
   69           (* Need to +1 because the string we matched started with \0
   70            * character.
   71            *)
   72           let addrs = List.map ((+^) 1L) addrs in
   73           List.map (fun addr -> (symbol, addr)) addrs
   74       ) common_ksyms
   75     ) in
   76 
   77   let sym_tables : (int64 * int64) list =
   78     List.concat (
   79       List.map (
   80         fun (source_symbol, addr) ->
   81           let addrs = Kernel.find_all_pointers k addr in
   82 
   83           (* struct kernel_symbol {
   84            *   unsigned long value;
   85            *   const char *name; <--- each of addrs (could) point here
   86            * } symbols[];
   87            *)
   88 
   89           (* Look at 'value' field and see if it's likely to be a
   90            * value.  Filter out if not.
   91            *)
   92           let addrs = List.filter (
   93             fun a ->
   94               let a2 = Kernel.pred_word k a in
   95               let a2p = Kernel.follow_pointer k a2 in
   96               (* We wouldn't expect the value to point somewhere near
   97                * to the name.
   98                *)
   99               Int64.abs (addr -^ a2p) > 32L
  100           ) addrs in
  101 
  102           (* Search back and forward for beginning and end of symbol table. *)
  103           let symtab_start_addrs = List.map (
  104             fun addr ->
  105               let rec loop addr =
  106                 (* '*addr' should point to a C identifier.  If it
  107                  * does, step backwards to the previous symbol table
  108                  * entry.
  109                  *)
  110                 let addrp = Kernel.follow_pointer k addr in
  111                 if Kernel.is_C_identifier k addrp then
  112                   loop (Kernel.pred_word k (Kernel.pred_word k addr))
  113                 else
  114                   Kernel.succ_word k addr
  115               in
  116               loop addr
  117           ) addrs in
  118 
  119           List.iter (
  120             fun start_addr ->
  121               debug "start_addr %Lx from %s" start_addr source_symbol
  122           ) symtab_start_addrs;
  123 
  124           List.map (
  125             fun start_addr ->
  126               let rec loop addr =
  127                 let addr2 = Kernel.succ_word k addr in (* &name *)
  128                 let addr2p = Kernel.follow_pointer k addr2 in (* name itself *)
  129                 if Kernel.is_C_identifier k addr2p then
  130                   loop (Kernel.succ_word k addr2)
  131                 else
  132                   addr
  133               in
  134               let end_addr = loop start_addr in
  135               start_addr, end_addr -^ start_addr
  136           ) symtab_start_addrs
  137       ) sym_addrs
  138     ) in
  139 
  140   debug "candidate symbol tables:";
  141   List.iter (
  142     fun (start, size) ->
  143       debug "\tstart %Lx size %Ld" start size
  144   ) sym_tables;
  145 
  146   (* Simply ignore any symbol table candidates which are too small. *)
  147   let sym_tables = List.filter (fun (_, size) -> size > 64L) sym_tables in
  148 
  149   (* Vote for the most popular symbol table. *)
  150   let freqs = frequency sym_tables in
  151   match freqs with
  152   | [] ->
  153       (* No symbol table, so this is likely not a kernel that we
  154        * know how to parse.
  155        *)
  156       raise Not_found
  157 
  158   | (_, (start_addr, size)) :: _ ->
  159       (* Take the most popular symbol table candidate and discard
  160        * the others.  Parse this into a list of symbols.
  161        *)
  162       let rec loop addr acc =
  163         if addr < start_addr +^ size then
  164           let value = Kernel.follow_pointer k addr in (* value *)
  165           let addr2 = Kernel.succ_word k addr in (* &name *)
  166           let addr2p = Kernel.follow_pointer k addr2 in (* name itself *)
  167           let symbol = Kernel.get_string k addr2p in
  168           let acc = (symbol, value) :: acc in
  169           loop (Kernel.succ_word k addr2) acc
  170         else
  171           List.rev acc
  172       in
  173       loop start_addr []