Explorar o código

feat: unwinding and printing stack backtrace

Use unwinding crate to unwind the stack and print stack trace.

Sightly adjust the linker script and move eh_frame into rodata section.

Due to limited kernel image size, there might be some problems on x86_64
platforms. Further fixes needed but won't be fixed for now.

Signed-off-by: greatbridf <greatbridf@icloud.com>
(cherry picked from commit 6bb54d9eae13b76768f011c44222b25b785b83e0)
Signed-off-by: greatbridf <greatbridf@icloud.com>
greatbridf hai 5 meses
pai
achega
34a6252968

+ 1 - 0
.cargo/config.toml

@@ -1,6 +1,7 @@
 [build]
 target = "riscv64gc-unknown-none-elf"
 target-dir = 'build'
+rustflags = ["-C", "force-unwind-tables"]
 
 [unstable]
 build-std-features = ['compiler-builtins-mem']

+ 16 - 0
Cargo.lock

@@ -153,6 +153,7 @@ dependencies = [
  "posix_types",
  "slab_allocator",
  "stalloc",
+ "unwinding",
  "virtio-drivers",
  "xmas-elf",
 ]
@@ -265,6 +266,12 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
 
+[[package]]
+name = "gimli"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe"
+
 [[package]]
 name = "intrusive-collections"
 version = "0.9.7"
@@ -453,6 +460,15 @@ version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
+[[package]]
+name = "unwinding"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60612c845ef41699f39dc8c5391f252942c0a88b7d15da672eff0d14101bbd6d"
+dependencies = [
+ "gimli",
+]
+
 [[package]]
 name = "virtio-drivers"
 version = "0.11.0"

+ 3 - 3
Cargo.toml

@@ -38,6 +38,9 @@ stalloc = { version = "0.6.1", default-features = false, features = [
 [target.'cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))'.dependencies]
 virtio-drivers = { version = "0.11.0" }
 
+[target.'cfg(target_arch = "riscv64")'.dependencies]
+unwinding = { version = "0.2.8", default-features = false, features = ["unwinder", "fde-static", "personality", "panic"] }
+
 [features]
 default = []
 trace_pci = []
@@ -50,9 +53,6 @@ smp = []
 [profile.release]
 debug = true
 
-[profile.dev]
-panic = "abort"
-
 [profile.dev.package.eonix_preempt]
 opt-level = "s"
 

+ 2 - 2
crates/eonix_hal/src/arch/loongarch64/link.x

@@ -91,6 +91,6 @@ SECTIONS {
     } > VDSO AT> RAM
 
     VDSO_PADDR = LOADADDR(.vdso);
-    __kernel_end = ABSOLUTE(LOADADDR(.vdso) + SIZEOF(.vdso));
+    __kernel_end = __edata;
 }
-INSERT BEFORE .bss;
+INSERT BEFORE .data.after;

+ 0 - 2
crates/eonix_hal/src/arch/loongarch64/memory.x

@@ -12,12 +12,10 @@ REGION_ALIAS("REGION_TEXT", KIMAGE);
 REGION_ALIAS("REGION_RODATA", KIMAGE);
 REGION_ALIAS("REGION_DATA", KIMAGE);
 REGION_ALIAS("REGION_BSS", KBSS);
-REGION_ALIAS("REGION_EHFRAME", KIMAGE);
 
 REGION_ALIAS("LINK_REGION_TEXT", RAM);
 REGION_ALIAS("LINK_REGION_RODATA", RAM);
 REGION_ALIAS("LINK_REGION_DATA", RAM);
 REGION_ALIAS("LINK_REGION_BSS", RAM);
-REGION_ALIAS("LINK_REGION_EHFRAME", RAM);
 
 _stext = ORIGIN(REGION_TEXT) + LOADADDR(.text) - ORIGIN(RAM);

+ 3 - 2
crates/eonix_hal/src/arch/riscv64/link.x

@@ -43,7 +43,6 @@ SECTIONS {
 
     KIMAGE_PAGES = (__edata - _stext + 0x1000 - 1) / 0x1000;
     KIMAGE_32K_COUNT = (KIMAGE_PAGES + 8 - 1) / 8;
-    __kernel_end = .;
 
     BSS_LENGTH = ABSOLUTE(__ebss - __sbss);
 }
@@ -89,4 +88,6 @@ SECTIONS {
 
     VDSO_PADDR = LOADADDR(.vdso);
 }
-INSERT AFTER .data;
+INSERT BEFORE .data.after;
+
+__kernel_end = __edata;

+ 0 - 2
crates/eonix_hal/src/arch/riscv64/memory.x

@@ -12,12 +12,10 @@ REGION_ALIAS("REGION_TEXT", KIMAGE);
 REGION_ALIAS("REGION_RODATA", KIMAGE);
 REGION_ALIAS("REGION_DATA", KIMAGE);
 REGION_ALIAS("REGION_BSS", KBSS);
-REGION_ALIAS("REGION_EHFRAME", KIMAGE);
 
 REGION_ALIAS("LINK_REGION_TEXT", RAM);
 REGION_ALIAS("LINK_REGION_RODATA", RAM);
 REGION_ALIAS("LINK_REGION_DATA", RAM);
 REGION_ALIAS("LINK_REGION_BSS", RAM);
-REGION_ALIAS("LINK_REGION_EHFRAME", RAM);
 
 _stext = ORIGIN(REGION_TEXT) + LOADADDR(.text) - ORIGIN(RAM);

+ 14 - 9
crates/eonix_hal/src/link.x.in

@@ -18,6 +18,15 @@ SECTIONS {
         __srodata = .;
 
         *(.rodata .rodata.*);
+        
+        . = ALIGN(8);
+
+        PROVIDE(__eh_frame = .);
+        PROVIDE(__executable_start = __stext);
+
+        KEEP(*(.eh_frame_hdr));
+        KEEP(*(.eh_frame));
+        KEEP(*(.eh_frame.*));
 
     } > REGION_RODATA AT> LINK_REGION_RODATA
 
@@ -32,6 +41,11 @@ SECTIONS {
 
     } > REGION_DATA AT> LINK_REGION_DATA
 
+    .data.after :
+    {
+        __data_after = .;
+    } > REGION_DATA AT> LINK_REGION_DATA
+
     __edata = .;
 
     .bss (NOLOAD) : ALIGN(16)
@@ -45,16 +59,7 @@ SECTIONS {
 
     __ebss = .;
 
-    .eh_frame : ALIGN(16)
-    {
-        __seh_frame = .;
-
-        KEEP(*(.eh_frame .eh_frame*));
-
-    } > REGION_EHFRAME AT> LINK_REGION_EHFRAME
-
     . = ALIGN(0x1000);
-    __eeh_frame = .;
 }
 
 SECTIONS {

+ 8 - 0
src/lib.rs

@@ -9,6 +9,9 @@
 
 extern crate alloc;
 
+#[cfg(any(target_arch = "riscv64", target_arch = "x86_64"))]
+extern crate unwinding;
+
 mod driver;
 mod fs;
 mod hash;
@@ -16,6 +19,8 @@ mod io;
 mod kernel;
 mod kernel_init;
 mod net;
+#[cfg(any(target_arch = "riscv64", target_arch = "x86_64"))]
+mod panic;
 mod path;
 mod prelude;
 mod rcu;
@@ -53,6 +58,9 @@ use prelude::*;
 
 #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))]
 fn do_panic() -> ! {
+    #[cfg(target_arch = "riscv64")]
+    panic::stack_trace();
+
     shutdown();
 }
 

+ 29 - 0
src/panic.rs

@@ -0,0 +1,29 @@
+use core::ffi::c_void;
+
+use eonix_log::println_fatal;
+use unwinding::abi::{
+    UnwindContext, UnwindReasonCode, _Unwind_Backtrace, _Unwind_GetIP, _Unwind_GetRegionStart,
+};
+
+pub fn stack_trace() {
+    struct CallbackData {
+        counter: usize,
+    }
+
+    extern "C" fn callback(unwind_ctx: &UnwindContext<'_>, arg: *mut c_void) -> UnwindReasonCode {
+        let data = unsafe { &mut *(arg as *mut CallbackData) };
+        data.counter += 1;
+
+        println_fatal!(
+            "{:4}: {:#018x} - <unknown> at function {:#018x}",
+            data.counter,
+            _Unwind_GetIP(unwind_ctx),
+            _Unwind_GetRegionStart(unwind_ctx),
+        );
+
+        UnwindReasonCode::NO_REASON
+    }
+
+    let mut data = CallbackData { counter: 0 };
+    _Unwind_Backtrace(callback, &raw mut data as *mut c_void);
+}