Skip to content
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
1,919 changes: 1,210 additions & 709 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion capture-probe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ description = "Crate for capturing stack dumps of embedded devices with a debugg
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
probe-rs = "0.20.0"
probe-rs = "0.29.1"
stackdump-core = { version = "0.4.0", path = "../core" }

10 changes: 10 additions & 0 deletions capture-probe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ impl<'a, 'probe> StackdumpCapturer<'a, 'probe> {
let starting_register = match self.0.get_mut().architecture() {
probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::R0,
probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::X0,
probe_rs::Architecture::Xtensa => {
return Err(probe_rs::Error::NotImplemented(
"register capture for Xtensa",
))
}
};

Ok(VecRegisterData::new(starting_register, register_data))
Expand All @@ -43,6 +48,11 @@ impl<'a, 'probe> StackdumpCapturer<'a, 'probe> {
let starting_register = match self.0.get_mut().architecture() {
probe_rs::Architecture::Arm => stackdump_core::gimli::Arm::S0,
probe_rs::Architecture::Riscv => stackdump_core::gimli::RiscV::F0,
probe_rs::Architecture::Xtensa => {
return Err(probe_rs::Error::NotImplemented(
"register capture for Xtensa",
))
}
};

Ok(Some(VecRegisterData::new(starting_register, register_data)))
Expand Down
2 changes: 1 addition & 1 deletion capture/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "stackdump-capture"
version = "0.5.0"
edition = "2021"
rust-version = "1.59"
rust-version = "1.88"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/tweedegolf/stackdump"
repository = "https://github.com/tweedegolf/stackdump"
Expand Down
4 changes: 2 additions & 2 deletions capture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ We need to be able to persist all the data across the reboot.
If you have a filesystem or something similar, you could write it to there.
But most embedded systems have got some SRAM so we could keep it in uninitialized memory.

```rust
```rust,ignore
use core::mem::MaybeUninit;
use stackdump_core::memory_region::ArrayMemoryRegion;
use stackdump_core::register_data::ArrayRegisterData;
Expand All @@ -69,7 +69,7 @@ static mut FPU_REGISTERS_CAPTURE: MaybeUninit<ArrayRegisterData<32, u32>> = Mayb
We also need to be able to detect at bootup if a stackdump has been captured.
The best way is to have an uninitialized integer present that can have a specific value to indicate the dump has been made.

```rust
```rust,ignore
use core::mem::MaybeUninit;

#[link_section = ".uninit"]
Expand Down
3 changes: 3 additions & 0 deletions capture/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::env;

fn main() {
println!("cargo::rustc-check-cfg=cfg(cortex_m)");
println!("cargo::rustc-check-cfg=cfg(has_fpu)");

let target = env::var("TARGET").unwrap();

let is_cortex_m = target.starts_with("thumbv6m-")
Expand Down
2 changes: 1 addition & 1 deletion capture/src/cortex_m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ fn capture_stack<const SIZE: usize>(stack_pointer: u32, stack: &mut ArrayMemoryR
/// Get the start address of the stack. The stack grows to lower addresses,
/// so this should be the highest stack address you can get.
fn stack_start() -> u32 {
unsafe { &_stack_start as *const _ as u32 }
&raw const _stack_start as u32
}

let stack_size = stack_start().saturating_sub(stack_pointer).min(SIZE as u32);
Expand Down
2 changes: 1 addition & 1 deletion capture/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]
#![warn(missing_docs)]

#[cfg(any(cortex_m, doc, test))]
Expand Down
8 changes: 4 additions & 4 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "stackdump-cli"
version = "0.1.8"
edition = "2021"
rust-version = "1.59"
rust-version = "1.88"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/tweedegolf/stackdump"
repository = "https://github.com/tweedegolf/stackdump"
Expand All @@ -17,8 +17,8 @@ description = "Crate for capturing stack dumps"
clap = { version = "4.2.1", features = ["derive", "color", "suggestions"] }
stackdump-trace = { version = "0.4.0", path = "../trace" }
stackdump-capture-probe = { version = "0.4.0", path = "../capture-probe" }
env_logger = "0.10"
env_logger = "0.11.8"
log = "0.4.14"
textwrap = { version = "0.16.0", features = ["terminal_size"] }
colored = "2"
probe-rs = "0.20.0"
colored = "3.0.0"
probe-rs = "0.29.1"
32 changes: 13 additions & 19 deletions cli/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use std::{
sync::atomic::{AtomicUsize, Ordering},
};

use env_logger::fmt::{Color, Style, StyledValue};
use log::Level;
use env_logger::fmt::style::Style;

pub fn init_logger() {
env_logger::builder()
Expand All @@ -19,16 +18,20 @@ pub fn init_logger() {

let max_width = max_target_width(&target);

let mut style = f.style();
let level = colored_level(&mut style, record.level());
let level_style = f.default_level_style(record.level());

let mut style = f.style();
let target = style.set_bold(true).value(Padded {
value: target,
width: max_width,
});
let target_style = Style::new().bold();

writeln!(f, " {} {} > {}", level, target, record.args())
writeln!(
f,
" {level_style}{}{level_style:#} {target_style}{}{target_style:#} > {}",
record.level().as_str(),
Padded {
value: target,
width: max_width,
},
record.args()
)
})
.init();
}
Expand All @@ -43,15 +46,6 @@ impl<T: fmt::Display> fmt::Display for Padded<T> {
write!(f, "{: <width$}", self.value, width = self.width)
}
}
fn colored_level(style: &mut Style, level: Level) -> StyledValue<'_, &'static str> {
match level {
Level::Trace => style.set_color(Color::Magenta).value("TRACE"),
Level::Debug => style.set_color(Color::Blue).value("DEBUG"),
Level::Info => style.set_color(Color::Green).value("INFO "),
Level::Warn => style.set_color(Color::Yellow).value("WARN "),
Level::Error => style.set_color(Color::Red).value("ERROR"),
}
}

fn max_target_width(target: &str) -> usize {
static MAX_MODULE_WIDTH: AtomicUsize = AtomicUsize::new(0);
Expand Down
2 changes: 1 addition & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use clap::{Parser, Subcommand};
use colored::Colorize;
use probe::trace_probe;
use probe_rs::DebugProbeSelector;
use probe_rs::probe::DebugProbeSelector;
use stackdump_trace::{
platform::cortex_m::CortexMPlatform,
render_colors::Theme,
Expand Down Expand Up @@ -118,7 +118,7 @@

pub(crate) fn print_frames(frames: Vec<stackdump_trace::Frame<u32>>, args: &Arguments) {
for (i, frame) in frames.iter().enumerate() {
print!("{}: ", i);

Check warning on line 121 in cli/src/main.rs

View workflow job for this annotation

GitHub Actions / clippy

variables can be used directly in the `format!` string

warning: variables can be used directly in the `format!` string --> cli/src/main.rs:121:9 | 121 | print!("{}: ", i); | ^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args = note: `#[warn(clippy::uninlined_format_args)]` on by default help: change this to | 121 - print!("{}: ", i); 121 + print!("{i}: "); |

let frame_text = frame.display(
true,
Expand Down
12 changes: 9 additions & 3 deletions cli/src/probe.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::Arguments;
use probe_rs::{config::TargetSelector, DebugProbeSelector, Permissions, Probe, Session};
use probe_rs::{
config::TargetSelector,
probe::{list::Lister, DebugProbeSelector},
Permissions, Session, SessionConfig,
};
use stackdump_capture_probe::StackdumpCapturer;
use stackdump_trace::{
platform::cortex_m::CortexMPlatform, stackdump_core::device_memory::DeviceMemory,
Expand All @@ -16,8 +20,10 @@ pub(crate) fn trace_probe(
let elf_data = std::fs::read(elf_file)?;

let mut session = match probe_selector {
Some(selector) => Probe::open(selector)?.attach(target_selector, Permissions::default())?,
None => Session::auto_attach(target_selector, Permissions::default())?,
Some(selector) => Lister::new()
.open(selector)?
.attach(target_selector, Permissions::default())?,
None => Session::auto_attach(target_selector, SessionConfig::default())?,
};
let mut core = session.core(core.unwrap_or(0))?;

Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description = "Crate for stack dump definitions"
[dependencies]
arrayvec = { version = "0.7.2", default-features = false, features = ["serde"] }
serde = { version = "1.0.136", default-features = false, features = ["derive"] }
gimli = { version = "0.28.0", default-features = false }
gimli = { version = "0.32.0", default-features = false }
funty = { version = "2.0.0", default-features = false }

[features]
Expand Down
6 changes: 3 additions & 3 deletions core/src/memory_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl<const SIZE: usize> ArrayMemoryRegion<SIZE> {
/// assert_eq!(region1, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// assert_eq!(region2, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// ```
pub fn bytes(&self) -> MemoryRegionIterator {
pub fn bytes(&self) -> MemoryRegionIterator<'_> {
MemoryRegionIterator::new(self.start_address, &self.data)
}

Expand Down Expand Up @@ -215,7 +215,7 @@ impl VecMemoryRegion {
/// assert_eq!(region1, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// assert_eq!(region2, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// ```
pub fn bytes(&self) -> MemoryRegionIterator {
pub fn bytes(&self) -> MemoryRegionIterator<'_> {
MemoryRegionIterator::new(self.start_address, &self.data)
}

Expand Down Expand Up @@ -342,7 +342,7 @@ impl<'a> SliceMemoryRegion<'a> {
/// assert_eq!(region1, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// assert_eq!(region2, ArrayMemoryRegion::<4>::from_iter(&mut intermediate_iter));
/// ```
pub fn bytes(&self) -> MemoryRegionIterator {
pub fn bytes(&self) -> MemoryRegionIterator<'_> {
let start_address = self.data.as_ptr() as u64;
MemoryRegionIterator::new(start_address, self.data)
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/register_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
/// assert_eq!(regs1, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
/// assert_eq!(regs2, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
/// ```
pub fn bytes(&self) -> RegisterDataBytesIterator<RB> {
pub fn bytes(&self) -> RegisterDataBytesIterator<'_, RB> {
RegisterDataBytesIterator {
index: 0,
starting_register_number: self.starting_register_number,
Expand Down Expand Up @@ -197,7 +197,7 @@
/// assert_eq!(regs1, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
/// assert_eq!(regs2, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
/// ```
pub fn bytes(&self) -> RegisterDataBytesIterator<RB> {
pub fn bytes(&self) -> RegisterDataBytesIterator<'_, RB> {
RegisterDataBytesIterator {
index: 0,
starting_register_number: self.starting_register_number,
Expand Down Expand Up @@ -317,7 +317,7 @@
}

fn size_hint(&self) -> (usize, Option<usize>) {
let remaining_length = 5 + self.registers.len() * core::mem::size_of::<RB>() - self.index;

Check warning on line 320 in core/src/register_data.rs

View workflow job for this annotation

GitHub Actions / clippy

manual slice size calculation

warning: manual slice size calculation --> core/src/register_data.rs:320:36 | 320 | let remaining_length = 5 + self.registers.len() * core::mem::size_of::<RB>() - self.index; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(self.registers)` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation = note: `#[warn(clippy::manual_slice_size_calculation)]` on by default
(remaining_length, Some(remaining_length))
}
}
Expand Down
17 changes: 9 additions & 8 deletions trace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ categories = ["embedded"]
description = "Crate for tracing stack dumps"

[dependencies]
addr2line = "0.21.0"
gimli = "0.28.0"
addr2line = "0.25.0"
gimli = "0.32.0"
object = "0.37.1"
bitvec = "1.0.0"
stackdump-core = { version = "0.4.0", path = "../core" }
thiserror = "1.0.30"
thiserror = "2.0.12"
log = "0.4.14"
trees = "0.4.2"
colored = "2.0.0"
phf = { version = "0.11", features = ["macros"] }
colored = "3.0.0"
phf = { version = "0.12.1", features = ["macros"] }
funty = { version = "2.0.0", default-features = false }
strum = "0.25.0"
strum_macros = "0.25.2"
strum = "0.27.2"
strum_macros = "0.27.2"

[dev-dependencies]
simple_logger = "4.1.0"
simple_logger = "5.0.0"
2 changes: 1 addition & 1 deletion trace/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub enum TraceError {
#[error("The elf file does not contain the required `{0}` section")]
MissingElfSection(String),
#[error("The elf file could not be read: {0}")]
ObjectReadError(#[from] addr2line::object::Error),
ObjectReadError(#[from] object::Error),
#[error("An IO error occured: {0}")]
IOError(Rc<std::io::Error>),
#[error("Some memory could not be read: {0}")]
Expand Down
1 change: 1 addition & 0 deletions trace/src/gimli_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ where
}
}

#[allow(dead_code)]
pub trait AttributeExt<R: Reader> {
fn required_u8_value(&self) -> Result<u8, TraceError>;
fn required_u16_value(&self) -> Result<u16, TraceError>;
Expand Down
8 changes: 4 additions & 4 deletions trace/src/platform/cortex_m/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
use super::{Platform, UnwindResult};
use crate::error::TraceError;
use crate::{Frame, FrameType};
use addr2line::object::{Object, ObjectSection, ObjectSymbol};
use core::ops::Range;
use gimli::{
BaseAddresses, CfaRule, DebugFrame, EndianSlice, LittleEndian, RegisterRule, RunTimeEndian,
UnwindContext, UnwindSection, UnwindTableRow,
};
use object::{Object, ObjectSection, ObjectSymbol};
use stackdump_core::device_memory::DeviceMemory;

const THUMB_BIT: u32 = 1;
Expand All @@ -20,13 +20,13 @@
reset_vector_address_range: Range<u32>,
text_address_range: Range<u32>,
bases: BaseAddresses,
unwind_context: UnwindContext<EndianSlice<'data, LittleEndian>>,
unwind_context: UnwindContext<usize>,
}

impl<'data> CortexMPlatform<'data> {
fn apply_unwind_info(
device_memory: &mut DeviceMemory<<Self as Platform<'data>>::Word>,
unwind_info: UnwindTableRow<EndianSlice<LittleEndian>>,
unwind_info: UnwindTableRow<usize>,
) -> Result<bool, TraceError> {
let updated = match unwind_info.cfa() {
CfaRule::RegisterAndOffset { register, offset } => {
Expand Down Expand Up @@ -157,7 +157,7 @@
impl<'data> Platform<'data> for CortexMPlatform<'data> {
type Word = u32;

fn create_context(elf: &addr2line::object::File<'data, &'data [u8]>) -> Result<Self, TraceError>
fn create_context(elf: &object::File<'data, &'data [u8]>) -> Result<Self, TraceError>
where
Self: Sized,
{
Expand Down Expand Up @@ -295,10 +295,10 @@
line: None,
column: None,
},
frame_type: FrameType::Corrupted(format!(
"Could not read address {:#10X} from the stack",
address
)),

Check warning on line 301 in trace/src/platform/cortex_m/mod.rs

View workflow job for this annotation

GitHub Actions / clippy

variables can be used directly in the `format!` string

warning: variables can be used directly in the `format!` string --> trace/src/platform/cortex_m/mod.rs:298:62 | 298 | ... frame_type: FrameType::Corrupted(format!( | ________________________________________________________^ 299 | | ... "Could not read address {:#10X} from the stack", 300 | | ... address 301 | | ... )), | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args = note: `#[warn(clippy::uninlined_format_args)]` on by default
variables: Vec::new(),
}),
});
Expand Down
Loading
Loading