Skip to content

Commit 2f300d2

Browse files
committed
Enable turning on symbolic cov separately from execution trace capture
1 parent 369ace3 commit 2f300d2

File tree

9 files changed

+260
-99
lines changed

9 files changed

+260
-99
lines changed

src/haps/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ impl Tsffs {
173173
self.save_execution_trace()?;
174174
}
175175

176+
if self.symbolic_coverage {
177+
self.save_symbolic_coverage()?;
178+
}
179+
176180
debug!(self.as_conf_object(), "Resuming simulation");
177181

178182
run_alone(|| {
@@ -380,6 +384,10 @@ impl Tsffs {
380384
self.save_execution_trace()?;
381385
}
382386

387+
if self.symbolic_coverage {
388+
self.save_symbolic_coverage()?;
389+
}
390+
383391
debug!(self.as_conf_object(), "Resuming simulation");
384392

385393
run_alone(|| {
@@ -481,6 +489,10 @@ impl Tsffs {
481489
self.save_execution_trace()?;
482490
}
483491

492+
if self.symbolic_coverage {
493+
self.save_symbolic_coverage()?;
494+
}
495+
484496
debug!(self.as_conf_object(), "Resuming simulation");
485497

486498
run_alone(|| {

src/lib.rs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -935,41 +935,46 @@ impl Tsffs {
935935
Ok(())
936936
}
937937

938-
/// Save the current execution trace to a file
939-
pub fn save_execution_trace(&mut self) -> Result<()> {
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-
}
938+
pub fn save_symbolic_coverage(&mut self) -> Result<()> {
939+
if self.symbolic_coverage_directory.is_dir() {
940+
create_dir_all(&self.symbolic_coverage_directory)?;
941+
}
954942

955-
let trace_path = execution_trace_dir.join(format!("{:x}.json", hash));
943+
debug!(
944+
self.as_conf_object(),
945+
"Saving symbolic coverage to {}",
946+
self.symbolic_coverage_directory.display()
947+
);
956948

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-
}
949+
self.coverage.to_html(&self.symbolic_coverage_directory)?;
962950

963-
if !symbolic_coverage_directory.is_dir() {
964-
create_dir_all(&symbolic_coverage_directory)?;
965-
}
951+
debug!(
952+
self.as_conf_object(),
953+
"Symbolic coverage saved to {}",
954+
self.symbolic_coverage_directory.display()
955+
);
956+
957+
Ok(())
958+
}
966959

967-
println!("Saving coverage information to symbolic coverage directory {symbolic_coverage_directory:?}");
968-
coverage.to_html(&symbolic_coverage_directory)?;
960+
/// Save the current execution trace to a file
961+
pub fn save_execution_trace(&mut self) -> Result<()> {
962+
let mut hasher = DefaultHasher::new();
963+
self.execution_trace.hash(&mut hasher);
964+
let hash = hasher.finish();
969965

970-
Ok::<(), anyhow::Error>(())
971-
});
966+
if !self.execution_trace_directory.is_dir() {
967+
create_dir_all(&self.execution_trace_directory)?;
968+
}
972969

970+
let trace_path = self
971+
.execution_trace_directory
972+
.join(format!("{:x}.json", hash));
973+
974+
if !trace_path.exists() {
975+
let trace_file = File::create(&trace_path)?;
976+
to_writer(trace_file, &self.execution_trace)?;
977+
}
973978
Ok(())
974979
}
975980
}

src/log/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ impl Tsffs {
152152
if self.save_interesting_execution_traces {
153153
self.save_execution_trace()?;
154154
}
155+
156+
if self.symbolic_coverage {
157+
self.save_symbolic_coverage()?;
158+
}
155159
}
156160
FuzzerMessage::Crash { indices, input } => {
157161
info!(
@@ -184,6 +188,10 @@ impl Tsffs {
184188
if self.save_solution_execution_traces {
185189
self.save_execution_trace()?;
186190
}
191+
192+
if self.symbolic_coverage {
193+
self.save_symbolic_coverage()?;
194+
}
187195
}
188196
FuzzerMessage::Timeout { indices, input } => {
189197
info!(
@@ -216,6 +224,10 @@ impl Tsffs {
216224
if self.save_timeout_execution_traces {
217225
self.save_execution_trace()?;
218226
}
227+
228+
if self.symbolic_coverage {
229+
self.save_symbolic_coverage()?;
230+
}
219231
}
220232
}
221233

src/os/windows/debug_info.rs

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ use std::{
1111
};
1212

1313
use lending_iterator::{windows_mut, LendingIterator};
14-
use simics::{debug, get_object, info, ConfObject};
14+
use simics::{debug, get_object, info, warn, ConfObject};
1515
use windows::Win32::System::{
1616
Diagnostics::Debug::{
1717
IMAGE_DEBUG_DIRECTORY, IMAGE_DEBUG_TYPE_CODEVIEW, IMAGE_DIRECTORY_ENTRY_DEBUG,
1818
IMAGE_NT_HEADERS64,
1919
},
20-
SystemServices::IMAGE_DOS_HEADER,
20+
SystemServices::{FILE_NOTIFY_FULL_INFORMATION, IMAGE_DOS_HEADER},
2121
};
2222

2323
use crate::{os::DebugInfoConfig, source_cov::SourceCache};
@@ -448,14 +448,18 @@ impl ProcessModule {
448448
)
449449
})
450450
.collect::<Vec<_>>();
451-
Some(SymbolInfo::new(
451+
let info = SymbolInfo::new(
452452
procedure_rva.0 as u64,
453453
self.base,
454454
procedure_symbol.len as u64,
455455
symbol_name.to_string().to_string(),
456456
self.full_name.clone(),
457457
lines,
458-
))
458+
);
459+
if let Ok(o) = get_object("tsffs") {
460+
debug!(o, "Got symbol: {:?}", info);
461+
}
462+
Some(info)
459463
})
460464
.collect::<Vec<_>>()
461465
})
@@ -604,49 +608,67 @@ impl Module {
604608
.iterator()
605609
.filter_map(|line| line.ok())
606610
.filter_map(|line_info| {
607-
line_program
608-
.get_file_info(line_info.file_index)
609-
.ok()
610-
.and_then(|line_file_info| {
611-
string_table
612-
.get(line_file_info.name)
613-
.map(|line_file_name| (line_file_info, line_file_name))
614-
.ok()
615-
})
616-
.and_then(|(line_file_info, line_file_name)| {
617-
line_info.offset.to_rva(&address_map).map(|line_rva| {
618-
(line_file_info, line_file_name, line_rva, line_info)
619-
})
620-
})
621-
.and_then(
622-
|(line_file_info, line_file_name, line_rva, line_info)| {
623-
source_cache
624-
.lookup_pdb(
625-
&line_file_info,
626-
&line_file_name.to_string(),
627-
)
628-
.ok()
629-
.flatten()
630-
.map(|p| p.to_path_buf())
631-
.map(|file_path| LineInfo {
632-
rva: line_rva.0 as u64,
633-
size: line_info.length.unwrap_or(1),
634-
file_path,
635-
start_line: line_info.line_start,
636-
end_line: line_info.line_end,
637-
})
638-
},
639-
)
611+
let Ok(line_file_info) =
612+
line_program.get_file_info(line_info.file_index)
613+
else {
614+
if let Ok(o) = get_object("tsffs") {
615+
debug!(o, "No file info for line {:?}", line_info);
616+
}
617+
return None;
618+
};
619+
620+
let Ok(line_file_name) = string_table.get(line_file_info.name)
621+
else {
622+
if let Ok(o) = get_object("tsffs") {
623+
debug!(o, "No file name for line {:?}", line_file_info);
624+
}
625+
return None;
626+
};
627+
628+
let Some(line_rva) = line_info.offset.to_rva(&address_map) else {
629+
if let Ok(o) = get_object("tsffs") {
630+
debug!(o, "No RVA for line {:?}", line_info);
631+
}
632+
return None;
633+
};
634+
635+
let Ok(Some(source_file)) = source_cache
636+
.lookup_pdb(&line_file_info, &line_file_name.to_string())
637+
else {
638+
if let Ok(o) = get_object("tsffs") {
639+
debug!(o, "No source file path for line {:?}", line_info);
640+
}
641+
return None;
642+
};
643+
644+
let info = LineInfo {
645+
rva: line_rva.0 as u64,
646+
size: line_info.length.unwrap_or(1),
647+
file_path: source_file.to_path_buf(),
648+
start_line: line_info.line_start,
649+
end_line: line_info.line_end,
650+
};
651+
if let Ok(o) = get_object("tsffs") {
652+
debug!(o, "Got line info {:?}", line_info);
653+
}
654+
655+
Some(info)
640656
})
641657
.collect::<Vec<_>>();
642-
Some(SymbolInfo::new(
658+
659+
let info = SymbolInfo::new(
643660
procedure_rva.0 as u64,
644661
self.base,
645662
procedure_symbol.len as u64,
646663
symbol_name.to_string().to_string(),
647664
self.full_name.clone(),
648665
lines,
649-
))
666+
);
667+
668+
if let Ok(o) = get_object("tsffs") {
669+
debug!(o, "Got symbol: {:?}", info);
670+
}
671+
Some(info)
650672
})
651673
.collect::<Vec<_>>()
652674
})

src/os/windows/mod.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use intervaltree::IntervalTree;
55
use kernel::{find_kernel_with_idt, KernelInfo};
66
use raw_cstr::AsRawCstr;
77
use simics::{
8-
get_interface, get_object, get_processor_number, info, sys::cpu_cb_handle_t, warn, ConfObject,
9-
CpuInstrumentationSubscribeInterface, IntRegisterInterface, ProcessorInfoV2Interface,
8+
debug, get_interface, get_object, get_processor_number, info, sys::cpu_cb_handle_t, warn,
9+
ConfObject, CpuInstrumentationSubscribeInterface, IntRegisterInterface,
10+
ProcessorInfoV2Interface,
1011
};
1112
use std::{
1213
collections::{hash_map::Entry, HashMap, HashSet},
@@ -158,7 +159,10 @@ impl WindowsOsInfo {
158159
m.intervals(source_cache).ok().or_else(|| {
159160
get_object("tsffs")
160161
.and_then(|obj| {
161-
warn!(obj, "Failed to get intervals for module {}", &m.full_name);
162+
debug!(
163+
obj,
164+
"Failed (or skipped) getting intervals for module {}", &m.full_name
165+
);
162166
Err(
163167
anyhow!("Failed to get intervals for module {}", &m.full_name)
164168
.into(),
@@ -185,9 +189,10 @@ impl WindowsOsInfo {
185189
m.intervals(source_cache).ok().or_else(|| {
186190
get_object("tsffs")
187191
.and_then(|obj| {
188-
warn!(
192+
debug!(
189193
obj,
190-
"Failed to get intervals for module {}", &m.full_name
194+
"Failed (or skipped) getting intervals for module {}",
195+
&m.full_name
191196
);
192197
Err(anyhow!(
193198
"Failed to get intervals for module {}",

src/source_cov/html.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ pub(crate) struct HtmlSummaryInfo {
3030
pub(crate) hit_functions: usize,
3131
}
3232

33+
impl std::fmt::Display for HtmlSummaryInfo {
34+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35+
write!(
36+
f,
37+
"HtmlSummaryInfo {{ is_dir: {}, top_level: {:?}, parent: {:?}, filename: {:?}, total_lines: {}, hit_lines: {}, total_functions: {}, hit_functions: {} }}",
38+
self.is_dir, self.top_level, self.parent, self.filename, self.total_lines, self.hit_lines, self.total_functions, self.hit_functions
39+
)
40+
}
41+
}
42+
3343
define! {
3444
Head {
3545
}

0 commit comments

Comments
 (0)