Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

Backtrace options #250

Merged
merged 13 commits into from
Sep 2, 2021
Merged
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
29 changes: 25 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,35 @@ $ echo $?

⚠️ **NOTE** when you run your application with `probe-run`, the `HardFault` handler (default or user-defined) will *NOT* be executed.

### Forcing backtraces
### Backtrace options
#### --backtrace

If you'd like to see a backtrace at the end of successful program runs as well, you can enable this by setting the `--force-backtrace` flag:
The `--backtrace` flag is optional and can get passed the following values:

* `--backtrace=always` - forced backtrace (if you'd like to see a backtrace at the end of successful program run)
* `--backtrace=never` - suppresed backtrace
* `--backtrace=auto` - default, shows a backtrace if the program panics or the stack overflows

Run it like this (example for a forced backtrace):

``` console
$ cargo run --bin hello --backtrace=always
```

#### --backtrace-limit

The `--backtrace-limit` flag is optional and defaults to 50. It is possible to set any number.

`--backtrace-limit=0` is accepted and means "no limit".

To show a shortened backtrace showing 5 frames, run:

``` console
$ cargo run --bin hello --force-backtrace
$ cargo run --bin panic --backtrace-limit=5
```

Note: if `--backtrace=never` is set, setting `--backtrace-limit` has no effect.

## Troubleshooting

### `probe-run --list-probes` says "No devices were found."
Expand Down Expand Up @@ -273,7 +294,7 @@ For easier copy-paste-ability, here's an example how to try out your local `prob

```console
$ cd probe-run/
$ PROBE_RUN_IGNORE_VERSION=1 cargo run -- --chip nRF52840_xxAA --max-backtrace-len=10 hello
$ PROBE_RUN_IGNORE_VERSION=1 cargo run -- --chip nRF52840_xxAA --backtrace-limit=10 hello
ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆ
environment variables extra flags binary to be
(optional) (optional) flashed & run
Expand Down
47 changes: 39 additions & 8 deletions src/backtrace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,29 @@ mod pp;
mod symbolicate;
mod unwind;

#[derive(PartialEq, Eq)]
pub(crate) enum BacktraceOptions {
Auto,
Never,
Always,
}

impl From<&String> for BacktraceOptions {
BriocheBerlin marked this conversation as resolved.
Show resolved Hide resolved
fn from(item: &String) -> Self {
match item.as_str() {
"auto" | "Auto" => BacktraceOptions::Auto,
"never" | "Never" => BacktraceOptions::Never,
"always" | "Always" => BacktraceOptions::Always,
_ => panic!("options for `--backtrace` are `auto`, `never`, `always`."),
}
}
}

pub(crate) struct Settings<'p> {
pub(crate) current_dir: &'p Path,
pub(crate) max_backtrace_len: u32,
pub(crate) force_backtrace: bool,
pub(crate) backtrace: BacktraceOptions,
pub(crate) panic_present: bool,
pub(crate) backtrace_limit: u32,
pub(crate) shorten_paths: bool,
}

Expand All @@ -20,7 +39,7 @@ pub(crate) fn print(
core: &mut Core,
elf: &Elf,
active_ram_region: &Option<RamRegion>,
settings: &Settings,
settings: &mut Settings<'_>,
) -> anyhow::Result<Outcome> {
let unwind = unwind::target(core, elf, active_ram_region);

Expand All @@ -31,12 +50,24 @@ pub(crate) fn print(
.iter()
.any(|raw_frame| raw_frame.is_exception());

let print_backtrace = settings.force_backtrace
|| unwind.outcome == Outcome::StackOverflow
|| unwind.corrupted
|| contains_exception;
let print_backtrace = match settings.backtrace {
BacktraceOptions::Never => false,
BacktraceOptions::Always => true,
BacktraceOptions::Auto => {
settings.panic_present
|| unwind.outcome == Outcome::StackOverflow
|| unwind.corrupted
|| contains_exception
}
};

// `0` disables the limit and we want to show _all_ frames
if settings.backtrace_limit == 0 {
let frames_number = &frames.len();
settings.backtrace_limit = *frames_number as u32;
}
BriocheBerlin marked this conversation as resolved.
Show resolved Hide resolved

if print_backtrace && settings.max_backtrace_len > 0 {
if print_backtrace && settings.backtrace_limit > 0 {
pp::backtrace(&frames, settings);

if unwind.corrupted {
Expand Down
6 changes: 3 additions & 3 deletions src/backtrace/pp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::dep;

use super::{symbolicate::Frame, Settings};

/// Pretty prints processed backtrace frames up to `max_backtrace_len`
/// Pretty prints processed backtrace frames up to `backtrace_limit`
pub(crate) fn backtrace(frames: &[Frame], settings: &Settings) {
println!("{}", "stack backtrace:".dimmed());

Expand Down Expand Up @@ -59,10 +59,10 @@ pub(crate) fn backtrace(frames: &[Frame], settings: &Settings) {

frame_index += 1;

if frame_index >= settings.max_backtrace_len {
if frame_index >= settings.backtrace_limit {
log::warn!(
"maximum backtrace length of {} reached; cutting off the rest.const ",
settings.max_backtrace_len
settings.backtrace_limit
);
log::warn!("note: re-run with `--max-backtrace-len=<your maximum>` to extend this limit");

Expand Down
8 changes: 4 additions & 4 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ pub(crate) struct Opts {
#[structopt(short = "V", long)]
version: bool,

/// Print a backtrace even if the program ran successfully
#[structopt(long)]
pub(crate) force_backtrace: bool,
/// Disable or enable backtrace (auto in case of panic or stack overflow).
#[structopt(long, default_value = "auto")]
pub(crate) backtrace: String,

/// Configure the number of lines to print before a backtrace gets cut off
#[structopt(long, default_value = "50")]
pub(crate) max_backtrace_len: u32,
pub(crate) backtrace_limit: u32,

/// Whether to shorten paths (e.g. to crates.io dependencies) in backtraces and defmt logs
#[structopt(long)]
Expand Down
12 changes: 8 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,22 @@ fn run_target_program(elf_path: &Path, chip_name: &str, opts: &cli::Opts) -> any
.map(|canary| canary.touched(&mut core, elf))
.transpose()?
.unwrap_or(false);
let backtrace_settings = backtrace::Settings {

let panic_present = canary_touched || halted_due_to_signal;

let mut backtrace_settings = backtrace::Settings {
current_dir,
max_backtrace_len: opts.max_backtrace_len,
force_backtrace: opts.force_backtrace || canary_touched || halted_due_to_signal,
backtrace_limit: opts.backtrace_limit,
backtrace: (&opts.backtrace).into(),
panic_present,
shorten_paths: opts.shorten_paths,
};

let outcome = backtrace::print(
&mut core,
elf,
&target_info.active_ram_region,
&backtrace_settings,
&mut backtrace_settings,
)?;

core.reset_and_halt(TIMEOUT)?;
Expand Down
4 changes: 2 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ rustflags = [
Write your test that captures `probe-run`s output for your test ELF and check the result with `insta::assert_snapshot!(run_output);`

### 3. cargo insta review
When you run `cargo test -- -ignored` for the first time after you've added your new test, it will fail.
When you run `cargo test -- --ignored` for the first time after you've added your new test, it will fail.
This first run creates a snapshot which you can then store as a "known good"

run
```console
$ cargo install insta
$ cargo install cargo-insta
$ cargo insta review
```

Expand Down
Loading