From 2174887a4382d491f67058a8336cfe57c2faa746 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 1 Jan 1970 00:00:00 +0000 Subject: [PATCH] Understand void* pointers, and extract more kernel structures. --- extract/codegen/kerneldb_to_parser.ml | 76 +++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/extract/codegen/kerneldb_to_parser.ml b/extract/codegen/kerneldb_to_parser.ml index 2a46b68..e4c7519 100644 --- a/extract/codegen/kerneldb_to_parser.ml +++ b/extract/codegen/kerneldb_to_parser.ml @@ -80,7 +80,13 @@ let structs = [ "dev_list'next", { mandatory_field = false; list_head_adjustment = true }; "next", { mandatory_field = false; list_head_adjustment = true }; "name", ordinary_field; - "dev_addr", ordinary_field; + "flags", ordinary_field; + "operstate", ordinary_field; + "mtu", ordinary_field; + "perm_addr", ordinary_field; + "addr_len", ordinary_field; + "ip_ptr", ordinary_field; + "ip6_ptr", ordinary_field; ] }; "net", { @@ -93,6 +99,36 @@ let structs = [ { mandatory_field = true; list_head_adjustment = false }; ] }; + "in_device", { + opener = "struct in_device {"; closer = "};"; mandatory_struct = true; + fields = [ + "ifa_list", ordinary_field; + ]; + }; + "inet6_dev", { + opener = "struct inet6_dev {"; closer = "};"; mandatory_struct = true; + fields = [ + "addr_list", ordinary_field; + ]; + }; + "in_ifaddr", { + opener = "struct in_ifaddr {"; closer = "};"; mandatory_struct = true; + fields = [ + "ifa_next", ordinary_field; + "ifa_local", ordinary_field; + "ifa_address", ordinary_field; + "ifa_mask", ordinary_field; + "ifa_broadcast", ordinary_field; + ]; + }; + "inet6_ifaddr", { + opener = "struct inet6_ifaddr {"; closer = "};"; mandatory_struct = true; + fields = [ + (*"addr'in6_u'u6_addr8", ordinary_field;*) + "prefix_len", ordinary_field; + "lst_next", ordinary_field; + ]; + }; ] let debug = false @@ -338,8 +374,9 @@ Example (from toplevel of virt-mem source tree): * XXX Even better would be to have a proper interface to libdwarves. *) let re_offsetsize = Pcre.regexp "/\\*\\s+(\\d+)\\s+(\\d+)\\s+\\*/" in - let re_intfield = Pcre.regexp "int\\s+(\\w+);" in + let re_intfield = Pcre.regexp "(?:int|char)\\s+(\\w+);" in let re_ptrfield = Pcre.regexp "struct\\s+(\\w+)\\s*\\*\\s*(\\w+);" in + let re_voidptrfield = Pcre.regexp "void\\s*\\*\\s*(\\w+);" in let re_strfield = Pcre.regexp "char\\s+(\\w+)\\[(\\d+)\\];" in let re_structopener = Pcre.regexp "(struct|union)\\s+.*{$" in let re_structcloser = Pcre.regexp "}\\s*(\\w+)?(\\[\\d+\\])?;" in @@ -424,6 +461,20 @@ Example (from toplevel of virt-mem source tree): Not_found -> parse basename lines ); + | line :: lines when Pcre.pmatch ~rex:re_voidptrfield line -> + (* A void* field. *) + let subs = Pcre.exec ~rex:re_voidptrfield line in + let name = Pcre.get_substring subs 1 in + (try + let subs = Pcre.exec ~rex:re_offsetsize line in + let offset = int_of_string (Pcre.get_substring subs 1) in + let size = int_of_string (Pcre.get_substring subs 2) in + (name, (`VoidPtr, offset, size)) + :: parse basename lines + with + Not_found -> parse basename lines + ); + | line :: lines when Pcre.pmatch ~rex:re_strfield line -> (* A string (char array) field. *) let subs = Pcre.exec ~rex:re_strfield line in @@ -468,6 +519,7 @@ Example (from toplevel of virt-mem source tree): (* That got us all the fields, but we only care about * the wanted_fields. *) + let all_fields = fields in let fields = List.filter ( fun (name, _) -> List.mem_assoc name wanted_fields ) fields in @@ -475,8 +527,15 @@ Example (from toplevel of virt-mem source tree): (* Also check we have all the mandatory fields. *) List.iter ( fun (wanted_field, { mandatory_field = mandatory }) -> - if mandatory && not (List.mem_assoc wanted_field fields) then - failwith (sprintf "%s: structure %s is missing required field %s" basename struct_name wanted_field) + if mandatory && not (List.mem_assoc wanted_field fields) + then ( + eprintf "%s: structure %s is missing required field %s\n" basename struct_name wanted_field; + eprintf "fields found in this structure:\n"; + List.iter ( + fun (name, _) -> eprintf "\t%s\n" name + ) all_fields; + exit 1 + ); ) wanted_fields; (* Prefix all the field names with the structure name. *) @@ -504,6 +563,8 @@ Example (from toplevel of virt-mem source tree): printf " int %s; " field_name | `Ptr struct_name -> printf " struct %s *%s; " struct_name field_name + | `VoidPtr -> + printf " void *%s; " field_name | `Str width -> printf " char %s[%d]; " field_name width ); @@ -708,9 +769,9 @@ Example (from toplevel of virt-mem source tree): <:ctyp< $lid:name$ : int64 >> | (name, (`Int, { mandatory_field = false })) -> <:ctyp< $lid:name$ : int64 option >> - | (name, (`Ptr _, { mandatory_field = true })) -> + | (name, ((`VoidPtr|`Ptr _), { mandatory_field = true })) -> <:ctyp< $lid:name$ : Virt_mem_mmap.addr >> - | (name, (`Ptr _, { mandatory_field = false })) -> + | (name, ((`VoidPtr|`Ptr _), { mandatory_field = false })) -> <:ctyp< $lid:name$ : Virt_mem_mmap.addr option >> | (name, (`Str _, { mandatory_field = true })) -> <:ctyp< $lid:name$ : string >> @@ -807,8 +868,7 @@ Example (from toplevel of virt-mem source tree): String.concat ";\n " ( List.map ( function - | (field_name, (`Int, offset, size)) - | (field_name, (`Ptr _, offset, size)) -> + | (field_name, ((`Int|`Ptr _|`VoidPtr), offset, size)) -> (* 'zero+' is a hack to force the type to int64. *) sprintf "%s : zero+%d : offset(%d), %s" field_name (size*8) (offset*8) endian -- 1.8.3.1