Skip to content

Commit 0010ac3

Browse files
committed
REP: first version of patch candidates
1 parent 84106d9 commit 0010ac3

File tree

5 files changed

+137
-7
lines changed

5 files changed

+137
-7
lines changed

chb/app/InstrXData.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,9 @@ def has_indirect_call_target_exprs(self) -> bool:
334334
return (len(self.tags) == 2 and self.tags[1] == "u" and len(self.args) > 1)
335335

336336
def call_target(self, ixd: "InterfaceDictionary") -> "CallTarget":
337-
if self.has_call_target():
337+
if self.has_call_target() and self.is_bx_call:
338+
return ixd.call_target(self.args[-5])
339+
elif self.has_call_target():
338340
return ixd.call_target(self.args[-1])
339341
else:
340342
raise UF.CHBError(

chb/buffer/LibraryCallCallsites.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,22 @@ class LibraryCallSideeffect:
5151
def __init__(
5252
self,
5353
summary: "FunctionSummary",
54+
faddr: str,
5455
instr: "Instruction",
5556
pre: "PreDerefWrite") -> None:
5657
self._summary = summary
58+
self._faddr = faddr
5759
self._instr = instr
5860
self._pre = pre
5961

6062
@property
6163
def summary(self) -> "FunctionSummary":
6264
return self._summary
6365

66+
@property
67+
def faddr(self) -> str:
68+
return self._faddr
69+
6470
@property
6571
def instr(self) -> "Instruction":
6672
return self._instr
@@ -286,7 +292,8 @@ def derefwrites(self) -> List[LibraryCallSideeffect]:
286292
for pre in self.preconditions:
287293
if pre.is_deref_write:
288294
pre = cast("PreDerefWrite", pre)
289-
lcwrite = LibraryCallSideeffect(self.summary, self.instr, pre)
295+
lcwrite = LibraryCallSideeffect(
296+
self.summary, self.faddr, self.instr, pre)
290297
result.append(lcwrite)
291298
return result
292299

@@ -446,6 +453,13 @@ def patch_candidates(self) -> List["Instruction"]:
446453
result.append(c.instr)
447454
return result
448455

456+
def patch_callsites(self) -> List[LibraryCallSideeffect]:
457+
result: List[LibraryCallSideeffect] = []
458+
for (_, ics) in self.callsites.items():
459+
for cs in ics.values():
460+
result.extend(cs.patch_candidates)
461+
return result
462+
449463
def patch_candidates_distribution(self) -> Dict[str, int]:
450464
result: Dict[str, int] = {}
451465
for (_, ics) in self.callsites.items():

chb/cmdline/chkx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,41 @@ def parse() -> argparse.Namespace:
11711171
report_bufferbounds.set_defaults(func=REP.report_buffer_bounds)
11721172

11731173

1174+
# --- report patch candidates
1175+
report_patchcandidates = reportparsers.add_parser("patchcandidates")
1176+
report_patchcandidates.add_argument("xname", help="name of executable")
1177+
report_patchcandidates.add_argument(
1178+
"--output", "-o",
1179+
help="name of output file (without extension)")
1180+
report_patchcandidates.add_argument(
1181+
"--json",
1182+
action="store_true",
1183+
help="output results in json format")
1184+
report_patchcandidates.add_argument(
1185+
"--targets",
1186+
nargs="*",
1187+
default=[],
1188+
help="list of target library functions to include")
1189+
report_patchcandidates.add_argument(
1190+
"--verbose", "-v",
1191+
action="store_true",
1192+
help="print functions examined")
1193+
report_patchcandidates.add_argument(
1194+
"--loglevel", "-log",
1195+
choices=UL.LogLevel.options(),
1196+
default="NONE",
1197+
help="activate logging with the given level (default to stderr)")
1198+
report_patchcandidates.add_argument(
1199+
"--logfilename",
1200+
help="name of file to write log messages")
1201+
report_patchcandidates.add_argument(
1202+
"--logfilemode",
1203+
choices=["a", "w"],
1204+
default="a",
1205+
help="file mode for log file: append (a, default), or write (w)")
1206+
1207+
report_patchcandidates.set_defaults(func=REP.report_patch_candidates)
1208+
11741209
'''
11751210
11761211
# -- report application calls --
@@ -1195,7 +1230,7 @@ def parse() -> argparse.Namespace:
11951230
report_iocs.set_defaults(func=reportiocs)
11961231
'''
11971232

1198-
# -------------------------------------------------------------- summaries subcommand
1233+
# ----------------------------------------------------- summaries subcommand
11991234

12001235
parser_summaries = subparsers.add_parser("summaries")
12011236
parser_summaries.set_defaults(func=SC.summariescommand)

chb/cmdline/reportcmds.py

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -988,8 +988,6 @@ def perc(v: float) -> str:
988988
exit(0)
989989

990990

991-
992-
993991
def report_buffer_bounds(args: argparse.Namespace) -> NoReturn:
994992

995993
# arguments
@@ -1122,3 +1120,84 @@ def write_json_result(
11221120
reverse=True):
11231121
print(name.ljust(24) + str(count).rjust(5))
11241122
exit(0)
1123+
1124+
1125+
def report_patch_candidates(args: argparse.Namespace) -> NoReturn:
1126+
1127+
# arguments
1128+
xname = args.xname
1129+
xoutput: Optional[str] = args.output
1130+
xjson: bool = args.json
1131+
xverbose: bool = args.verbose
1132+
xtargets: List[str] = args.targets
1133+
loglevel: str = args.loglevel
1134+
logfilename: Optional[str] = args.logfilename
1135+
logfilemode: str = args.logfilemode
1136+
1137+
try:
1138+
(path, xfile) = UC.get_path_filename(xname)
1139+
UF.check_analysis_results(path, xfile)
1140+
except UF.CHBError as e:
1141+
print(str(e.wrap()))
1142+
exit(1)
1143+
1144+
UC.set_logging(
1145+
loglevel,
1146+
path,
1147+
logfilename=logfilename,
1148+
mode=logfilemode,
1149+
msg="report_patch_candidates invoked")
1150+
1151+
xinfo = XI.XInfo()
1152+
xinfo.load(path, xfile)
1153+
1154+
app = UC.get_app(path, xfile, xinfo)
1155+
1156+
n_calls: int = 0
1157+
libcalls = LibraryCallCallsites()
1158+
1159+
for (faddr, blocks) in app.call_instructions().items():
1160+
fn = app.function(faddr)
1161+
1162+
for (baddr, instrs) in blocks.items():
1163+
for instr in instrs:
1164+
n_calls += 1
1165+
calltgt = instr.call_target
1166+
if calltgt.is_so_target and calltgt.name in xtargets:
1167+
libcalls.add_library_callsite(faddr, instr)
1168+
1169+
print("Number of calls: " + str(n_calls))
1170+
1171+
patchcallsites = libcalls.patch_callsites()
1172+
1173+
for pc in sorted(patchcallsites, key=lambda pc:pc.faddr):
1174+
instr = cast("ARMInstruction", pc.instr)
1175+
dstarg = pc.dstarg
1176+
if dstarg is None:
1177+
chklogger.logger.warning(
1178+
"No expression found for destination argument: %s",
1179+
str(instr))
1180+
continue
1181+
dstoffset = dstarg.stack_address_offset()
1182+
fn = instr.armfunction
1183+
stackframe = fn.stackframe
1184+
stackbuffer = stackframe.get_stack_buffer(dstoffset)
1185+
if stackbuffer is None:
1186+
chklogger.logger.warning(
1187+
"No stackbuffer found for %s at offset %s",
1188+
str(instr), str(dstoffset))
1189+
continue
1190+
buffersize = stackbuffer.size
1191+
1192+
print(" " + pc.instr.iaddr + " " + pc.instr.annotation)
1193+
print(" - faddr: " + pc.faddr)
1194+
print(" - iaddr: " + pc.instr.iaddr)
1195+
print(" - target function: " + str(pc.summary.name))
1196+
print(" - stack offset: " + str(dstoffset))
1197+
print(" - length argument: " + str(pc.lenarg))
1198+
print(" - buffersize: " + str(buffersize))
1199+
print("")
1200+
1201+
print("Number of patch callsites: " + str(len(patchcallsites)))
1202+
1203+
exit(0)

chb/models/FunctionSummary.py

Lines changed: 2 additions & 2 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-2023 Aarno Labs LLC
9+
# Copyright (c) 2021-2024 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
@@ -42,7 +42,7 @@
4242

4343

4444
class FunctionSummary:
45-
"Signature and summary semantics for a function."""
45+
"""Signature and summary semantics for a function."""
4646

4747
def __init__(self,
4848
library: "FunctionSummaryLibrary",

0 commit comments

Comments
 (0)