Skip to content

Commit b29f97e

Browse files
committed
ARM: astprov conversion for result types
1 parent a6486a7 commit b29f97e

File tree

9 files changed

+149
-52
lines changed

9 files changed

+149
-52
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-20241111"
1+
chbversion: str = "0.3.0-20250203"

chb/arm/opcodes/ARMAdd.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,15 @@ def pointer_arithmetic_expr() -> AST.ASTExpr:
353353

354354
chklogger.logger.error(
355355
"Second operand pointer variable not yet supported for %s at "
356-
+ "address %s",
357-
str(rhs3), iaddr)
356+
+ "address %s; rrhs1: %s; hl_rhs1: %s; hl_rhs2: %s; hl_rhs1_type: %s;"
357+
+ " hl_rhs2_type: %s",
358+
str(rhs3),
359+
iaddr,
360+
str(rrhs1),
361+
str(hl_rhs1),
362+
str(hl_rhs2),
363+
str(hl_rhs1_type),
364+
str(hl_rhs2_type))
358365
return astree.mk_temp_lval_expression()
359366

360367

@@ -392,8 +399,14 @@ def pointer_arithmetic_expr() -> AST.ASTExpr:
392399

393400
elif (hl_lhs_type is not None and hl_lhs_type.is_pointer):
394401
hl_rhs = pointer_arithmetic_expr()
395-
if rhs3.is_constant_expression:
396-
astree.set_ssa_value(str(hl_lhs), hl_rhs)
402+
if str(hl_rhs).startswith("astmem_tmp"):
403+
chklogger.logger.error(
404+
"Unable to compute pointer arithmetic expression for %s "
405+
"at address %s",
406+
str(rhs3), iaddr)
407+
else:
408+
if rhs3.is_constant_expression:
409+
astree.set_ssa_value(str(hl_lhs), hl_rhs)
397410

398411
else:
399412
hl_rhs = XU.xxpr_to_ast_def_expr(rhs3, xdata, iaddr, astree)

chb/arm/opcodes/ARMStoreMultipleIncrementAfter.py

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,34 @@ def ldmstm_xpr(self, index: int, msg: str) -> "XXpr":
6969
def xdst(self) -> "XXpr":
7070
return self.ldmstm_xpr(0, "xdst")
7171

72+
@property
73+
def is_xdst_unknown(self) -> bool:
74+
return self.xdata.xprs_r[0] is None
75+
7276
@property
7377
def xsrc(self) -> "XXpr":
7478
return self.ldmstm_xpr(1, "xsrc")
7579

80+
@property
81+
def is_xsrc_unknowns(self) -> bool:
82+
return self.xdata.xprs_r[1] is None
83+
7684
@property
7785
def xxdst(self) -> "XXpr":
7886
return self.ldmstm_xpr(2, "xxdst")
7987

88+
@property
89+
def is_xxdst_unknown(self) -> bool:
90+
return self.xdata.xprs_r[2] is None
91+
8092
@property
8193
def xxsrc(self) -> "XXpr":
8294
return self.ldmstm_xpr(3, "xxsrc")
8395

96+
@property
97+
def is_xxsrc_unknown(self) -> bool:
98+
return self.xdata.xprs_r[3] is None
99+
84100
@property
85101
def copysize(self) -> int:
86102
if self.is_ldmstm_aggregate:
@@ -90,17 +106,39 @@ def copysize(self) -> int:
90106

91107
@property
92108
def annotation(self) -> str:
93-
if self.is_ldmstm_aggregate:
94-
return (
95-
"memcpy(" +
96-
str(self.xxdst)
97-
+ ", "
98-
+ str(self.xxsrc)
99-
+ ", "
100-
+ str(self.copysize)
101-
+ ")")
109+
if self.is_ok:
110+
if self.is_ldmstm_aggregate:
111+
return (
112+
"memcpy(" +
113+
str(self.xxdst)
114+
+ ", "
115+
+ str(self.xxsrc)
116+
+ ", "
117+
+ str(self.copysize)
118+
+ ")")
119+
else:
120+
return "not yet supported"
102121
else:
103-
return "not yet supported"
122+
if self.is_ldmstm_aggregate:
123+
if self.is_xxdst_unknown and self.is_xxsrc_unknown:
124+
dst = str(self.xdst)
125+
src = str(self.xsrc)
126+
elif self.is_xxdst_unknown:
127+
dst = str(self.xdst)
128+
src = str(self.xxsrc)
129+
else:
130+
dst = str(self.xxdst)
131+
src = str(self.xsrc)
132+
return (
133+
"memcpy("
134+
+ dst
135+
+ ", "
136+
+ src
137+
+ ", "
138+
+ str(self.copysize)
139+
+ ")")
140+
else:
141+
return "not yet supported"
104142

105143

106144

@@ -166,10 +204,7 @@ def is_store_instruction(self, xdata: InstrXData) -> bool:
166204

167205
def annotation(self, xdata: InstrXData) -> str:
168206
xd = ARMStoreMultipleIncrementAfterXData(xdata)
169-
if xd.is_ok:
170-
return xd.annotation
171-
else:
172-
return "Error value"
207+
return xd.annotation
173208

174209
def ast_prov_ldmstmcopy(
175210
self,
@@ -232,8 +267,13 @@ def ast_prov_ldmstmcopy(
232267

233268
xd = ARMStoreMultipleIncrementAfterXData(xdata)
234269
if not xd.is_ok:
235-
chklogger.logger.error(
236-
"Encountered error value at address %s", iaddr)
270+
if xd.is_xxsrc_unknown and xd.is_xxdst_unknown:
271+
chklogger.logger.error(
272+
"LDM-STM-memcpy: (%s): src and dst unknown", iaddr)
273+
elif xd.is_xxsrc_unknown:
274+
chklogger.logger.error("LDM-STM-memcpy: (%s): src unknown", iaddr)
275+
else:
276+
chklogger.logger.error("LDM-STM-memcpy: (%s): dst unknown", iaddr)
237277
return ([], [])
238278

239279
xdst = xd.xdst

chb/arm/opcodes/ARMUnsignedExtendHalfword.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,9 @@ def ast_prov(
197197
astree.add_lval_defuses(hl_lhs, defuses[0])
198198
astree.add_lval_defuses_high(hl_lhs, defuseshigh[0])
199199

200+
if astree.has_register_variable_intro(iaddr):
201+
rvintro = astree.get_register_variable_intro(iaddr)
202+
if rvintro.has_cast():
203+
astree.add_expose_instruction(hl_assign.instrid)
204+
200205
return ([hl_assign], [ll_assign])

chb/astinterface/ASTICodeTransformer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def transform_instruction_sequence_stmt(
105105
"Transfor [%s]: global lhs", str(instr))
106106
instrs.append(instr)
107107
else:
108-
chklogger.logger.debug("Transform [%s]: remove", str(instr))
108+
chklogger.logger.info("Transform [%s]: remove", str(instr))
109109
else:
110110
instrs.append(instr)
111111
return self.astinterface.mk_instr_sequence(

chb/astinterface/ASTInterface.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@
6262
from chb.astinterface.ASTIProvenance import ASTIProvenance
6363
import chb.astinterface.ASTIUtil as AU
6464

65-
from chb.userdata.UserHints import FunctionAnnotation, RegisterVarIntro
65+
from chb.userdata.UserHints import (
66+
FunctionAnnotation, RegisterVarIntro, StackVarIntro)
6667

6768
import chb.util.fileutil as UF
6869
from chb.util.loggingutil import chklogger
@@ -302,13 +303,16 @@ def get_register_variable_intro(self, iaddr: str) -> RegisterVarIntro:
302303
raise UF.CHBError("No function annotation found")
303304

304305
def has_stack_variable_intro(self, offset: int) -> bool:
305-
return offset in self.stackvarintros
306+
fnannotation = self.function_annotation
307+
if fnannotation is not None:
308+
return fnannotation.has_stack_variable_introduction(offset)
309+
return False
306310

307-
def get_stack_variable_intro(self, offset: int) -> str:
308-
if self.has_stack_variable_intro(offset):
309-
return self.stackvarintros[offset]
310-
else:
311-
raise UF.CHBError("No stack-variable intro found for " + str(offset))
311+
def get_stack_variable_intro(self, offset: int) -> StackVarIntro:
312+
fnannotation = self.function_annotation
313+
if fnannotation is not None:
314+
return fnannotation.get_stack_variable_introduction(offset)
315+
raise UF.CHBError("No function annotation found")
312316

313317
def set_available_expressions(
314318
self, aexprs: Dict[str, Dict[str, Tuple[int, int, str]]]) -> None:
@@ -1095,13 +1099,15 @@ def mk_stack_variable_lval(
10951099
return self.stack_variables[offset]
10961100

10971101
# create a new stack variable
1098-
if offset in self.stackvarintros:
1099-
vname = self.stackvarintros[offset]
1102+
if self.has_stack_variable_intro(offset):
1103+
svintro = self.get_stack_variable_intro(offset)
1104+
vname = svintro.name
11001105
else:
11011106
if offset < 0:
11021107
vname = "localstackvar_" + str(-offset)
11031108
else:
11041109
vname = "stack_" + str(offset)
1110+
11051111
size: Optional[int] = None
11061112
if vtype is not None:
11071113
size = self.type_size_in_bytes(vtype)

chb/invariants/VAssemblyVariable.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ def __str__(self) -> str:
330330
elif self.is_realigned_stack_variable:
331331
offset = self.offset.offsetvalue()
332332
return 'varr.' + '{0:04d}'.format(offset)
333+
elif self.offset.is_no_offset:
334+
return "*" + str(self.base)
333335
return str(str(self.base)) + '[' + str(self.offset) + ']'
334336

335337

chb/invariants/VConstantValueVariable.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#
77
# Copyright (c) 2016-2020 Kestrel Technology LLC
88
# Copyright (c) 2020 Henny 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
@@ -197,7 +197,10 @@ def variable(self) -> "XVariable":
197197

198198
@property
199199
def register(self) -> "Register":
200-
raise UF.CHBError("Constant value is not an initial register value")
200+
raise UF.CHBError(
201+
"Constant value is not an initial register value: "
202+
+ str(self)
203+
+ " (" + self.tags[0] + ")")
201204

202205
def argument_deref_arg_offset(self, inbytes: bool = False) -> Tuple[int, int]:
203206
raise UF.CHBError("argument_deref_arg_offset not supported on "
@@ -372,7 +375,9 @@ def is_function_return_deref_value(self) -> bool:
372375
if avar.is_memory_variable and avar.is_basevar_variable:
373376
xbasevar = avar.basevar
374377
offset = avar.offset
375-
return xbasevar.is_function_return_value and offset.is_constant_offset
378+
return (
379+
xbasevar.is_function_return_value
380+
and (offset.is_constant_offset or offset.is_no_offset))
376381
else:
377382
return False
378383

@@ -595,7 +600,7 @@ def register(self) -> Register:
595600
return self.bd.register(self.args[1])
596601

597602
def __str__(self) -> str:
598-
return self.name
603+
return self.name + "(" + self.iaddr + ", " + str(self.tgttype) + ")"
599604

600605

601606
@varregistry.register_tag("fp", VConstantValueVariable)

chb/invariants/XXprUtil.py

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def xconstant_to_ast_expr(
149149
gvaddrtype = gvaddr.ctype(astree.ctyper)
150150
if gvaddrtype is not None and gvaddrtype.is_array:
151151
# array already is an address
152-
return astree.mk_lval_expr(lval)
152+
return astree.mk_start_of(lval)
153153
else:
154154
return astree.mk_address_of(lval)
155155
else:
@@ -259,7 +259,7 @@ def vreturn_deref_value_to_ast_lval_expression(
259259
astree: ASTInterface,
260260
anonymous: bool = False) -> AST.ASTExpr:
261261

262-
if not offset.is_constant_value_offset:
262+
if not (offset.is_constant_value_offset or offset.is_no_offset):
263263
chklogger.logger.error(
264264
"Non-constant offset: %s not yet supported at address %s",
265265
str(offset), iaddr)
@@ -669,7 +669,7 @@ def vinitmemory_value_to_ast_lval_expression(
669669

670670
if avar.is_memory_variable and avar.is_basevar_variable:
671671
avar = cast("VMemoryVariable", avar)
672-
if not avar.offset.is_constant_value_offset:
672+
if not (avar.offset.is_constant_value_offset or avar.offset.is_no_offset):
673673
chklogger.logger.error(
674674
"Non-constant offset: %s not yet supported at address %s",
675675
str(avar.offset), iaddr)
@@ -852,6 +852,8 @@ def xvariable_to_ast_def_lval_expression(
852852
return astree.mk_temp_lval_expression()
853853

854854
else:
855+
chklogger.logger.error(
856+
"No rdefs found for %s at address %s", str(reg), iaddr)
855857
return astree.mk_temp_lval_expression()
856858

857859
if xvar.is_global_variable:
@@ -890,7 +892,17 @@ def xvariable_to_ast_def_lval_expression(
890892
return astree.mk_vinfo_lval_expression(vinfo, anonymous=anonymous)
891893

892894
if xvar.is_typecast_value:
893-
tcvar = cast("VTypeCastValue", xvar.denotation)
895+
tcvar = cast("VTypeCastValue", xvar.denotation.auxvar)
896+
variaddr = tcvar.iaddr
897+
varreg = tcvar.register
898+
if variaddr in astree.ssa_intros and str(varreg) in astree.ssa_intros[variaddr]:
899+
vinfo = astree.ssa_intros[variaddr][str(varreg)]
900+
ssavalue = astree.get_ssa_value(vinfo.vname)
901+
if ssavalue is not None:
902+
return ssavalue
903+
else:
904+
return astree.mk_vinfo_lval_expression(
905+
vinfo, anonymous=anonymous)
894906
chklogger.logger.error(
895907
"AST def conversion of typecast value %s to lval at address %s "
896908
+ "not yet supported",
@@ -1755,19 +1767,32 @@ def vargument_deref_value_to_ast_lval(
17551767
anonymous: bool = False) -> AST.ASTLval:
17561768

17571769
if offset.is_no_offset:
1758-
asmvar = cast("VAuxiliaryVariable", basevar.denotation)
1759-
vinitvar = cast("VInitialRegisterValue", asmvar.auxvar)
1760-
xinitarg = vinitregister_value_to_ast_lval_expression(
1761-
vinitvar, xdata, iaddr, astree, anonymous=anonymous)
1762-
argtype = xinitarg.ctype(astree.ctyper)
1763-
if argtype is None:
1764-
chklogger.logger.error(
1765-
"Untyped dereferenced argument value %s not yet supported at "
1766-
+ "address %s",
1767-
str(xinitarg), iaddr)
1768-
return astree.mk_temp_lval()
1769-
else:
1770-
return astree.mk_memref_lval(xinitarg, anonymous=anonymous)
1770+
if basevar.is_initial_register_value:
1771+
asmvar = cast("VAuxiliaryVariable", basevar.denotation)
1772+
vinitvar = cast("VInitialRegisterValue", asmvar.auxvar)
1773+
xinitarg = vinitregister_value_to_ast_lval_expression(
1774+
vinitvar, xdata, iaddr, astree, anonymous=anonymous)
1775+
argtype = xinitarg.ctype(astree.ctyper)
1776+
if argtype is None:
1777+
chklogger.logger.error(
1778+
"Untyped dereferenced argument value %s not yet supported at "
1779+
+ "address %s",
1780+
str(xinitarg), iaddr)
1781+
return astree.mk_temp_lval()
1782+
else:
1783+
return astree.mk_memref_lval(xinitarg, anonymous=anonymous)
1784+
1785+
if basevar.is_function_return_value:
1786+
asmvar = cast("VAuxiliaryVariable", basevar.denotation)
1787+
frvinitrvar = cast("VFunctionReturnValue", asmvar.auxvar)
1788+
callsite = frvinitrvar.callsite
1789+
if callsite in astree.ssa_intros:
1790+
if len(astree.ssa_intros[callsite]) == 1:
1791+
vinfo = list(astree.ssa_intros[callsite].values())[0]
1792+
vtype = vinfo.vtype
1793+
vexpr = astree.mk_vinfo_lval_expression(
1794+
vinfo, anonymous=anonymous)
1795+
return astree.mk_memref_lval(vexpr, anonymous=anonymous)
17711796

17721797
if not offset.is_constant_value_offset:
17731798
chklogger.logger.error(
@@ -1977,6 +2002,7 @@ def xmemory_dereference_lval(
19772002
anonymous: bool = False) -> AST.ASTLval:
19782003

19792004
xaddr = xxpr_to_ast_def_expr(address, xdata, iaddr, astree)
2005+
19802006
if xaddr.is_ast_binary_op:
19812007
xaddr = cast(AST.ASTBinaryOp, xaddr)
19822008
if xaddr.exp1.is_ast_startof:

0 commit comments

Comments
 (0)