From d470019b1e675a04473cbb3c3eeaf180c8665e6d Mon Sep 17 00:00:00 2001 From: LoGin Date: Wed, 1 Nov 2023 22:12:19 +0800 Subject: [PATCH] patch add mini backtrace (#416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * support rust panic backtrace mini-backtrace has llvm's unwind cpp source to support backtrace/unwind. as unwind/backtrace needs dynamically allocates memory, mini-backtrace uses stack memory to capture fixed number of backtrace to avoid heap allocation. as unwind library needed, it needs to turn on eh_frame_hdr * 修改忘了生成kernel.elf的问题 * 设置backtrace是默认的feature --------- Co-authored-by: Yao Zhao --- kernel/Cargo.toml | 9 ++++++-- kernel/src/Makefile | 29 +++++++++++++++++++------- kernel/src/debug/traceback/traceback.c | 2 +- kernel/src/driver/net/virtio_net.rs | 3 ++- kernel/src/lib.rs | 21 +++++++++++++++++++ kernel/src/link.lds | 14 ++++++++++++- tools/bootstrap.sh | 19 +++++++++++++++-- 7 files changed, 83 insertions(+), 14 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c2b0ff964..82dd7b6ab 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,6 +12,11 @@ crate-type = ["staticlib"] [workspace] members = [ "src/libs/intertrait" ] +[features] +default = ["backtrace"] +# 内核栈回溯 +backtrace = [] + # 运行时依赖项 [dependencies] x86 = "0.52.0" @@ -36,6 +41,7 @@ acpi = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/acpi-rs.git" intertrait = { path = "src/libs/intertrait" } linkme = "0.2" ida = { path = "src/libs/ida" } +mini-backtrace = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/mini-backtrace.git", rev = "ba98506685" } # 构建时依赖项 [build-dependencies] @@ -54,5 +60,4 @@ debug = true # Controls whether the compiler passes `-g` # The release profile, used for `cargo build --release` [profile.release] -debug = false - +debug = false \ No newline at end of file diff --git a/kernel/src/Makefile b/kernel/src/Makefile index eb71a9b5d..900d5ec70 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -10,7 +10,19 @@ LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns))) # 控制操作系统使用的中断控制器 _INTR_8259A_ _INTR_APIC_ PIC := _INTR_APIC_ -CFLAGS = $(GLOBAL_CFLAGS) -fno-pie -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include + +# unwind/backtrace related +UNWIND_ENABLE ?= yes +CFLAGS_UNWIND = +LDFLAGS_UNWIND = +RUSTFLAGS_UNWIND = +ifeq ($(UNWIND_ENABLE), yes) + CFLAGS_UNWIND = -funwind-tables + LDFLAGS_UNWIND = --eh-frame-hdr + RUSTFLAGS_UNWIND = -Cforce-unwind-tables -Clink-arg=-Wl,eh_frame.ld +endif + +CFLAGS = $(GLOBAL_CFLAGS) -fno-pie $(CFLAGS_UNWIND) -D $(PIC) -I $(shell pwd) -I $(shell pwd)/include -I $(shell pwd)/arch/x86_64/include export ASFLAGS := --64 @@ -32,12 +44,12 @@ main.o: main.c kernel_rust: rustup default nightly - cargo +nightly-2023-01-21 build --release --target ./arch/x86_64/x86_64-unknown-none.json + RUSTFLAGS="$(RUSTFLAGS_UNWIND)" cargo +nightly-2023-01-21 build --release --target ./arch/x86_64/x86_64-unknown-none.json all: kernel @echo "Linking kernel..." - $(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds --no-relax + $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a -T link.lds --no-relax # 生成kallsyms current_dir=$(pwd) @@ -51,11 +63,14 @@ all: kernel # 重新链接 @echo "Re-Linking kernel..." @echo $(shell find . -name "*.o") - $(LD) -b elf64-x86-64 -z muldefs -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds --no-relax + $(LD) -b elf64-x86-64 -z muldefs $(LDFLAGS_UNWIND) -o kernel head.o main.o $(shell find . -name "*.o") ../target/x86_64-unknown-none/release/libdragonos_kernel.a ./debug/kallsyms.o -T link.lds --no-relax @echo "Generating kernel ELF file..." # 生成内核文件 - $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 kernel ../../bin/kernel/kernel.elf -# $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../../bin/kernel/kernel.elf +ifeq ($(UNWIND_ENABLE), yes) + $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 kernel ../../bin/kernel/kernel.elf +else + $(OBJCOPY) -I elf64-x86-64 -O elf64-x86-64 -R ".eh_frame" kernel ../../bin/kernel/kernel.elf +endif @echo "Kernel Build Done." ECHO: @@ -76,4 +91,4 @@ clean: echo "Clean in dir: $$subdir";\ cd $$subdir && $(MAKE) clean;\ cd .. ;\ - done \ No newline at end of file + done diff --git a/kernel/src/debug/traceback/traceback.c b/kernel/src/debug/traceback/traceback.c index 352e3a460..d9474eb60 100644 --- a/kernel/src/debug/traceback/traceback.c +++ b/kernel/src/debug/traceback/traceback.c @@ -2,7 +2,7 @@ #include #include -static int lookup_kallsyms(uint64_t addr, int level) +int lookup_kallsyms(uint64_t addr, int level) { const char *str = (const char *)&kallsyms_names; diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 3cca5e517..b2a0ba6c5 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -15,7 +15,8 @@ use crate::{ kobject::{KObjType, KObject, KObjectState}, }, virtio::virtio_impl::HalImpl, - }, kerror, kinfo, + }, + kerror, kinfo, libs::spinlock::SpinLock, net::{generate_iface_id, NET_DRIVERS}, syscall::SystemError, diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 63f27900a..aefc146c7 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -74,6 +74,13 @@ use crate::mm::allocator::kernel_allocator::KernelAllocator; use crate::process::ProcessManager; +#[cfg(feature = "backtrace")] +extern crate mini_backtrace; + +extern "C" { + fn lookup_kallsyms(addr: u64, level: i32) -> i32; +} + // 声明全局的分配器 #[cfg_attr(not(test), global_allocator)] pub static KERNEL_ALLOCATOR: KernelAllocator = KernelAllocator; @@ -108,6 +115,20 @@ pub fn panic(info: &PanicInfo) -> ! { } } + #[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; + } + }; + } + println!("Current PCB:\n\t{:?}", *(ProcessManager::current_pcb())); ProcessManager::exit(usize::MAX); + unreachable!(); } diff --git a/kernel/src/link.lds b/kernel/src/link.lds index de460f742..58fd6a82b 100644 --- a/kernel/src/link.lds +++ b/kernel/src/link.lds @@ -71,10 +71,22 @@ SECTIONS _ebss = .; } + eh_frame = .; + .eh_frame (eh_frame): AT(eh_frame - KERNEL_VMA) + { + __eh_frame_hdr_start = .; + *(.eh_frame_hdr) + __eh_frame_hdr_end = .; + __eh_frame_start = .; + *(.eh_frame) + *(.rela.eh_frame) + __eh_frame_end = .; + } + _end = .; /DISCARD/ : { - *(.eh_frame) + /* *(.eh_frame) */ } } diff --git a/tools/bootstrap.sh b/tools/bootstrap.sh index 39dcefbab..3dc26a935 100644 --- a/tools/bootstrap.sh +++ b/tools/bootstrap.sh @@ -64,6 +64,21 @@ install_ubuntu_debian_pkg() } +install_archlinux_pkg() +{ + pkgman="pacman" + echo "检测到 ArchLinux" + echo "正在更新包管理器的列表..." + sudo "${pkgman}" -Sy + echo "正在安装所需的包..." + sudo "${pkgman}" -S --needed --noconfirm \ + curl wget bridge-utils dnsmasq \ + diffutils pkgconf which unzip util-linux dosfstools \ + gcc make flex texinfo gmp mpfr qemu-base \ + libmpc libssl-dev + +} + install_osx_pkg() { echo "Detected OSX! 暂不支持Mac OSX的一键安装!" @@ -194,7 +209,7 @@ else solus "$emulator" || exit 1 # Arch linux elif hash 2>/dev/null pacman; then - archLinux "$emulator" || exit 1 + install_archlinux_pkg || exit 1 # FreeBSD elif hash 2>/dev/null pkg; then freebsd "$emulator" || exit 1 @@ -221,4 +236,4 @@ USR=$USER sudo adduser $USR kvm sudo chown $USR /dev/kvm -congratulations \ No newline at end of file +congratulations