Skip to content

Commit 5b0b6a9

Browse files
committed
ARM: add astprov for STMIB
1 parent 6c63031 commit 5b0b6a9

File tree

3 files changed

+145
-10
lines changed

3 files changed

+145
-10
lines changed

chb/arm/ARMCallOpcode.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,10 @@ def ast_call_prov(
278278
hl_lhs = XU.xvariable_to_ast_lval(
279279
lhs, xdata, iaddr, astree, ctype=asttype)
280280

281-
if rtype.is_void or defuses[0] is None:
281+
# Note that defuses[0] may be None even when defuseshigh[0] is not
282+
# None. This happens when the return value's only use is as a
283+
# return value of the caller's function itself.
284+
if rtype.is_void or ((defuses[0] is None) and (defuseshigh[0] is None)):
282285
chklogger.logger.info(
283286
"Unused: introduced ssa-variable: %s for return value of %s "
284287
+ "at address %s",

chb/arm/opcodes/ARMStoreMultipleIncrementBefore.py

Lines changed: 139 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------------------------------------------------
55
# The MIT License (MIT)
66
#
7-
# Copyright (c) 2021-2023 Aarno Labs LLC
7+
# Copyright (c) 2021-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
@@ -25,20 +25,69 @@
2525
# SOFTWARE.
2626
# ------------------------------------------------------------------------------
2727

28-
from typing import List, TYPE_CHECKING
28+
from typing import cast, List, Tuple, TYPE_CHECKING
2929

3030
from chb.app.InstrXData import InstrXData
3131

3232
from chb.arm.ARMDictionaryRecord import armregistry
33-
from chb.arm.ARMOpcode import ARMOpcode, simplify_result
33+
from chb.arm.ARMOpcode import ARMOpcode, ARMOpcodeXData, simplify_result
3434
from chb.arm.ARMOperand import ARMOperand
3535

36-
import chb.util.fileutil as UF
36+
import chb.ast.ASTNode as AST
37+
from chb.astinterface.ASTInterface import ASTInterface
38+
39+
import chb.invariants.XXprUtil as XU
3740

41+
import chb.util.fileutil as UF
3842
from chb.util.IndexedTable import IndexedTableValue
43+
from chb.util.loggingutil import chklogger
44+
3945

4046
if TYPE_CHECKING:
4147
from chb.arm.ARMDictionary import ARMDictionary
48+
from chb.invariants.VAssemblyVariable import VMemoryVariable
49+
from chb.invariants.XVariable import XVariable
50+
from chb.invariants.XXpr import XXpr
51+
52+
53+
class ARMStoreMultipleIncrementBeforeXData(ARMOpcodeXData):
54+
55+
def __init__(self, xdata: InstrXData) -> None:
56+
ARMOpcodeXData.__init__(self, xdata)
57+
58+
@property
59+
def regcount(self) -> int:
60+
return len(self.xdata.vars_r) - 1
61+
62+
@property
63+
def baselhs(self) -> "XVariable":
64+
return self.var(0, "baselhs")
65+
66+
@property
67+
def is_baselhs_known(self) -> bool:
68+
return self.xdata.vars_r[0] is not None
69+
70+
@property
71+
def memlhss(self) -> List["XVariable"]:
72+
return [self.var(i, "memlhs-" + str(i))
73+
for i in range(1, self.regcount + 1)]
74+
75+
@property
76+
def rhss(self) -> List["XXpr"]:
77+
return [self.xpr(i, "rhs-" + str(i))
78+
for i in range(3, self.regcount + 3)]
79+
80+
@property
81+
def annotation(self) -> str:
82+
wbu = self.writeback_update()
83+
if self.is_ok:
84+
assigns: List[str] = []
85+
for (memlhs, rhs) in zip(self.memlhss, self.rhss):
86+
assigns.append(str(memlhs) + " := " + str(rhs))
87+
return ": ".join(assigns) + wbu
88+
else:
89+
return "Error value"
90+
4291

4392

4493
@armregistry.register_tag("STMIB", ARMOpcode)
@@ -65,13 +114,94 @@ def __init__(
65114
def operands(self) -> List[ARMOperand]:
66115
return [self.armd.arm_operand(self.args[i]) for i in [1, 2]]
67116

117+
@property
118+
def opargs(self) -> List[ARMOperand]:
119+
return [self.armd.arm_operand(self.args[i]) for i in [1, 2, 3]]
120+
68121
def is_store_instruction(self, xdata: InstrXData) -> bool:
69122
return True
70123

71124
def annotation(self, xdata: InstrXData) -> str:
72-
"""xdata format: a:vxx .
73-
74-
xprs[0..n]: rhs expressions
75-
"""
125+
xd = ARMStoreMultipleIncrementBeforeXData(xdata)
126+
return xd.annotation
76127

77-
return '; "'.join(" := ? := " + str(x) for x in xdata.xprs)
128+
def ast_prov(
129+
self,
130+
astree: ASTInterface,
131+
iaddr: str,
132+
bytestring: str,
133+
xdata: InstrXData) -> Tuple[
134+
List[AST.ASTInstruction], List[AST.ASTInstruction]]:
135+
136+
xd = ARMStoreMultipleIncrementBeforeXData(xdata)
137+
if not xd.is_ok:
138+
chklogger.logger.error(
139+
"STMIB: Error value encountered at address %s", iaddr)
140+
return ([], [])
141+
142+
annotations: List[str] = [iaddr, "STMIB"]
143+
144+
ll_instrs: List[AST.ASTInstruction] = []
145+
hl_instrs: List[AST.ASTInstruction] = []
146+
147+
(baselval, _, _) = self.opargs[0].ast_lvalue(astree)
148+
(baserval, _, _) = self.opargs[0].ast_rvalue(astree)
149+
150+
memlhss = xd.memlhss
151+
regrhss = xd.rhss
152+
regrdefs = xdata.reachingdefs[1:]
153+
memuses = xdata.defuses[1:]
154+
memuseshigh = xdata.defuseshigh[1:]
155+
156+
regsop = self.opargs[1]
157+
registers = regsop.registers
158+
base_offset = 4
159+
for (i, r) in enumerate(registers):
160+
161+
# low-level assignments
162+
163+
base_offset_c = astree.mk_integer_constant(base_offset)
164+
addr = astree.mk_binary_op("plus", baserval, base_offset_c)
165+
ll_lhs = astree.mk_memref_lval(addr)
166+
ll_rhs = astree.mk_register_variable_expr(r)
167+
ll_assign = astree.mk_assign(
168+
ll_lhs,
169+
ll_rhs,
170+
iaddr=iaddr,
171+
bytestring=bytestring,
172+
annotations=annotations)
173+
ll_instrs.append(ll_assign)
174+
175+
# high-level assignments
176+
177+
memlhs = memlhss[i]
178+
regrhs = regrhss[i]
179+
180+
hl_lhs = XU.xvariable_to_ast_lval(memlhs, xdata, iaddr, astree)
181+
hl_rhs = XU.xxpr_to_ast_def_expr(regrhs, xdata, iaddr, astree)
182+
hl_assign = astree.mk_assign(
183+
hl_lhs,
184+
hl_rhs,
185+
iaddr=iaddr,
186+
bytestring=bytestring,
187+
annotations=annotations)
188+
hl_instrs.append(hl_assign)
189+
190+
astree.add_instr_mapping(hl_assign, ll_assign)
191+
astree.add_instr_address(hl_assign, [iaddr])
192+
astree.add_expr_mapping(hl_rhs, ll_rhs)
193+
astree.add_lval_mapping(hl_lhs, ll_lhs)
194+
astree.add_expr_reachingdefs(ll_rhs, [regrdefs[i]])
195+
astree.add_lval_defuses(hl_lhs, memuses[i])
196+
astree.add_lval_defuses_high(hl_lhs, memuseshigh[i])
197+
198+
base_offset += 4
199+
200+
if (
201+
(memlhs.is_memory_variable
202+
and cast("VMemoryVariable", memlhs.denotation).base.is_basevar)):
203+
astree.add_expose_instruction(hl_assign.instrid)
204+
205+
# TODO: add writeback update
206+
207+
return (hl_instrs, ll_instrs)

chb/astinterface/ASTInterfaceFunction.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ def set_invariants(self) -> None:
250250
if loc.startswith("F:"):
251251
# skip invariants on addresses inlined by the analysis
252252
continue
253+
if loc == "exit":
254+
continue
253255
for fact in invariants[loc]:
254256
instr = self.function.instruction(loc)
255257
if fact.is_nonrelational:

0 commit comments

Comments
 (0)