Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update to new backtrace lib #1049

Merged
merged 5 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
11 changes: 9 additions & 2 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ members = [
[features]
default = ["backtrace", "kvm", "fatfs", "fatfs-secure"]
# 内核栈回溯
backtrace = []
backtrace = ["dep:unwinding"]
# kvm
kvm = []

Expand Down Expand Up @@ -67,9 +67,16 @@ lru = "0.12.3"

rbpf = { path = "crates/rbpf" }
printf-compat = { version = "0.1.1", default-features = false }

unwinding = { git = "https://github.com/Godones/unwinding.git", branch = "hook", default-features = false, optional = true, features = [
"unwinder",
"fde-gnu-eh-frame-hdr",
"panic",
"personality"
]}

# target为x86_64时,使用下面的依赖
[target.'cfg(target_arch = "x86_64")'.dependencies]
mini-backtrace = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/mini-backtrace.git", rev = "e0b1d90940" }
multiboot2 = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/multiboot2", rev = "05739aab40" }
raw-cpuid = "11.0.1"
x86 = "=0.52.0"
Expand Down
4 changes: 2 additions & 2 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ include ./env.mk
ifeq ($(ARCH), x86_64)
export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json
else ifeq ($(ARCH), riscv64)
export TARGET_JSON=riscv64gc-unknown-none-elf
export TARGET_JSON=arch/riscv64/riscv64gc-unknown-none-elf.json
endif

export CARGO_ZBUILD=-Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem
Expand All @@ -27,7 +27,7 @@ clean:
fmt:
RUSTFLAGS="$(RUSTFLAGS)" cargo fmt --all $(FMT_CHECK)
ifeq ($(ARCH), x86_64)
RUSTFLAGS="$(RUSTFLAGS)" cargo clippy --all-features
# RUSTFLAGS="$(RUSTFLAGS)" cargo clippy --all-features
endif


Expand Down
28 changes: 22 additions & 6 deletions kernel/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ CFLAGS_UNWIND =
LDFLAGS_UNWIND =
RUSTFLAGS_UNWIND =
ifeq ($(UNWIND_ENABLE), yes)
CFLAGS_UNWIND = -funwind-tables
ifeq ($(ARCH), x86_64)
LDFLAGS_UNWIND = --eh-frame-hdr
RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld
endif
CFLAGS_UNWIND = -funwind-tables
LDFLAGS_UNWIND = --eh-frame-hdr
RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld
endif

RUSTFLAGS += $(RUSTFLAGS_UNWIND)
Expand Down Expand Up @@ -58,15 +56,33 @@ ECHO:
@echo "$@"

$(kernel_subdirs): ECHO

$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" kernel_root_path="$(shell pwd)"

kernel: $(kernel_subdirs) kernel_rust

__link_riscv64_kernel:
@echo "Linking kernel..."
$(LD) -b elf64-littleriscv -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/riscv64gc-unknown-none-elf/release/libdragonos_kernel.a -T arch/riscv64/link.ld --no-relax
# 生成kallsyms
current_dir=$(pwd)

@dbg='debug';for x in $$dbg; do \
cd $$x;\
$(MAKE) generate_kallsyms kernel_root_path="$(shell pwd)"||exit 1;\
cd ..;\
done

# 重新链接
@echo "Re-Linking kernel..."
@echo $(shell find . -name "*.o")
$(LD) -b elf64-littleriscv -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/riscv64gc-unknown-none-elf/release/libdragonos_kernel.a ./debug/kallsyms.o -T arch/riscv64/link.ld --no-relax
@echo "Generating kernel ELF file..."

ifeq ($(UNWIND_ENABLE), yes)
$(OBJCOPY) -I elf64-littleriscv -O elf64-littleriscv kernel ../../bin/kernel/kernel.elf
else
$(OBJCOPY) -I elf64-littleriscv -O elf64-littleriscv -R ".eh_frame" kernel ../../bin/kernel/kernel.elf
endif
@rm kernel
$(MAKE) __dragon_stub PAYLOAD_ELF="$(shell pwd)/../../bin/kernel/kernel.elf"

Expand Down
2 changes: 2 additions & 0 deletions kernel/src/arch/riscv64/link.ld
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ SECTIONS

. = ALIGN(4096);
text_start_pa = .;
__executable_start = .;
.text (text_start_pa): AT(text_start_pa - KERNEL_VMA)
{
_text = .;
Expand All @@ -39,6 +40,7 @@ SECTIONS
*(.text.*)

_etext = .;
__etext = .;
}
. = ALIGN(32768);
data_start_pa = .;
Expand Down
28 changes: 28 additions & 0 deletions kernel/src/arch/riscv64/riscv64gc-unknown-none-elf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"arch": "riscv64",
"code-model": "medium",
"cpu": "generic-rv64",
"crt-objects-fallback": "false",
"data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
"eh-frame-header": false,
"emit-debug-gdb-scripts": false,
"features": "+m,+a,+f,+d,+c",
"linker": "rust-lld",
"linker-flavor": "gnu-lld",
"llvm-abiname": "lp64d",
"llvm-target": "riscv64",
"max-atomic-width": 64,
"metadata": {
"description": "Bare RISC-V (RV64IMAFDC ISA)",
"host_tools": false,
"std": false,
"tier": 2
},
"panic-strategy": "unwind",
"relocation-model": "static",
"supported-sanitizers": [
"shadow-call-stack",
"kernel-address"
],
"target-pointer-width": "64"
}
3 changes: 2 additions & 1 deletion kernel/src/arch/riscv64/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ pub(super) fn syscall_handler(syscall_num: usize, frame: &mut TrapFrame) -> () {

let args = [frame.a0, frame.a1, frame.a2, frame.a3, frame.a4, frame.a5];
syscall_return!(
Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize),
Syscall::catch_handle(syscall_num, &args, frame)
.unwrap_or_else(|e| e.to_posix_errno() as usize),
frame,
false
);
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/arch/x86_64/link.lds
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SECTIONS
. = ALIGN(32768);
. += KERNEL_VMA;
text_start_pa = .;
__executable_start = .;
.text (text_start_pa): AT(text_start_pa - KERNEL_VMA)
{
_text = .;
Expand All @@ -37,6 +38,7 @@ SECTIONS
*(.text.*)

_etext = .;
__etext = .;
}
. = ALIGN(32768);
data_start_pa = .;
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/arch/x86_64/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
_ => {}
}
syscall_return!(
Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize)
as u64,
Syscall::catch_handle(syscall_num, &args, frame)
.unwrap_or_else(|e| e.to_posix_errno() as usize) as u64,
frame,
show
);
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/arch/x86_64/x86_64-unknown-none.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
"executables": true,
"features": "-mmx,-sse,+soft-float",
"disable-redzone": true,
"panic-strategy": "abort"
"panic-strategy": "unwind"
}
79 changes: 63 additions & 16 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,11 @@ extern crate wait_queue_macros;

use crate::mm::allocator::kernel_allocator::KernelAllocator;

#[cfg(all(feature = "backtrace", target_arch = "x86_64"))]
extern crate mini_backtrace;
#[cfg(feature = "backtrace")]
use unwinding::{
abi::{UnwindContext, UnwindReasonCode, _Unwind_GetIP},
panic::UserUnwindTrace,
};

extern "C" {
fn lookup_kallsyms(addr: u64, level: i32) -> i32;
Expand All @@ -105,12 +108,37 @@ extern "C" {
pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator;

/// 全局的panic处理函数
///
Godones marked this conversation as resolved.
Show resolved Hide resolved
/// How to use unwinding lib:
///
/// ```
/// pub fn test_unwind() {
/// struct UnwindTest;
/// impl Drop for UnwindTest {
/// fn drop(&mut self) {
/// println!("Drop UnwindTest");
/// }
/// }
/// let res1 = unwinding::panic::catch_unwind(|| {
/// let _unwind_test = UnwindTest;
/// println!("Test panic...");
/// panic!("Test panic");
/// });
/// assert_eq!(res1.is_err(), true);
/// let res2 = unwinding::panic::catch_unwind(|| {
/// let _unwind_test = UnwindTest;
/// println!("Test no panic...");
/// 0
/// });
/// assert_eq!(res2.is_ok(), true);
/// }
/// ```
///
#[cfg(target_os = "none")]
#[panic_handler]
#[no_mangle]
pub fn panic(info: &PanicInfo) -> ! {
use log::error;
use process::ProcessManager;

error!("Kernel Panic Occurred.");

Expand All @@ -128,21 +156,40 @@ pub fn panic(info: &PanicInfo) -> ! {
}
}
println!("Message:\n\t{}", info.message());

#[cfg(all(feature = "backtrace", target_arch = "x86_64"))]
#[cfg(feature = "backtrace")]
{
unsafe {
let bt = mini_backtrace::Backtrace::<16>::capture();
println!("Rust Panic Backtrace:");
let mut level = 0;
for frame in bt.frames {
lookup_kallsyms(frame as u64, level);
level += 1;
}
};
let mut data = CallbackData { counter: 0 };
println!("Rust Panic Backtrace:");
let res = unwinding::panic::begin_panic_with_hook::<Tracer>(
alloc::boxed::Box::new(()),
&mut data,
);
log::error!("panic unreachable: {:?}", res.0);
}
println!(
"Current PCB:\n\t{:?}",
process::ProcessManager::current_pcb()
);
process::ProcessManager::exit(usize::MAX)
}

println!("Current PCB:\n\t{:?}", (ProcessManager::current_pcb()));
/// User hook for unwinding
///
/// During stack backtrace, the user can print the function location of the current stack frame.
struct Tracer;
struct CallbackData {
counter: usize,
}
impl UserUnwindTrace for Tracer {
type Arg = CallbackData;

ProcessManager::exit(usize::MAX);
fn trace(ctx: &UnwindContext<'_>, arg: *mut Self::Arg) -> UnwindReasonCode {
let data = unsafe { &mut *(arg) };
data.counter += 1;
let pc = _Unwind_GetIP(ctx);
unsafe {
lookup_kallsyms(pc as u64, data.counter as i32);
}
UnwindReasonCode::NO_REASON
}
}
11 changes: 11 additions & 0 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ impl Syscall {

return r;
}
/// 系统调用分发器,用于分发系统调用。
///
/// 与[handle]不同,这个函数会捕获系统调用处理函数的panic,返回错误码。
pub fn catch_handle(
syscall_num: usize,
args: &[usize],
frame: &mut TrapFrame,
) -> Result<usize, SystemError> {
let res = unwinding::panic::catch_unwind(|| Self::handle(syscall_num, args, frame));
res.unwrap_or_else(|_e| Err(SystemError::ENOTRECOVERABLE))
}
fslongjin marked this conversation as resolved.
Show resolved Hide resolved
/// @brief 系统调用分发器,用于分发系统调用。
///
/// 这个函数内,需要根据系统调用号,调用对应的系统调用处理函数。
Expand Down
Loading