Skip to content

Commit b4c6a9c

Browse files
committed
AST: restore available expressions
1 parent 7a2a70a commit b4c6a9c

File tree

8 files changed

+312
-113
lines changed

8 files changed

+312
-113
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-20241003"
1+
chbversion: str = "0.3.0-20241005"

chb/arm/ARMCallOpcode.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,18 @@ def ast_call_prov(
219219
else:
220220
rtype = ctinfo.target_interface.signature.returntype
221221
asttype = rtype.convert(astree.typconverter)
222-
if not (rtype.is_void or defuses[0] is None):
223-
hl_lhs = XU.xvariable_to_ast_lval(
224-
lhs, xdata, iaddr, astree, ctype=asttype)
222+
223+
# Create a lhs even if it is not used, because the ssa value
224+
# introduced may be used in the available expressions.
225+
hl_lhs = XU.xvariable_to_ast_lval(
226+
lhs, xdata, iaddr, astree, ctype=asttype)
227+
228+
if rtype.is_void or defuses[0] is None:
229+
chklogger.logger.info(
230+
"Unused: introduced ssa-variable: %s for return value of %s "
231+
+ "at address %s",
232+
str(hl_lhs), str(hl_tgt), iaddr)
233+
hl_lhs = None
225234

226235
# argument data
227236

chb/ast/AbstractSyntaxTree.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -852,14 +852,17 @@ def mk_named_lval(
852852
vdescr: Optional[str] = None,
853853
offset: AST.ASTOffset = nooffset,
854854
optlvalid: Optional[int] = None,
855-
storage: Optional[ASTStorage] = None) -> AST.ASTLval:
855+
storage: Optional[ASTStorage] = None,
856+
anonymous: bool = False) -> AST.ASTLval:
856857
var = self.mk_named_variable(
857858
vname,
858859
vtype=vtype,
859860
parameter=parameter,
860861
globaladdress=globaladdress,
861862
llref=llref,
862863
vdescr=vdescr)
864+
if optlvalid is None and anonymous:
865+
optlvalid = -1
863866
return self.mk_lval(
864867
var,
865868
offset,
@@ -959,7 +962,10 @@ def mk_named_lval_expression(
959962
offset: AST.ASTOffset = nooffset,
960963
optlvalid: Optional[int] = None,
961964
optexprid: Optional[int] = None,
962-
storage: Optional[ASTStorage] = None) -> AST.ASTLvalExpr:
965+
storage: Optional[ASTStorage] = None,
966+
anonymous: bool = False) -> AST.ASTLvalExpr:
967+
if optlvalid is None and anonymous:
968+
optlvalid = -1
963969
lval = self.mk_named_lval(
964970
vname,
965971
vtype=vtype,

chb/astinterface/ASTInterface.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,13 +582,15 @@ def mk_global_variable_expr(
582582
vtype: Optional[AST.ASTTyp] = None,
583583
offset: AST.ASTOffset = nooffset,
584584
globaladdress: int = 0,
585-
llref: bool = False) -> AST.ASTExpr:
585+
llref: bool = False,
586+
anonymous: bool = False) -> AST.ASTExpr:
586587
return self.astree.mk_named_lval_expression(
587588
name,
588589
offset=offset,
589590
vtype=vtype,
590591
globaladdress=globaladdress,
591-
llref=llref)
592+
llref=llref,
593+
anonymous=anonymous)
592594

593595
# ------------------------------------------------------ make statements ---
594596

chb/astinterface/ASTInterfaceFunction.py

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,6 @@ def complete_instruction_connections(self) -> None:
244244
self.astinterface.add_instr_mapping(hl_instr, ll_instr)
245245

246246
def set_invariants(self) -> None:
247-
pass
248-
249-
'''
250247
invariants = self.function.invariants
251248
aexprs: Dict[str, Dict[str, Tuple[int, int, str]]] = {}
252249
for loc in sorted(invariants):
@@ -263,47 +260,72 @@ def set_invariants(self) -> None:
263260
# Exclude auxiliary analysis variables
264261
continue
265262

266-
var = XU.xvariable_to_ast_lvals(
263+
if fact.variable.is_constant_value_variable:
264+
# Exclude invariants that equate symbolic constants
265+
# with constant values
266+
continue
267+
268+
var = XU.xvariable_to_ast_lval(
267269
fact.variable,
268270
instr.xdata,
271+
instr.iaddr,
269272
self.astinterface,
270-
anonymous=True)[0]
273+
anonymous=True)
274+
271275
varindex = var.index(self.astinterface.serializer)
272276
value = fact.value
273277
if value.is_singleton_value:
274278
aexpr: ASTExpr = self.astinterface.mk_integer_constant(
275279
value.singleton_value)
276280
aexprindex = aexpr.index(self.astinterface.serializer)
281+
277282
elif value.is_symbolic_expression:
278-
aexpr = XU.xxpr_to_ast_exprs(
283+
aexpr = XU.xxpr_to_ast_def_expr(
279284
fact.value.expr,
280285
instr.xdata,
281286
instr.iaddr,
282287
self.astinterface,
283-
anonymous=True)[0]
288+
anonymous=True)
284289
aexprindex = aexpr.index(self.astinterface.serializer)
285290
else:
286291
continue
287292
aexprs.setdefault(loc, {})
288293
aexprs[loc][str(var)] = (varindex, aexprindex, str(aexpr))
294+
289295
if fact.is_initial_var_equality:
290296
fact = cast("InitialVarEqualityFact", fact)
291-
var = XU.xvariable_to_ast_lvals(
297+
298+
if fact.variable.is_constant_value_variable:
299+
continue
300+
301+
if fact.variable.is_global_variable:
302+
continue
303+
304+
# Filter out initial-value equalities on return values
305+
if "rtn_" in str(fact.variable):
306+
continue
307+
308+
var = XU.xvariable_to_ast_lval(
292309
fact.variable,
293310
instr.xdata,
311+
instr.iaddr,
294312
self.astinterface,
295-
anonymous=True)[0]
313+
anonymous=True)
314+
296315
varindex = var.index(self.astinterface.serializer)
297-
aelval = XU.xvariable_to_ast_lvals(
316+
aexpr = XU.xvariable_to_ast_def_lval_expression(
298317
fact.initial_value,
299318
instr.xdata,
300-
self.astinterface)[0]
301-
aexpr = self.astinterface.mk_lval_expr(aelval)
319+
instr.iaddr,
320+
self.astinterface)
321+
302322
aexprindex = aexpr.index(self.astinterface.serializer)
303323
aexprs.setdefault(loc, {})
304324
aexprs[loc][str(var)] = (varindex, aexprindex, str(aexpr))
325+
326+
num_aexprs = sum(len(aexprs[a]) for a in aexprs)
327+
chklogger.logger.info("Set %d available expressions", num_aexprs)
305328
self.astinterface.set_available_expressions(aexprs)
306-
'''
307329

308330
def set_return_sequences(self) -> None:
309331
"""Currently only supports Thumb-2 stack-adjustment, pop return sequence."""

chb/cmdline/astcmds.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def buildast(args: argparse.Namespace) -> NoReturn:
142142
functions: List[str] = args.functions
143143
hints: List[str] = args.hints # names of json files
144144
xpatchresultsfile = args.patch_results_file
145+
hide_globals: bool = args.hide_globals
145146
remove_edges: List[str] = args.remove_edges
146147
add_edges: List[str] = args.add_edges
147148
verbose: bool = args.verbose
@@ -354,7 +355,7 @@ def buildast(args: argparse.Namespace) -> NoReturn:
354355
print("// --------------------------------------------------")
355356
prettyprinter = ASTCPrettyPrinter(
356357
localsymboltable, annotations=astinterface.annotations)
357-
print(prettyprinter.to_c(asts[0], include_globals=True))
358+
print(prettyprinter.to_c(asts[0], include_globals=(not hide_globals)))
358359
functions_lifted += 1
359360

360361
else:

chb/cmdline/chkx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,10 @@ def parse() -> argparse.Namespace:
670670
buildast.add_argument(
671671
"--patch_results_file",
672672
help="name of patch results file (required if there are trampolines)")
673+
buildast.add_argument(
674+
"--hide_globals",
675+
help="do not include global declarations and definitions in printed output",
676+
action="store_true")
673677
buildast.add_argument(
674678
"--remove_edges",
675679
nargs="*",

0 commit comments

Comments
 (0)