Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5c6419d
XD: remove ssa values
sipma Mar 21, 2025
b44ae59
ASTI: allow for string return value
sipma Mar 23, 2025
44cad10
ARM:LDR: update for conversion to C expressions
sipma Mar 25, 2025
c8e85d2
ARM:STR: update for conversion to C expressions
sipma Mar 25, 2025
c3e3d81
ARM:STRH: update for conversion to C expressions
sipma Mar 25, 2025
e311ef1
ARM:EOR: update for conversion to C expressions
sipma Mar 25, 2025
43db341
ARM: update call instructions for conversion to C expressions
sipma Mar 25, 2025
bc069f1
ARM:STRB: update for conversion to C expressions
sipma Mar 25, 2025
09ddec0
ARM:ORR: update for conversion to C expressions
sipma Mar 25, 2025
c3a1af6
ARM:SUB: update for conversion to C expressions
sipma Mar 25, 2025
74db23e
ARM:BX: update for conversion to C expressions (BX LR only)
sipma Mar 25, 2025
9d702a5
ARM:AST: updates for conversion to C expressions
sipma Mar 25, 2025
e1078b2
ARM:ADD: update for conversion to C expressions
sipma Mar 25, 2025
c0497fc
ARM:RSB: update for conversion to C expressions
sipma Mar 25, 2025
550b78e
ARM:MOV: update for conversion to C expressions
sipma Mar 26, 2025
87cdaa6
ARM:ASR: update for conversion to C expressions
sipma Mar 26, 2025
a83cfe0
ARM:AND: update for conversion to C expressions
sipma Mar 26, 2025
474c59b
ARM:ADR: update for conversion to C expressions
sipma Mar 26, 2025
dca7526
ARM:MUL: update for conversion to C expressions
sipma Mar 26, 2025
74254ed
ARM:LDM: update for conversion to C expressions
sipma Mar 26, 2025
5de29f5
ARM:STM: update for conversion to C expressions
sipma Mar 26, 2025
c80e92e
ARM:BIC: update for conversion to C expressions
sipma Mar 26, 2025
f73eb39
CMD: add option to annotate stats
sipma Mar 27, 2025
d1e0683
ARM:STM: update for conversion to C expressions
sipma Mar 27, 2025
5c3a94b
ARM:CMP: update for conversion to C expressions
sipma Mar 27, 2025
61ab3cc
ARM:Branch: update for conversion to C expressions
sipma Mar 27, 2025
cfcd1f4
XXPRUTIL: add error handling
sipma Mar 27, 2025
ee592f4
ARM:LDR: restructure writeback
sipma Mar 27, 2025
7d6bd88
ARM:LDRH: conversion for c expressions
sipma Mar 28, 2025
bfd35da
ARM:POP: conversion of return value for c expressions
sipma Mar 28, 2025
2cfa2ed
CMD: add tags to result metrics
sipma Mar 29, 2025
6d093ce
XXPR: add support for baseptr array index offset
sipma Apr 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions chb/app/AppResultFunctionMetrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
# Copyright (c) 2016-2020 Kestrel Technology LLC
# Copyright (c) 2020 Henny Sipma
# Copyright (c) 2021 Aarno Labs LLC
# Copyright (c) 2021-2025 Aarno Labs LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand All @@ -28,7 +28,7 @@
# ------------------------------------------------------------------------------
import xml.etree.ElementTree as ET

from typing import Dict, Optional, TYPE_CHECKING
from typing import Dict, List, Optional, TYPE_CHECKING

import chb.util.fileutil as UF

Expand Down Expand Up @@ -236,22 +236,28 @@ def as_dictionary(self) -> Dict[str, str]:
def metrics_to_string(
self,
shownocallees: bool = False,
space: str = " ") -> str:
space: str = " ",
tags: List[str] = [],
taglen: int = 0) -> str:
callcount = ''
name = ''
unrc = ''
ftags = "".ljust(taglen)
if shownocallees and (not self.has_name()):
if self.call_count == 0:
callcount = ' (no callees)'
if self.has_name():
name = ' (' + self.name + ')'
if self.unresolved_call_count > 0:
unrc = str(self.unresolved_call_count)
if len(tags) > 0:
ftags = (" [" + ",".join(tags) + "]").ljust(taglen)

return (str(self.faddr).ljust(10) + space
+ '{:6.1f}'.format(self.espp) + space
+ '{:6.1f}'.format(self.readsp) + space
+ '{:6.1f}'.format(self.writesp) + space
+ unrc.rjust(6) + space
+ str(self.block_count).rjust(6) + space
+ str(self.instruction_count).rjust(6) + space
+ '{:8.3f}'.format(self.time) + name + callcount)
+ '{:8.3f}'.format(self.time) + ftags + name + callcount)
2 changes: 1 addition & 1 deletion chb/app/AppResultMetrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
# Copyright (c) 2016-2020 Kestrel Technology LLC
# Copyright (c) 2020 Henny Sipma
# Copyright (c) 2021-2024 Aarno Labs LLC
# Copyright (c) 2021-2025 Aarno Labs LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion chb/app/CHVersion.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
chbversion: str = "0.3.0-20250318"
chbversion: str = "0.3.0-20250401"
10 changes: 6 additions & 4 deletions chb/app/Cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,14 @@ def ast(self,
if astblock.has_return:
instr = astblock.last_instruction
rv = instr.return_value()
astexpr: Optional[AST.ASTExpr] = None
if rv is not None and not astree.returns_void():
astexpr: Optional[AST.ASTExpr] = XU.xxpr_to_ast_def_expr(
astexpr = XU.xxpr_to_ast_def_expr(
rv, instr.xdata, instr.iaddr, astree)
else:
astexpr = None
# astexpr = astexprs[0] if len(astexprs) == 1 else None
if rv.is_string_reference:
cstr = rv.constant.string_reference()
straddr = hex(rv.constant.value)
astexpr = astree.mk_string_constant(astexpr, cstr, straddr)
rtnstmt = astree.mk_return_stmt(astexpr, instr.iaddr, instr.bytestring)
blockstmts[n] = [blocknode, rtnstmt]
else:
Expand Down
141 changes: 108 additions & 33 deletions chb/app/InstrXData.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ def __init__(
IndexedTableValue.__init__(self, ixval.index, ixval.tags, ixval.args)
self._fnd = fnd
self.expanded = False
self._ssavals: List[XVariable] = []
self._vars: List[XVariable] = []
self._vars_r: List[Optional[XVariable]] = []
self._cvars_r: List[Optional[XVariable]] = []
self._types: List["BCTyp"] = []
self._xprs: List[XXpr] = []
self._xprs_r: List[Optional[XXpr]] = []
self._cxprs_r: List[Optional[XXpr]] = []
self._intervals: List[XInterval] = []
self._strs: List[str] = []
self._ints: List[int] = []
Expand Down Expand Up @@ -130,33 +131,16 @@ def vars_r(self) -> List[Optional[XVariable]]:
return self._vars_r

@property
def types(self) -> List["BCTyp"]:
def cvars_r(self) -> List[Optional[XVariable]]:
if not self.expanded:
self._expand()
return self._types
return self._cvars_r

@property
def ssavals(self) -> List[XVariable]:
def types(self) -> List["BCTyp"]:
if not self.expanded:
self._expand()
return self._ssavals

def has_ssaval(self, register: str) -> bool:
for v in self._ssavals:
if v.is_ssa_register_value:
ssaval = v.ssa_register_value()
if str(ssaval.register) == register:
return True
return False

def get_ssaval(self, register: str) -> "SSARegisterValue":
for v in self._ssavals:
if v.is_ssa_register_value:
ssaval = v.ssa_register_value()
if str(ssaval.register) == register:
return ssaval
raise UF.CHBError(
"No ssa value found for register " + register)
return self._types

def get_var(self, index: int) -> XVariable:
if index < len(self.vars):
Expand All @@ -180,6 +164,17 @@ def get_var_x(self, index: int) -> Optional[XVariable]:
+ str(len(self.vars))
+ ")")

def get_cvar_r(self, index: int) -> Optional[XVariable]:
if index < len(self.cvars_r):
return self.cvars_r[index]
else:
raise UF.CHBError(
"xdata: cvar-index out-of-bound: "
+ str(index)
+ " (length is "
+ str(len(self.cvars_r))
+ ")")

@property
def xprs(self) -> List[XXpr]:
if not self.expanded:
Expand All @@ -192,6 +187,12 @@ def xprs_r(self) -> List[Optional[XXpr]]:
self._expand()
return self._xprs_r

@property
def cxprs_r(self) -> List[Optional[XXpr]]:
if not self.expanded:
self._expand()
return self._cxprs_r

@property
def intervals(self) -> List[XInterval]:
if not self.expanded:
Expand Down Expand Up @@ -256,22 +257,60 @@ def is_ok(self) -> bool:

key = self.tags[0]
if key.startswith("ar:"):
return all(self.vars_r) and all(self.xprs_r)
return all(self.vars_r) and all(self.xprs_r) and all(self.cxprs_r)
else:
return True

def has_var_r(self, index: int) -> bool:
return index >= 0 and index < len(self.vars_r)

def is_var_ok(self, index: int) -> bool:
if self.has_var_r(index):
v = self.vars_r[index]
return v is not None
return False

def has_cvar_r(self, index: int) -> bool:
return index >= 0 and index < len(self.cvars_r)

def is_cvar_ok(self, index: int) -> bool:
if self.has_cvar_r(index):
v = self.cvars_r[index]
return v is not None
return False

def has_xpr_r(self, index: int) -> bool:
return index >= 0 and index < len(self.xprs_r)

def is_xpr_ok(self, index: int) -> bool:
if self.has_xpr_r(index):
x = self.xprs_r[index]
return x is not None
return False

def has_cxpr_r(self, index: int) -> bool:
return index >= 0 and index < len(self.cxprs_r)

def is_cxpr_ok(self, index: int) -> bool:
if self.has_cxpr_r(index):
cx = self.cxprs_r[index]
return cx is not None
return False

@property
def error_values(self) -> Tuple[List[int], List[int]]:
def error_values(self) -> Tuple[List[int], List[int], List[int]]:

key = self.tags[0]
if key.startswith("ar:"):
vars_e: List[int] = [
i for i in range(0, len(self.vars_r)) if self.vars_r[i] is None]
xprs_e: List[int] = [
i for i in range(0, len(self.xprs_r)) if self.xprs_r[i] is None]
return (vars_e, xprs_e)
cxprs_e: List[int] = [
i for i in range(0, len(self.cxprs_r)) if self.cxprs_r[i] is None]
return (vars_e, xprs_e, cxprs_e)
else:
return ([], [])
return ([], [], [])


def _expand(self) -> None:
Expand Down Expand Up @@ -314,6 +353,12 @@ def _expand(self) -> None:
else:
self._vars.append(xd.variable(arg))

elif c == "w":
if arg == -2:
self._cvars_r.append(None)
else:
self._cvars_r.append(xd.variable(arg))

elif c == "x":
if use_result:
if arg == -2:
Expand All @@ -323,6 +368,11 @@ def _expand(self) -> None:
else:
self._xprs.append(xd.xpr(arg))

elif c == "c":
if arg == -2:
self._cxprs_r.append(None)
else:
self._cxprs_r.append(xd.xpr(arg))
elif c == "a":
self._xprs.append(xd.xpr(arg))
elif c == "s":
Expand Down Expand Up @@ -353,8 +403,6 @@ def _expand(self) -> None:
flagrdef = varinvd.var_invariant_fact(arg) if arg >= 0 else None
flagrdef = cast(Optional[FlagReachingDefFact], flagrdef)
self._flagreachingdefs.append(flagrdef)
elif c == "c":
self._ssavals.append(xd.variable(arg))
else:
raise UF.CHBError("Key letter not recognized: " + c)

Expand All @@ -364,6 +412,7 @@ def is_function_argument(self) -> bool:

@property
def function_argument_callsite(self) -> AsmAddress:
# Currently only used in x86
if self.is_function_argument:
return self.bdictionary.address(self.args[2])
else:
Expand Down Expand Up @@ -434,6 +483,9 @@ def has_branch_conditions(self) -> bool:
def has_condition_setter(self) -> bool:
return len(self.tags) == 4 and self.tags[1] == "TF"

def has_missing_branch_conditions(self) -> bool:
return len(self.tags) > 1 and self.tags[1] == "TF:no-x"

def get_condition_setter(self) -> str:
if len(self.tags) > 2:
return self.tags[2]
Expand Down Expand Up @@ -497,9 +549,29 @@ def get_base_update_xpr(self) -> XXpr:
"Unexpected error value in base-update expression")
return self.xprdictionary.xpr(xbuval)

def get_base_update_cxpr(self) -> XXpr:
cbutag = next(t for t in self.tags if t.startswith("cbu:"))
cix = int(cbutag[4:])
cbuval = self.args[cix]
if cbuval == -2:
chklogger.logger.info(
"Base update c expression unavailable, fall back to expression")
return self.get_base_update_xpr()
else:
return self.xprdictionary.xpr(cbuval)

def has_return_xpr(self) -> bool:
return any(s.startswith("return:") for s in self.tags)

def has_return_cxpr(self) -> bool:
if any(s.startswith("return:") for s in self.tags):
rvtag = next(t for t in self.tags if t.startswith("return:"))
rvix = int(rvtag[7:])
rval = self.args[rvix + 2]
return rval >= 0
else:
return False

def get_return_xpr(self) -> XXpr:
rvtag = next(t for t in self.tags if t.startswith("return:"))
rvix = int(rvtag[7:])
Expand All @@ -516,6 +588,14 @@ def get_return_xxpr(self) -> XXpr:
raise UF.CHBError("Unexpected error in rewritten return value")
return self.xprdictionary.xpr(rval)

def get_return_cxpr(self) -> XXpr:
rvtag = next(t for t in self.tags if t.startswith("return:"))
rvix = int(rvtag[7:])
rval = self.args[rvix + 2]
if rval == -2:
raise UF.CHBError("Unexpected error in C return value")
return self.xprdictionary.xpr(rval)

@property
def is_aggregate_jumptable(self) -> bool:
return "agg-jt" in self.tags
Expand Down Expand Up @@ -577,9 +657,4 @@ def __str__(self) -> str:
lines.append("defuses[" + str(i) + "] = " + str(d))
for (i, du) in enumerate(self.defuseshigh):
lines.append("defuseshigh[" + str(i) + "] = " + str(du))
for (i, s) in enumerate(self.ssavals):
line = "ssa[" + str(i) + "] = " + str(s)
if s.is_ssa_register_value:
line += " -> register " + str(s.ssa_register_value().register)
lines.append(line)
return "\n".join(lines)
Loading