Experimental automated 'follower' code.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 15 Aug 2008 18:05:50 +0000 (19:05 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 15 Aug 2008 18:05:50 +0000 (19:05 +0100)
22 files changed:
extract/codegen/code_generation.ml
extract/codegen/code_generation.mli
extract/codegen/compile_kerneldb.ml
extract/codegen/pahole_parser.ml
extract/codegen/pahole_parser.mli
extract/codegen/struct_classify.ml
extract/codegen/struct_classify.mli
ifconfig/.depend
ifconfig/virt_ifconfig.ml
lib/.depend
lib/Makefile.in
lib/kernel.ml
lib/kernel.mli
lib/virt_mem.ml
lib/virt_mem_kernels.ml
lib/virt_mem_net_devices.ml
lib/virt_mem_net_devices.mli
lib/virt_mem_tasks.ml
lib/virt_mem_tasks.mli
lib/virt_mem_types.mli
ps/.depend
ps/virt_ps.ml

index eaec4c8..7b0262b 100644 (file)
@@ -74,6 +74,12 @@ let concat_sig_items items =
   | x :: xs ->
       List.fold_left (fun xs x -> <:sig_item< $xs$ $x$ >>) x xs
 
+let concat_exprs exprs =
+  match exprs with
+  | [] -> assert false
+  | x :: xs ->
+      List.fold_left (fun xs x -> <:expr< $xs$ ; $x$ >>) x xs
+
 let concat_record_fields fields =
   match fields with
     | [] -> assert false
@@ -96,6 +102,13 @@ let build_tuple_from_exprs exprs =
       Ast.ExTup (_loc,
                 List.fold_left (fun xs x -> Ast.ExCom (_loc, x, xs)) x xs)
 
+let build_tuple_from_patts patts =
+  match patts with
+  | [] | [_] -> assert false
+  | x :: xs ->
+      Ast.PaTup (_loc,
+                List.fold_left (fun xs x -> Ast.PaCom (_loc, x, xs)) x xs)
+
 type code = Ast.str_item * Ast.sig_item
 
 let ocaml_type_of_field_type = function
@@ -112,7 +125,7 @@ let generate_types xs =
        fun { SC.sf_name = sf_name; sf_fields = fields } ->
          if fields <> [] then (
            let fields = List.map (
-             fun { PP.field_name = name; PP.field_type = t } ->
+             fun (name, t) ->
                let t = ocaml_type_of_field_type t in
                <:ctyp< $lid:sf_name^"_"^name$ : $t$ >>
            ) fields in
@@ -130,7 +143,7 @@ let generate_types xs =
        fun { SC.cf_name = cf_name; cf_fields = fields } ->
          if fields <> [] then (
            let fields = List.map (
-             fun { PP.field_name = name; PP.field_type = t } ->
+             fun (name, t) ->
                let t = ocaml_type_of_field_type t in
                <:ctyp< $lid:cf_name^"_"^name$ : $t$ >>
            ) fields in
@@ -145,24 +158,13 @@ let generate_types xs =
       let cflist = concat_str_items cflist in
 
       <:str_item<
-        type ('a, 'b) $lid:struct_name$ = {
-         $lid:struct_name^"_shape"$ : 'a;
-         $lid:struct_name^"_content"$ : 'b;
-       }
+        type ('a, 'b) $lid:struct_name$ = 'a * 'b ;;
        $sflist$
        $cflist$
       >>
   ) xs in
 
-  let sigs =
-    List.map (
-      fun (struct_name, _, _) ->
-       <:sig_item<
-          type ('a, 'b) $lid:struct_name$
-       >>
-    ) xs in
-
-  concat_str_items strs, concat_sig_items sigs
+  concat_str_items strs, <:sig_item< >>
 
 let generate_offsets xs =
   (* Only need to generate the offset_of_* functions for fields
@@ -232,11 +234,6 @@ let generate_offsets xs =
     ) fields in
 
   let strs = concat_str_items strs in
-  let strs =
-    <:str_item<
-      module StringMap = Map.Make (String) ;;
-      $strs$
-    >> in
 
   strs, <:sig_item< >>
 
@@ -255,12 +252,6 @@ let generate_parsers xs =
     ) xs in
 
   let strs = concat_str_items strs in
-  let strs =
-    <:str_item<
-      let match_err = "failed to match kernel structure" ;;
-      let zero = 0 ;;
-      $strs$
-    >> in
 
   (* The shared parser functions.
    * 
@@ -318,14 +309,22 @@ let generate_parsers xs =
 
          let shape_assignments =
            List.map (
-             fun { PP.field_name = field_name;
-                   field_type = field_type;
-                   field_offset = offset } ->
+             fun (field_name, field_type) ->
+
+               (* Go and look up the field offset in the correct kernel. *)
+               let { PP.field_offset = offset } =
+                 List.find (fun { PP.field_name = name } -> field_name = name)
+                   structure.PP.struct_fields in
 
+               (* Generate assignment code, if necessary we can adjust
+                * the list_head.
+                *)
                match field_type with
                | PP.FListHeadPointer None ->
-                   sprintf "%s_%s = Int64.sub %s %dL"
-                     sf.SC.sf_name field_name field_name offset
+                   sprintf "%s_%s = (if %s <> 0L then Int64.sub %s %dL else %s)"
+                     sf.SC.sf_name field_name
+                     field_name
+                     field_name offset field_name
 
                | PP.FListHeadPointer (Some (other_struct_name,
                                             other_field_name)) ->
@@ -334,13 +333,15 @@ let generate_parsers xs =
                     * offset_of_<struct>_<field> to find it.
                     *)
                    sprintf "%s_%s = (
-                      let offset = offset_of_%s_%s kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub %s offset
+                      if %s <> 0L then (
+                        let offset = offset_of_%s_%s kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub %s offset
+                      ) else %s
                     )"
-                     sf.SC.sf_name field_name
+                     sf.SC.sf_name field_name field_name
                      other_struct_name other_field_name
-                     field_name
+                     field_name field_name
                | _ ->
                    sprintf "%s_%s = %s" sf.SC.sf_name field_name field_name
            ) sf.SC.sf_fields in
@@ -352,7 +353,7 @@ let generate_parsers xs =
 
          let content_assignments =
            List.map (
-             fun { PP.field_name = field_name } ->
+             fun (field_name, _) ->
                sprintf "%s_%s = %s" cf.SC.cf_name field_name field_name
            ) cf.SC.cf_fields in
 
@@ -365,15 +366,14 @@ let generate_parsers xs =
            sprintf "
   bitmatch bits with
   | { %s } ->
-      let shape =
+      let s =
       %s in
-      let content =
+      let c =
       %s in
-      { %s_shape = shape; %s_content = content }
+      (s, c)
   | { _ } ->
       raise (Virt_mem_types.ParseError (%S, %S, match_err))"
              patterns shape_assignments content_assignments
-             struct_name struct_name
              struct_name pa_name in
 
          Hashtbl.add subs pa_name code
@@ -382,17 +382,268 @@ let generate_parsers xs =
 
   (strs, <:sig_item< >>), subs
 
-let output_interf ~output_file types offsets parsers =
-  let sigs = concat_sig_items [ types; offsets; parsers ] in
+(* Helper functions to store things in a fixed-length tuple very efficiently.
+ * Note that the tuple length must be >= 2.
+ *)
+type tuple = string list
+
+let tuple_create fields : tuple = fields
+
+(* Generates 'let _, _, resultpatt, _ = tupleexpr in body'. *)
+let tuple_generate_extract fields field resultpatt tupleexpr body =
+  let patts = List.map (
+    fun name -> if name = field then resultpatt else <:patt< _ >>
+  ) fields in
+  let result = build_tuple_from_patts patts in
+  <:expr< let $result$ = $tupleexpr$ in $body$ >>
+
+(* Generates '(fieldexpr1, fieldexpr2, ...)'. *)
+let tuple_generate_construct fieldexprs =
+  build_tuple_from_exprs fieldexprs
+
+type follower_t =
+  | Missing of string | Follower of string | KernelVersion of string
+
+let generate_followers xs =
+  (* Tuple of follower functions, just a list of struct_names. *)
+  let follower_tuple = tuple_create (List.map fst xs) in
+
+  (* A shape-follow function for every structure/shape. *)
+  let strs = List.map (
+    fun (struct_name, (_, sflist, _, _)) ->
+      List.map (
+       fun { SC.sf_name = sf_name; sf_fields = fields } ->
+         let body = List.fold_right (
+           fun (name, typ) body ->
+             let follower_name =
+               match typ with
+               | PP.FListHeadPointer None -> struct_name
+               | PP.FListHeadPointer (Some (struct_name, _)) -> struct_name
+               | PP.FStructPointer struct_name -> struct_name
+               | _ -> assert false in
+             tuple_generate_extract follower_tuple follower_name
+               <:patt< f >> <:expr< followers >>
+               <:expr<
+                 let map =
+                   f load followers map shape.$lid:sf_name^"_"^name$ in $body$
+               >>
+         ) fields <:expr< map >> in
+
+         <:str_item<
+           let $lid:sf_name^"_follower"$ load followers map shape =
+             $body$
+         >>
+      ) sflist
+  ) xs in
+  let strs = List.concat strs in
+
+  (* A follower function for every kernel version / structure.  When this
+   * function is called starting at some known root, it will load every
+   * reachable kernel structure.
+   *)
+  let strs =
+    let common =
+      (* Share as much common code as possible to minimize generated
+       * code size and benefit i-cache.
+       *)
+      <:str_item<
+       let kv_follower kernel_version struct_name total_size
+           parserfn followerfn
+           load followers map addr =
+         if addr <> 0L && not (AddrMap.mem addr map) then (
+           let map = AddrMap.add addr (struct_name, total_size) map in
+           let bits = load struct_name addr total_size in
+           let shape, _ = parserfn kernel_version bits in
+           followerfn load followers map shape
+         )
+         else map
+      >> in
+
+    let fs =
+      List.map (
+       fun (struct_name, (kernels, _, sfhash, pahash)) ->
+         List.map (
+           fun ({ PP.kernel_version = version; kv_i = kv_i },
+                { PP.struct_total_size = total_size }) ->
+             let { SC.pa_name = pa_name } = Hashtbl.find pahash version in
+             let { SC.sf_name = sf_name } = Hashtbl.find sfhash version in
+
+             let fname = sprintf "%s_kv%d_follower" struct_name kv_i in
+
+             <:str_item<
+               let $lid:fname$ =
+                 kv_follower
+                   $str:version$ $str:struct_name$ $`int:total_size$
+                   $lid:pa_name$ $lid:sf_name^"_follower"$
+             >>
+         ) kernels
+      ) xs in
+
+    let strs = strs @ [ common ] @ List.concat fs in
+    strs in
+
+  (* A map from kernel versions to follower functions.
+   *
+   * For each struct, we have a list of kernel versions which contain
+   * that struct.  Some kernels are missing a particular struct, so
+   * that is turned into a ParseError exception.
+   *)
+  let strs =
+    let nr_kernels =
+      List.fold_left max 0
+       (List.map (fun (_, (kernels, _, _, _)) -> List.length kernels) xs) in
+    let nr_structs = List.length xs in
+    let array = Array.make_matrix nr_kernels (nr_structs+1) (Missing "") in
+    List.iteri (
+      fun si (struct_name, _) ->
+       for i = 0 to nr_kernels - 1 do
+         array.(i).(si+1) <- Missing struct_name
+       done
+    ) xs;
+    List.iteri (
+      fun si (struct_name, (kernels, _, _, _)) ->
+       List.iter (
+         fun ({ PP.kernel_version = version; kv_i = kv_i }, _) ->
+           array.(kv_i).(0) <- KernelVersion version;
+           array.(kv_i).(si+1) <-
+             Follower (sprintf "%s_kv%d_follower" struct_name kv_i)
+       ) kernels
+    ) xs;
+
+    let array = Array.map (
+      fun row ->
+       match Array.to_list row with
+       | [] | (Missing _|Follower _) :: _ -> assert false
+       | KernelVersion kernel_version :: followers -> kernel_version, followers
+    ) array in
+
+    let map = List.fold_left (
+      fun map (kernel_version, followers) ->
+       let followers = List.map (
+         function
+         | Follower fname ->
+             <:expr< $lid:fname$ >>
+
+         (* no follower for this kernel/struct combination *)
+         | Missing struct_name ->
+             <:expr<
+               fun _ _ _ _ ->
+                 raise (
+                   Virt_mem_types.ParseError (
+                     $str:struct_name$, "follower_map", struct_missing_err
+                   )
+                 )
+             >>
+         | KernelVersion _ -> assert false
+       ) followers in
+       let followers = tuple_generate_construct followers in
+
+       <:expr< StringMap.add $str:kernel_version$ $followers$ $map$ >>
+    ) <:expr< StringMap.empty >> (Array.to_list array) in
+
+    let str =
+      <:str_item<
+       let follower_map = $map$
+      >> in
+    strs @ [ str ] in
+
+  (* Finally a publicly exposed follower function. *)
+  let strs =
+    let fs =
+      List.map (
+       fun (struct_name, (kernels, _, _, _)) ->
+         let fname = sprintf "%s_follower" struct_name in
+
+         let body =
+           tuple_generate_extract follower_tuple struct_name
+             <:patt< f >> <:expr< followers >>
+             <:expr<
+               f load followers AddrMap.empty addr
+             >> in
+
+         <:str_item<
+           let $lid:fname$ kernel_version load addr =
+             let followers =
+               try StringMap.find kernel_version follower_map
+               with Not_found ->
+                 unknown_kernel_version kernel_version $str:struct_name$ in
+             $body$
+         >>
+      ) xs in
+
+    strs @ fs in
+
+  let sigs =
+    List.map (
+      fun (struct_name, _) ->
+       <:sig_item<
+          val $lid:struct_name^"_follower"$ :
+           kernel_version ->
+           (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+           Virt_mem_mmap.addr ->
+           (string * int) AddrMap.t
+         >>
+    ) xs in
+
+  concat_str_items strs, concat_sig_items sigs
+
+let output_interf ~output_file types offsets parsers followers =
+  (* Some standard code that appears at the top of the interface file. *)
+  let prologue =
+    <:sig_item<
+      module AddrMap : sig
+       type key = Virt_mem_mmap.addr
+       type 'a t = 'a Map.Make(Int64).t
+       val empty : 'a t
+       val is_empty : 'a t -> bool
+       val add : key -> 'a -> 'a t -> 'a t
+       val find : key -> 'a t -> 'a
+       val remove : key -> 'a t -> 'a t
+       val mem : key -> 'a t -> bool
+       val iter : (key -> 'a -> unit) -> 'a t -> unit
+       val map : ('a -> 'b) -> 'a t -> 'b t
+       val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t
+       val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+       val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
+       val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
+      end ;;
+      type kernel_version = string ;;
+    >> in
+
+  let sigs =
+    concat_sig_items [ prologue; types; offsets; parsers; followers ] in
   Printers.OCaml.print_interf ~output_file sigs
 
 (* Finally generate the output files. *)
 let re_subst = Pcre.regexp "^(.*)\"(\\w+_parser_\\d+)\"(.*)$"
 
-let output_implem ~output_file types offsets parsers parser_subs =
-  let new_output_file = output_file ^ ".new" in
+let output_implem ~output_file types offsets parsers parser_subs followers =
+  (* Some standard code that appears at the top of the implementation file. *)
+  let prologue =
+    <:str_item<
+      module StringMap = Map.Make (String) ;;
+      module AddrMap = Map.Make (Int64) ;;
+      type kernel_version = string ;;
+
+      let match_err = "failed to match kernel structure" ;;
+      let struct_missing_err = "struct does not exist in this kernel version" ;;
+
+      let unknown_kernel_version version struct_name =
+       invalid_arg (Printf.sprintf "%s: unknown kernel version or
+struct %s is not supported in this kernel.
+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"
+                      version struct_name) ;;
 
-  let strs = concat_str_items [ types; offsets; parsers ] in
+      let zero = 0 ;;
+    >> in
+
+  let strs =
+    concat_str_items [ prologue; types; offsets; parsers; followers ] in
+
+  (* Write the new implementation to .ml.new file. *)
+  let new_output_file = output_file ^ ".new" in
   Printers.OCaml.print_implem ~output_file:new_output_file strs;
 
   (* Substitute the parser bodies in the output file. *)
index c2e1271..e359647 100644 (file)
@@ -76,12 +76,29 @@ val generate_parsers : (string * Struct_classify.parser_ list) list ->
        by the contents of the returned hash table in {!output_implem}.
     *)
 
+(** {2 Generate followers}
+
+    The "followers" are functions which recursively follow every
+    structure in the kernel, starting out at known root structures
+    such as [init_task] and [init_net].  Their job is to (a) find
+    every kernel structure, (b) ensure it is loaded into our
+    memory map, (c) produce a map of address -> structure.
+*)
+
+val generate_followers :
+  (string * ((Pahole_parser.info * Pahole_parser.structure) list
+            * Struct_classify.shape_field_struct list
+            * Struct_classify.sfhash * Struct_classify.pahash)) list ->
+  code
+  (** [generate_followers] generates the follower functions. *)
+
 (** {2 Output final files} *)
 
 val output_interf : output_file:string ->
   Camlp4.PreCast.Syntax.Ast.sig_item ->
   Camlp4.PreCast.Syntax.Ast.sig_item ->
   Camlp4.PreCast.Syntax.Ast.sig_item ->
+  Camlp4.PreCast.Syntax.Ast.sig_item ->
   unit
   (** Output the interface file. *)
 
@@ -90,5 +107,6 @@ val output_implem : output_file:string ->
   Camlp4.PreCast.Syntax.Ast.str_item ->
   Camlp4.PreCast.Syntax.Ast.str_item ->
   (string, string) Hashtbl.t ->
+  Camlp4.PreCast.Syntax.Ast.str_item ->
   unit
   (** Output the implementation file. *)
index 2f7e89a..4ad221f 100644 (file)
@@ -47,9 +47,9 @@ let good_structs = [
                    "comm"; "pid" ];
     field_metadata = [
       "tasks'next", ListHeadIsReally None;
-      "tasks'prev", ListHeadIsReally None;
+      (*"tasks'prev", ListHeadIsReally None; XXX point to 'next *)
       "run_list'next", ListHeadIsReally None;
-      "run_list'prev", ListHeadIsReally None;
+      (*"run_list'prev", ListHeadIsReally None; XXX point to 'next *)
     ];
   };
   "net_device", {
@@ -59,7 +59,7 @@ let good_structs = [
                    "addr_len" ];
     field_metadata = [
       "dev_list'next", ListHeadIsReally None;
-      "dev_list'prev", ListHeadIsReally None;
+      (*"dev_list'prev", ListHeadIsReally None; XXX point to 'next *)
       "ip_ptr", VoidPointerIsReally "in_device";
       "ip6_ptr", VoidPointerIsReally "inet6_dev";
     ];
@@ -307,7 +307,7 @@ Options:
          fun { SC.sf_name = name; sf_fields = fields } ->
            printf "    type %s = {\n" name;
            List.iter (
-             fun { PP.field_name = name; field_type = typ } ->
+             fun (name, typ) ->
                printf "      %s %s;\n" (PP.string_of_f_type typ) name
            ) fields;
            printf "    }\n";
@@ -318,7 +318,7 @@ Options:
          fun { SC.cf_name = name; cf_fields = fields } ->
            printf "    type %s = {\n" name;
            List.iter (
-             fun { PP.field_name = name; field_type = typ } ->
+             fun (name, typ) ->
                printf "      %s %s;\n" (PP.string_of_f_type typ) name
            ) fields;
            printf "    }\n";
@@ -361,16 +361,23 @@ Options:
       ) structures
     ) in
 
+  let implem_followers, interf_followers =
+    CG.generate_followers (
+      List.map (
+       fun (struct_name, (kernels, _, sflist, sfhash, _, _, _, pahash)) ->
+         (struct_name, (kernels, sflist, sfhash, pahash))
+      ) structures
+    ) in
+
   (* Output the generated code. *)
   let output_file = outputdir // "kernel.mli" in
   printf "Writing kernel data interface to %s ...\n%!" output_file;
   CG.output_interf ~output_file
-    interf_types interf_offsets interf_parsers;
+    interf_types interf_offsets interf_parsers interf_followers;
 
   let output_file = outputdir // "kernel.ml" in
   printf "Writing kernel data parsers to %s ...\n%!" output_file;
   CG.output_implem ~output_file
-    implem_types implem_offsets implem_parsers
-    subst_parsers;
+    implem_types implem_offsets implem_parsers subst_parsers implem_followers;
 
   printf "Finished.\n"
index f8b5bd1..99e36de 100644 (file)
@@ -27,6 +27,7 @@ let (//) = Filename.concat
 type pathname = string
 
 type info = {
+  kv_i : int;
   kernel_version : string;
   arch : string;
   basename : string;
@@ -54,7 +55,7 @@ and f_type =
   | FString of int
 
 let string_of_info i =
-  sprintf "%s: %s %s" i.basename i.kernel_version i.arch
+  sprintf "%s: %s (%d) %s" i.basename i.kernel_version i.kv_i i.arch
 
 let rec string_of_structure s =
   let fields = List.map string_of_field s.struct_fields in
@@ -92,8 +93,8 @@ let list_kernels path =
   (* Parse in the *.info files.  These have historically had a few different
    * formats that we need to support.
    *)
-  let infos = List.map (
-    fun filename ->
+  let infos = List.mapi (
+    fun filename ->
       (* Get the basename (for getting the .data file later on). *)
       let basename = Filename.chop_suffix filename ".info" in
 
@@ -146,7 +147,8 @@ let list_kernels path =
 
       (*printf "%s -> %s %s\n%!" basename version arch;*)
 
-      { basename = basename; arch = arch;
+      { kv_i = i;
+       basename = basename; arch = arch;
        kernel_version = version }
   ) infos in
   infos
index 9c335a7..8444e5f 100644 (file)
@@ -32,6 +32,8 @@ type pathname = string
   (** Path and filenames. *)
 
 type info = {
+  kv_i : int;                         (** Each kernel is given a unique
+                                          number. *)
   kernel_version : string;            (** Kernel version that this matches. *)
   arch : string;                      (** Architecture, eg. "i686", "ppc64". *)
   basename : string;                  (** [basename.info] is the info
index d959a1f..376c301 100644 (file)
@@ -42,13 +42,13 @@ let classify_field names = function
 type shape_field_struct = {
   sf_i : int;
   sf_name : string;
-  sf_fields : PP.field list;
+  sf_fields : (string * PP.f_type) list;
 }
 
 and content_field_struct = {
   cf_i : int;
   cf_name : string;
-  cf_fields : PP.field list;
+  cf_fields : (string * PP.f_type) list;
 }
 
 and parser_ = {
@@ -88,7 +88,7 @@ let unique =
 
 (* Minimization of shape fields & content fields. *)
 
-let cmp { PP.field_name = n1 } { PP.field_name = n2 } = compare n1 n2
+let cmp (n1,_) (n2,_) = compare n1 n2
 
 let hash_values h = Hashtbl.fold (fun _ v vs -> v :: vs) h []
 
@@ -97,9 +97,10 @@ let minimize_shape_field_structs struct_name names kernels =
   let rh = Hashtbl.create 13 in
 
   let only_shape_fields =
-    List.filter (
-      fun { PP.field_type = typ } ->
-       classify_field names typ = ShapeField
+    List.filter_map (
+      fun { PP.field_name = name; field_type = typ } ->
+       if classify_field names typ = ShapeField then Some (name, typ)
+       else None
     )
   in
 
@@ -110,7 +111,7 @@ let minimize_shape_field_structs struct_name names kernels =
         { PP.struct_fields = fields; struct_name = name_check }) ->
       assert (struct_name = name_check);
       let fields = List.sort ~cmp (only_shape_fields fields) in
-      let key = List.map (fun { PP.field_name = name } -> name) fields in
+      let key = List.map fst fields in
       let sf =
        try Hashtbl.find h key
        with Not_found ->
@@ -129,9 +130,10 @@ let minimize_content_field_structs struct_name names kernels =
   let rh = Hashtbl.create 13 in
 
   let only_content_fields =
-    List.filter (
-      fun { PP.field_type = typ } ->
-       classify_field names typ = ContentField
+    List.filter_map (
+      fun { PP.field_name = name; field_type = typ } ->
+       if classify_field names typ = ContentField then Some (name, typ)
+       else None
     )
   in
 
@@ -142,7 +144,7 @@ let minimize_content_field_structs struct_name names kernels =
         { PP.struct_fields = fields; struct_name = name_check }) ->
       assert (struct_name = name_check);
       let fields = List.sort ~cmp (only_content_fields fields) in
-      let key = List.map (fun { PP.field_name = name } -> name) fields in
+      let key = List.map fst fields in
       let cf =
        try Hashtbl.find h key
        with Not_found ->
index 23508d7..b0cd5da 100644 (file)
@@ -107,14 +107,14 @@ val classify_field : string list -> Pahole_parser.f_type -> f_class
 type shape_field_struct = {
   sf_i : int;                          (** Unique number. *)
   sf_name : string;                    (** Structure name in output. *)
-  sf_fields : Pahole_parser.field list;        (** Shape fields. *)
+  sf_fields : (string * Pahole_parser.f_type) list; (** Shape fields. *)
 }
     (** The type of a shape field structure. *)
 
 and content_field_struct = {
   cf_i : int;                          (** Unique number. *)
   cf_name : string;                    (** Structure name in output. *)
-  cf_fields : Pahole_parser.field list; (** Content fields. *)
+  cf_fields : (string * Pahole_parser.f_type) list; (** Content fields. *)
 }
     (** The type of a content field structure. *)
 
index fcca15c..9a29dc0 100644 (file)
@@ -1,6 +1,4 @@
 virt_ifconfig.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmi \
-    ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi \
-    ../lib/kernel_task_struct.cmi 
+    ../lib/virt_mem_gettext.cmo 
 virt_ifconfig.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
-    ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx \
-    ../lib/kernel_task_struct.cmx 
+    ../lib/virt_mem_gettext.cmx 
index 55da968..b423fe3 100644 (file)
@@ -23,6 +23,7 @@ open Virt_mem_gettext.Gettext
 open Virt_mem_utils
 open Virt_mem_types
 
+(*
 open Kernel_task_struct
 
 let run debug { domname = domname; mem = mem } { net_devices = net_devices } =
@@ -46,3 +47,4 @@ virt-ifconfig prints a network interfaces for virtual machines.
 
 let () =
   Virt_mem.register "ifconfig" summary description ~needs_net_devices:true ~run
+*)
index 301269c..3cec6b3 100644 (file)
@@ -1,10 +1,9 @@
+kernel.cmi: virt_mem_mmap.cmi 
 virt_mem_kallsyms.cmi: virt_mem_types.cmi 
 virt_mem_ksyms.cmi: virt_mem_types.cmi 
 virt_mem_list_head.cmi: virt_mem_types.cmi virt_mem_mmap.cmi 
 virt_mem.cmi: virt_mem_types.cmi 
 virt_mem_mmap.cmi: virt_mem_utils.cmo 
-virt_mem_net_devices.cmi: virt_mem_types.cmi 
-virt_mem_tasks.cmi: virt_mem_types.cmi 
 virt_mem_types.cmi: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_utsname.cmi: virt_mem_types.cmi 
 kernel.cmo: virt_mem_types.cmi virt_mem_mmap.cmi kernel.cmi 
@@ -32,25 +31,23 @@ virt_mem_list_head.cmo: virt_mem_utils.cmo virt_mem_types.cmi \
 virt_mem_list_head.cmx: virt_mem_utils.cmx virt_mem_types.cmx \
     virt_mem_mmap.cmx virt_mem_list_head.cmi 
 virt_mem.cmo: virt_mem_version.cmo virt_mem_utsname.cmi virt_mem_utils.cmo \
-    virt_mem_types.cmi virt_mem_tasks.cmi virt_mem_net_devices.cmi \
-    virt_mem_mmap.cmi virt_mem_ksyms.cmi virt_mem_kernels.cmo \
-    virt_mem_kallsyms.cmi virt_mem_gettext.cmo virt_mem.cmi 
+    virt_mem_types.cmi virt_mem_mmap.cmi virt_mem_ksyms.cmi \
+    virt_mem_kernels.cmo virt_mem_kallsyms.cmi virt_mem_gettext.cmo \
+    kernel.cmi virt_mem.cmi 
 virt_mem.cmx: virt_mem_version.cmx virt_mem_utsname.cmx virt_mem_utils.cmx \
-    virt_mem_types.cmx virt_mem_tasks.cmx virt_mem_net_devices.cmx \
-    virt_mem_mmap.cmx virt_mem_ksyms.cmx virt_mem_kernels.cmx \
-    virt_mem_kallsyms.cmx virt_mem_gettext.cmx virt_mem.cmi 
+    virt_mem_types.cmx virt_mem_mmap.cmx virt_mem_ksyms.cmx \
+    virt_mem_kernels.cmx virt_mem_kallsyms.cmx virt_mem_gettext.cmx \
+    kernel.cmx virt_mem.cmi 
 virt_mem_mmap.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi 
 virt_mem_mmap.cmx: virt_mem_utils.cmx virt_mem_mmap.cmi 
 virt_mem_net_devices.cmo: virt_mem_utils.cmo virt_mem_types.cmi \
-    virt_mem_mmap.cmi virt_mem_list_head.cmi virt_mem_gettext.cmo \
-    virt_mem_net_devices.cmi 
+    virt_mem_gettext.cmo virt_mem_net_devices.cmi 
 virt_mem_net_devices.cmx: virt_mem_utils.cmx virt_mem_types.cmx \
-    virt_mem_mmap.cmx virt_mem_list_head.cmx virt_mem_gettext.cmx \
-    virt_mem_net_devices.cmi 
+    virt_mem_gettext.cmx virt_mem_net_devices.cmi 
 virt_mem_tasks.cmo: virt_mem_utils.cmo virt_mem_types.cmi \
-    virt_mem_list_head.cmi virt_mem_gettext.cmo virt_mem_tasks.cmi 
+    virt_mem_gettext.cmo virt_mem_tasks.cmi 
 virt_mem_tasks.cmx: virt_mem_utils.cmx virt_mem_types.cmx \
-    virt_mem_list_head.cmx virt_mem_gettext.cmx virt_mem_tasks.cmi 
+    virt_mem_gettext.cmx virt_mem_tasks.cmi 
 virt_mem_types.cmo: virt_mem_utils.cmo virt_mem_mmap.cmi virt_mem_types.cmi 
 virt_mem_types.cmx: virt_mem_utils.cmx virt_mem_mmap.cmx virt_mem_types.cmi 
 virt_mem_utsname.cmo: virt_mem_utils.cmo virt_mem_types.cmi virt_mem_mmap.cmi \
index b452e1b..e96a542 100644 (file)
@@ -59,12 +59,13 @@ OBJS                = virt_mem_gettext.cmo \
                  virt_mem_ksyms.cmo \
                  virt_mem_kallsyms.cmo \
                  virt_mem_utsname.cmo \
-                 virt_mem_tasks.cmo \
-                 virt_mem_net_devices.cmo \
                  virt_mem.cmo \
                  virt_mem_capture.cmo \
                  virt_mem_dump.cmo
 
+#                virt_mem_tasks.cmo
+#                virt_mem_net_devices.cmo
+
 XOBJS          = $(OBJS:%.cmo=%.cmx)
 
 all:   $(TARGETS)
@@ -75,6 +76,13 @@ virt_mem.cma: $(OBJS)
 virt_mem.cmxa: $(XOBJS)
        ocamlmklib -o virt_mem $^
 
+# The autogenerated code in kernel.ml contains recursive types.
+kernel.cmo: kernel.ml
+       $(OCAMLFIND) ocamlc -rectypes $(OCAMLCFLAGS) $(OCAMLCPACKAGES) -c $<
+
+kernel.cmx: kernel.ml
+       $(OCAMLFIND) ocamlopt -rectypes $(OCAMLOPTFLAGS) $(OCAMLOPTPACKAGES) -c $<
+
 # Just for testing Virt_mem_mmap module:
 test_mmap: virt_mem_utils.cmx virt_mem_mmap_c.o virt_mem_mmap.cmx test_mmap.cmx
        ocamlfind ocamlopt \
index 4ce4b55..d04ef22 100644 (file)
  * that you do 'make update-kernel-structs'.
  *)
 
-type ('a, 'b) task_struct =
-  { task_struct_shape : 'a; task_struct_content : 'b
-  };;
-type task_struct_shape_fields_2 =
-  { task_struct_shape_fields_2_tasks'next : Virt_mem_mmap.addr;
-    task_struct_shape_fields_2_tasks'prev : Virt_mem_mmap.addr
-  };;
+module StringMap = Map.Make(String);;
+module AddrMap = Map.Make(Int64);;
+type kernel_version = string;;
+let match_err = "failed to match kernel structure";;
+let struct_missing_err = "struct does not exist in this kernel version";;
+let unknown_kernel_version version struct_name =
+  invalid_arg
+    (Printf.sprintf
+       "%s: unknown kernel version or
+struct %s is not supported in this kernel.
+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
+"
+       version struct_name);;
+let zero = 0;;
+type ('a, 'b) task_struct = ('a * 'b);;
 type task_struct_shape_fields_1 =
-  { task_struct_shape_fields_1_run_list'next : Virt_mem_mmap.addr;
-    task_struct_shape_fields_1_run_list'prev : Virt_mem_mmap.addr;
-    task_struct_shape_fields_1_tasks'next : Virt_mem_mmap.addr;
-    task_struct_shape_fields_1_tasks'prev : Virt_mem_mmap.addr
-  };;
-type task_struct_content_fields_3 =
-  { task_struct_content_fields_3_comm : string;
-    task_struct_content_fields_3_normal_prio : int64;
-    task_struct_content_fields_3_pid : int64;
-    task_struct_content_fields_3_prio : int64;
-    task_struct_content_fields_3_state : int64;
-    task_struct_content_fields_3_static_prio : int64
+  { task_struct_shape_fields_1_tasks'next : Virt_mem_mmap.addr
   };;
-type ('a, 'b) net_device = { net_device_shape : 'a; net_device_content : 'b };;
-type net_device_shape_fields_12 =
-  { net_device_shape_fields_12_ip6_ptr : Virt_mem_mmap.addr;
-    net_device_shape_fields_12_ip_ptr : Virt_mem_mmap.addr;
-    net_device_shape_fields_12_next : Virt_mem_mmap.addr
+type task_struct_content_fields_2 =
+  { task_struct_content_fields_2_comm : string;
+    task_struct_content_fields_2_normal_prio : int64;
+    task_struct_content_fields_2_pid : int64;
+    task_struct_content_fields_2_prio : int64;
+    task_struct_content_fields_2_state : int64;
+    task_struct_content_fields_2_static_prio : int64;
+    task_struct_content_fields_2_tasks'prev : Virt_mem_mmap.addr
   };;
-type net_device_shape_fields_13 =
-  { net_device_shape_fields_13_dev_list'next : Virt_mem_mmap.addr;
-    net_device_shape_fields_13_dev_list'prev : Virt_mem_mmap.addr;
-    net_device_shape_fields_13_ip6_ptr : Virt_mem_mmap.addr;
-    net_device_shape_fields_13_ip_ptr : Virt_mem_mmap.addr
+type ('a, 'b) net_device = ('a * 'b);;
+type net_device_shape_fields_8 =
+  { net_device_shape_fields_8_dev_list'next : Virt_mem_mmap.addr;
+    net_device_shape_fields_8_ip6_ptr : Virt_mem_mmap.addr;
+    net_device_shape_fields_8_ip_ptr : Virt_mem_mmap.addr
   };;
-type net_device_content_fields_14 =
-  { net_device_content_fields_14_addr_len : int64;
-    net_device_content_fields_14_flags : int64;
-    net_device_content_fields_14_mtu : int64;
-    net_device_content_fields_14_name : string;
-    net_device_content_fields_14_operstate : int64;
-    net_device_content_fields_14_perm_addr : string
+type net_device_content_fields_9 =
+  { net_device_content_fields_9_addr_len : int64;
+    net_device_content_fields_9_dev_list'prev : Virt_mem_mmap.addr;
+    net_device_content_fields_9_flags : int64;
+    net_device_content_fields_9_mtu : int64;
+    net_device_content_fields_9_name : string;
+    net_device_content_fields_9_operstate : int64;
+    net_device_content_fields_9_perm_addr : string
   };;
-type ('a, 'b) net = { net_shape : 'a; net_content : 'b };;
-type net_shape_fields_22 =
-  { net_shape_fields_22_dev_base_head'next : Virt_mem_mmap.addr;
-    net_shape_fields_22_dev_base_head'prev : Virt_mem_mmap.addr
+type ('a, 'b) net = ('a * 'b);;
+type net_shape_fields_14 =
+  { net_shape_fields_14_dev_base_head'next : Virt_mem_mmap.addr;
+    net_shape_fields_14_dev_base_head'prev : Virt_mem_mmap.addr
   };;
-type net_content_fields_23 = unit;;
-type ('a, 'b) in_device = { in_device_shape : 'a; in_device_content : 'b };;
-type in_device_shape_fields_28 =
-  { in_device_shape_fields_28_ifa_list : Virt_mem_mmap.addr
+type net_content_fields_15 = unit;;
+type ('a, 'b) in_device = ('a * 'b);;
+type in_device_shape_fields_20 =
+  { in_device_shape_fields_20_ifa_list : Virt_mem_mmap.addr
   };;
-type in_device_content_fields_29 = unit;;
-type ('a, 'b) inet6_dev = { inet6_dev_shape : 'a; inet6_dev_content : 'b };;
-type inet6_dev_shape_fields_34 =
-  { inet6_dev_shape_fields_34_addr_list : Virt_mem_mmap.addr
+type in_device_content_fields_21 = unit;;
+type ('a, 'b) inet6_dev = ('a * 'b);;
+type inet6_dev_shape_fields_26 =
+  { inet6_dev_shape_fields_26_addr_list : Virt_mem_mmap.addr
   };;
-type inet6_dev_content_fields_35 = unit;;
-type ('a, 'b) in_ifaddr = { in_ifaddr_shape : 'a; in_ifaddr_content : 'b };;
-type in_ifaddr_shape_fields_40 =
-  { in_ifaddr_shape_fields_40_ifa_next : Virt_mem_mmap.addr
+type inet6_dev_content_fields_27 = unit;;
+type ('a, 'b) in_ifaddr = ('a * 'b);;
+type in_ifaddr_shape_fields_32 =
+  { in_ifaddr_shape_fields_32_ifa_next : Virt_mem_mmap.addr
   };;
-type in_ifaddr_content_fields_41 =
-  { in_ifaddr_content_fields_41_ifa_address : int64;
-    in_ifaddr_content_fields_41_ifa_broadcast : int64;
-    in_ifaddr_content_fields_41_ifa_local : int64;
-    in_ifaddr_content_fields_41_ifa_mask : int64
+type in_ifaddr_content_fields_33 =
+  { in_ifaddr_content_fields_33_ifa_address : int64;
+    in_ifaddr_content_fields_33_ifa_broadcast : int64;
+    in_ifaddr_content_fields_33_ifa_local : int64;
+    in_ifaddr_content_fields_33_ifa_mask : int64
   };;
-type ('a, 'b) inet6_ifaddr =
-  { inet6_ifaddr_shape : 'a; inet6_ifaddr_content : 'b
+type ('a, 'b) inet6_ifaddr = ('a * 'b);;
+type inet6_ifaddr_shape_fields_38 =
+  { inet6_ifaddr_shape_fields_38_lst_next : Virt_mem_mmap.addr
   };;
-type inet6_ifaddr_shape_fields_46 =
-  { inet6_ifaddr_shape_fields_46_lst_next : Virt_mem_mmap.addr
+type inet6_ifaddr_content_fields_39 =
+  { inet6_ifaddr_content_fields_39_prefix_len : int64
   };;
-type inet6_ifaddr_content_fields_47 =
-  { inet6_ifaddr_content_fields_47_prefix_len : int64
-  };;
-module StringMap = Map.Make(String);;
 let offset_of_net_device_dev_list'next =
   let map =
-    StringMap.add "2.6.27-0.226.rc1.git5.fc10.ppc" 48
-      (StringMap.add "2.6.26.1-9.fc9.ppc64" 72
-         (StringMap.add "2.6.25.14-69.fc8.x86_64" 72
-            (StringMap.add "2.6.24-0.167.rc8.git4.fc9.ppc64" 72
-               (StringMap.add "2.6.22-0.23.rc7.git6.fc8.ppc" 48 StringMap.
-                  empty))))
+    StringMap.add "2.6.25.14-69.fc8.i686" 48
+      (StringMap.add "2.6.25.14-108.fc9.ppc" 48
+         (StringMap.add "2.6.25.11-97.fc9.i686" 48
+            (StringMap.add "2.6.25.14-69.fc8.ppc64" 72
+               (StringMap.add "2.6.25.14-69.fc8.i586" 48
+                  (StringMap.add "2.6.25.11-97.fc9.x86_64" 72
+                     (StringMap.add "2.6.25.14-108.fc9.x86_64" 72
+                        (StringMap.add "2.6.25.14-69.fc8.ppc" 48
+                           (StringMap.add "2.6.25.14-108.fc9.i686" 48
+                              (StringMap.add "2.6.25.14-108.fc9.i586" 48
+                                 (StringMap.add "2.6.25.14-108.fc9.ppc64" 72
+                                    (StringMap.add "2.6.25.14-69.fc8.x86_64"
+                                       72 StringMap.empty)))))))))))
   in fun kernel_version -> StringMap.find kernel_version map;;
-let match_err = "failed to match kernel structure";;
-let zero = 0;;
+let task_struct_parser_3 kernel_version bits = 
+  bitmatch bits with
+  | { state : zero+64 : offset(0), littleendian;
+      prio : zero+32 : offset(224), littleendian;
+      static_prio : zero+32 : offset(256), littleendian;
+      normal_prio : zero+32 : offset(288), littleendian;
+      tasks'next : zero+64 : offset(3840), littleendian;
+      tasks'prev : zero+64 : offset(3904), littleendian;
+      pid : zero+32 : offset(4352), littleendian;
+      comm : 128 : offset(8392), string } ->
+      let s =
+      { task_struct_shape_fields_1_tasks'next = (if tasks'next <> 0L then Int64.sub tasks'next 480L else tasks'next) } in
+      let c =
+      { task_struct_content_fields_2_comm = comm;
+        task_struct_content_fields_2_normal_prio = normal_prio;
+        task_struct_content_fields_2_pid = pid;
+        task_struct_content_fields_2_prio = prio;
+        task_struct_content_fields_2_state = state;
+        task_struct_content_fields_2_static_prio = static_prio;
+        task_struct_content_fields_2_tasks'prev = tasks'prev } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_3", match_err));;
 let task_struct_parser_4 kernel_version bits = 
   bitmatch bits with
-  | { state : zero+32 : offset(0), littleendian;
-      prio : zero+32 : offset(192), littleendian;
-      static_prio : zero+32 : offset(224), littleendian;
-      normal_prio : zero+32 : offset(256), littleendian;
-      run_list'next : zero+32 : offset(288), littleendian;
-      run_list'prev : zero+32 : offset(320), littleendian;
-      tasks'next : zero+32 : offset(992), littleendian;
-      tasks'prev : zero+32 : offset(1024), littleendian;
-      pid : zero+32 : offset(1344), littleendian;
-      comm : 128 : offset(3232), string } ->
-      let shape =
-      { task_struct_shape_fields_1_run_list'next = Int64.sub run_list'next 36L;
-        task_struct_shape_fields_1_run_list'prev = Int64.sub run_list'prev 40L;
-        task_struct_shape_fields_1_tasks'next = Int64.sub tasks'next 124L;
-        task_struct_shape_fields_1_tasks'prev = Int64.sub tasks'prev 128L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
+  | { state : zero+64 : offset(0), bigendian;
+      prio : zero+32 : offset(224), bigendian;
+      static_prio : zero+32 : offset(256), bigendian;
+      normal_prio : zero+32 : offset(288), bigendian;
+      tasks'next : zero+64 : offset(3840), bigendian;
+      tasks'prev : zero+64 : offset(3904), bigendian;
+      pid : zero+32 : offset(4352), bigendian;
+      comm : 128 : offset(8392), string } ->
+      let s =
+      { task_struct_shape_fields_1_tasks'next = (if tasks'next <> 0L then Int64.sub tasks'next 480L else tasks'next) } in
+      let c =
+      { task_struct_content_fields_2_comm = comm;
+        task_struct_content_fields_2_normal_prio = normal_prio;
+        task_struct_content_fields_2_pid = pid;
+        task_struct_content_fields_2_prio = prio;
+        task_struct_content_fields_2_state = state;
+        task_struct_content_fields_2_static_prio = static_prio;
+        task_struct_content_fields_2_tasks'prev = tasks'prev } in
+      (s, c)
   | { _ } ->
       raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_4", match_err));;
 let task_struct_parser_5 kernel_version bits = 
   bitmatch bits with
-  | { state : zero+64 : offset(0), bigendian;
-      prio : zero+32 : offset(320), bigendian;
-      static_prio : zero+32 : offset(352), bigendian;
-      normal_prio : zero+32 : offset(384), bigendian;
-      run_list'next : zero+64 : offset(448), bigendian;
-      run_list'prev : zero+64 : offset(512), bigendian;
-      tasks'next : zero+64 : offset(1600), bigendian;
-      tasks'prev : zero+64 : offset(1664), bigendian;
-      pid : zero+32 : offset(2208), bigendian;
-      comm : 128 : offset(5440), string } ->
-      let shape =
-      { task_struct_shape_fields_1_run_list'next = Int64.sub run_list'next 36L;
-        task_struct_shape_fields_1_run_list'prev = Int64.sub run_list'prev 40L;
-        task_struct_shape_fields_1_tasks'next = Int64.sub tasks'next 124L;
-        task_struct_shape_fields_1_tasks'prev = Int64.sub tasks'prev 128L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
+  | { state : zero+32 : offset(0), littleendian;
+      prio : zero+32 : offset(160), littleendian;
+      static_prio : zero+32 : offset(192), littleendian;
+      normal_prio : zero+32 : offset(224), littleendian;
+      tasks'next : zero+32 : offset(3200), littleendian;
+      tasks'prev : zero+32 : offset(3232), littleendian;
+      pid : zero+32 : offset(3552), littleendian;
+      comm : 128 : offset(5896), string } ->
+      let s =
+      { task_struct_shape_fields_1_tasks'next = (if tasks'next <> 0L then Int64.sub tasks'next 400L else tasks'next) } in
+      let c =
+      { task_struct_content_fields_2_comm = comm;
+        task_struct_content_fields_2_normal_prio = normal_prio;
+        task_struct_content_fields_2_pid = pid;
+        task_struct_content_fields_2_prio = prio;
+        task_struct_content_fields_2_state = state;
+        task_struct_content_fields_2_static_prio = static_prio;
+        task_struct_content_fields_2_tasks'prev = tasks'prev } in
+      (s, c)
   | { _ } ->
       raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_5", match_err));;
 let task_struct_parser_6 kernel_version bits = 
   bitmatch bits with
-  | { state : zero+64 : offset(0), littleendian;
-      prio : zero+32 : offset(320), littleendian;
-      static_prio : zero+32 : offset(352), littleendian;
-      normal_prio : zero+32 : offset(384), littleendian;
-      run_list'next : zero+64 : offset(448), littleendian;
-      run_list'prev : zero+64 : offset(512), littleendian;
-      tasks'next : zero+64 : offset(1536), littleendian;
-      tasks'prev : zero+64 : offset(1600), littleendian;
-      pid : zero+32 : offset(2144), littleendian;
-      comm : 128 : offset(5440), string } ->
-      let shape =
-      { task_struct_shape_fields_1_run_list'next = Int64.sub run_list'next 36L;
-        task_struct_shape_fields_1_run_list'prev = Int64.sub run_list'prev 40L;
-        task_struct_shape_fields_1_tasks'next = Int64.sub tasks'next 124L;
-        task_struct_shape_fields_1_tasks'prev = Int64.sub tasks'prev 128L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
+  | { state : zero+32 : offset(0), littleendian;
+      prio : zero+32 : offset(160), littleendian;
+      static_prio : zero+32 : offset(192), littleendian;
+      normal_prio : zero+32 : offset(224), littleendian;
+      tasks'next : zero+32 : offset(3232), littleendian;
+      tasks'prev : zero+32 : offset(3264), littleendian;
+      pid : zero+32 : offset(3584), littleendian;
+      comm : 128 : offset(5928), string } ->
+      let s =
+      { task_struct_shape_fields_1_tasks'next = (if tasks'next <> 0L then Int64.sub tasks'next 404L else tasks'next) } in
+      let c =
+      { task_struct_content_fields_2_comm = comm;
+        task_struct_content_fields_2_normal_prio = normal_prio;
+        task_struct_content_fields_2_pid = pid;
+        task_struct_content_fields_2_prio = prio;
+        task_struct_content_fields_2_state = state;
+        task_struct_content_fields_2_static_prio = static_prio;
+        task_struct_content_fields_2_tasks'prev = tasks'prev } in
+      (s, c)
   | { _ } ->
       raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_6", match_err));;
 let task_struct_parser_7 kernel_version bits = 
@@ -182,226 +198,51 @@ let task_struct_parser_7 kernel_version bits =
       prio : zero+32 : offset(160), bigendian;
       static_prio : zero+32 : offset(192), bigendian;
       normal_prio : zero+32 : offset(224), bigendian;
-      run_list'next : zero+32 : offset(256), bigendian;
-      run_list'prev : zero+32 : offset(288), bigendian;
-      tasks'next : zero+32 : offset(2176), bigendian;
-      tasks'prev : zero+32 : offset(2208), bigendian;
-      pid : zero+32 : offset(2528), bigendian;
-      comm : 128 : offset(4416), string } ->
-      let shape =
-      { task_struct_shape_fields_1_run_list'next = Int64.sub run_list'next 36L;
-        task_struct_shape_fields_1_run_list'prev = Int64.sub run_list'prev 40L;
-        task_struct_shape_fields_1_tasks'next = Int64.sub tasks'next 124L;
-        task_struct_shape_fields_1_tasks'prev = Int64.sub tasks'prev 128L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
+      tasks'next : zero+32 : offset(3328), bigendian;
+      tasks'prev : zero+32 : offset(3360), bigendian;
+      pid : zero+32 : offset(3680), bigendian;
+      comm : 128 : offset(6056), string } ->
+      let s =
+      { task_struct_shape_fields_1_tasks'next = (if tasks'next <> 0L then Int64.sub tasks'next 416L else tasks'next) } in
+      let c =
+      { task_struct_content_fields_2_comm = comm;
+        task_struct_content_fields_2_normal_prio = normal_prio;
+        task_struct_content_fields_2_pid = pid;
+        task_struct_content_fields_2_prio = prio;
+        task_struct_content_fields_2_state = state;
+        task_struct_content_fields_2_static_prio = static_prio;
+        task_struct_content_fields_2_tasks'prev = tasks'prev } in
+      (s, c)
   | { _ } ->
       raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_7", match_err));;
-let task_struct_parser_8 kernel_version bits = 
-  bitmatch bits with
-  | { state : zero+64 : offset(0), bigendian;
-      prio : zero+32 : offset(224), bigendian;
-      static_prio : zero+32 : offset(256), bigendian;
-      normal_prio : zero+32 : offset(288), bigendian;
-      run_list'next : zero+64 : offset(320), bigendian;
-      run_list'prev : zero+64 : offset(384), bigendian;
-      tasks'next : zero+64 : offset(3648), bigendian;
-      tasks'prev : zero+64 : offset(3712), bigendian;
-      pid : zero+32 : offset(4160), bigendian;
-      comm : 128 : offset(7752), string } ->
-      let shape =
-      { task_struct_shape_fields_1_run_list'next = Int64.sub run_list'next 36L;
-        task_struct_shape_fields_1_run_list'prev = Int64.sub run_list'prev 40L;
-        task_struct_shape_fields_1_tasks'next = Int64.sub tasks'next 124L;
-        task_struct_shape_fields_1_tasks'prev = Int64.sub tasks'prev 128L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_8", match_err));;
-let task_struct_parser_9 kernel_version bits = 
-  bitmatch bits with
-  | { state : zero+64 : offset(0), littleendian;
-      prio : zero+32 : offset(224), littleendian;
-      static_prio : zero+32 : offset(256), littleendian;
-      normal_prio : zero+32 : offset(288), littleendian;
-      tasks'next : zero+64 : offset(3840), littleendian;
-      tasks'prev : zero+64 : offset(3904), littleendian;
-      pid : zero+32 : offset(4352), littleendian;
-      comm : 128 : offset(8392), string } ->
-      let shape =
-      { task_struct_shape_fields_2_tasks'next = Int64.sub tasks'next 480L;
-        task_struct_shape_fields_2_tasks'prev = Int64.sub tasks'prev 488L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_9", match_err));;
-let task_struct_parser_10 kernel_version bits = 
-  bitmatch bits with
-  | { state : zero+64 : offset(0), bigendian;
-      prio : zero+32 : offset(256), bigendian;
-      static_prio : zero+32 : offset(288), bigendian;
-      normal_prio : zero+32 : offset(320), bigendian;
-      tasks'next : zero+64 : offset(4096), bigendian;
-      tasks'prev : zero+64 : offset(4160), bigendian;
-      pid : zero+32 : offset(4608), bigendian;
-      comm : 128 : offset(8712), string } ->
-      let shape =
-      { task_struct_shape_fields_2_tasks'next = Int64.sub tasks'next 480L;
-        task_struct_shape_fields_2_tasks'prev = Int64.sub tasks'prev 488L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_10", match_err));;
-let task_struct_parser_11 kernel_version bits = 
-  bitmatch bits with
-  | { state : zero+32 : offset(0), bigendian;
-      prio : zero+32 : offset(192), bigendian;
-      static_prio : zero+32 : offset(224), bigendian;
-      normal_prio : zero+32 : offset(256), bigendian;
-      tasks'next : zero+32 : offset(3712), bigendian;
-      tasks'prev : zero+32 : offset(3744), bigendian;
-      pid : zero+32 : offset(4064), bigendian;
-      comm : 128 : offset(6464), string } ->
-      let shape =
-      { task_struct_shape_fields_2_tasks'next = Int64.sub tasks'next 480L;
-        task_struct_shape_fields_2_tasks'prev = Int64.sub tasks'prev 488L } in
-      let content =
-      { task_struct_content_fields_3_comm = comm;
-        task_struct_content_fields_3_normal_prio = normal_prio;
-        task_struct_content_fields_3_pid = pid;
-        task_struct_content_fields_3_prio = prio;
-        task_struct_content_fields_3_state = state;
-        task_struct_content_fields_3_static_prio = static_prio } in
-      { task_struct_shape = shape; task_struct_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("task_struct", "task_struct_parser_11", match_err));;
-let net_device_parser_15 kernel_version bits = 
+let net_device_parser_10 kernel_version bits = 
   bitmatch bits with
   | { name : 128 : offset(0), string;
-      next : zero+32 : offset(384), littleendian;
-      flags : zero+32 : offset(704), littleendian;
-      operstate : zero+8 : offset(784), littleendian;
-      mtu : zero+32 : offset(800), littleendian;
-      perm_addr : 256 : offset(896), string;
-      addr_len : zero+8 : offset(1152), littleendian;
-      ip_ptr : zero+32 : offset(1344), littleendian;
-      ip6_ptr : zero+32 : offset(1408), littleendian } ->
-      let shape =
-      { net_device_shape_fields_12_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_12_ip_ptr = ip_ptr;
-        net_device_shape_fields_12_next = next } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_15", match_err));;
-let net_device_parser_16 kernel_version bits = 
-  bitmatch bits with
-  | { name : 128 : offset(0), string;
-      next : zero+64 : offset(576), bigendian;
-      flags : zero+32 : offset(1152), bigendian;
-      operstate : zero+8 : offset(1232), bigendian;
-      mtu : zero+32 : offset(1248), bigendian;
-      perm_addr : 256 : offset(1408), string;
-      addr_len : zero+8 : offset(1664), bigendian;
-      ip_ptr : zero+64 : offset(1984), bigendian;
-      ip6_ptr : zero+64 : offset(2112), bigendian } ->
-      let shape =
-      { net_device_shape_fields_12_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_12_ip_ptr = ip_ptr;
-        net_device_shape_fields_12_next = next } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_16", match_err));;
-let net_device_parser_17 kernel_version bits = 
-  bitmatch bits with
-  | { name : 128 : offset(0), string;
-      next : zero+64 : offset(576), littleendian;
-      flags : zero+32 : offset(1152), littleendian;
-      operstate : zero+8 : offset(1232), littleendian;
-      mtu : zero+32 : offset(1248), littleendian;
-      perm_addr : 256 : offset(1408), string;
-      addr_len : zero+8 : offset(1664), littleendian;
-      ip_ptr : zero+64 : offset(1984), littleendian;
-      ip6_ptr : zero+64 : offset(2112), littleendian } ->
-      let shape =
-      { net_device_shape_fields_12_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_12_ip_ptr = ip_ptr;
-        net_device_shape_fields_12_next = next } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_17", match_err));;
-let net_device_parser_18 kernel_version bits = 
-  bitmatch bits with
-  | { name : 128 : offset(0), string;
-      dev_list'next : zero+32 : offset(384), bigendian;
-      dev_list'prev : zero+32 : offset(416), bigendian;
-      flags : zero+32 : offset(1472), bigendian;
-      operstate : zero+8 : offset(1552), bigendian;
-      mtu : zero+32 : offset(1568), bigendian;
-      perm_addr : 256 : offset(1664), string;
-      addr_len : zero+8 : offset(1920), bigendian;
-      ip_ptr : zero+32 : offset(2112), bigendian;
-      ip6_ptr : zero+32 : offset(2176), bigendian } ->
-      let shape =
-      { net_device_shape_fields_13_dev_list'next = Int64.sub dev_list'next 48L;
-        net_device_shape_fields_13_dev_list'prev = Int64.sub dev_list'prev 52L;
-        net_device_shape_fields_13_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_13_ip_ptr = ip_ptr } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_18", match_err));;
-let net_device_parser_19 kernel_version bits = 
+      dev_list'next : zero+64 : offset(576), littleendian;
+      dev_list'prev : zero+64 : offset(640), littleendian;
+      flags : zero+32 : offset(2880), littleendian;
+      operstate : zero+8 : offset(2960), littleendian;
+      mtu : zero+32 : offset(2976), littleendian;
+      perm_addr : 256 : offset(3136), string;
+      addr_len : zero+8 : offset(3392), littleendian;
+      ip_ptr : zero+64 : offset(3840), littleendian;
+      ip6_ptr : zero+64 : offset(3968), littleendian } ->
+      let s =
+      { net_device_shape_fields_8_dev_list'next = (if dev_list'next <> 0L then Int64.sub dev_list'next 72L else dev_list'next);
+        net_device_shape_fields_8_ip6_ptr = ip6_ptr;
+        net_device_shape_fields_8_ip_ptr = ip_ptr } in
+      let c =
+      { net_device_content_fields_9_addr_len = addr_len;
+        net_device_content_fields_9_dev_list'prev = dev_list'prev;
+        net_device_content_fields_9_flags = flags;
+        net_device_content_fields_9_mtu = mtu;
+        net_device_content_fields_9_name = name;
+        net_device_content_fields_9_operstate = operstate;
+        net_device_content_fields_9_perm_addr = perm_addr } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_10", match_err));;
+let net_device_parser_11 kernel_version bits = 
   bitmatch bits with
   | { name : 128 : offset(0), string;
       dev_list'next : zero+64 : offset(576), bigendian;
@@ -413,377 +254,766 @@ let net_device_parser_19 kernel_version bits =
       addr_len : zero+8 : offset(3392), bigendian;
       ip_ptr : zero+64 : offset(3840), bigendian;
       ip6_ptr : zero+64 : offset(3968), bigendian } ->
-      let shape =
-      { net_device_shape_fields_13_dev_list'next = Int64.sub dev_list'next 48L;
-        net_device_shape_fields_13_dev_list'prev = Int64.sub dev_list'prev 52L;
-        net_device_shape_fields_13_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_13_ip_ptr = ip_ptr } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_19", match_err));;
-let net_device_parser_20 kernel_version bits = 
+      let s =
+      { net_device_shape_fields_8_dev_list'next = (if dev_list'next <> 0L then Int64.sub dev_list'next 72L else dev_list'next);
+        net_device_shape_fields_8_ip6_ptr = ip6_ptr;
+        net_device_shape_fields_8_ip_ptr = ip_ptr } in
+      let c =
+      { net_device_content_fields_9_addr_len = addr_len;
+        net_device_content_fields_9_dev_list'prev = dev_list'prev;
+        net_device_content_fields_9_flags = flags;
+        net_device_content_fields_9_mtu = mtu;
+        net_device_content_fields_9_name = name;
+        net_device_content_fields_9_operstate = operstate;
+        net_device_content_fields_9_perm_addr = perm_addr } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_11", match_err));;
+let net_device_parser_12 kernel_version bits = 
   bitmatch bits with
   | { name : 128 : offset(0), string;
-      dev_list'next : zero+64 : offset(576), littleendian;
-      dev_list'prev : zero+64 : offset(640), littleendian;
-      flags : zero+32 : offset(2880), littleendian;
-      operstate : zero+8 : offset(2960), littleendian;
-      mtu : zero+32 : offset(2976), littleendian;
-      perm_addr : 256 : offset(3136), string;
-      addr_len : zero+8 : offset(3392), littleendian;
-      ip_ptr : zero+64 : offset(3840), littleendian;
-      ip6_ptr : zero+64 : offset(3968), littleendian } ->
-      let shape =
-      { net_device_shape_fields_13_dev_list'next = Int64.sub dev_list'next 48L;
-        net_device_shape_fields_13_dev_list'prev = Int64.sub dev_list'prev 52L;
-        net_device_shape_fields_13_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_13_ip_ptr = ip_ptr } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_20", match_err));;
-let net_device_parser_21 kernel_version bits = 
+      dev_list'next : zero+32 : offset(384), littleendian;
+      dev_list'prev : zero+32 : offset(416), littleendian;
+      flags : zero+32 : offset(1568), littleendian;
+      operstate : zero+8 : offset(1648), littleendian;
+      mtu : zero+32 : offset(1664), littleendian;
+      perm_addr : 256 : offset(1760), string;
+      addr_len : zero+8 : offset(2016), littleendian;
+      ip_ptr : zero+32 : offset(2304), littleendian;
+      ip6_ptr : zero+32 : offset(2368), littleendian } ->
+      let s =
+      { net_device_shape_fields_8_dev_list'next = (if dev_list'next <> 0L then Int64.sub dev_list'next 48L else dev_list'next);
+        net_device_shape_fields_8_ip6_ptr = ip6_ptr;
+        net_device_shape_fields_8_ip_ptr = ip_ptr } in
+      let c =
+      { net_device_content_fields_9_addr_len = addr_len;
+        net_device_content_fields_9_dev_list'prev = dev_list'prev;
+        net_device_content_fields_9_flags = flags;
+        net_device_content_fields_9_mtu = mtu;
+        net_device_content_fields_9_name = name;
+        net_device_content_fields_9_operstate = operstate;
+        net_device_content_fields_9_perm_addr = perm_addr } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_12", match_err));;
+let net_device_parser_13 kernel_version bits = 
   bitmatch bits with
   | { name : 128 : offset(0), string;
       dev_list'next : zero+32 : offset(384), bigendian;
       dev_list'prev : zero+32 : offset(416), bigendian;
-      flags : zero+32 : offset(1536), bigendian;
-      operstate : zero+8 : offset(1616), bigendian;
-      mtu : zero+32 : offset(1632), bigendian;
+      flags : zero+32 : offset(1568), bigendian;
+      operstate : zero+8 : offset(1648), bigendian;
+      mtu : zero+32 : offset(1664), bigendian;
       perm_addr : 256 : offset(1760), string;
       addr_len : zero+8 : offset(2016), bigendian;
-      ip_ptr : zero+32 : offset(2432), bigendian;
-      ip6_ptr : zero+32 : offset(2496), bigendian } ->
-      let shape =
-      { net_device_shape_fields_13_dev_list'next = Int64.sub dev_list'next 48L;
-        net_device_shape_fields_13_dev_list'prev = Int64.sub dev_list'prev 52L;
-        net_device_shape_fields_13_ip6_ptr = ip6_ptr;
-        net_device_shape_fields_13_ip_ptr = ip_ptr } in
-      let content =
-      { net_device_content_fields_14_addr_len = addr_len;
-        net_device_content_fields_14_flags = flags;
-        net_device_content_fields_14_mtu = mtu;
-        net_device_content_fields_14_name = name;
-        net_device_content_fields_14_operstate = operstate;
-        net_device_content_fields_14_perm_addr = perm_addr } in
-      { net_device_shape = shape; net_device_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_21", match_err));;
-let net_parser_24 kernel_version bits = 
-  bitmatch bits with
-  | { dev_base_head'next : zero+64 : offset(704), bigendian;
-      dev_base_head'prev : zero+64 : offset(768), bigendian } ->
-      let shape =
-      { net_shape_fields_22_dev_base_head'next = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'next offset
+      ip_ptr : zero+32 : offset(2304), bigendian;
+      ip6_ptr : zero+32 : offset(2368), bigendian } ->
+      let s =
+      { net_device_shape_fields_8_dev_list'next = (if dev_list'next <> 0L then Int64.sub dev_list'next 48L else dev_list'next);
+        net_device_shape_fields_8_ip6_ptr = ip6_ptr;
+        net_device_shape_fields_8_ip_ptr = ip_ptr } in
+      let c =
+      { net_device_content_fields_9_addr_len = addr_len;
+        net_device_content_fields_9_dev_list'prev = dev_list'prev;
+        net_device_content_fields_9_flags = flags;
+        net_device_content_fields_9_mtu = mtu;
+        net_device_content_fields_9_name = name;
+        net_device_content_fields_9_operstate = operstate;
+        net_device_content_fields_9_perm_addr = perm_addr } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("net_device", "net_device_parser_13", match_err));;
+let net_parser_18 kernel_version bits = 
+  bitmatch bits with
+  | { dev_base_head'next : zero+32 : offset(416), littleendian;
+      dev_base_head'prev : zero+32 : offset(448), littleendian } ->
+      let s =
+      { net_shape_fields_14_dev_base_head'next = (
+                      if dev_base_head'next <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'next offset
+                      ) else dev_base_head'next
                     );
-        net_shape_fields_22_dev_base_head'prev = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'prev offset
+        net_shape_fields_14_dev_base_head'prev = (
+                      if dev_base_head'prev <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'prev offset
+                      ) else dev_base_head'prev
                     ) } in
-      let content =
+      let c =
       () in
-      { net_shape = shape; net_content = content }
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("net", "net_parser_18", match_err));;
+let net_parser_19 kernel_version bits = 
+  bitmatch bits with
+  | { dev_base_head'next : zero+32 : offset(416), bigendian;
+      dev_base_head'prev : zero+32 : offset(448), bigendian } ->
+      let s =
+      { net_shape_fields_14_dev_base_head'next = (
+                      if dev_base_head'next <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'next offset
+                      ) else dev_base_head'next
+                    );
+        net_shape_fields_14_dev_base_head'prev = (
+                      if dev_base_head'prev <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'prev offset
+                      ) else dev_base_head'prev
+                    ) } in
+      let c =
+      () in
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("net", "net_parser_24", match_err));;
-let net_parser_25 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("net", "net_parser_19", match_err));;
+let net_parser_16 kernel_version bits = 
   bitmatch bits with
   | { dev_base_head'next : zero+64 : offset(768), littleendian;
       dev_base_head'prev : zero+64 : offset(832), littleendian } ->
-      let shape =
-      { net_shape_fields_22_dev_base_head'next = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'next offset
+      let s =
+      { net_shape_fields_14_dev_base_head'next = (
+                      if dev_base_head'next <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'next offset
+                      ) else dev_base_head'next
                     );
-        net_shape_fields_22_dev_base_head'prev = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'prev offset
+        net_shape_fields_14_dev_base_head'prev = (
+                      if dev_base_head'prev <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'prev offset
+                      ) else dev_base_head'prev
                     ) } in
-      let content =
+      let c =
       () in
-      { net_shape = shape; net_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("net", "net_parser_25", match_err));;
-let net_parser_26 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("net", "net_parser_16", match_err));;
+let net_parser_17 kernel_version bits = 
   bitmatch bits with
   | { dev_base_head'next : zero+64 : offset(768), bigendian;
       dev_base_head'prev : zero+64 : offset(832), bigendian } ->
-      let shape =
-      { net_shape_fields_22_dev_base_head'next = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'next offset
-                    );
-        net_shape_fields_22_dev_base_head'prev = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'prev offset
-                    ) } in
-      let content =
-      () in
-      { net_shape = shape; net_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("net", "net_parser_26", match_err));;
-let net_parser_27 kernel_version bits = 
-  bitmatch bits with
-  | { dev_base_head'next : zero+32 : offset(448), bigendian;
-      dev_base_head'prev : zero+32 : offset(480), bigendian } ->
-      let shape =
-      { net_shape_fields_22_dev_base_head'next = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'next offset
+      let s =
+      { net_shape_fields_14_dev_base_head'next = (
+                      if dev_base_head'next <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'next offset
+                      ) else dev_base_head'next
                     );
-        net_shape_fields_22_dev_base_head'prev = (
-                      let offset = offset_of_net_device_dev_list'next kernel_version in
-                      let offset = Int64.of_int offset in
-                      Int64.sub dev_base_head'prev offset
+        net_shape_fields_14_dev_base_head'prev = (
+                      if dev_base_head'prev <> 0L then (
+                        let offset = offset_of_net_device_dev_list'next kernel_version in
+                        let offset = Int64.of_int offset in
+                        Int64.sub dev_base_head'prev offset
+                      ) else dev_base_head'prev
                     ) } in
-      let content =
+      let c =
       () in
-      { net_shape = shape; net_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("net", "net_parser_27", match_err));;
-let in_device_parser_30 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("net", "net_parser_17", match_err));;
+let in_device_parser_24 kernel_version bits = 
   bitmatch bits with
   | { ifa_list : zero+32 : offset(96), littleendian } ->
-      let shape =
-      { in_device_shape_fields_28_ifa_list = ifa_list } in
-      let content =
+      let s =
+      { in_device_shape_fields_20_ifa_list = ifa_list } in
+      let c =
       () in
-      { in_device_shape = shape; in_device_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_30", match_err));;
-let in_device_parser_33 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_24", match_err));;
+let in_device_parser_25 kernel_version bits = 
   bitmatch bits with
   | { ifa_list : zero+32 : offset(96), bigendian } ->
-      let shape =
-      { in_device_shape_fields_28_ifa_list = ifa_list } in
-      let content =
+      let s =
+      { in_device_shape_fields_20_ifa_list = ifa_list } in
+      let c =
       () in
-      { in_device_shape = shape; in_device_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_33", match_err));;
-let in_device_parser_32 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_25", match_err));;
+let in_device_parser_22 kernel_version bits = 
   bitmatch bits with
   | { ifa_list : zero+64 : offset(128), littleendian } ->
-      let shape =
-      { in_device_shape_fields_28_ifa_list = ifa_list } in
-      let content =
+      let s =
+      { in_device_shape_fields_20_ifa_list = ifa_list } in
+      let c =
       () in
-      { in_device_shape = shape; in_device_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_32", match_err));;
-let in_device_parser_31 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_22", match_err));;
+let in_device_parser_23 kernel_version bits = 
   bitmatch bits with
   | { ifa_list : zero+64 : offset(128), bigendian } ->
-      let shape =
-      { in_device_shape_fields_28_ifa_list = ifa_list } in
-      let content =
+      let s =
+      { in_device_shape_fields_20_ifa_list = ifa_list } in
+      let c =
       () in
-      { in_device_shape = shape; in_device_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_31", match_err));;
-let inet6_dev_parser_36 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("in_device", "in_device_parser_23", match_err));;
+let inet6_dev_parser_30 kernel_version bits = 
   bitmatch bits with
   | { addr_list : zero+32 : offset(32), littleendian } ->
-      let shape =
-      { inet6_dev_shape_fields_34_addr_list = addr_list } in
-      let content =
+      let s =
+      { inet6_dev_shape_fields_26_addr_list = addr_list } in
+      let c =
       () in
-      { inet6_dev_shape = shape; inet6_dev_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_36", match_err));;
-let inet6_dev_parser_39 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_30", match_err));;
+let inet6_dev_parser_31 kernel_version bits = 
   bitmatch bits with
   | { addr_list : zero+32 : offset(32), bigendian } ->
-      let shape =
-      { inet6_dev_shape_fields_34_addr_list = addr_list } in
-      let content =
+      let s =
+      { inet6_dev_shape_fields_26_addr_list = addr_list } in
+      let c =
       () in
-      { inet6_dev_shape = shape; inet6_dev_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_39", match_err));;
-let inet6_dev_parser_38 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_31", match_err));;
+let inet6_dev_parser_28 kernel_version bits = 
   bitmatch bits with
   | { addr_list : zero+64 : offset(64), littleendian } ->
-      let shape =
-      { inet6_dev_shape_fields_34_addr_list = addr_list } in
-      let content =
+      let s =
+      { inet6_dev_shape_fields_26_addr_list = addr_list } in
+      let c =
       () in
-      { inet6_dev_shape = shape; inet6_dev_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_38", match_err));;
-let inet6_dev_parser_37 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_28", match_err));;
+let inet6_dev_parser_29 kernel_version bits = 
   bitmatch bits with
   | { addr_list : zero+64 : offset(64), bigendian } ->
-      let shape =
-      { inet6_dev_shape_fields_34_addr_list = addr_list } in
-      let content =
+      let s =
+      { inet6_dev_shape_fields_26_addr_list = addr_list } in
+      let c =
       () in
-      { inet6_dev_shape = shape; inet6_dev_content = content }
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_37", match_err));;
-let in_ifaddr_parser_42 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_dev", "inet6_dev_parser_29", match_err));;
+let in_ifaddr_parser_36 kernel_version bits = 
   bitmatch bits with
   | { ifa_next : zero+32 : offset(0), littleendian;
       ifa_local : zero+32 : offset(128), littleendian;
       ifa_address : zero+32 : offset(160), littleendian;
       ifa_mask : zero+32 : offset(192), littleendian;
       ifa_broadcast : zero+32 : offset(224), littleendian } ->
-      let shape =
-      { in_ifaddr_shape_fields_40_ifa_next = ifa_next } in
-      let content =
-      { in_ifaddr_content_fields_41_ifa_address = ifa_address;
-        in_ifaddr_content_fields_41_ifa_broadcast = ifa_broadcast;
-        in_ifaddr_content_fields_41_ifa_local = ifa_local;
-        in_ifaddr_content_fields_41_ifa_mask = ifa_mask } in
-      { in_ifaddr_shape = shape; in_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_42", match_err));;
-let in_ifaddr_parser_45 kernel_version bits = 
+      let s =
+      { in_ifaddr_shape_fields_32_ifa_next = ifa_next } in
+      let c =
+      { in_ifaddr_content_fields_33_ifa_address = ifa_address;
+        in_ifaddr_content_fields_33_ifa_broadcast = ifa_broadcast;
+        in_ifaddr_content_fields_33_ifa_local = ifa_local;
+        in_ifaddr_content_fields_33_ifa_mask = ifa_mask } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_36", match_err));;
+let in_ifaddr_parser_37 kernel_version bits = 
   bitmatch bits with
   | { ifa_next : zero+32 : offset(0), bigendian;
       ifa_local : zero+32 : offset(128), bigendian;
       ifa_address : zero+32 : offset(160), bigendian;
       ifa_mask : zero+32 : offset(192), bigendian;
       ifa_broadcast : zero+32 : offset(224), bigendian } ->
-      let shape =
-      { in_ifaddr_shape_fields_40_ifa_next = ifa_next } in
-      let content =
-      { in_ifaddr_content_fields_41_ifa_address = ifa_address;
-        in_ifaddr_content_fields_41_ifa_broadcast = ifa_broadcast;
-        in_ifaddr_content_fields_41_ifa_local = ifa_local;
-        in_ifaddr_content_fields_41_ifa_mask = ifa_mask } in
-      { in_ifaddr_shape = shape; in_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_45", match_err));;
-let in_ifaddr_parser_43 kernel_version bits = 
-  bitmatch bits with
-  | { ifa_next : zero+64 : offset(0), bigendian;
-      ifa_local : zero+32 : offset(256), bigendian;
-      ifa_address : zero+32 : offset(288), bigendian;
-      ifa_mask : zero+32 : offset(320), bigendian;
-      ifa_broadcast : zero+32 : offset(352), bigendian } ->
-      let shape =
-      { in_ifaddr_shape_fields_40_ifa_next = ifa_next } in
-      let content =
-      { in_ifaddr_content_fields_41_ifa_address = ifa_address;
-        in_ifaddr_content_fields_41_ifa_broadcast = ifa_broadcast;
-        in_ifaddr_content_fields_41_ifa_local = ifa_local;
-        in_ifaddr_content_fields_41_ifa_mask = ifa_mask } in
-      { in_ifaddr_shape = shape; in_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_43", match_err));;
-let in_ifaddr_parser_44 kernel_version bits = 
+      let s =
+      { in_ifaddr_shape_fields_32_ifa_next = ifa_next } in
+      let c =
+      { in_ifaddr_content_fields_33_ifa_address = ifa_address;
+        in_ifaddr_content_fields_33_ifa_broadcast = ifa_broadcast;
+        in_ifaddr_content_fields_33_ifa_local = ifa_local;
+        in_ifaddr_content_fields_33_ifa_mask = ifa_mask } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_37", match_err));;
+let in_ifaddr_parser_34 kernel_version bits = 
   bitmatch bits with
   | { ifa_next : zero+64 : offset(0), littleendian;
       ifa_local : zero+32 : offset(256), littleendian;
       ifa_address : zero+32 : offset(288), littleendian;
       ifa_mask : zero+32 : offset(320), littleendian;
       ifa_broadcast : zero+32 : offset(352), littleendian } ->
-      let shape =
-      { in_ifaddr_shape_fields_40_ifa_next = ifa_next } in
-      let content =
-      { in_ifaddr_content_fields_41_ifa_address = ifa_address;
-        in_ifaddr_content_fields_41_ifa_broadcast = ifa_broadcast;
-        in_ifaddr_content_fields_41_ifa_local = ifa_local;
-        in_ifaddr_content_fields_41_ifa_mask = ifa_mask } in
-      { in_ifaddr_shape = shape; in_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_44", match_err));;
-let inet6_ifaddr_parser_48 kernel_version bits = 
-  bitmatch bits with
-  | { prefix_len : zero+32 : offset(128), littleendian;
-      lst_next : zero+32 : offset(1024), littleendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_48", match_err));;
-let inet6_ifaddr_parser_50 kernel_version bits = 
+      let s =
+      { in_ifaddr_shape_fields_32_ifa_next = ifa_next } in
+      let c =
+      { in_ifaddr_content_fields_33_ifa_address = ifa_address;
+        in_ifaddr_content_fields_33_ifa_broadcast = ifa_broadcast;
+        in_ifaddr_content_fields_33_ifa_local = ifa_local;
+        in_ifaddr_content_fields_33_ifa_mask = ifa_mask } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_34", match_err));;
+let in_ifaddr_parser_35 kernel_version bits = 
   bitmatch bits with
-  | { prefix_len : zero+32 : offset(128), littleendian;
-      lst_next : zero+64 : offset(1856), littleendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_50", match_err));;
-let inet6_ifaddr_parser_49 kernel_version bits = 
-  bitmatch bits with
-  | { prefix_len : zero+32 : offset(128), bigendian;
-      lst_next : zero+64 : offset(1472), bigendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_49", match_err));;
-let inet6_ifaddr_parser_51 kernel_version bits = 
+  | { ifa_next : zero+64 : offset(0), bigendian;
+      ifa_local : zero+32 : offset(256), bigendian;
+      ifa_address : zero+32 : offset(288), bigendian;
+      ifa_mask : zero+32 : offset(320), bigendian;
+      ifa_broadcast : zero+32 : offset(352), bigendian } ->
+      let s =
+      { in_ifaddr_shape_fields_32_ifa_next = ifa_next } in
+      let c =
+      { in_ifaddr_content_fields_33_ifa_address = ifa_address;
+        in_ifaddr_content_fields_33_ifa_broadcast = ifa_broadcast;
+        in_ifaddr_content_fields_33_ifa_local = ifa_local;
+        in_ifaddr_content_fields_33_ifa_mask = ifa_mask } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("in_ifaddr", "in_ifaddr_parser_35", match_err));;
+let inet6_ifaddr_parser_42 kernel_version bits = 
   bitmatch bits with
   | { prefix_len : zero+32 : offset(128), littleendian;
-      lst_next : zero+64 : offset(1472), littleendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
+      lst_next : zero+32 : offset(832), littleendian } ->
+      let s =
+      { inet6_ifaddr_shape_fields_38_lst_next = lst_next } in
+      let c =
+      { inet6_ifaddr_content_fields_39_prefix_len = prefix_len } in
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_51", match_err));;
-let inet6_ifaddr_parser_52 kernel_version bits = 
-  bitmatch bits with
-  | { prefix_len : zero+32 : offset(128), bigendian;
-      lst_next : zero+32 : offset(928), bigendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
-  | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_52", match_err));;
-let inet6_ifaddr_parser_53 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_42", match_err));;
+let inet6_ifaddr_parser_40 kernel_version bits = 
   bitmatch bits with
   | { prefix_len : zero+32 : offset(128), littleendian;
       lst_next : zero+64 : offset(1280), littleendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
+      let s =
+      { inet6_ifaddr_shape_fields_38_lst_next = lst_next } in
+      let c =
+      { inet6_ifaddr_content_fields_39_prefix_len = prefix_len } in
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_53", match_err));;
-let inet6_ifaddr_parser_54 kernel_version bits = 
+      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_40", match_err));;
+let inet6_ifaddr_parser_41 kernel_version bits = 
   bitmatch bits with
   | { prefix_len : zero+32 : offset(128), bigendian;
       lst_next : zero+64 : offset(1280), bigendian } ->
-      let shape =
-      { inet6_ifaddr_shape_fields_46_lst_next = lst_next } in
-      let content =
-      { inet6_ifaddr_content_fields_47_prefix_len = prefix_len } in
-      { inet6_ifaddr_shape = shape; inet6_ifaddr_content = content }
+      let s =
+      { inet6_ifaddr_shape_fields_38_lst_next = lst_next } in
+      let c =
+      { inet6_ifaddr_content_fields_39_prefix_len = prefix_len } in
+      (s, c)
   | { _ } ->
-      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_54", match_err));;
+      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_41", match_err));;
+let inet6_ifaddr_parser_43 kernel_version bits = 
+  bitmatch bits with
+  | { prefix_len : zero+32 : offset(128), bigendian;
+      lst_next : zero+32 : offset(800), bigendian } ->
+      let s =
+      { inet6_ifaddr_shape_fields_38_lst_next = lst_next } in
+      let c =
+      { inet6_ifaddr_content_fields_39_prefix_len = prefix_len } in
+      (s, c)
+  | { _ } ->
+      raise (Virt_mem_types.ParseError ("inet6_ifaddr", "inet6_ifaddr_parser_43", match_err));;
+let task_struct_shape_fields_1_follower load followers map shape =
+  let (_, _, _, _, _, _, f) = followers in
+  let map = f load followers map shape.task_struct_shape_fields_1_tasks'next
+  in map;;
+let net_device_shape_fields_8_follower load followers map shape =
+  let (_, _, _, _, _, f, _) = followers in
+  let map =
+    f load followers map shape.net_device_shape_fields_8_dev_list'next in
+  let (_, _, f, _, _, _, _) = followers in
+  let map = f load followers map shape.net_device_shape_fields_8_ip6_ptr in
+  let (_, _, _, f, _, _, _) = followers in
+  let map = f load followers map shape.net_device_shape_fields_8_ip_ptr
+  in map;;
+let net_shape_fields_14_follower load followers map shape =
+  let (_, _, _, _, _, f, _) = followers in
+  let map =
+    f load followers map shape.net_shape_fields_14_dev_base_head'next in
+  let (_, _, _, _, _, f, _) = followers in
+  let map = f load followers map shape.net_shape_fields_14_dev_base_head'prev
+  in map;;
+let in_device_shape_fields_20_follower load followers map shape =
+  let (_, f, _, _, _, _, _) = followers in
+  let map = f load followers map shape.in_device_shape_fields_20_ifa_list
+  in map;;
+let inet6_dev_shape_fields_26_follower load followers map shape =
+  let (f, _, _, _, _, _, _) = followers in
+  let map = f load followers map shape.inet6_dev_shape_fields_26_addr_list
+  in map;;
+let in_ifaddr_shape_fields_32_follower load followers map shape =
+  let (_, f, _, _, _, _, _) = followers in
+  let map = f load followers map shape.in_ifaddr_shape_fields_32_ifa_next
+  in map;;
+let inet6_ifaddr_shape_fields_38_follower load followers map shape =
+  let (f, _, _, _, _, _, _) = followers in
+  let map = f load followers map shape.inet6_ifaddr_shape_fields_38_lst_next
+  in map;;
+let kv_follower kernel_version struct_name total_size parserfn followerfn
+                load followers map addr =
+  if (addr <> 0L) && (not (AddrMap.mem addr map))
+  then
+    (let map = AddrMap.add addr (struct_name, total_size) map in
+     let bits = load struct_name addr total_size in
+     let (shape, _) = parserfn kernel_version bits
+     in followerfn load followers map shape)
+  else map;;
+let task_struct_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "task_struct" 2496
+    task_struct_parser_3 task_struct_shape_fields_1_follower;;
+let task_struct_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "task_struct" 2524
+    task_struct_parser_4 task_struct_shape_fields_1_follower;;
+let task_struct_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "task_struct" 1832
+    task_struct_parser_5 task_struct_shape_fields_1_follower;;
+let task_struct_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "task_struct" 1832
+    task_struct_parser_6 task_struct_shape_fields_1_follower;;
+let task_struct_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "task_struct" 1952 task_struct_parser_7
+    task_struct_shape_fields_1_follower;;
+let task_struct_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "task_struct" 2496
+    task_struct_parser_3 task_struct_shape_fields_1_follower;;
+let task_struct_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "task_struct" 2496
+    task_struct_parser_3 task_struct_shape_fields_1_follower;;
+let task_struct_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "task_struct" 1832 task_struct_parser_5
+    task_struct_shape_fields_1_follower;;
+let task_struct_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "task_struct" 2524
+    task_struct_parser_4 task_struct_shape_fields_1_follower;;
+let task_struct_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "task_struct" 1832 task_struct_parser_6
+    task_struct_shape_fields_1_follower;;
+let task_struct_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "task_struct" 1952 task_struct_parser_7
+    task_struct_shape_fields_1_follower;;
+let task_struct_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "task_struct" 1832 task_struct_parser_6
+    task_struct_shape_fields_1_follower;;
+let net_device_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "net_device" 1752
+    net_device_parser_10 net_device_shape_fields_8_follower;;
+let net_device_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "net_device" 1776
+    net_device_parser_11 net_device_shape_fields_8_follower;;
+let net_device_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "net_device" 1212 net_device_parser_12
+    net_device_shape_fields_8_follower;;
+let net_device_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "net_device" 1212 net_device_parser_12
+    net_device_shape_fields_8_follower;;
+let net_device_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "net_device" 904 net_device_parser_13
+    net_device_shape_fields_8_follower;;
+let net_device_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "net_device" 1752
+    net_device_parser_10 net_device_shape_fields_8_follower;;
+let net_device_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "net_device" 1752
+    net_device_parser_10 net_device_shape_fields_8_follower;;
+let net_device_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "net_device" 1212 net_device_parser_12
+    net_device_shape_fields_8_follower;;
+let net_device_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "net_device" 1776 net_device_parser_11
+    net_device_shape_fields_8_follower;;
+let net_device_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "net_device" 1212 net_device_parser_12
+    net_device_shape_fields_8_follower;;
+let net_device_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "net_device" 904 net_device_parser_13
+    net_device_shape_fields_8_follower;;
+let net_device_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "net_device" 1212 net_device_parser_12
+    net_device_shape_fields_8_follower;;
+let net_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "net" 488 net_parser_16
+    net_shape_fields_14_follower;;
+let net_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "net" 488 net_parser_17
+    net_shape_fields_14_follower;;
+let net_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "net" 284 net_parser_18
+    net_shape_fields_14_follower;;
+let net_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "net" 284 net_parser_18
+    net_shape_fields_14_follower;;
+let net_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "net" 276 net_parser_19
+    net_shape_fields_14_follower;;
+let net_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "net" 488 net_parser_16
+    net_shape_fields_14_follower;;
+let net_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "net" 488 net_parser_16
+    net_shape_fields_14_follower;;
+let net_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "net" 284 net_parser_18
+    net_shape_fields_14_follower;;
+let net_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "net" 488 net_parser_17
+    net_shape_fields_14_follower;;
+let net_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "net" 284 net_parser_18
+    net_shape_fields_14_follower;;
+let net_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "net" 276 net_parser_19
+    net_shape_fields_14_follower;;
+let net_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "net" 284 net_parser_18
+    net_shape_fields_14_follower;;
+let in_device_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "in_device" 368 in_device_parser_22
+    in_device_shape_fields_20_follower;;
+let in_device_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "in_device" 368 in_device_parser_23
+    in_device_shape_fields_20_follower;;
+let in_device_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "in_device" 244 in_device_parser_24
+    in_device_shape_fields_20_follower;;
+let in_device_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "in_device" 244 in_device_parser_24
+    in_device_shape_fields_20_follower;;
+let in_device_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "in_device" 236 in_device_parser_25
+    in_device_shape_fields_20_follower;;
+let in_device_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "in_device" 368 in_device_parser_22
+    in_device_shape_fields_20_follower;;
+let in_device_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "in_device" 368 in_device_parser_22
+    in_device_shape_fields_20_follower;;
+let in_device_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "in_device" 244 in_device_parser_24
+    in_device_shape_fields_20_follower;;
+let in_device_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "in_device" 368 in_device_parser_23
+    in_device_shape_fields_20_follower;;
+let in_device_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "in_device" 244 in_device_parser_24
+    in_device_shape_fields_20_follower;;
+let in_device_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "in_device" 236 in_device_parser_25
+    in_device_shape_fields_20_follower;;
+let in_device_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "in_device" 244 in_device_parser_24
+    in_device_shape_fields_20_follower;;
+let inet6_dev_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "inet6_dev" 536 inet6_dev_parser_28
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "inet6_dev" 536 inet6_dev_parser_29
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "inet6_dev" 356 inet6_dev_parser_30
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "inet6_dev" 356 inet6_dev_parser_30
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "inet6_dev" 348 inet6_dev_parser_31
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "inet6_dev" 536 inet6_dev_parser_28
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "inet6_dev" 536 inet6_dev_parser_28
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "inet6_dev" 356 inet6_dev_parser_30
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "inet6_dev" 536 inet6_dev_parser_29
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "inet6_dev" 356 inet6_dev_parser_30
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "inet6_dev" 348 inet6_dev_parser_31
+    inet6_dev_shape_fields_26_follower;;
+let inet6_dev_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "inet6_dev" 356 inet6_dev_parser_30
+    inet6_dev_shape_fields_26_follower;;
+let in_ifaddr_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "in_ifaddr" 71 in_ifaddr_parser_34
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "in_ifaddr" 71 in_ifaddr_parser_35
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "in_ifaddr" 55 in_ifaddr_parser_36
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "in_ifaddr" 55 in_ifaddr_parser_36
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "in_ifaddr" 55 in_ifaddr_parser_37
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "in_ifaddr" 71 in_ifaddr_parser_34
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "in_ifaddr" 71 in_ifaddr_parser_34
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "in_ifaddr" 55 in_ifaddr_parser_36
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "in_ifaddr" 71 in_ifaddr_parser_35
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "in_ifaddr" 55 in_ifaddr_parser_36
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "in_ifaddr" 55 in_ifaddr_parser_37
+    in_ifaddr_shape_fields_32_follower;;
+let in_ifaddr_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "in_ifaddr" 55 in_ifaddr_parser_36
+    in_ifaddr_shape_fields_32_follower;;
+let inet6_ifaddr_kv0_follower =
+  kv_follower "2.6.25.14-69.fc8.x86_64" "inet6_ifaddr" 200
+    inet6_ifaddr_parser_40 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv1_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc64" "inet6_ifaddr" 200
+    inet6_ifaddr_parser_41 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv2_follower =
+  kv_follower "2.6.25.14-108.fc9.i586" "inet6_ifaddr" 128
+    inet6_ifaddr_parser_42 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv3_follower =
+  kv_follower "2.6.25.14-108.fc9.i686" "inet6_ifaddr" 128
+    inet6_ifaddr_parser_42 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv4_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc" "inet6_ifaddr" 124
+    inet6_ifaddr_parser_43 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv5_follower =
+  kv_follower "2.6.25.14-108.fc9.x86_64" "inet6_ifaddr" 200
+    inet6_ifaddr_parser_40 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv6_follower =
+  kv_follower "2.6.25.11-97.fc9.x86_64" "inet6_ifaddr" 200
+    inet6_ifaddr_parser_40 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv7_follower =
+  kv_follower "2.6.25.14-69.fc8.i586" "inet6_ifaddr" 128
+    inet6_ifaddr_parser_42 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv8_follower =
+  kv_follower "2.6.25.14-69.fc8.ppc64" "inet6_ifaddr" 200
+    inet6_ifaddr_parser_41 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv9_follower =
+  kv_follower "2.6.25.11-97.fc9.i686" "inet6_ifaddr" 128
+    inet6_ifaddr_parser_42 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv10_follower =
+  kv_follower "2.6.25.14-108.fc9.ppc" "inet6_ifaddr" 124
+    inet6_ifaddr_parser_43 inet6_ifaddr_shape_fields_38_follower;;
+let inet6_ifaddr_kv11_follower =
+  kv_follower "2.6.25.14-69.fc8.i686" "inet6_ifaddr" 128
+    inet6_ifaddr_parser_42 inet6_ifaddr_shape_fields_38_follower;;
+let follower_map =
+  StringMap.add "2.6.25.14-69.fc8.i686"
+    (inet6_ifaddr_kv11_follower, in_ifaddr_kv11_follower,
+     inet6_dev_kv11_follower, in_device_kv11_follower, net_kv11_follower,
+     net_device_kv11_follower, task_struct_kv11_follower)
+    (StringMap.add "2.6.25.14-108.fc9.ppc"
+       (inet6_ifaddr_kv10_follower, in_ifaddr_kv10_follower,
+        inet6_dev_kv10_follower, in_device_kv10_follower, net_kv10_follower,
+        net_device_kv10_follower, task_struct_kv10_follower)
+       (StringMap.add "2.6.25.11-97.fc9.i686"
+          (inet6_ifaddr_kv9_follower, in_ifaddr_kv9_follower,
+           inet6_dev_kv9_follower, in_device_kv9_follower, net_kv9_follower,
+           net_device_kv9_follower, task_struct_kv9_follower)
+          (StringMap.add "2.6.25.14-69.fc8.ppc64"
+             (inet6_ifaddr_kv8_follower, in_ifaddr_kv8_follower,
+              inet6_dev_kv8_follower, in_device_kv8_follower,
+              net_kv8_follower, net_device_kv8_follower,
+              task_struct_kv8_follower)
+             (StringMap.add "2.6.25.14-69.fc8.i586"
+                (inet6_ifaddr_kv7_follower, in_ifaddr_kv7_follower,
+                 inet6_dev_kv7_follower, in_device_kv7_follower,
+                 net_kv7_follower, net_device_kv7_follower,
+                 task_struct_kv7_follower)
+                (StringMap.add "2.6.25.11-97.fc9.x86_64"
+                   (inet6_ifaddr_kv6_follower, in_ifaddr_kv6_follower,
+                    inet6_dev_kv6_follower, in_device_kv6_follower,
+                    net_kv6_follower, net_device_kv6_follower,
+                    task_struct_kv6_follower)
+                   (StringMap.add "2.6.25.14-108.fc9.x86_64"
+                      (inet6_ifaddr_kv5_follower, in_ifaddr_kv5_follower,
+                       inet6_dev_kv5_follower, in_device_kv5_follower,
+                       net_kv5_follower, net_device_kv5_follower,
+                       task_struct_kv5_follower)
+                      (StringMap.add "2.6.25.14-69.fc8.ppc"
+                         (inet6_ifaddr_kv4_follower, in_ifaddr_kv4_follower,
+                          inet6_dev_kv4_follower, in_device_kv4_follower,
+                          net_kv4_follower, net_device_kv4_follower,
+                          task_struct_kv4_follower)
+                         (StringMap.add "2.6.25.14-108.fc9.i686"
+                            (inet6_ifaddr_kv3_follower,
+                             in_ifaddr_kv3_follower, inet6_dev_kv3_follower,
+                             in_device_kv3_follower, net_kv3_follower,
+                             net_device_kv3_follower,
+                             task_struct_kv3_follower)
+                            (StringMap.add "2.6.25.14-108.fc9.i586"
+                               (inet6_ifaddr_kv2_follower,
+                                in_ifaddr_kv2_follower,
+                                inet6_dev_kv2_follower,
+                                in_device_kv2_follower, net_kv2_follower,
+                                net_device_kv2_follower,
+                                task_struct_kv2_follower)
+                               (StringMap.add "2.6.25.14-108.fc9.ppc64"
+                                  (inet6_ifaddr_kv1_follower,
+                                   in_ifaddr_kv1_follower,
+                                   inet6_dev_kv1_follower,
+                                   in_device_kv1_follower, net_kv1_follower,
+                                   net_device_kv1_follower,
+                                   task_struct_kv1_follower)
+                                  (StringMap.add "2.6.25.14-69.fc8.x86_64"
+                                     (inet6_ifaddr_kv0_follower,
+                                      in_ifaddr_kv0_follower,
+                                      inet6_dev_kv0_follower,
+                                      in_device_kv0_follower,
+                                      net_kv0_follower,
+                                      net_device_kv0_follower,
+                                      task_struct_kv0_follower)
+                                     StringMap.empty)))))))))));;
+let task_struct_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "task_struct" in
+  let (_, _, _, _, _, _, f) = followers
+  in f load followers AddrMap.empty addr;;
+let net_device_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "net_device" in
+  let (_, _, _, _, _, f, _) = followers
+  in f load followers AddrMap.empty addr;;
+let net_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "net" in
+  let (_, _, _, _, f, _, _) = followers
+  in f load followers AddrMap.empty addr;;
+let in_device_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "in_device" in
+  let (_, _, _, f, _, _, _) = followers
+  in f load followers AddrMap.empty addr;;
+let inet6_dev_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "inet6_dev" in
+  let (_, _, f, _, _, _, _) = followers
+  in f load followers AddrMap.empty addr;;
+let in_ifaddr_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "in_ifaddr" in
+  let (_, f, _, _, _, _, _) = followers
+  in f load followers AddrMap.empty addr;;
+let inet6_ifaddr_follower kernel_version load addr =
+  let followers =
+    try StringMap.find kernel_version follower_map
+    with | Not_found -> unknown_kernel_version kernel_version "inet6_ifaddr" in
+  let (f, _, _, _, _, _, _) = followers
+  in f load followers AddrMap.empty addr;;
index 3cc41e7..1dcb173 100644 (file)
@@ -1,9 +1,49 @@
-type ('a, 'b) task_struct;;
-type ('a, 'b) net_device;;
-type ('a, 'b) net;;
-type ('a, 'b) in_device;;
-type ('a, 'b) inet6_dev;;
-type ('a, 'b) in_ifaddr;;
-type ('a, 'b) inet6_ifaddr;;
+module AddrMap :
+  sig
+    type key = Virt_mem_mmap.addr;;
+    type 'a t = 'a Map.Make(Int64).t;;
+    val empty : 'a t;;
+    val is_empty : 'a t -> bool;;
+    val add : key -> 'a -> 'a t -> 'a t;;
+    val find : key -> 'a t -> 'a;;
+    val remove : key -> 'a t -> 'a t;;
+    val mem : key -> 'a t -> bool;;
+    val iter : (key -> 'a -> unit) -> 'a t -> unit;;
+    val map : ('a -> 'b) -> 'a t -> 'b t;;
+    val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t;;
+    val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b;;
+    val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int;;
+    val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool;;
+  end;;
+type kernel_version = string;;
 
 
+
+val task_struct_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val net_device_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val net_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val in_device_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val inet6_dev_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val in_ifaddr_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
+val inet6_ifaddr_follower :
+  kernel_version ->
+    (string -> Virt_mem_mmap.addr -> int -> Bitstring.bitstring) ->
+      Virt_mem_mmap.addr -> (string * int) AddrMap.t;;
index 32da18e..2ed0c5a 100644 (file)
@@ -569,10 +569,25 @@ Possibly the '-T' command line parameter was used inconsistently.");
        fun (image, ({ ksyms = ksyms; utsname = utsname } as kdata)) ->
          match ksyms, utsname with
          | Some ksyms, Some { uts_kernel_release = kversion } ->
+             let image = ref image in
+             let load struct_name addr size =
+               printf "load for task, %s: %Lx %d ...\n" struct_name addr size;
+               let mapped =
+                 Virt_mem_mmap.is_mapped_range !image.mem addr size in
+               if not mapped then image := load_memory !image addr size;
+               let bits = Virt_mem_mmap.get_bytes !image.mem addr size in
+               Bitstring.bitstring_of_string bits
+             in
+             let init_task = Ksymmap.find "init_task" ksyms in
+             let map =
+               Kernel.task_struct_follower kversion load init_task in
+
+             (*
              let image, tasks =
                Virt_mem_tasks.find_tasks debug image ksyms kversion in
              let kdata = { kdata with tasks = tasks } in
-             image, kdata
+             *)
+             !image, kdata
          | _, _ -> image, kdata
       ) images in
 
@@ -584,11 +599,42 @@ Possibly the '-T' command line parameter was used inconsistently.");
        fun (image, ({ ksyms = ksyms; utsname = utsname } as kdata)) ->
          match ksyms, utsname with
          | Some ksyms, Some { uts_kernel_release = kversion } ->
+             let image = ref image in
+             let load struct_name addr size =
+               printf "load for net dev, %s: %Lx %d ...\n" struct_name addr size;
+               let mapped =
+                 Virt_mem_mmap.is_mapped_range !image.mem addr size in
+               if not mapped then image := load_memory !image addr size;
+               let bits = Virt_mem_mmap.get_bytes !image.mem addr size in
+               Bitstring.bitstring_of_string bits
+             in
+             let map =
+               try
+                 let dev_base = Ksymmap.find "dev_base" ksyms in
+                 let map =
+                   Kernel.net_device_follower kversion load dev_base in
+                 Some map
+               with Not_found ->
+                 try
+                   let dev_base_head = Ksymmap.find "dev_base_head" ksyms in
+                   (* XXX adjust to get offset of start of net_device *)
+                   assert false
+                 with Not_found ->
+                   try
+                     let init_net = Ksymmap.find "init_net" ksyms in
+                     let map =
+                       Kernel.net_follower kversion load init_net in
+                     Some map
+                   with Not_found ->
+                     eprintf (f_"%s: cannot find dev_base, dev_base_head or init_net symbols in kernel image.\n") !image.domname;
+                     None in
+(*
              let image, net_devices =
                Virt_mem_net_devices.find_net_devices debug
                  image ksyms kversion in
              let kdata = { kdata with net_devices = net_devices } in
-             image, kdata
+*)
+             !image, kdata
          | _, _ -> image, kdata
       ) images in
 
index 9d7b9db..9460224 100644 (file)
@@ -1,6 +1,7 @@
 let kernels =
-  [ "2.6.21-1.3128.fc7.i586"; "2.6.21-1.3128.fc7.i686";
-    "2.6.21-1.3141.fc7.ppc64"; "2.6.21-1.3141.fc7.x86_64";
-    "2.6.21-1.3190.fc7.x86_64"; "2.6.22-0.23.rc7.git6.fc8.ppc";
-    "2.6.24-0.167.rc8.git4.fc9.ppc64"; "2.6.25.14-69.fc8.x86_64";
-    "2.6.26.1-9.fc9.ppc64"; "2.6.27-0.226.rc1.git5.fc10.ppc" ];;
+  [ "2.6.25.11-97.fc9.i686"; "2.6.25.11-97.fc9.x86_64";
+    "2.6.25.14-108.fc9.i586"; "2.6.25.14-108.fc9.i686";
+    "2.6.25.14-108.fc9.ppc"; "2.6.25.14-108.fc9.ppc64";
+    "2.6.25.14-108.fc9.x86_64"; "2.6.25.14-69.fc8.i586";
+    "2.6.25.14-69.fc8.i686"; "2.6.25.14-69.fc8.ppc";
+    "2.6.25.14-69.fc8.ppc64"; "2.6.25.14-69.fc8.x86_64" ];;
index ad72662..f4e3ee7 100644 (file)
@@ -23,6 +23,7 @@ open Virt_mem_gettext.Gettext
 open Virt_mem_utils
 open Virt_mem_types
 
+(*
 open Kernel_net_device
 open Kernel_net
 
@@ -156,3 +157,4 @@ and map_next kernel_version image addr f =
       failwith (sprintf (f_"%s: too many network devices") image.domname);
   in
   loop 0 image [] addr
+*)
index 193e427..3b301e1 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *)
 
+(*
 val find_net_devices : bool ->
   Virt_mem_types.image ->
   Virt_mem_types.ksymmap ->
   string ->
   Virt_mem_types.image * Virt_mem_types.net_device list option
 (** Find and load the net device list. *)
+*)
index b75a711..c7e5203 100644 (file)
@@ -23,6 +23,7 @@ open Virt_mem_gettext.Gettext
 open Virt_mem_utils
 open Virt_mem_types
 
+(*
 open Kernel_task_struct
 
 let max_tasks = 10000
@@ -77,3 +78,4 @@ supported Linux distribution, see this page about adding support:
 
        image, Some tasks
   )
+*)
index 13764bf..15592c2 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *)
 
+(*
 val find_tasks : bool ->
   Virt_mem_types.image ->
   Virt_mem_types.ksymmap ->
   string ->
   Virt_mem_types.image * Virt_mem_types.task list option
 (** Find and load the process table. *)
+*)
index ff4f147..58fadb5 100644 (file)
@@ -130,12 +130,6 @@ exception ParseError of string * string * string
       The fields are: structure name, function which raised the error,
       error message. *)
 
-type fieldsig = {
-  field_available : bool; (** Field available in this kernel version? *)
-  field_offset : int;   (** Offset of field in this kernel version. *)
-}
-  (** Returned by [Kernel_*.field_signature_of_*] functions. *)
-
 (** {2 Functions to load kernel memory} *)
 
 type load_memory_error =
index c170c41..0614d06 100644 (file)
@@ -1,6 +1,4 @@
 virt_ps.cmo: ../lib/virt_mem_utils.cmo ../lib/virt_mem_types.cmi \
-    ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi \
-    ../lib/kernel_task_struct.cmi 
+    ../lib/virt_mem_gettext.cmo ../lib/virt_mem.cmi 
 virt_ps.cmx: ../lib/virt_mem_utils.cmx ../lib/virt_mem_types.cmx \
-    ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx \
-    ../lib/kernel_task_struct.cmx 
+    ../lib/virt_mem_gettext.cmx ../lib/virt_mem.cmx 
index fe538a9..340266a 100644 (file)
@@ -23,6 +23,7 @@ open Virt_mem_gettext.Gettext
 open Virt_mem_utils
 open Virt_mem_types
 
+(*
 open Kernel_task_struct
 
 let run debug { domname = domname; mem = mem } { tasks = tasks } =
@@ -38,6 +39,9 @@ let run debug { domname = domname; mem = mem } { tasks = tasks } =
     fun task ->
       printf "%5Ld      %s\n" task.task_pid task.task_comm
   ) tasks
+*)
+
+let run debug _ _ = ()
 
 let summary = s_"list processes in virtual machine"
 let description = s_"\