and f_type =
| FStructPointer of string
| FVoidPointer
- | FListHeadPointer
+ | FAnonListHeadPointer
+ | FListHeadPointer of string
| FInteger
| FString of int
and string_of_field f =
sprintf "%s %s; /* offset = %d, size = %d */"
- f.field_name (string_of_f_type f.field_type)
+ (string_of_f_type f.field_type) f.field_name
f.field_offset f.field_size
and string_of_f_type = function
- | FStructPointer struct_name -> sprintf "struct %s*" struct_name
+ | FStructPointer struct_name -> sprintf "struct %s *" struct_name
| FVoidPointer -> "void *"
- | FListHeadPointer -> "struct list_head *"
+ | FAnonListHeadPointer -> "struct list_head *"
+ | FListHeadPointer struct_name ->
+ sprintf "struct /* %s */ list_head *" struct_name
| FInteger -> "int"
| FString width -> sprintf "char[%d]" width
if struct_name <> "list_head" then
FStructPointer struct_name
else
- FListHeadPointer in
+ FAnonListHeadPointer in
let field =
{ field_name = name; field_type = field_type;
field_offset = offset; field_size = size } in
) fields in
List.fold_left max 0 fields in
- Some { struct_name = struct_name;
- struct_fields = fields;
- struct_total_size = total_size }
+ (* Sort the structure fields by field offset. They are
+ * probably already in this order, but just make sure.
+ *)
+ let cmp { field_offset = o1 } { field_offset = o2 } = compare o1 o2 in
+ let fields = List.sort ~cmp fields in
+
+ Some (
+ struct_name,
+ { struct_name = struct_name;
+ struct_fields = fields;
+ struct_total_size = total_size }
+ )
) struct_names in
structures
+
+(* XXX This loop is O(n^3), luckily n is small! *)
+let transpose good_struct_names kernels =
+ List.map (
+ fun struct_name ->
+ let kernels =
+ List.filter_map (
+ fun (info, structures) ->
+ try
+ let s = List.assoc struct_name structures in
+ Some (info, s)
+ with
+ Not_found -> None
+ ) kernels in
+
+ (* Sort the kernels, which makes the generated output more stable
+ * and makes patches more useful.
+ *)
+ let kernels = List.sort kernels in
+
+ struct_name, kernels
+ ) good_struct_names
+
+let get_fields structures =
+ (* Use a hash table to accumulate the fields as we find them.
+ * The key is the field name. The value is the field type and the
+ * kernel version where first seen (for error reporting). If
+ * we meet the field again, we check its type hasn't changed.
+ * Finally, we can use the hash to pull out all field names and
+ * types.
+ *)
+ let h = Hashtbl.create 13 in
+
+ List.iter (
+ fun ({kernel_version = version},
+ {struct_name = struct_name; struct_fields = fields}) ->
+ List.iter (
+ fun {field_name = name; field_type = typ} ->
+ try
+ let (field_type, version_first_seen) = Hashtbl.find h name in
+ if typ <> field_type then (
+ eprintf "Error: %s.%s: field changed type between kernel versions.\n"
+ struct_name name;
+ eprintf "In version %s it had type %s.\n"
+ version_first_seen (string_of_f_type field_type);
+ eprintf "In version %s it had type %s.\n"
+ version (string_of_f_type typ);
+ eprintf "The code cannot handle fields which change type like this.\n";
+ eprintf "See extract/codegen/pahole_parser.mli for more details.\n";
+ exit 1
+ )
+ with Not_found ->
+ Hashtbl.add h name (typ, version)
+ ) fields
+ ) structures;
+
+ let fields =
+ Hashtbl.fold (
+ fun name (typ, _) fields ->
+ (name, typ) :: fields
+ ) h [] in
+
+ List.sort fields