This repository has been archived by the owner on Jan 30, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
mod.rs
120 lines (103 loc) · 3.17 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::path::Path;
use probe_rs::{config::RamRegion, Core};
use crate::elf::Elf;
mod pp;
mod symbolicate;
mod unwind;
#[derive(PartialEq, Eq)]
pub(crate) enum BacktraceOptions {
Auto,
Never,
Always,
}
impl From<&String> for BacktraceOptions {
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) backtrace: BacktraceOptions,
pub(crate) panic_present: bool,
pub(crate) backtrace_limit: u32,
pub(crate) shorten_paths: bool,
}
/// (virtually) unwinds the target's program and prints its backtrace
pub(crate) fn print(
core: &mut Core,
elf: &Elf,
active_ram_region: &Option<RamRegion>,
settings: &mut Settings<'_>,
) -> anyhow::Result<Outcome> {
let unwind = unwind::target(core, elf, active_ram_region);
let frames = symbolicate::frames(&unwind.raw_frames, settings.current_dir, elf);
let contains_exception = unwind
.raw_frames
.iter()
.any(|raw_frame| raw_frame.is_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;
}
if print_backtrace && settings.backtrace_limit > 0 {
pp::backtrace(&frames, settings);
if unwind.corrupted {
log::warn!("call stack was corrupted; unwinding could not be completed");
}
if let Some(err) = unwind.processing_error {
log::error!(
"error occurred during backtrace creation: {:?}\n \
the backtrace may be incomplete.",
err
);
}
}
Ok(unwind.outcome)
}
/// Target program outcome
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum Outcome {
HardFault,
Ok,
StackOverflow,
}
impl Outcome {
pub(crate) fn log(&self) {
match self {
Outcome::StackOverflow => {
log::error!("the program has overflowed its stack");
}
Outcome::HardFault => {
log::error!("the program panicked");
}
Outcome::Ok => {
log::info!("device halted without error");
}
}
}
}
/// Converts `Outcome` to an exit code.
impl From<Outcome> for i32 {
fn from(outcome: Outcome) -> i32 {
match outcome {
Outcome::HardFault | Outcome::StackOverflow => crate::SIGABRT,
Outcome::Ok => 0,
}
}
}