Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/src/config/common-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ is desired.
- [Enable Logging and Set Log path](#enable-logging-and-set-log-path)
- [Keep All Corpus Entries](#keep-all-corpus-entries)
- [Use Initial Buffer Contents As Corpus](#use-initial-buffer-contents-as-corpus)
- [Disable Auto-Continue in Repro Mode](#disable-auto-continue-in-repro-mode)

## Solution Configuration

Expand Down Expand Up @@ -342,3 +343,13 @@ buffer can be used as a seed corpus entry. This can be enabled with:
```python
@tsffs.use_initial_as_corpus = True
```

### Disable Auto-Continue in Repro Mode

By default, when running in [repro mode](../fuzzing/analyzing-results.md), TSFFS
automatically resumes simulation after preparing the testcase. To instead pause
and let an external debugger (for example a GDB stub) control resume, set:

```python
@tsffs.repro_auto_continue = False
```
12 changes: 12 additions & 0 deletions docs/src/fuzzing/analyzing-results.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,15 @@ Repro mode can be run after stopping execution, or before executing the fuzzing
```python
@tsffs.iface.fuzz.repro("%simics%/solutions/TESTCASE")
```

By default, repro mode automatically resumes simulation after preparing the
testcase. If you need to attach an external debugger (for example a GDB stub)
before execution begins, you can disable auto-continue so that when the harness
is triggered, TSFFS prepares the testcase but waits for you to resume manually:

```python
@tsffs.repro_auto_continue = False
```

See [Disable Auto-Continue in Repro Mode](../config/common-options.md#disable-auto-continue-in-repro-mode)
for more details.
6 changes: 6 additions & 0 deletions docs/src/tutorials/edk2-uefi/reproducing-runs.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,9 @@ capabilities that SIMICS offers. When you're done exploring, run `c` to continue
You can change the testcase you are examining by choosing a different one with
`tsffs.iface.fuzz.repro`, but you cannot resume fuzzing after entering repro mode due
to inconsistencies with the simulated system clock.

> **Tip:** If you want to attach a debugger (such as a GDB stub) before the
> testcase executes, set `@tsffs.repro_auto_continue = False`. When the harness
> is triggered, TSFFS will prepare the testcase but wait for you to resume
> simulation manually. See [Disable Auto-Continue in Repro Mode](../../config/common-options.md#disable-auto-continue-in-repro-mode)
> for details.
51 changes: 36 additions & 15 deletions src/haps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,19 @@ impl Tsffs {
self.execution_trace.0.clear();
self.save_repro_bookmark_if_needed()?;

debug!(self.as_conf_object(), "Resuming simulation");
if self.should_auto_continue_repro() {
debug!(self.as_conf_object(), "Resuming simulation");

run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
} else {
info!(
self.as_conf_object(),
"Repro testcase prepared; waiting for external resume."
);
}

Ok(())
}
Expand Down Expand Up @@ -220,12 +227,19 @@ impl Tsffs {
self.save_symbolic_coverage()?;
}

debug!(self.as_conf_object(), "Resuming simulation");
if self.should_auto_continue_repro() {
debug!(self.as_conf_object(), "Resuming simulation");

run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
} else {
info!(
self.as_conf_object(),
"Repro testcase prepared; waiting for external resume."
);
}

Ok(())
}
Expand Down Expand Up @@ -290,12 +304,19 @@ impl Tsffs {
self.execution_trace.0.clear();
self.save_repro_bookmark_if_needed()?;

debug!(self.as_conf_object(), "Resuming simulation");
if self.should_auto_continue_repro() {
debug!(self.as_conf_object(), "Resuming simulation");

run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
} else {
info!(
self.as_conf_object(),
"Repro testcase prepared; waiting for external resume."
);
}

Ok(())
}
Expand Down
17 changes: 12 additions & 5 deletions src/interfaces/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
use anyhow::{anyhow, Result};
use libafl::inputs::HasBytesVec;
use simics::{
continue_simulation, debug, interface, lookup_file, run_alone, AsConfObject, AttrValue,
continue_simulation, debug, info, interface, lookup_file, run_alone, AsConfObject, AttrValue,
ConfObject, GenericAddress,
};
use std::{
Expand Down Expand Up @@ -50,10 +50,17 @@ impl Tsffs {
self.get_and_write_testcase()?;
self.post_timeout_event()?;

run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
if self.should_auto_continue_repro() {
run_alone(|| {
continue_simulation(0)?;
Ok(())
})?;
} else {
info!(
self.as_conf_object(),
"Repro testcase prepared; waiting for external resume."
);
}
}

Ok(())
Expand Down
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ pub(crate) struct Tsffs {
/// Whether the fuzzer should stop on compiled-in harnesses. If set to `True`, the fuzzer
/// will start fuzzing when a harness macro is executed.
pub stop_on_harness: bool,
#[class(attribute(optional, default = true))]
/// Whether TSFFS should automatically resume simulation after preparing a repro testcase.
///
/// When set to `False`, TSFFS will prepare repro execution state (snapshot restore,
/// testcase write, timeout event, bookmark) but not call continue. This is useful when
/// an external debugger (for example a GDB stub) should control resume.
pub repro_auto_continue: bool,
#[class(attribute(optional, default = 0))]
/// The index number which is passed to the platform-specific magic instruction HAP
/// by a compiled-in harness to signal that the fuzzer should start the fuzzing loop.
Expand Down Expand Up @@ -858,6 +865,11 @@ impl Tsffs {

Ok(())
}

/// Return true if TSFFS should continue simulation after preparing repro state.
pub fn should_auto_continue_repro(&self) -> bool {
self.repro_testcase.is_none() || self.repro_auto_continue
}
}

impl Tsffs {
Expand Down
Loading