Use the object crate for panic backtraces

This increases the kernel image size by about 16kb, but in return
significantly simplifies things.
This commit is contained in:
bjorn3
2025-09-13 20:55:39 +02:00
parent ad4ea619e8
commit 30bbafdfa4
5 changed files with 35 additions and 198 deletions
Generated
+10 -23
View File
@@ -82,16 +82,6 @@ name = "fdt"
version = "0.2.0-alpha1"
source = "git+https://github.com/repnop/fdt.git?rev=2fb1409edd1877c714a0aa36b6a7c5351004be54#2fb1409edd1877c714a0aa36b6a7c5351004be54"
[[package]]
name = "goblin"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
dependencies = [
"plain",
"scroll",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
@@ -127,10 +117,10 @@ dependencies = [
"byteorder",
"cc",
"fdt",
"goblin",
"hashbrown 0.14.5",
"indexmap",
"linked_list_allocator 0.9.1",
"object",
"raw-cpuid",
"redox-path",
"redox_syscall",
@@ -180,18 +170,21 @@ version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "proc-macro2"
version = "1.0.95"
@@ -273,12 +266,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scroll"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec"
[[package]]
name = "serde"
version = "1.0.219"
+3 -3
View File
@@ -25,10 +25,10 @@ slab = { version = "0.4", default-features = false }
# TODO: Remove
indexmap = { version = "2.5.0", default-features = false }
[dependencies.goblin]
version = "0.2.1"
[dependencies.object]
version = "0.37.1"
default-features = false
features = ["elf32", "elf64"]
features = ["read_core", "elf"]
[dependencies.rustc-demangle]
version = "0.1.16"
-126
View File
@@ -1,126 +0,0 @@
//! ELF executables
use alloc::string::String;
use goblin::elf::section_header::SHT_SYMTAB;
#[cfg(target_arch = "x86")]
pub use goblin::elf32::{header, program_header, section_header, sym};
#[cfg(any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64"
))]
pub use goblin::elf64::{header, section_header, sym};
/// An ELF executable
pub struct Elf<'a> {
pub data: &'a [u8],
header: &'a header::Header,
}
impl<'a> Elf<'a> {
/// Create a ELF executable from data
pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
if data.len() < header::SIZEOF_EHDR {
Err(format!(
"Elf: Not enough data: {} < {}",
data.len(),
header::SIZEOF_EHDR
))
} else if &data[..header::SELFMAG] != header::ELFMAG {
Err(format!(
"Elf: Invalid magic: {:?} != {:?}",
&data[..header::SELFMAG],
header::ELFMAG
))
} else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) {
Err(format!(
"Elf: Invalid architecture: {:?} != {:?}",
data.get(header::EI_CLASS),
header::ELFCLASS
))
} else {
Ok(Elf {
data,
header: unsafe { &*(data.as_ptr() as usize as *const header::Header) },
})
}
}
pub fn sections(&'a self) -> ElfSections<'a> {
ElfSections {
data: self.data,
header: self.header,
i: 0,
}
}
pub fn symbols(&'a self) -> Option<ElfSymbols<'a>> {
let mut symtab_opt = None;
for section in self.sections() {
if section.sh_type == SHT_SYMTAB {
symtab_opt = Some(section);
break;
}
}
if let Some(symtab) = symtab_opt {
Some(ElfSymbols {
data: self.data,
symtab,
i: 0,
})
} else {
None
}
}
}
pub struct ElfSections<'a> {
data: &'a [u8],
header: &'a header::Header,
i: usize,
}
impl<'a> Iterator for ElfSections<'a> {
type Item = &'a section_header::SectionHeader;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.header.e_shnum as usize {
let item = unsafe {
&*((self.data.as_ptr() as usize
+ self.header.e_shoff as usize
+ self.i * self.header.e_shentsize as usize)
as *const section_header::SectionHeader)
};
self.i += 1;
Some(item)
} else {
None
}
}
}
pub struct ElfSymbols<'a> {
data: &'a [u8],
symtab: &'a section_header::SectionHeader,
i: usize,
}
impl<'a> Iterator for ElfSymbols<'a> {
type Item = &'a sym::Sym;
fn next(&mut self) -> Option<Self::Item> {
if self.i < (self.symtab.sh_size as usize) / sym::SIZEOF_SYM {
let item = unsafe {
&*((self.data.as_ptr() as usize
+ self.symtab.sh_offset as usize
+ self.i * sym::SIZEOF_SYM) as *const sym::Sym)
};
self.i += 1;
Some(item)
} else {
None
}
}
}
-3
View File
@@ -105,9 +105,6 @@ mod debugger;
/// Architecture-independent devices
mod devices;
/// ELF file parsing
mod elf;
/// Event handling
mod event;
+22 -43
View File
@@ -1,15 +1,18 @@
//! Intrinsics for panic handling
use core::{panic::PanicInfo, slice, str, sync::atomic::Ordering};
use goblin::elf::sym;
use core::{panic::PanicInfo, slice, sync::atomic::Ordering};
#[cfg(target_pointer_width = "32")]
use object::read::elf::ElfFile32 as ElfFile;
#[cfg(target_pointer_width = "64")]
use object::read::elf::ElfFile64 as ElfFile;
use object::{elf::STT_FUNC, NativeEndian, Object, ObjectSymbol};
use rmm::VirtualAddress;
use rustc_demangle::demangle;
use crate::{
arch::{consts::USER_END_OFFSET, interrupt::trace::StackTrace},
context, cpu_id,
elf::Elf,
interrupt,
context, cpu_id, interrupt,
memory::KernelMapper,
start::KERNEL_SIZE,
syscall,
@@ -104,47 +107,23 @@ pub unsafe fn symbol_trace(addr: usize) {
let kernel_ptr = crate::KERNEL_OFFSET as *const u8;
let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst));
if let Ok(elf) = Elf::from(kernel_slice) {
let mut strtab_opt = None;
for section in elf.sections() {
if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB {
strtab_opt = Some(section);
break;
}
let obj = ElfFile::<NativeEndian>::parse(kernel_slice).unwrap();
for sym in obj.symbols() {
if sym.elf_symbol().st_type() != STT_FUNC {
continue;
}
if !(addr >= sym.address() as usize && addr < (sym.address() + sym.size()) as usize) {
continue;
}
if let Some(symbols) = elf.symbols() {
for sym in symbols {
if sym::st_type(sym.st_info) == sym::STT_FUNC
&& addr >= sym.st_value as usize
&& addr < (sym.st_value + sym.st_size) as usize
{
println!(
" {:>016X}+{:>04X}",
sym.st_value,
addr - sym.st_value as usize
);
println!(
" {:>016X}+{:>04X}",
sym.address(),
addr - sym.address() as usize
);
if let Some(strtab) = strtab_opt {
let start = strtab.sh_offset as usize + sym.st_name as usize;
let mut end = start;
while end < elf.data.len() {
let b = elf.data[end];
end += 1;
if b == 0 {
break;
}
}
if end > start {
let sym_slice = &elf.data[start..end - 1];
if let Ok(sym_name) = str::from_utf8(sym_slice) {
println!(" {:#}", demangle(sym_name));
}
}
}
}
}
if let Ok(sym_name) = sym.name() {
println!(" {:#}", demangle(sym_name));
}
}
}