Skip to content

Commit 046d5f6

Browse files
committed
CHB: add function annotations
1 parent e81bcfe commit 046d5f6

20 files changed

+793
-73
lines changed

CodeHawk/CHB/bchcmdline/bCHXBinaryAnalyzer.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,8 +847,6 @@ let main () =
847847
let _ = pr_timing [STR "bdictionary loaded"] in
848848
let _ = load_bc_files () in
849849
let _ = pr_timing [STR "bc files loaded"] in
850-
let _ = system_info#initialize in
851-
let _ = pr_timing [STR "system info initialized"] in
852850
let _ = load_interface_dictionary () in
853851
let _ = pr_timing [STR "interface dictionary loaded"] in
854852
let _ = load_arm_dictionary () in
@@ -869,6 +867,8 @@ let main () =
869867
let _ =
870868
if (List.length system_info#ifiles > 0) then
871869
pr_timing [STR "c header files parsed"] in
870+
let _ = system_info#initialize in
871+
let _ = pr_timing [STR "system info initialized"] in
872872
let index = file_metrics#get_index in
873873
let logcmd = "analyze_" ^ (string_of_int index) in
874874
let analysisstart = Unix.gettimeofday () in

CodeHawk/CHB/bchlib/bCHBCTypeUtil.ml

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
Copyright (c) 2005-2019 Kestrel Technology LLC
88
Copyright (c) 2020 Henny B. Sipma
9-
Copyright (c) 2021-2024 Aarno Labs LLC
9+
Copyright (c) 2021-2025 Aarno Labs LLC
1010
1111
Permission is hereby granted, free of charge, to any person obtaining a copy
1212
of this software and associated documentation files (the "Software"), to deal
@@ -148,6 +148,48 @@ let t_vararg_function (returntype:btype_t) (args:bfunarg_t list) =
148148
let t_function_anon (returntype:btype_t) =
149149
TFun (returntype, None, false, [])
150150

151+
(* =========================================================== string -> type *)
152+
153+
let convert_string_to_type (name: string): btype_t traceresult =
154+
match name with
155+
| "char" -> Ok (TInt (IChar, []))
156+
| "signed char" -> Ok (TInt (ISChar, []))
157+
| "unsigned char" -> Ok (TInt (IUChar, []))
158+
| "wchar_t" -> Ok (TInt (IWChar, []))
159+
| "bool" -> Ok (TInt (IBool, []))
160+
| "int" -> Ok (TInt (IInt, []))
161+
| "unsigned int" -> Ok (TInt (IUInt, []))
162+
| "short" -> Ok (TInt (IShort, []))
163+
| "unsigned short" -> Ok (TInt (IUShort, []))
164+
| "long" -> Ok (TInt (ILong, []))
165+
| "unsigned long" -> Ok (TInt (IULong, []))
166+
| "long long" -> Ok (TInt (ILongLong, []))
167+
| "unsigned long long" -> Ok (TInt (IULongLong, []))
168+
| "int8_t" -> Ok (TInt (ISChar, []))
169+
| "uint8_t" -> Ok (TInt (IUChar, []))
170+
| "int16_t" -> Ok (TInt (IShort, []))
171+
| "uint16_t" -> Ok (TInt (IUShort, []))
172+
| "int32_t" -> Ok (TInt (IInt, []))
173+
| "uint32_t" -> Ok (TInt (IUInt, []))
174+
| "int64_t" -> Ok (TInt (ILongLong, []))
175+
| "uint64_t" -> Ok (TInt (IULongLong, []))
176+
| "int128_t" -> Ok (TInt (IInt128, []))
177+
| "uint128_t" -> Ok (TInt (IUInt128, []))
178+
| "float" -> Ok (TFloat (FFloat, FScalar, []))
179+
| "double" -> Ok (TFloat (FDouble, FScalar, []))
180+
| "long double" -> Ok (TFloat (FLongDouble, FScalar, []))
181+
| "complex" -> Ok (TFloat (FComplexFloat, FScalar, []))
182+
| "double complex" -> Ok (TFloat (FComplexDouble, FScalar, []))
183+
| "long double complex" -> Ok (TFloat (FComplexLongDouble, FScalar, []))
184+
| "void" -> Ok (TVoid [])
185+
| _ ->
186+
if bcfiles#has_typedef name then
187+
Ok (bcfiles#get_typedef name)
188+
else
189+
Error [
190+
__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
191+
^ "unable to convert type name " ^ name]
192+
151193
(* =============================================================== attributes *)
152194

153195
let get_attributes (t: btype_t): b_attributes_t =
@@ -1109,6 +1151,17 @@ let get_struct_field_at_offset
11091151
end
11101152

11111153

1154+
let is_sub_struct (ckey1: int) (ckey2: int) =
1155+
let cinfo2 = get_compinfo_by_key ckey2 in
1156+
let field0 = get_struct_field_at_offset cinfo2 0 in
1157+
match field0 with
1158+
| Some (bfinfo, 0) ->
1159+
(match bfinfo.bftype with
1160+
| TComp (i, _) -> ckey1 = i
1161+
| _ -> false)
1162+
| _ -> false
1163+
1164+
11121165
let rec get_compinfo_scalar_type_at_offset
11131166
(cinfo: bcompinfo_t) (offset: int): btype_t option =
11141167
let finfos = cinfo.bcfields in

CodeHawk/CHB/bchlib/bCHBCTypeUtil.mli

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
Copyright (c) 2005-2019 Kestrel Technology LLC
88
Copyright (c) 2020 Henny B. Sipma
9-
Copyright (c) 2021-2024 Aarno Labs LLC
9+
Copyright (c) 2021-2025 Aarno Labs LLC
1010
1111
Permission is hereby granted, free of charge, to any person obtaining a copy
1212
of this software and associated documentation files (the "Software"), to deal
@@ -126,6 +126,17 @@ val t_vararg_function: btype_t -> bfunarg_t list -> btype_t
126126
val t_function_anon: btype_t -> btype_t (* arguments not known *)
127127

128128

129+
(** {1 Types from strings} *)
130+
131+
(** [convert_string_to_type name] attempts to convert [name] into a [btype_t].
132+
Valid names include the standard names for the integer and float types,
133+
as well as typedef names.
134+
135+
If [name] is not a standard type name or typedef name, an Error is returned.
136+
*)
137+
val convert_string_to_type: string -> btype_t traceresult
138+
139+
129140
(** {1 Type predicates}*)
130141

131142
val is_void: btype_t -> bool
@@ -256,6 +267,10 @@ val get_compinfo_scalar_type_at_offset: bcompinfo_t -> int -> btype_t option
256267

257268
val get_compinfo_by_key: int -> bcompinfo_t
258269

270+
(** [is_sub_struct ckey1 ckey2] returns [true] if the first field (at offset 0)
271+
of the struct with key [ckey2] is a struct with key [ckey1].*)
272+
val is_sub_struct: int -> int -> bool
273+
259274

260275
(** {2 Fieldinfos}*)
261276

CodeHawk/CHB/bchlib/bCHFloc.ml

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -639,13 +639,45 @@ object (self)
639639
(var: variable_t)
640640
(numoffset: numerical_t): variable_t traceresult =
641641
let inv = self#inv in
642+
let mk_memvar memref_r memoffset_r =
643+
TR.tbind
644+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
645+
(fun memref ->
646+
if memref#is_global_reference then
647+
TR.tbind
648+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__)
649+
^ ": memref:global")
650+
(fun memoff ->
651+
TR.tbind
652+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
653+
self#env#mk_global_variable
654+
(get_total_constant_offset memoff))
655+
memoffset_r
656+
else
657+
TR.tmap
658+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
659+
(fun memoff ->
660+
(self#env#mk_offset_memory_variable memref memoff))
661+
memoffset_r)
662+
memref_r in
663+
642664
if inv#is_base_offset_constant var then
643665
let (base, offset) = inv#get_base_offset_constant var in
644666
let memoffset = numoffset#add offset in
645-
TR.tmap
646-
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
647-
(fun memref -> self#env#mk_memory_variable ~size memref memoffset)
648-
(self#env#mk_base_sym_reference base)
667+
let memref_r = self#env#mk_base_sym_reference base in
668+
let memoff_r =
669+
TR.tbind
670+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
671+
(fun basevar ->
672+
let optbasetype = self#env#get_variable_type basevar in
673+
let basetype =
674+
match optbasetype with
675+
| Some t when is_pointer t -> ptr_deref t
676+
| _ -> t_unknown in
677+
address_memory_offset basetype (num_constant_expr memoffset))
678+
(self#env#get_variable base#getSeqNumber) in
679+
mk_memvar memref_r memoff_r
680+
649681
else
650682
let varx =
651683
if align > 1 then
@@ -670,27 +702,7 @@ object (self)
670702
^ ")"]
671703
| _ ->
672704
let (memref_r, memoffset_r) = self#decompose_memaddr address in
673-
TR.tbind
674-
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
675-
(fun memref ->
676-
if memref#is_global_reference then
677-
TR.tbind
678-
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__)
679-
^ ": memref:global")
680-
(fun memoff ->
681-
TR.tbind
682-
self#env#mk_global_variable
683-
(get_total_constant_offset memoff))
684-
memoffset_r
685-
else
686-
TR.tbind
687-
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
688-
(fun memoff ->
689-
TR.tmap
690-
(self#env#mk_memory_variable memref)
691-
(get_total_constant_offset memoff))
692-
memoffset_r)
693-
memref_r
705+
mk_memvar memref_r memoffset_r
694706

695707
method get_memory_variable_1
696708
?(align=1) (* alignment of var value *)
@@ -753,6 +765,7 @@ object (self)
753765
(fun v -> v)
754766
(default ())
755767
(TR.tbind
768+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
756769
self#env#mk_global_variable
757770
(get_total_constant_offset memoffset))
758771
else
@@ -797,6 +810,7 @@ object (self)
797810
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
798811
(fun memoff ->
799812
TR.tmap
813+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
800814
(self#env#mk_memory_variable memref)
801815
(get_total_constant_offset memoff))
802816
memoff_r)
@@ -849,6 +863,7 @@ object (self)
849863
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": memref:global")
850864
(fun memoff ->
851865
TR.tbind
866+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
852867
(self#env#mk_global_variable ~size)
853868
(get_total_constant_offset memoff))
854869
memoff_r
@@ -857,6 +872,7 @@ object (self)
857872
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
858873
(fun memoff ->
859874
TR.tmap
875+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
860876
(self#env#mk_memory_variable memref)
861877
(get_total_constant_offset memoff))
862878
memoff_r)
@@ -893,6 +909,7 @@ object (self)
893909
(fun v -> v)
894910
(default ())
895911
(TR.tbind
912+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
896913
self#env#mk_global_variable
897914
(get_total_constant_offset memoffset))
898915
else
@@ -1254,7 +1271,10 @@ object (self)
12541271
| [base] ->
12551272
let offset = simplify_xpr (XOp (XMinus, [x; XVar base])) in
12561273
let memref_r = self#env#mk_base_variable_reference base in
1257-
let memoff_r =
1274+
let vartype = self#f#env#get_variable_type base in
1275+
let vartype = match vartype with None -> t_unknown | Some t -> t in
1276+
let memoff_r = address_memory_offset vartype offset in
1277+
(*
12581278
(match offset with
12591279
| XConst (IntConst n) -> Ok (ConstantOffset (n, NoOffset))
12601280
| XOp (XMult, [XConst (IntConst n); XVar v]) ->
@@ -1263,7 +1283,7 @@ object (self)
12631283
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
12641284
^ "Offset from base "
12651285
^ (x2s (XVar base))
1266-
^ " not recognized: " ^ (x2s offset)]) in
1286+
^ " not recognized: " ^ (x2s offset)]) in *)
12671287
(memref_r, memoff_r)
12681288

12691289
(* no known pointers, have to find a base *)
@@ -1681,7 +1701,31 @@ object (self)
16811701
let reqN () = self#env#mk_num_temp in
16821702
let reqC = self#env#request_num_constant in
16831703
let (rhscmds, rhs_c) = xpr_to_numexpr reqN reqC rhs in
1684-
rhscmds @ [ASSIGN_NUM (lhs, rhs_c)]
1704+
let cmds = rhscmds @ [ASSIGN_NUM (lhs, rhs_c)] in
1705+
let fndata = self#f#get_function_data in
1706+
match fndata#get_regvar_intro self#ia with
1707+
| Some rvi when rvi.rvi_cast && Option.is_some rvi.rvi_vartype ->
1708+
TR.tfold
1709+
~ok:(fun reg ->
1710+
let ty = Option.get rvi.rvi_vartype in
1711+
let tcvar =
1712+
self#f#env#mk_typecast_value self#cia rvi.rvi_name ty reg in
1713+
begin
1714+
log_result __FILE__ __LINE__
1715+
["Create typecast var for "
1716+
^ (register_to_string reg)
1717+
^ " at "
1718+
^ self#cia];
1719+
cmds @ [ASSIGN_NUM (lhs, NUM_VAR tcvar)]
1720+
end)
1721+
~error:(fun e ->
1722+
begin
1723+
log_error_result __FILE__ __LINE__
1724+
("expected a register variable" :: e);
1725+
cmds
1726+
end)
1727+
(self#f#env#get_register lhs)
1728+
| _ -> cmds
16851729

16861730
(* Note: recording of loads and stores is performed by the different
16871731
architectures directly in FnXXXDictionary.*)

0 commit comments

Comments
 (0)