Skip to content

Commit ef75640

Browse files
committed
XXPR: add support for baseptr array index offset
1 parent 5753d90 commit ef75640

File tree

6 files changed

+101
-21
lines changed

6 files changed

+101
-21
lines changed

chb/app/CHVersion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
chbversion: str = "0.3.0-20250329"
1+
chbversion: str = "0.3.0-20250401"

chb/arm/opcodes/ARMStoreRegisterByte.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ def ast_prov(
278278
rhs = xd.xxrt
279279
else:
280280
rhs = xd.xrt
281+
281282
hl_rhs = XU.xxpr_to_ast_def_expr(rhs, xdata, iaddr, astree)
282283

283284
rdefs = xdata.reachingdefs

chb/astinterface/ASTICodeTransformer.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------------------------------------------------
55
# The MIT License (MIT)
66
#
7-
# Copyright (c) 2022-2024 Aarno Labs LLC
7+
# Copyright (c) 2022-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
@@ -85,28 +85,29 @@ def transform_instruction_sequence_stmt(
8585
and not self.provenance.has_expose_instruction(instr.instrid)):
8686
chklogger.logger.info(
8787
"Remove [%s]: has ssa value", str(instr))
88-
continue
89-
if self.provenance.has_active_lval_defuse_high(instr.lhs.lvalid):
90-
chklogger.logger.debug(
88+
elif self.provenance.has_active_lval_defuse_high(instr.lhs.lvalid):
89+
chklogger.logger.info(
9190
"Transform [%s]: active lval_defuse_high: %s",
9291
str(instr),
9392
self.provenance.active_lval_defuse_high(instr.lhs.lvalid))
9493
instrs.append(instr)
9594
elif self.provenance.has_lval_store(instr.lhs.lvalid):
96-
chklogger.logger.debug(
95+
chklogger.logger.info(
9796
"Transform [%s]: lval_store", str(instr))
9897
instrs.append(instr)
9998
elif self.provenance.has_expose_instruction(instr.instrid):
10099
chklogger.logger.info(
101100
"Transform [%s]: expose instruction", str(instr))
102101
instrs.append(instr)
103102
elif instr.lhs.lhost.is_global:
104-
chklogger.logger.debug(
105-
"Transfor [%s]: global lhs", str(instr))
103+
chklogger.logger.info(
104+
"Transform [%s]: global lhs", str(instr))
106105
instrs.append(instr)
107106
else:
108107
chklogger.logger.info("Transform [%s]: remove", str(instr))
109108
else:
109+
chklogger.logger.info(
110+
"Transform [%s]: include by default", str(instr))
110111
instrs.append(instr)
111112
return self.astinterface.mk_instr_sequence(
112113
instrs,

chb/cmdline/commandutil.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -638,21 +638,22 @@ def results_stats(args: argparse.Namespace) -> NoReturn:
638638
mode=logfilemode,
639639
msg="results stats invoked")
640640

641-
tags: Dict[str, List[str]] = {}
641+
tagdata: Dict[str, Any] = {}
642642
if tagfile is not None:
643643
with open(tagfile, "r") as fp:
644644
tagdata = json.load(fp)
645-
for (key, flist) in tagdata["keys"].items():
646-
for faddr in flist:
647-
tags.setdefault(faddr, [])
648-
if not key in tags[faddr]:
649-
tags[faddr].append(key)
645+
646+
functiontags: Dict[str, List[str]] = {}
647+
648+
if "function-tags" in tagdata:
649+
functiontags = tagdata["function-tags"]
650650

651651
maxlen = 0
652-
for (faddr, keys) in tags.items():
653-
taglen = 4 + len(",".join(keys))
652+
for (faddr, keys) in functiontags.items():
653+
taglen = len(",".join(keys))
654654
if taglen > maxlen:
655655
maxlen = taglen
656+
maxlen = maxlen + 4 if maxlen > 0 else 0
656657

657658
xinfo = XI.XInfo()
658659
xinfo.load(path, xfile)
@@ -672,8 +673,8 @@ def results_stats(args: argparse.Namespace) -> NoReturn:
672673
else:
673674
sortkey = lambda f: int(f.faddr, 16)
674675
for f in sorted(stats.get_function_results(), key=sortkey):
675-
if f.faddr in tags:
676-
fn_tags = tags[f.faddr]
676+
if f.faddr in functiontags:
677+
fn_tags = functiontags[f.faddr]
677678
else:
678679
fn_tags = []
679680
if "hide" in fn_tags:

chb/invariants/VMemoryOffset.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
| FieldOffset of string * int * memory_offset_t "f" 2 2
3737
| IndexOffset of variable_t * int * memory_offset_t "i" 1 3
3838
| ArrayIndexOffset of xpr_t * memory_offset_t "a" 1 2
39+
| BasePtrArrayIndexOffset of xpr_t * memory_offset_t "p" 1 2
3940
| UnknownOffset "u" 1 0
4041
4142
"""
@@ -84,6 +85,10 @@ def is_index_offset(self) -> bool:
8485
def is_array_index_offset(self) -> bool:
8586
return False
8687

88+
@property
89+
def is_baseptr_array_index_offset(self) -> bool:
90+
return False
91+
8792
@property
8893
def is_no_offset(self) -> bool:
8994
return False
@@ -388,6 +393,39 @@ def __str__(self) -> str:
388393
return "[" + str(self.index_expression) + "]" + str(self.offset)
389394

390395

396+
@varregistry.register_tag("p", VMemoryOffset)
397+
class VMemoryOffsetBasePtrArrayIndexOffset(VMemoryOffset):
398+
"""Array index offset
399+
400+
args[0]: index of index expression in xprdictionary
401+
args[1]: index of next-level offset in vardictionary
402+
"""
403+
404+
def __init__(
405+
self,
406+
vd: "FnVarDictionary",
407+
ixval: IndexedTableValue) -> None:
408+
VMemoryOffset.__init__(self, vd, ixval)
409+
410+
@property
411+
def index_expression(self) -> "XXpr":
412+
return self.xd.xpr(self.args[0])
413+
414+
@property
415+
def offset(self) -> VMemoryOffset:
416+
return self.vd.memory_offset(self.args[1])
417+
418+
@property
419+
def is_baseptr_array_index_offset(self) -> bool:
420+
return True
421+
422+
def has_no_offset(self) -> bool:
423+
return self.offset.is_no_offset
424+
425+
def __str__(self) -> str:
426+
return "[" + str(self.index_expression) + "]" + str(self.offset)
427+
428+
391429
@varregistry.register_tag("u", VMemoryOffset)
392430
class VMemoryOffsetUnknown(VMemoryOffset):
393431

chb/invariants/XXprUtil.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
VMemoryOffsetConstantOffset,
123123
VMemoryOffsetFieldOffset,
124124
VMemoryOffsetArrayIndexOffset,
125+
VMemoryOffsetBasePtrArrayIndexOffset,
125126
VMemoryOffsetIndexOffset)
126127
from chb.mips.MIPSRegister import MIPSRegister
127128

@@ -437,7 +438,10 @@ def memory_variable_to_lval_expression(
437438
return astree.mk_memref_expr(
438439
astbase, offset=astoffset, anonymous=anonymous)
439440

440-
else:
441+
elif (
442+
offset.is_field_offset
443+
or offset.is_array_index_offset
444+
or offset.is_constant_value_offset):
441445
astlval = xvariable_to_ast_def_lval_expression(
442446
base.basevar, xdata, iaddr, astree, anonymous=anonymous)
443447
if offset.is_field_offset:
@@ -451,10 +455,27 @@ def memory_variable_to_lval_expression(
451455
elif offset.is_constant_value_offset:
452456
astoffset = astree.mk_scalar_index_offset(offset.offsetvalue())
453457
else:
458+
chklogger.logger.warning(
459+
"Offset %s not yet handled at address %s",
460+
str(offset), iaddr)
454461
astoffset = nooffset
455462
return astree.mk_memref_expr(
456463
astlval, offset=astoffset, anonymous=anonymous)
457464

465+
elif offset.is_baseptr_array_index_offset:
466+
astlval = xvariable_to_ast_def_lval_expression(
467+
base.basevar, xdata, iaddr, astree, anonymous=anonymous)
468+
offset = cast("VMemoryOffsetBasePtrArrayIndexOffset", offset)
469+
(ptroffset, astoffset) = base_ptr_array_offset_to_ast_offset(
470+
offset, xdata, iaddr, astree, anonymous=anonymous)
471+
if ptroffset.is_integer_constant_zero:
472+
return astree.mk_memref_expr(
473+
astlval, offset=astoffset, anonymous=anonymous)
474+
else:
475+
ptrexpr = astree.mk_binary_op("plus", ptroffset, astlval)
476+
return astree.mk_memref_expr(
477+
ptrexpr, offset=astoffset, anonymous=anonymous)
478+
458479
name = str(base)
459480

460481
if not astree.globalsymboltable.has_symbol(name):
@@ -1499,6 +1520,25 @@ def stack_variable_to_ast_lval(
14991520
return astree.mk_temp_lval()
15001521

15011522

1523+
def base_ptr_array_offset_to_ast_offset(
1524+
offset: "VMemoryOffsetBasePtrArrayIndexOffset",
1525+
xdata: "InstrXData",
1526+
iaddr: str,
1527+
astree: ASTInterface,
1528+
anonymous: bool = False) -> Tuple[AST.ASTExpr, AST.ASTOffset]:
1529+
1530+
indexxpr = xxpr_to_ast_def_expr(
1531+
offset.index_expression, xdata, iaddr, astree, anonymous=anonymous)
1532+
1533+
if offset.has_no_offset() and indexxpr.is_integer_constant:
1534+
return (indexxpr, nooffset)
1535+
1536+
chklogger.logger.error(
1537+
"Base ptr array offset %s not yet handled at address %s",
1538+
str(offset), iaddr)
1539+
return (astree.mk_integer_constant(0), nooffset)
1540+
1541+
15021542
def array_offset_to_ast_offset(
15031543
offset: "VMemoryOffsetArrayIndexOffset",
15041544
xdata: "InstrXData",
@@ -1675,8 +1715,7 @@ def xvariable_to_ast_lval(
16751715
if (
16761716
rhs is not None
16771717
and (rhs.is_constant
1678-
or (rhs.is_constant_value_variable
1679-
and not rhs.is_function_return_value))):
1718+
or (rhs.is_constant_value_variable))):
16801719
astrhs: Optional[AST.ASTExpr] = xxpr_to_ast_def_expr(
16811720
rhs, xdata, iaddr, astree, anonymous=anonymous)
16821721
else:

0 commit comments

Comments
 (0)