@@ -63,7 +63,7 @@ use simics::{
6363// which is necessary because this module is compatible with base versions which cross the
6464// deprecation boundary
6565use simics:: { restore_snapshot, save_snapshot} ;
66- use source_cov:: { Coverage , SourceCache } ;
66+ use source_cov:: { lcov :: Records , SourceCache } ;
6767use state:: StopReason ;
6868use std:: {
6969 alloc:: { alloc_zeroed, Layout } ,
@@ -75,7 +75,7 @@ use std::{
7575 ptr:: null_mut,
7676 str:: FromStr ,
7777 sync:: mpsc:: { Receiver , Sender } ,
78- thread:: JoinHandle ,
78+ thread:: { spawn , JoinHandle } ,
7979 time:: SystemTime ,
8080} ;
8181use tracer:: {
@@ -422,6 +422,10 @@ pub(crate) struct Tsffs {
422422 /// Whether symbolic coverage should be collected for system components by downloading
423423 /// executable and debug info files where possible.
424424 pub symbolic_coverage_system : bool ,
425+ #[ class( attribute( optional, default = lookup_file( "%simics%" ) ?. join( "symbolic-coverage" ) ) ) ]
426+ /// Directory in which source files are located. Source files do not need to be arranged in
427+ /// the same directory structure as the compiled source, and are looked up by hash.
428+ pub symbolic_coverage_directory : PathBuf ,
425429
426430 /// Handle for the core simulation stopped hap
427431 stop_hap_handle : HapHandle ,
@@ -478,7 +482,7 @@ pub(crate) struct Tsffs {
478482 execution_trace : ExecutionTrace ,
479483 /// The current line coverage state comprising the total execution. This is not
480484 /// cleared and is persistent across the full campaign until the fuzzer stops.
481- coverage : Coverage ,
485+ coverage : Records ,
482486
483487 /// The name of the fuzz snapshot, if saved
484488 snapshot_name : OnceCell < String > ,
@@ -724,6 +728,10 @@ impl Tsffs {
724728 warn ! ( self . as_conf_object( ) , "Failed to disable VMP: {}" , e) ;
725729 }
726730
731+ // Initialize the source cache for source/line lookups
732+ info ! ( self . as_conf_object( ) , "Initializing source cache" ) ;
733+ self . source_file_cache = SourceCache :: new ( & self . debuginfo_source_directory ) ?;
734+
727735 self . log ( LogMessage :: startup ( ) ) ?;
728736
729737 #[ cfg( simics_version_7) ]
@@ -929,23 +937,38 @@ impl Tsffs {
929937
930938 /// Save the current execution trace to a file
931939 pub fn save_execution_trace ( & mut self ) -> Result < ( ) > {
932- let mut hasher = DefaultHasher :: new ( ) ;
933- self . execution_trace . hash ( & mut hasher) ;
934- let hash = hasher. finish ( ) ;
940+ let execution_trace = self . execution_trace . clone ( ) ;
941+ let execution_trace_dir = self . execution_trace_directory . clone ( ) ;
942+ let coverage = self . coverage . clone ( ) ;
943+ let symbolic_coverage_directory = self . symbolic_coverage_directory . clone ( ) ;
944+ // We just fire and forget this thread -- we won't know if it fails but it's basically
945+ // guaranteed not to. This stops us from having to wait every exec to write a huge file.
946+ spawn ( move || {
947+ let mut hasher = DefaultHasher :: new ( ) ;
948+ execution_trace. hash ( & mut hasher) ;
949+ let hash = hasher. finish ( ) ;
950+
951+ if !execution_trace_dir. is_dir ( ) {
952+ create_dir_all ( & execution_trace_dir) ?;
953+ }
935954
936- if !self . execution_trace_directory . is_dir ( ) {
937- create_dir_all ( & self . execution_trace_directory ) ?;
938- }
955+ let trace_path = execution_trace_dir. join ( format ! ( "{:x}.json" , hash) ) ;
939956
940- let trace_path = self
941- . execution_trace_directory
942- . join ( format ! ( "{:x}.json" , hash) ) ;
957+ if !trace_path. exists ( ) {
958+ let trace_file = File :: create ( & trace_path) ?;
959+ println ! ( "Saving execution trace to {}" , trace_path. display( ) ) ;
960+ to_writer ( trace_file, & execution_trace) ?;
961+ }
962+
963+ if !symbolic_coverage_directory. is_dir ( ) {
964+ create_dir_all ( & symbolic_coverage_directory) ?;
965+ }
943966
944- if !trace_path . exists ( ) {
945- let trace_file = File :: create ( trace_path ) ?;
967+ println ! ( "Saving coverage information to symbolic coverage directory {symbolic_coverage_directory:?}" ) ;
968+ coverage . to_html ( & symbolic_coverage_directory ) ?;
946969
947- to_writer ( trace_file , & self . execution_trace ) ? ;
948- }
970+ Ok :: < ( ) , anyhow :: Error > ( ( ) )
971+ } ) ;
949972
950973 Ok ( ( ) )
951974 }
0 commit comments