Add debug infos on panic

This commit is contained in:
2026-03-22 14:27:56 +01:00
parent 897775f63a
commit 15ecefb5fb
14 changed files with 282 additions and 50 deletions

View File

@@ -0,0 +1,128 @@
use addr2line::Context;
use object::{Object, ObjectSymbol, SymbolKind};
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
#[repr(C, packed(4))]
#[derive(Debug)]
struct RawSymbol {
addr: u64,
line: u32,
name_off: u32,
file_off: u32,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let elf_path = "../target/riscv64/debug/kernel-rust";
let bin_data = std::fs::read(elf_path)?;
let obj_file = object::File::parse(&*bin_data)?;
let context = Context::new(&obj_file)?;
let mut symbols_list = Vec::new();
let mut string_table = Vec::new();
let mut str_cache = HashMap::new();
// Helper pour gérer la table des chaînes (String Table)
let mut add_string = |s: &str| -> u32 {
*str_cache.entry(s.to_string()).or_insert_with(|| {
let off = string_table.len() as u32;
string_table.extend_from_slice(s.as_bytes());
string_table.push(0); // Null terminator
off
})
};
println!("Extraction des symboles depuis {}...", elf_path);
obj_file.symbols().enumerate().for_each(|(i, sym)| {
// On ne garde que les fonctions (Text)
if sym.kind() == SymbolKind::Text && sym.size() > 0 {
let addr = sym.address();
let raw_name = sym.name().unwrap_or("unknown");
let name = format!("{:#}", rustc_demangle::demangle(raw_name));
let mut frames = context.find_frames(addr).skip_all_loads().unwrap();
let (file, line) = if let Ok(Some(frame)) = frames.next() {
let f = frame
.location
.as_ref()
.and_then(|l| {
l.file.and_then(|file| {
Path::new(file)
.strip_prefix(std::env::current_dir().unwrap().parent().unwrap())
.map_or(Some(file), |p| p.to_str())
})
})
.unwrap_or("unknown");
let l = frame.location.as_ref().and_then(|l| l.line).unwrap_or(0);
(f, l)
} else {
("unknown", 0)
};
symbols_list.push(RawSymbol {
addr,
line,
name_off: add_string(&name),
file_off: add_string(file),
});
}
});
// Tri par adresse pour la recherche binaire au runtime
symbols_list.sort_by_key(|s| s.addr);
let idx = match symbols_list.binary_search_by_key(&(0x000000008004073c), |s| s.addr) {
Ok(i) => i,
Err(i) if i > 0 => i - 1,
_ => panic!(),
};
println!("{:?}", unsafe {
get_str(
string_table
.as_ptr()
.add(symbols_list[idx].name_off as usize),
)
});
// Écriture du fichier symbols.bin
let mut f = BufWriter::new(File::create("../target/symbols.bin")?);
// Header : [u64: count] [u64: string_table_offset]
let header_size = 16;
let sym_table_size = symbols_list.len() * std::mem::size_of::<RawSymbol>();
f.write_all(&(symbols_list.len() as u64).to_le_bytes())?;
f.write_all(&((header_size + sym_table_size) as u64).to_le_bytes())?;
// Table des symboles
for sym in &symbols_list {
unsafe {
let bytes = std::slice::from_raw_parts(
(sym as *const RawSymbol) as *const u8,
std::mem::size_of::<RawSymbol>(),
);
f.write_all(bytes)?;
}
}
// Table des noms
f.write_all(&string_table)?;
println!(
"Terminé ! {} symboles écrits dans symbols.bin",
symbols_list.len()
);
Ok(())
}
unsafe fn get_str(ptr: *const u8) -> &'static str {
let mut len = 0;
while *ptr.add(len) != 0 {
len += 1;
}
core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len))
}