Skip to content

Commit 780b162

Browse files
authored
Logging Enhancements (#87)
1 parent 729c03d commit 780b162

File tree

6 files changed

+300
-16
lines changed

6 files changed

+300
-16
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ version = "0.2.1"
2121

2222
[package.metadata.simics]
2323
package-number = 31337
24-
25-
version = "6.1.0"
24+
version = "6.1.1"
2625

2726
[lib]
2827
crate-type = ["cdylib", "rlib"]
@@ -76,6 +75,7 @@ num-derive = "0.4.2"
7675
tracing-subscriber = "0.3.18"
7776
tracing = { version = "0.1.40", features = ["log"] }
7877
yaxpeax-arm = "0.2.5"
78+
chrono = "0.4.38"
7979

8080
[dev-dependencies]
8181
simics-test = { path = "simics-rs/simics-test" }

src/fuzzer/feedbacks/mod.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,14 @@ where
6565
.ok_or_else(|| {
6666
libafl::Error::unknown("Failed to get observer from observers tuple")
6767
})?;
68+
6869
let map_state = state
6970
.named_metadata_map_mut()
7071
.get_mut::<MapFeedbackMetadata<T>>(self.name())
7172
.ok_or_else(|| libafl::Error::unknown("Failed to get metadata"))?;
73+
7274
let len = observer.len();
75+
7376
if map_state.history_map.len() < len {
7477
map_state.history_map.resize(len, observer.initial());
7578
}
@@ -106,6 +109,106 @@ where
106109
.ok_or_else(|| libafl::Error::unknown("Failed to send report"))?;
107110
}
108111

112+
if *exit_kind == ExitKind::Crash {
113+
let observer = observers
114+
.match_name::<O>(self.observer_name())
115+
.ok_or_else(|| {
116+
libafl::Error::unknown("Failed to get observer from observers tuple")
117+
})?;
118+
119+
let map_state = state
120+
.named_metadata_map_mut()
121+
.get_mut::<MapFeedbackMetadata<T>>(self.name())
122+
.ok_or_else(|| libafl::Error::unknown("Failed to get metadata"))?;
123+
124+
let len = observer.len();
125+
126+
if map_state.history_map.len() < len {
127+
map_state.history_map.resize(len, observer.initial());
128+
}
129+
130+
let history_map = map_state.history_map.as_slice();
131+
132+
let initial = observer.initial();
133+
134+
let mut indices = vec![];
135+
136+
for (i, item) in observer
137+
.as_iter()
138+
.copied()
139+
.enumerate()
140+
.filter(|(_, item)| *item != initial)
141+
{
142+
let existing = unsafe { *history_map.get_unchecked(i) };
143+
let reduced = R::reduce(existing, item);
144+
if N::is_novel(existing, reduced) {
145+
indices.push(i);
146+
}
147+
}
148+
149+
self.sender
150+
.get_mut()
151+
.and_then(|sender| {
152+
sender
153+
.send(FuzzerMessage::Crash {
154+
indices,
155+
input: input.target_bytes().as_slice().to_vec(),
156+
})
157+
.ok()
158+
})
159+
.ok_or_else(|| libafl::Error::unknown("Failed to send report"))?;
160+
}
161+
162+
if *exit_kind == ExitKind::Timeout {
163+
let observer = observers
164+
.match_name::<O>(self.observer_name())
165+
.ok_or_else(|| {
166+
libafl::Error::unknown("Failed to get observer from observers tuple")
167+
})?;
168+
169+
let map_state = state
170+
.named_metadata_map_mut()
171+
.get_mut::<MapFeedbackMetadata<T>>(self.name())
172+
.ok_or_else(|| libafl::Error::unknown("Failed to get metadata"))?;
173+
174+
let len = observer.len();
175+
176+
if map_state.history_map.len() < len {
177+
map_state.history_map.resize(len, observer.initial());
178+
}
179+
180+
let history_map = map_state.history_map.as_slice();
181+
182+
let initial = observer.initial();
183+
184+
let mut indices = vec![];
185+
186+
for (i, item) in observer
187+
.as_iter()
188+
.copied()
189+
.enumerate()
190+
.filter(|(_, item)| *item != initial)
191+
{
192+
let existing = unsafe { *history_map.get_unchecked(i) };
193+
let reduced = R::reduce(existing, item);
194+
if N::is_novel(existing, reduced) {
195+
indices.push(i);
196+
}
197+
}
198+
199+
self.sender
200+
.get_mut()
201+
.and_then(|sender| {
202+
sender
203+
.send(FuzzerMessage::Timeout {
204+
indices,
205+
input: input.target_bytes().as_slice().to_vec(),
206+
})
207+
.ok()
208+
})
209+
.ok_or_else(|| libafl::Error::unknown("Failed to send report"))?;
210+
}
211+
109212
Ok(is_interesting)
110213
}
111214

src/fuzzer/messages/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ use serde::Serialize;
77
pub(crate) enum FuzzerMessage {
88
String(String),
99
Interesting { indices: Vec<usize>, input: Vec<u8> },
10+
Crash { indices: Vec<usize>, input: Vec<u8> },
11+
Timeout { indices: Vec<usize>, input: Vec<u8> },
1012
}

src/haps/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,12 @@ impl Tsffs {
406406
.ok_or_else(|| anyhow!("No fuzzer tx channel"))?;
407407

408408
match kind {
409-
SolutionKind::Timeout => fuzzer_tx.send(ExitKind::Timeout)?,
409+
SolutionKind::Timeout => {
410+
self.timeouts += 1;
411+
fuzzer_tx.send(ExitKind::Timeout)?
412+
}
410413
SolutionKind::Exception | SolutionKind::Breakpoint | SolutionKind::Manual => {
414+
self.solutions += 1;
411415
fuzzer_tx.send(ExitKind::Crash)?
412416
}
413417
}
@@ -427,7 +431,7 @@ impl Tsffs {
427431
self.post_timeout_event()?;
428432
}
429433

430-
if self.save_all_execution_traces || self.save_solution_execution_traces {
434+
if self.save_all_execution_traces {
431435
self.save_execution_trace()?;
432436
}
433437

src/lib.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ use indoc::indoc;
3939
use libafl::{inputs::HasBytesVec, prelude::ExitKind};
4040
use libafl_bolts::prelude::OwnedMutSlice;
4141
use libafl_targets::AFLppCmpLogMap;
42+
use log::LogMessage;
4243
use magic::MagicNumber;
4344
use num_traits::FromPrimitive as _;
4445
use serde::{Deserialize, Serialize};
4546
use serde_json::to_writer;
4647
use simics::{
4748
break_simulation, class, debug, error, free_attribute, get_class, get_interface,
48-
get_processor_number, info, lookup_file, object_clock, run_command, run_python, simics_init,
49-
trace, version_base, AsConfObject, BreakpointId, ClassCreate, ClassObjectsFinalize, ConfObject,
49+
get_processor_number, lookup_file, object_clock, run_command, run_python, simics_init, trace,
50+
version_base, AsConfObject, BreakpointId, ClassCreate, ClassObjectsFinalize, ConfObject,
5051
CoreBreakpointMemopHap, CoreExceptionHap, CoreMagicInstructionHap, CoreSimulationStoppedHap,
5152
CpuInstrumentationSubscribeInterface, Event, EventClassFlag, FromConfObject, HapHandle,
5253
Interface, IntoAttrValueDict,
@@ -381,6 +382,9 @@ pub(crate) struct Tsffs {
381382
/// Whether to quit on iteration limit
382383
pub quit_on_iteration_limit: bool,
383384
#[class(attribute(optional, default = false))]
385+
/// Whether to save execution traces of test cases which result in a timeout
386+
pub save_timeout_execution_traces: bool,
387+
#[class(attribute(optional, default = false))]
384388
/// Whether to save execution traces of test cases which result in a solution
385389
pub save_solution_execution_traces: bool,
386390
#[class(attribute(optional, default = false))]
@@ -399,6 +403,12 @@ pub(crate) struct Tsffs {
399403
#[class(attribute(optional, default = false))]
400404
/// Whether execution traces should include just PC (vs instruction text and bytes)
401405
pub execution_trace_pc_only: bool,
406+
#[class(attribute(optional, default = true))]
407+
/// Whether a heartbeat message should be emitted every `heartbeat_interval` seconds
408+
pub heartbeat: bool,
409+
#[class(attribute(optional, default = 60))]
410+
/// The interval in seconds between heartbeat messages
411+
pub heartbeat_interval: u64,
402412

403413
#[attr_value(skip)]
404414
/// Handle for the core simulation stopped hap
@@ -489,6 +499,10 @@ pub(crate) struct Tsffs {
489499
// #[builder(default = SystemTime::now())]
490500
/// The time the fuzzer was started at
491501
start_time: OnceCell<SystemTime>,
502+
#[attr_value(skip)]
503+
// #[builder(default = SystemTime::now())]
504+
/// The time the fuzzer was started at
505+
last_heartbeat_time: Option<SystemTime>,
492506

493507
#[attr_value(skip)]
494508
log: OnceCell<File>,
@@ -521,6 +535,12 @@ pub(crate) struct Tsffs {
521535
#[attr_value(skip)]
522536
/// Whether snapshots are used. Snapshots are used on Simics 7.0.0 and later.
523537
use_snapshots: bool,
538+
#[attr_value(skip)]
539+
/// The number of timeouts so far
540+
timeouts: usize,
541+
#[attr_value(skip)]
542+
/// The number of solutions so far
543+
solutions: usize,
524544
}
525545

526546
impl ClassObjectsFinalize for Tsffs {
@@ -705,6 +725,8 @@ impl Tsffs {
705725
return Ok(());
706726
}
707727

728+
self.log(LogMessage::startup())?;
729+
708730
#[cfg(simics_version_7)]
709731
{
710732
if self.checkpoint_path.exists() {
@@ -845,9 +867,8 @@ impl Tsffs {
845867
start_processor_cpu,
846868
start_processor_clock,
847869
self.timeout,
848-
move |obj| {
870+
move |_obj| {
849871
let tsffs: &'static mut Tsffs = tsffs_ptr.into();
850-
info!(tsffs.as_conf_object_mut(), "timeout({:#x})", obj as usize);
851872
tsffs
852873
.stop_simulation(StopReason::Solution {
853874
kind: SolutionKind::Timeout,

0 commit comments

Comments
 (0)