mirror of
https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials.git
synced 2024-11-11 07:10:59 +00:00
115 lines
4.4 KiB
Rust
115 lines
4.4 KiB
Rust
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||
|
//
|
||
|
// Copyright (c) 2022 Andre Richter <andre.o.richter@gmail.com>
|
||
|
|
||
|
//! Backtracing support.
|
||
|
|
||
|
#[cfg(target_arch = "aarch64")]
|
||
|
#[path = "_arch/aarch64/backtrace.rs"]
|
||
|
mod arch_backtrace;
|
||
|
|
||
|
use crate::{
|
||
|
memory::{Address, Virtual},
|
||
|
symbols,
|
||
|
};
|
||
|
use core::fmt;
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
// Architectural Public Reexports
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
#[cfg(feature = "test_build")]
|
||
|
pub use arch_backtrace::{corrupt_link, corrupt_previous_frame_addr};
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
// Public Definitions
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
|
||
|
/// A backtrace item.
|
||
|
#[allow(missing_docs)]
|
||
|
pub enum BacktraceItem {
|
||
|
InvalidFramePointer(Address<Virtual>),
|
||
|
InvalidLink(Address<Virtual>),
|
||
|
Link(Address<Virtual>),
|
||
|
}
|
||
|
|
||
|
/// Pseudo-struct for printing a backtrace using its fmt::Display implementation.
|
||
|
pub struct Backtrace;
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
// Public Code
|
||
|
//--------------------------------------------------------------------------------------------------
|
||
|
|
||
|
impl fmt::Display for Backtrace {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||
|
writeln!(f, "Backtrace:")?;
|
||
|
writeln!(
|
||
|
f,
|
||
|
" ----------------------------------------------------------------------------------------------"
|
||
|
)?;
|
||
|
writeln!(
|
||
|
f,
|
||
|
" Address Function containing address"
|
||
|
)?;
|
||
|
writeln!(
|
||
|
f,
|
||
|
" ----------------------------------------------------------------------------------------------"
|
||
|
)?;
|
||
|
|
||
|
let mut fmt_res: fmt::Result = Ok(());
|
||
|
let trace_formatter =
|
||
|
|maybe_iter: Option<&mut dyn Iterator<Item = BacktraceItem>>| match maybe_iter {
|
||
|
None => fmt_res = writeln!(f, "ERROR! No valid stack frame found"),
|
||
|
Some(iter) => {
|
||
|
// Since the backtrace is printed, the first function is always
|
||
|
// core::fmt::write. Skip 1 so it is excluded and doesn't bloat the output.
|
||
|
for (i, backtrace_res) in iter.skip(1).enumerate() {
|
||
|
match backtrace_res {
|
||
|
BacktraceItem::InvalidFramePointer(addr) => {
|
||
|
fmt_res = writeln!(
|
||
|
f,
|
||
|
" {:>2}. ERROR! \
|
||
|
Encountered invalid frame pointer ({}) during backtrace",
|
||
|
i + 1,
|
||
|
addr
|
||
|
);
|
||
|
}
|
||
|
BacktraceItem::InvalidLink(addr) => {
|
||
|
fmt_res = writeln!(
|
||
|
f,
|
||
|
" {:>2}. ERROR! \
|
||
|
Link address ({}) is not contained in kernel .text section",
|
||
|
i + 1,
|
||
|
addr
|
||
|
);
|
||
|
}
|
||
|
BacktraceItem::Link(addr) => {
|
||
|
fmt_res = writeln!(
|
||
|
f,
|
||
|
" {:>2}. {:016x} | {:<50}",
|
||
|
i + 1,
|
||
|
addr.as_usize(),
|
||
|
match symbols::lookup_symbol(addr) {
|
||
|
Some(sym) => sym.name(),
|
||
|
_ => "Symbol not found",
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if fmt_res.is_err() {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
arch_backtrace::backtrace(trace_formatter);
|
||
|
fmt_res?;
|
||
|
|
||
|
writeln!(
|
||
|
f,
|
||
|
" ----------------------------------------------------------------------------------------------"
|
||
|
)
|
||
|
}
|
||
|
}
|