6666from chb .util .loggingutil import chklogger
6767
6868if TYPE_CHECKING :
69- from chb .api .CallTarget import StubTarget
69+ from chb .api .CallTarget import (
70+ StubTarget , CallTarget )
7071 from chb .api .FunctionStub import SOFunction
7172 from chb .app .AppAccess import AppAccess
7273 from chb .app .BasicBlock import BasicBlock
@@ -990,6 +991,30 @@ def perc(v: float) -> str:
990991 exit (0 )
991992
992993
994+ def write_json_result (xfilename : Optional [str ],
995+ jresult : JSONResult ,
996+ schema_name : str ,
997+ ) -> None :
998+ if jresult .is_ok :
999+ okresult = JU .jsonok (schema_name , jresult .content )
1000+ if xfilename is not None :
1001+ filename = xfilename + ".json"
1002+ with open (filename , "w" ) as fp :
1003+ json .dump (okresult , fp , indent = 2 )
1004+ chklogger .logger .info ("JSON output written to " + filename )
1005+ else :
1006+ print (json .dumps (okresult ))
1007+ else :
1008+ failresult = JU .jsonfail (jresult .reason )
1009+ if xfilename is not None :
1010+ filename = xfilename + ".json"
1011+ with open (filename , "w" ) as fp :
1012+ json .dump (failresult , fp , indent = 2 )
1013+ chklogger .logger .warning (
1014+ "JSON failure output written to " + filename )
1015+ else :
1016+ print (json .dumps (failresult ))
1017+
9931018def report_buffer_bounds (args : argparse .Namespace ) -> NoReturn :
9941019
9951020 # arguments
@@ -1023,49 +1048,27 @@ def report_buffer_bounds(args: argparse.Namespace) -> NoReturn:
10231048 if calltgt .is_so_target :
10241049 libcalls .add_library_callsite (faddr , baddr , instr )
10251050
1026- def write_json_result (
1027- xfilename : Optional [str ], jresult : JSONResult ) -> None :
1028- if jresult .is_ok :
1029- okresult = JU .jsonok ("bufferboundsassessment" , jresult .content )
1030- if xfilename is not None :
1031- filename = xfilename + ".json"
1032- with open (filename , "w" ) as fp :
1033- json .dump (okresult , fp , indent = 2 )
1034- chklogger .logger .info ("JSON output written to " + filename )
1035- else :
1036- print (json .dumps (okresult ))
1037- else :
1038- failresult = JU .jsonfail (jresult .reason )
1039- if xfilename is not None :
1040- filename = xfilename + ".json"
1041- with open (filename , "w" ) as fp :
1042- json .dump (failresult , fp , indent = 2 )
1043- chklogger .logger .warning (
1044- "JSON failure output written to " + filename )
1045- else :
1046- print (json .dumps (failresult ))
1047-
10481051 if xjson :
10491052 content : Dict [str , Any ] = {}
10501053 xinfodata = xinfo .to_json_result ()
10511054 if xinfodata .is_ok :
10521055 content ["identification" ] = xinfodata .content
10531056 else :
1054- write_json_result (xoutput , xinfodata )
1057+ write_json_result (xoutput , xinfodata , "bufferboundsassessment" )
10551058 analysisstats = app .result_metrics .to_json_result ()
10561059 if analysisstats .is_ok :
10571060 content ["analysis" ] = analysisstats .content
10581061 else :
1059- write_json_result (xoutput , analysisstats )
1062+ write_json_result (xoutput , analysisstats , "bufferboundsassessment" )
10601063
10611064 libcallsresult = libcalls .to_json_result ()
10621065 if libcallsresult .is_ok :
10631066 content ["bounds" ] = libcallsresult .content
10641067 else :
1065- write_json_result (xoutput , libcallsresult )
1068+ write_json_result (xoutput , libcallsresult , "bufferboundsassessment" )
10661069
10671070 write_json_result (xoutput , JSONResult (
1068- "libcboundsanalysis" , content , "ok" ))
1071+ "libcboundsanalysis" , content , "ok" ), "bufferboundsassessment" )
10691072
10701073 if not xverbose :
10711074 exit (0 )
@@ -1172,20 +1175,35 @@ def find_spare_instruction(
11721175 n_calls : int = 0
11731176 libcalls = LibraryCallCallsites ()
11741177
1175- for (faddr , blocks ) in app .call_instructions ().items ():
1176- fn = app .function (faddr )
1178+ include_all = xtargets == ['all' ]
11771179
1180+ def include_target (target : 'CallTarget' ) -> bool :
1181+ if include_all :
1182+ return True
1183+ return target .name in xtargets
1184+
1185+ for (faddr , blocks ) in app .call_instructions ().items ():
11781186 for (baddr , instrs ) in blocks .items ():
11791187 for instr in instrs :
11801188 n_calls += 1
11811189 calltgt = instr .call_target
1182- if calltgt .is_so_target and calltgt . name in xtargets :
1190+ if calltgt .is_so_target and include_target ( calltgt ) :
11831191 libcalls .add_library_callsite (faddr , baddr , instr )
11841192
1185- print ("Number of calls: " + str ( n_calls ) )
1193+ chklogger . logger . debug ("Number of calls: %s" , n_calls )
11861194
11871195 patchcallsites = libcalls .patch_callsites ()
11881196
1197+ content : Dict [str , Any ] = {}
1198+ if xjson :
1199+ xinfodata = xinfo .to_json_result ()
1200+ if xinfodata .is_ok :
1201+ content ["identification" ] = xinfodata .content
1202+ else :
1203+ write_json_result (xoutput , xinfodata , "patchcandidates" )
1204+
1205+ patch_records = []
1206+
11891207 for pc in sorted (patchcallsites , key = lambda pc :pc .faddr ):
11901208 instr = pc .instr
11911209 dstarg = pc .dstarg
@@ -1207,16 +1225,33 @@ def find_spare_instruction(
12071225 basicblock = fn .block (pc .baddr )
12081226 spare = find_spare_instruction (basicblock , instr .iaddr )
12091227
1210- print (" " + pc .instr .iaddr + " " + pc .instr .annotation )
1211- print (" - faddr: " + pc .faddr )
1212- print (" - iaddr: " + pc .instr .iaddr )
1213- print (" - target function: " + str (pc .summary .name ))
1214- print (" - stack offset: " + str (dstoffset ))
1215- print (" - length argument: " + str (pc .lenarg ))
1216- print (" - buffersize: " + str (buffersize ))
1217- print (" - spare: " + str (spare ))
1228+ jresult = pc .to_json_result (dstoffset , buffersize , spare )
1229+ if not jresult .is_ok :
1230+ chklogger .logger .warning ("Couldn't process patch callsite %s" , pc )
1231+ continue
1232+
1233+ patch_records .append (jresult .content )
1234+
1235+ content ["patch-records" ] = patch_records
1236+ chklogger .logger .debug ("Number of patch callsites: %s" , len (content ['patch-records' ]))
1237+
1238+ if xjson :
1239+ jcontent = JSONResult ("patchcandidates" , content , "ok" )
1240+ write_json_result (xoutput , jcontent , "patchcandidates" )
1241+ exit (0 )
1242+
1243+ for patch_record in content ["patch-records" ]:
1244+ print (" " + patch_record ['iaddr' ] + " " + patch_record ['annotation' ])
1245+ print (" - faddr: %s" % patch_record ['faddr' ])
1246+ print (" - iaddr: %s" % patch_record ['iaddr' ])
1247+ print (" - target function: %s" % patch_record ['target-function' ])
1248+ print (" - stack offset: %s" % patch_record ['stack-offset' ])
1249+ print (" - length argument: %s" % patch_record ['length-argument' ])
1250+ print (" - buffersize: %s" % patch_record ['buffersize' ])
1251+ print (" - spare: %s" % patch_record ['spare' ])
12181252 print ("" )
12191253
1220- print ("Number of patch callsites: " + str (len (patchcallsites )))
1254+ print ("Generated %d patch records from %d library calls" %
1255+ (len (content ['patch-records' ]), n_calls ))
12211256
12221257 exit (0 )
0 commit comments