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

add --shorten-paths #203

Merged
merged 4 commits into from
May 19, 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
3 changes: 2 additions & 1 deletion src/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(crate) struct Settings<'p> {
pub(crate) current_dir: &'p Path,
pub(crate) max_backtrace_len: u32,
pub(crate) force_backtrace: bool,
pub(crate) shorten_paths: bool,
}

/// (virtually) unwinds the target's program and prints its backtrace
Expand Down Expand Up @@ -45,7 +46,7 @@ pub(crate) fn print(
|| contains_exception;

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

if unwind.corrupted {
log::warn!("call stack was corrupted; unwinding could not be completed");
Expand Down
16 changes: 11 additions & 5 deletions src/backtrace/pp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use std::borrow::Cow;

use colored::Colorize as _;

use super::symbolicate::Frame;
use crate::utils;

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

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

let mut frame_index = 0;
Expand Down Expand Up @@ -38,7 +40,11 @@ pub(crate) fn backtrace(frames: &[Frame], max_backtrace_len: u32) {
println!("{}", colorized_line);

if let Some(location) = &subroutine.location {
let path = location.path.display();
let path = if settings.shorten_paths {
utils::shorten_paths(&location.path)
} else {
location.path.display().to_string()
};
let line = location.line;
let column = location
.column
Expand All @@ -56,10 +62,10 @@ pub(crate) fn backtrace(frames: &[Frame], max_backtrace_len: u32) {

frame_index += 1;

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

Expand Down
19 changes: 14 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod backtrace;
mod cortexm;
mod registers;
mod stacked;
mod utils;

use std::{
collections::HashSet,
Expand Down Expand Up @@ -92,6 +93,10 @@ struct Opts {
#[structopt(long, default_value = "50")]
max_backtrace_len: u32,

/// Whether to shorten paths (e.g. to crates.io dependencies) in backtraces and defmt logs
#[structopt(long)]
shorten_paths: bool,

/// Arguments passed after the ELF file path are discarded
#[structopt(name = "REST")]
_rest: Vec<String>,
Expand Down Expand Up @@ -136,6 +141,7 @@ fn notmain() -> anyhow::Result<i32> {

let force_backtrace = opts.force_backtrace;
let max_backtrace_len = opts.max_backtrace_len;
let shorten_paths = opts.shorten_paths;
let elf_path = opts.elf.as_deref().unwrap();
let chip = opts.chip.as_deref().unwrap();
let bytes = fs::read(elf_path)?;
Expand Down Expand Up @@ -450,14 +456,16 @@ fn notmain() -> anyhow::Result<i32> {

let (mut file, mut line, mut mod_path) = (None, None, None);
if let Some(loc) = loc {
let relpath =
let path =
if let Ok(relpath) = loc.file.strip_prefix(&current_dir) {
relpath
relpath.display().to_string()
} else if shorten_paths {
utils::shorten_paths(&loc.file)
} else {
// not relative; use full path
&loc.file
loc.file.display().to_string()
};
file = Some(relpath.display().to_string());

file = Some(path);
line = Some(loc.line as u32);
mod_path = Some(loc.module.clone());
}
Expand Down Expand Up @@ -545,6 +553,7 @@ fn notmain() -> anyhow::Result<i32> {
max_backtrace_len,
// TODO any other cases in which we should force a backtrace?
force_backtrace: force_backtrace || canary_touched || halted_due_to_signal,
shorten_paths,
};

let outcome = backtrace::print(
Expand Down
54 changes: 54 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::path::Path;

pub(crate) fn shorten_paths(path: &Path) -> String {
if let Some(dep) = Dependency::from_path(path) {
format!("[{}]/{}", dep.name_version, dep.path.display())
} else {
path.display().to_string()
}
}

struct Dependency<'p> {
name_version: &'p str,
path: &'p Path,
}

impl<'p> Dependency<'p> {
// as of Rust 1.52.1 this path looks like this on Linux
// /home/some-user/.cargo/registry/src/github.heygears.com-0123456789abcdef/crate-name-0.1.2/src/lib.rs
// on Windows the `/home/some-user` part becomes something else
fn from_path(path: &'p Path) -> Option<Self> {
if !path.is_absolute() {
return None;
}

let mut components = path.components();
let _registry = components.find(|component| match component {
std::path::Component::Normal(component) => *component == "registry",
Urhengulas marked this conversation as resolved.
Show resolved Hide resolved
_ => false,
})?;

if let std::path::Component::Normal(src) = components.next()? {
if src != "src" {
return None;
}
}

if let std::path::Component::Normal(github) = components.next()? {
let github = github.to_str()?;
if !github.starts_with("github.heygears.com-") {
return None;
}
}

if let std::path::Component::Normal(name_version) = components.next()? {
let name_version = name_version.to_str()?;
Some(Dependency {
name_version,
path: components.as_path(),
})
} else {
None
}
}
}