Skip to content

Commit 5f5adb3

Browse files
committed
CHB: improve on memory variable resolution
1 parent 3c7b34a commit 5f5adb3

File tree

10 files changed

+242
-60
lines changed

10 files changed

+242
-60
lines changed

CodeHawk/CHB/bchlib/bCHFloc.ml

Lines changed: 131 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ object (self)
651651
TR.tbind
652652
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
653653
self#env#mk_global_variable
654-
(get_total_constant_offset memoff))
654+
(get_total_constant_offset memoff))
655655
memoffset_r
656656
else
657657
TR.tmap
@@ -661,7 +661,36 @@ object (self)
661661
memoffset_r)
662662
memref_r in
663663

664-
if inv#is_base_offset_constant var then
664+
if self#f#env#is_addressof_symbolic_value var then
665+
let xaofv_r = self#f#env#get_addressof_symbolic_expr var in
666+
let memvar_r =
667+
TR.tbind
668+
(fun xaofv ->
669+
match xaofv with
670+
| XOp ((Xf "addressofvar"), [XVar v]) -> Ok v
671+
| _ ->
672+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
673+
^ "Expression is not an addressofvar expression: "
674+
^ (x2s xaofv)])
675+
xaofv_r in
676+
let memoff_r =
677+
TR.tbind
678+
(fun memvar ->
679+
let memtype = self#get_variable_type memvar in
680+
let memtype =
681+
match memtype with
682+
| Some t -> t
683+
| _ -> t_unknown in
684+
address_memory_offset memtype (num_constant_expr numoffset))
685+
memvar_r in
686+
TR.tbind
687+
(fun memvar ->
688+
TR.tbind
689+
(fun memoff -> self#f#env#add_memory_offset memvar memoff)
690+
memoff_r)
691+
memvar_r
692+
693+
else if inv#is_base_offset_constant var then
665694
let (base, offset) = inv#get_base_offset_constant var in
666695
let memoffset = numoffset#add offset in
667696
let memref_r = self#env#mk_base_sym_reference base in
@@ -686,7 +715,7 @@ object (self)
686715
else
687716
XVar var in
688717
let addr = XOp (XPlus, [varx; num_constant_expr numoffset]) in
689-
let address = inv#rewrite_expr addr in
718+
let address = simplify_xpr (inv#rewrite_expr addr) in
690719
match address with
691720
| XConst (IntConst n) ->
692721
let dw = numerical_mod_to_doubleword n in
@@ -701,8 +730,7 @@ object (self)
701730
^ system_info#get_image_base#to_hex_string
702731
^ ")"]
703732
| _ ->
704-
let (memref_r, memoffset_r) = self#decompose_memaddr address in
705-
mk_memvar memref_r memoffset_r
733+
self#get_var_at_address ~size:(Some size) address
706734

707735
method get_memory_variable_1
708736
?(align=1) (* alignment of var value *)
@@ -1246,22 +1274,72 @@ object (self)
12461274

12471275
method get_fts_parameter_expr (_p: fts_parameter_t) = None
12481276

1277+
method private normalize_addrvalue (x: xpr_t): xpr_t =
1278+
simplify_xpr x
1279+
12491280
method get_var_at_address
12501281
?(size=None)
12511282
?(btype=t_unknown)
12521283
(addrvalue: xpr_t): variable_t traceresult =
1253-
match memmap#xpr_containing_location addrvalue with
1254-
| Some gloc ->
1255-
(TR.tmap
1256-
(fun offset -> self#f#env#mk_gloc_variable gloc offset)
1257-
(gloc#address_memory_offset ~tgtsize:size ~tgtbtype:btype addrvalue))
1284+
match self#normalize_addrvalue addrvalue with
1285+
| XOp ((Xf "addressofvar"), [XVar v]) -> Ok v
1286+
| XOp (XPlus, [XOp ((Xf "addressofvar"), [XVar v]); xoff])
1287+
when self#f#env#is_global_variable v ->
1288+
let gvaddr_r = self#f#env#get_global_variable_address v in
1289+
TR.tbind
1290+
(fun gvaddr ->
1291+
if memmap#has_location gvaddr then
1292+
let gloc = memmap#get_location gvaddr in
1293+
TR.tmap
1294+
(fun offset -> self#f#env#mk_gloc_variable gloc offset)
1295+
(gloc#address_offset_memory_offset
1296+
~tgtsize:size ~tgtbtype:btype xoff)
1297+
else
1298+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
1299+
^ (p2s self#l#toPretty)
1300+
^ ": "
1301+
^ "Global location at address "
1302+
^ gvaddr#to_hex_string
1303+
^ " not found"])
1304+
gvaddr_r
12581305
| _ ->
1259-
let (memref_r, memoff_r) = self#decompose_memaddr addrvalue in
1260-
TR.tmap2
1261-
~msg1:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
1262-
(fun memref memoff ->
1263-
self#f#env#mk_offset_memory_variable memref memoff)
1264-
memref_r memoff_r
1306+
match memmap#xpr_containing_location addrvalue with
1307+
| Some gloc ->
1308+
(TR.tmap
1309+
(fun offset -> self#f#env#mk_gloc_variable gloc offset)
1310+
(gloc#address_memory_offset ~tgtsize:size ~tgtbtype:btype addrvalue))
1311+
| _ ->
1312+
let (memref_r, memoff_r) = self#decompose_memaddr addrvalue in
1313+
TR.tmap2
1314+
~msg1:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
1315+
(fun memref memoff ->
1316+
self#f#env#mk_offset_memory_variable memref memoff)
1317+
memref_r memoff_r
1318+
1319+
method private get_variable_type (v: variable_t): btype_t option =
1320+
if self#f#env#is_initial_register_value v then
1321+
let reg_r = self#f#env#get_initial_register_value_register v in
1322+
let param_r =
1323+
TR.tbind
1324+
(fun reg ->
1325+
if self#f#get_summary#has_parameter_for_register reg then
1326+
Ok (self#f#get_summary#get_parameter_for_register reg)
1327+
else
1328+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
1329+
^ (p2s v#toPretty)
1330+
^ " does not have an associated parameter"])
1331+
reg_r in
1332+
TR.tfold_default
1333+
(fun param -> Some param.apar_type)
1334+
(self#env#get_variable_type v)
1335+
param_r
1336+
else
1337+
self#env#get_variable_type v
1338+
1339+
method get_xpr_type (x: xpr_t): btype_t option =
1340+
match x with
1341+
| XVar v -> self#get_variable_type v
1342+
| _ -> None
12651343

12661344
method decompose_memaddr (x: xpr_t):
12671345
(memory_reference_int traceresult * memory_offset_t traceresult) =
@@ -1273,7 +1351,7 @@ object (self)
12731351
| [base] ->
12741352
let offset = simplify_xpr (XOp (XMinus, [x; XVar base])) in
12751353
let memref_r = self#env#mk_base_variable_reference base in
1276-
let vartype = self#f#env#get_variable_type base in
1354+
let vartype = self#get_variable_type base in
12771355
let vartype = match vartype with None -> t_unknown | Some t -> t in
12781356
let memoff_r = address_memory_offset vartype offset in
12791357
(*
@@ -1310,6 +1388,7 @@ object (self)
13101388
| _ ->
13111389
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
13121390
^ (p2s self#l#toPretty) ^ ": "
1391+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
13131392
^ "Offset from global base "
13141393
^ maxC#toString
13151394
^ " not recognized: " ^ (x2s offset)] in
@@ -1335,6 +1414,7 @@ object (self)
13351414
| _ ->
13361415
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
13371416
^ (p2s self#l#toPretty) ^ ": "
1417+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
13381418
^ "Offset from base "
13391419
^ (x2s (XVar base))
13401420
^ " not recognized: " ^ (x2s offset)] in
@@ -1364,6 +1444,7 @@ object (self)
13641444
| _ ->
13651445
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
13661446
^ (p2s self#l#toPretty) ^ ": "
1447+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
13671448
^ "Offset from base "
13681449
^ (x2s (XVar base))
13691450
^ " not recognized: " ^ (x2s offset)])
@@ -1384,6 +1465,7 @@ object (self)
13841465
let memref_r =
13851466
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
13861467
^ (p2s self#l#toPretty) ^ ": "
1468+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
13871469
^ "No candidate pointers. Left with maxC: "
13881470
^ maxC#toString] in
13891471
let memoff_r =
@@ -1395,6 +1477,7 @@ object (self)
13951477
let memref_r =
13961478
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
13971479
^ (p2s self#l#toPretty) ^ ": "
1480+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
13981481
^ "Multiple variables: "
13991482
^ (String.concat "; "
14001483
(List.map (fun v -> p2s v#toPretty) vars))] in
@@ -1407,6 +1490,7 @@ object (self)
14071490
let memref_r =
14081491
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
14091492
^ (p2s self#l#toPretty) ^ ": "
1493+
^ "decompose_memaddr: " ^ (x2s x) ^ ": "
14101494
^ "Multiple known pointers: "
14111495
^ (String.concat "; "
14121496
(List.map (fun v -> p2s v#toPretty) knownpointers))] in
@@ -1638,13 +1722,16 @@ object (self)
16381722
[BRANCH [LF.mkCode truecmds; LF.mkCode falsecmds]]
16391723

16401724
method private is_composite_symbolic_value (x: xpr_t): bool =
1641-
let is_external v = self#f#env#is_function_initial_value v in
1642-
let is_fixed_type v =
1643-
(is_external v)
1644-
|| (self#f#env#is_symbolic_value v) in
1645-
let vars = variables_in_expr x in
1646-
(List.length vars) > 0
1647-
&& List.for_all is_fixed_type (variables_in_expr x)
1725+
match x with
1726+
| XOp ((Xf "addressofvar"), [XVar _]) -> true
1727+
| _ ->
1728+
let is_external v = self#f#env#is_function_initial_value v in
1729+
let is_fixed_type v =
1730+
(is_external v)
1731+
|| (self#f#env#is_symbolic_value v) in
1732+
let vars = variables_in_expr x in
1733+
(List.length vars) > 0
1734+
&& List.for_all is_fixed_type (variables_in_expr x)
16481735

16491736
method get_assign_commands_r
16501737
?(signed=false)
@@ -1693,6 +1780,26 @@ object (self)
16931780
else
16941781
rhs in
16951782

1783+
let rhs =
1784+
(* if rhs is the address of a global variable create an address-of
1785+
expression for that global variable. *)
1786+
match rhs with
1787+
| XConst (IntConst n) ->
1788+
let dw = numerical_mod_to_doubleword n in
1789+
if memmap#has_location dw then
1790+
TR.tfold
1791+
~ok:(fun gv -> XOp ((Xf "addressofvar"), [XVar gv]))
1792+
~error:(fun e ->
1793+
begin
1794+
log_result
1795+
~tag:"assign global variable address" __FILE__ __LINE__ e;
1796+
rhs
1797+
end)
1798+
(self#f#env#mk_global_variable n)
1799+
else
1800+
rhs
1801+
| _ -> rhs in
1802+
16961803
let rhs =
16971804
(* if rhs is a composite symbolic expression, create a new variable
16981805
for it *)

CodeHawk/CHB/bchlib/bCHFunctionInfo.ml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,37 @@ object (self)
15361536

15371537
method is_signed_symbolic_value = varmgr#is_signed_symbolic_value
15381538

1539+
method is_addressof_symbolic_value (v: variable_t) =
1540+
if self#is_symbolic_value v then
1541+
let symx_r = self#get_symbolic_value_expr v in
1542+
TR.tfold_default
1543+
(fun symx ->
1544+
match symx with
1545+
| XOp ((Xf "addressofvar"), _) -> true
1546+
| _ -> false)
1547+
false
1548+
symx_r
1549+
else
1550+
false
1551+
1552+
method get_addressof_symbolic_expr (v: variable_t): xpr_t traceresult =
1553+
if self#is_addressof_symbolic_value v then
1554+
let symx_r = self#get_symbolic_value_expr v in
1555+
TR.tbind
1556+
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
1557+
(fun symx ->
1558+
match symx with
1559+
| XOp ((Xf "addressofvar"), [x]) -> Ok x
1560+
| _ ->
1561+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
1562+
^ "Not an addressofvar symbolic expression: "
1563+
^ (x2s symx)])
1564+
symx_r
1565+
else
1566+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ": "
1567+
^ "Not a symbolic-value expression: "
1568+
^ (p2s v#toPretty)]
1569+
15391570
method get_symbolic_value_expr (v: variable_t): xpr_t traceresult =
15401571
if self#is_symbolic_value v then
15411572
varmgr#get_symbolic_value_expr v

CodeHawk/CHB/bchlib/bCHFunctionSummary.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ object (self:'a)
146146
(BCH_failure
147147
(LBLOCK [STR "Internal error: get_parameter_for_register"]))
148148

149+
method has_parameter_for_register (reg: register_t): bool =
150+
Option.is_some
151+
(get_register_parameter_for_register self#get_function_interface reg)
152+
149153
method get_parameter_at_stack_offset (offset: int): fts_parameter_t =
150154
let spar = get_stack_parameter_at_offset self#get_function_interface offset in
151155
match spar with

CodeHawk/CHB/bchlib/bCHGlobalMemoryMap.ml

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
------------------------------------------------------------------------------
55
The MIT License (MIT)
66
7-
Copyright (c) 2024 Aarno Labs LLC
7+
Copyright (c) 2024-2025 Aarno Labs LLC
88
99
Permission is hereby granted, free of charge, to any person obtaining a copy
1010
of this software and associated documentation files (the "Software"), to deal
@@ -370,37 +370,41 @@ object (self)
370370
^ "xoffset: " ^ (x2s xoffset)
371371
^ "; btype: " ^ (btype_to_string btype)]
372372

373+
method address_offset_memory_offset
374+
?(tgtsize=None)
375+
?(tgtbtype=t_unknown)
376+
(xoffset: xpr_t): memory_offset_t traceresult =
377+
match xoffset with
378+
| XConst (IntConst n)
379+
when n#equal CHNumerical.numerical_zero
380+
&& Option.is_none tgtsize
381+
&& is_unknown_type tgtbtype ->
382+
Ok NoOffset
383+
| XConst (IntConst n)
384+
when n#equal CHNumerical.numerical_zero && (not self#is_typed) ->
385+
Ok NoOffset
386+
| XConst (IntConst n) when not self#is_typed ->
387+
Ok (ConstantOffset (n, NoOffset))
388+
| _ ->
389+
let tgtbtype =
390+
if is_unknown_type tgtbtype then None else Some tgtbtype in
391+
if self#is_struct then
392+
let btype = TR.tvalue (resolve_type self#btype) ~default:t_unknown in
393+
self#structvar_memory_offset ~tgtsize ~tgtbtype btype xoffset
394+
else if self#is_array then
395+
let btype = TR.tvalue (resolve_type self#btype) ~default:t_unknown in
396+
self#arrayvar_memory_offset ~tgtsize ~tgtbtype btype xoffset
397+
else
398+
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ":"
399+
^ (btype_to_string self#btype)
400+
^ " is not known to be a struct or array"]
401+
373402
method address_memory_offset
374403
?(tgtsize=None)
375404
?(tgtbtype=t_unknown)
376405
(xpr: xpr_t): memory_offset_t traceresult =
377-
tbind
378-
~msg:(__FILE__ ^ ":" ^ (string_of_int __LINE__))
379-
(fun xoffset ->
380-
match xoffset with
381-
| XConst (IntConst n)
382-
when n#equal CHNumerical.numerical_zero
383-
&& Option.is_none tgtsize
384-
&& is_unknown_type tgtbtype ->
385-
Ok NoOffset
386-
| XConst (IntConst n)
387-
when n#equal CHNumerical.numerical_zero && (not self#is_typed) ->
388-
Ok NoOffset
389-
| XConst (IntConst n) when not self#is_typed ->
390-
Ok (ConstantOffset (n, NoOffset))
391-
| _ ->
392-
let tgtbtype =
393-
if is_unknown_type tgtbtype then None else Some tgtbtype in
394-
if self#is_struct then
395-
let btype = TR.tvalue (resolve_type self#btype) ~default:t_unknown in
396-
self#structvar_memory_offset ~tgtsize ~tgtbtype btype xoffset
397-
else if self#is_array then
398-
let btype = TR.tvalue (resolve_type self#btype) ~default:t_unknown in
399-
self#arrayvar_memory_offset ~tgtsize ~tgtbtype btype xoffset
400-
else
401-
Error [__FILE__ ^ ":" ^ (string_of_int __LINE__) ^ ":"
402-
^ (btype_to_string self#btype)
403-
^ " is not known to be a struct or array"])
406+
TR.tbind
407+
(self#address_offset_memory_offset ~tgtsize ~tgtbtype)
404408
(self#address_offset xpr)
405409

406410
method initialvalue: globalvalue_t option = grec.gloc_initialvalue

0 commit comments

Comments
 (0)