Skip to content

Commit 670ca14

Browse files
committed
better backtrace
thanks rcore-os/rCore-Tutorial-v3#105 by Godones
1 parent 6380d07 commit 670ca14

File tree

10 files changed

+137
-20
lines changed

10 files changed

+137
-20
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
os/src/link_app.S
66
os/src/linker.ld
77
user/build
8+
9+
os/src/trace/kernel_symbol.S

os/Cargo.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

os/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4e
1515
easy-fs = { path = "../easy-fs" }
1616
volatile = "0.3"
1717
lose-net-stack = { git = "https://github.com/yfblock/lose-net-stack", rev = "db42380" }
18+
tracer = { git = "https://github.com/os-module/rtrace" }
19+
20+
[profile.release]
21+
debug = true

os/Makefile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ KERNEL_ENTRY_PA := 0x80200000
3131
OBJDUMP := rust-objdump --arch-name=riscv64
3232
OBJCOPY := rust-objcopy --binary-architecture=riscv64
3333

34-
# Disassembly
35-
DISASM ?= -x
34+
# Disassembly (--disassemble-all)
35+
DISASM ?= -D
3636

3737
# Run usertests or usershell
3838
TEST ?= 0
@@ -44,7 +44,7 @@ ifneq ($(strip $(USE_DISK)),)
4444
FS_IMG := $(USE_DISK)
4545
endif
4646

47-
build: env $(KERNEL_BIN) $(if $(strip $(USE_DISK)), ,fs-img)
47+
build: env stack_trace $(KERNEL_BIN) $(if $(strip $(USE_DISK)), ,fs-img)
4848

4949
env:
5050
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET)
@@ -61,11 +61,17 @@ fs-img: $(APPS)
6161
@cd ../easy-fs-fuse && cargo run --release -- -s ../user/src/bin -t ../user/target/$(TARGET)/$(MODE)/
6262

6363
$(APPS):
64+
# install trace_exe to generate elf symbol info
65+
stack_trace:
66+
(cargo install --list | awk '/^\w/ {print $1}' | grep "cargo-binutils") || cargo install --git https://github.com/os-module/elfinfo
6467

6568
kernel:
6669
@echo Platform: $(BOARD)
70+
@touch src/trace/kernel_symbol.S && rm src/trace/kernel_symbol.S
6771
@cp src/linker-$(BOARD).ld src/linker.ld
6872
@cargo build $(MODE_ARG)
73+
@(nm -n ${KERNEL_ELF} | trace_exe > src/trace/kernel_symbol.S)
74+
@cargo build $(MODE_ARG)
6975
@rm src/linker.ld
7076

7177
clean:

os/build.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
1+
use std::{fs::File, io::Write, path::Path};
2+
13
const TARGET_PATH: &str = "../user/target/riscv64gc-unknown-none-elf/release/";
24

35
fn main() {
46
println!("cargo:rerun-if-changed=../user/src");
57
println!("cargo:rerun-if-changed={}", TARGET_PATH);
8+
println!("cargo:rerun-if-changed={}", "src");
9+
let path = Path::new("src/trace/kernel_symbol.S");
10+
if !path.exists() {
11+
let mut f = File::create(path).unwrap();
12+
writeln!(
13+
f,
14+
r#"
15+
.section .rodata
16+
.align 3
17+
.globl symbol_num
18+
.globl symbol_address
19+
.globl symbol_index
20+
.globl symbol_name
21+
symbol_num:
22+
.quad {}
23+
symbol_address:
24+
symbol_index:
25+
symbol_name:"#,
26+
0
27+
)
28+
.unwrap();
29+
}
630
}

os/src/lang_item.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use core::{arch::asm, panic::PanicInfo};
1+
use core::panic::PanicInfo;
22

3-
use crate::{sbi::shutdown, task::current_kstack_top};
3+
use tracer::{FramePointTracer, Tracer};
4+
5+
use crate::sbi::shutdown;
46

57
#[panic_handler]
68
fn panic(info: &PanicInfo) -> ! {
@@ -14,23 +16,15 @@ fn panic(info: &PanicInfo) -> ! {
1416
} else {
1517
log::error!("Panicked: {}", info.message());
1618
}
17-
unsafe {
18-
backtrace();
19-
}
19+
backtrace();
2020
shutdown(true)
2121
}
2222

23-
unsafe fn backtrace() {
24-
let mut fp: usize;
25-
let stop = current_kstack_top();
26-
asm!("mv {}, s0", out(reg) fp);
23+
fn backtrace() {
2724
println!("---START BACKTRACE---");
28-
for i in 0..10 {
29-
if fp == stop {
30-
break;
31-
}
32-
println!("#{}:ra={:#x}", i, *((fp - 8) as *const usize));
33-
fp = *((fp - 16) as *const usize);
25+
let tracer = FramePointTracer::new(crate::trace::Provider);
26+
for v in tracer.trace() {
27+
println!("[{:#x}] (+{:0>4x}) {}", v.func_addr, v.bias, v.func_name);
3428
}
3529
println!("---END BACKTRACE---");
3630
}

os/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ mod sync;
2525
mod syscall;
2626
mod task;
2727
mod timer;
28+
mod trace;
2829
mod trap;
2930

3031
use core::arch::global_asm;

os/src/task/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ pub use manager::{add_task, pid2process, wakeup_task};
2222
pub use mem::*;
2323
pub use process::{FileMapping, MMapReserve, MapRange, ProcessControlBlock};
2424
pub use processor::{
25-
current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va,
26-
current_user_token, run_tasks, schedule, user_time_end, user_time_start,
25+
current_process, current_task, current_trap_cx, current_trap_cx_user_va, current_user_token,
26+
run_tasks, schedule, user_time_end, user_time_start,
2727
};
2828
pub use signal::{SignalFlags, MAX_SIG};
2929
pub use task::{TaskControlBlock, TaskStatus};

os/src/task/processor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub fn current_trap_cx_user_va() -> usize {
9393
.trap_cx_user_va()
9494
}
9595

96+
#[allow(unused)]
9697
pub fn current_kstack_top() -> usize {
9798
if let Some(task) = current_task() {
9899
task.kstack.get_top()

os/src/trace/mod.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use core::arch::global_asm;
2+
3+
use tracer::TracerProvider;
4+
5+
global_asm!(include_str!("kernel_symbol.S"));
6+
7+
extern "C" {
8+
fn symbol_num();
9+
fn symbol_address();
10+
fn symbol_index();
11+
fn symbol_name();
12+
}
13+
14+
pub struct Provider;
15+
16+
impl TracerProvider for Provider {
17+
fn address2symbol(&self, addr: usize) -> Option<(usize, &'static str)> {
18+
find_symbol_with_addr(addr)
19+
}
20+
}
21+
22+
pub fn find_symbol_with_addr(addr: usize) -> Option<(usize, &'static str)> {
23+
// println!("find_sym_w/addr {:#x}", addr);
24+
let symbol_num_addr = symbol_num as usize as *const usize;
25+
// println!("symbol_num_addr {:#x}", symbol_num_addr as usize);
26+
let symbol_num = unsafe { symbol_num_addr.read_volatile() };
27+
// println!("num = {}", symbol_num);
28+
if symbol_num == 0 {
29+
return None;
30+
}
31+
let symbol_addr = symbol_address as usize as *const usize; // 符号地址存储区域
32+
let addr_data = unsafe { core::slice::from_raw_parts(symbol_addr, symbol_num) };
33+
// find the symbol with the nearest address
34+
let mut index = -1isize;
35+
for i in 0..symbol_num - 1 {
36+
if addr >= addr_data[i] && addr < addr_data[i + 1] {
37+
index = i as isize;
38+
break;
39+
}
40+
}
41+
if addr == addr_data[symbol_num - 1] {
42+
index = (symbol_num - 1) as isize;
43+
}
44+
// println!("nearest addr to index = {}", index);
45+
if index == -1 {
46+
return None;
47+
}
48+
let index = index as usize;
49+
let symbol_index = symbol_index as usize as *const usize; // 符号字符串的起始位置
50+
let index_data = unsafe { core::slice::from_raw_parts(symbol_index, symbol_num) };
51+
let symbol_name = symbol_name as usize as *const u8; // 符号字符串
52+
let mut last = 0;
53+
unsafe {
54+
for i in index_data[index].. {
55+
let c = symbol_name.add(i);
56+
if *c == 0 {
57+
last = i;
58+
break;
59+
}
60+
}
61+
}
62+
let name = unsafe {
63+
core::slice::from_raw_parts(symbol_name.add(index_data[index]), last - index_data[index])
64+
};
65+
let name = core::str::from_utf8(name).unwrap();
66+
// println!("symbol = {}", name);
67+
Some((addr_data[index], name))
68+
}

0 commit comments

Comments
 (0)