44#
55
66from __future__ import annotations
7- from collections import namedtuple
8- from os . path import basename
9- from typing import TYPE_CHECKING , List
7+
8+ import os
9+ from typing import Any , TYPE_CHECKING , List , NamedTuple
1010
1111from .base import QlBaseCoverage
1212
1616
1717
1818# Adapted from https://github.com/nccgroup/Cartographer/blob/main/EZCOV.md#coverage-data
19- class bb_entry (namedtuple ('bb_entry' , 'offset size mod_id' )):
20- def csvline (self ):
21- offset = '0x{:08x}' .format (self .offset )
19+ class bb_entry (NamedTuple ):
20+ offset : int
21+ size : int
22+ mod_id : Any
23+
24+ def as_csv (self ) -> str :
25+ offset = f'{ self .offset :#010x} '
2226 mod_id = f"[ { self .mod_id if self .mod_id is not None else '' } ]"
27+
2328 return f"{ offset } ,{ self .size } ,{ mod_id } \n "
2429
2530class QlEzCoverage (QlBaseCoverage ):
@@ -42,6 +47,10 @@ def __init__(self, ql: Qiling):
4247 self .bb_callback = None
4348
4449 def block_callback (self , ql : Qiling , address : int , size : int ):
50+ img = ql .loader .find_containing_image (address )
51+
52+ if img is not None :
53+ self .basic_blocks .append (bb_entry (address - img .base , size , os .path .basename (img .path )))
4554
4655 def activate (self ) -> None :
4756 self .bb_callback = self .ql .hook_block (self .block_callback )
@@ -54,5 +63,5 @@ def dump_coverage(self, coverage_file: str) -> None:
5463 with open (coverage_file , "w" ) as cov :
5564 cov .write (f"EZCOV VERSION: { self .ezcov_version } \n " )
5665 cov .write ("# Qiling EZCOV exporter tool\n " )
57- for bb in self . basic_blocks :
58- cov .write (bb .csvline () )
66+
67+ cov .writelines (bb .as_csv () for bb in self . basic_blocks )
0 commit comments