33# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44#
55
6- from ctypes import Structure
7- from ctypes import c_uint32 , c_uint16
6+ from __future__ import annotations
7+
8+ from ctypes import Structure , c_uint32 , c_uint16
9+ from typing import TYPE_CHECKING , BinaryIO
810
911from .base import QlBaseCoverage
1012
1113
14+ if TYPE_CHECKING :
15+ from qiling import Qiling
16+
17+
1218# Adapted from https://www.ayrx.me/drcov-file-format
1319class bb_entry (Structure ):
1420 _fields_ = [
@@ -29,36 +35,35 @@ class QlDrCoverage(QlBaseCoverage):
2935
3036 FORMAT_NAME = "drcov"
3137
32- def __init__ (self , ql ):
38+ def __init__ (self , ql : Qiling ):
3339 super ().__init__ (ql )
3440
3541 self .drcov_version = 2
3642 self .drcov_flavor = 'drcov'
3743 self .basic_blocks = []
3844 self .bb_callback = None
3945
40- @staticmethod
41- def block_callback (ql , address , size , self ):
42- for mod_id , mod in enumerate (ql .loader .images ):
43- if mod .base <= address <= mod .end :
44- ent = bb_entry (address - mod .base , size , mod_id )
45- self .basic_blocks .append (ent )
46- break
46+ def activate (self ) -> None :
47+ self .bb_callback = self .ql .hook_block (self .block_callback )
4748
48- def activate (self ):
49- self .bb_callback = self .ql .hook_block (self .block_callback , user_data = self )
49+ def deactivate (self ) -> None :
50+ if self .bb_callback :
51+ self .ql .hook_del (self .bb_callback )
5052
51- def deactivate (self ):
52- self .ql .hook_del (self .bb_callback )
53+ def dump_coverage (self , coverage_file : str ) -> None :
54+ def __write_line (bio : BinaryIO , line : str ) -> None :
55+ bio .write (f'{ line } \n ' .encode ())
5356
54- def dump_coverage (self , coverage_file ):
5557 with open (coverage_file , "wb" ) as cov :
56- cov .write (f"DRCOV VERSION: { self .drcov_version } \n " .encode ())
57- cov .write (f"DRCOV FLAVOR: { self .drcov_flavor } \n " .encode ())
58- cov .write (f"Module Table: version { self .drcov_version } , count { len (self .ql .loader .images )} \n " .encode ())
59- cov .write ("Columns: id, base, end, entry, checksum, timestamp, path\n " .encode ())
58+ __write_line (cov , f"DRCOV VERSION: { self .drcov_version } " )
59+ __write_line (cov , f"DRCOV FLAVOR: { self .drcov_flavor } " )
60+ __write_line (cov , f"Module Table: version { self .drcov_version } , count { len (self .ql .loader .images )} " )
61+ __write_line (cov , "Columns: id, base, end, entry, checksum, timestamp, path" )
62+
6063 for mod_id , mod in enumerate (self . ql .loader .images ):
61- cov .write (f"{ mod_id } , { mod .base } , { mod .end } , 0, 0, 0, { mod .path } \n " .encode ())
62- cov .write (f"BB Table: { len (self .basic_blocks )} bbs\n " .encode ())
63- for bb in self .basic_blocks :
64+ __write_line (cov , f"{ mod_id } , { mod .base } , { mod .end } , 0, 0, 0, { mod .path } " )
65+
66+ __write_line (cov , f"BB Table: { len (self .basic_blocks )} bbs" )
67+
68+ for bb in self .basic_blocks .values ():
6469 cov .write (bytes (bb ))
0 commit comments