From 230f2e5e18726e8c4b3ed72a78d0fe4aa48fd701 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 25 Dec 2017 17:55:20 +0000 Subject: [PATCH] runtime: print (address-only) backtraces on core device panics. --- artiq/firmware/Cargo.lock | 5 +++ artiq/firmware/ksupport/Makefile | 2 +- artiq/firmware/libbacktrace_artiq/Cargo.toml | 8 +++++ artiq/firmware/libbacktrace_artiq/lib.rs | 38 ++++++++++++++++++++ artiq/firmware/runtime/Cargo.toml | 1 + artiq/firmware/runtime/Makefile | 16 +++++++-- artiq/firmware/runtime/lib.rs | 18 +++++----- artiq/firmware/runtime/runtime.ld | 21 +++++++---- conda/artiq-dev/meta.yaml | 2 +- 9 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 artiq/firmware/libbacktrace_artiq/Cargo.toml create mode 100644 artiq/firmware/libbacktrace_artiq/lib.rs diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 0cb9aef5b..353118496 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -13,6 +13,10 @@ dependencies = [ "board 0.0.0", ] +[[package]] +name = "backtrace_artiq" +version = "0.0.0" + [[package]] name = "bitflags" version = "1.0.1" @@ -150,6 +154,7 @@ version = "0.0.0" dependencies = [ "alloc_list 0.0.0", "amp 0.0.0", + "backtrace_artiq 0.0.0", "board 0.0.0", "build_artiq 0.0.0", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/artiq/firmware/ksupport/Makefile b/artiq/firmware/ksupport/Makefile index c45aea7a4..718b2c639 100644 --- a/artiq/firmware/ksupport/Makefile +++ b/artiq/firmware/ksupport/Makefile @@ -23,7 +23,7 @@ $(RUSTOUT)/libksupport.a: ksupport.elf: $(RUSTOUT)/libksupport.a glue.o $(LD) $(LDFLAGS) -T $(KSUPPORT_DIRECTORY)/ksupport.ld -o $@ $^ \ - -lunwind -lcompiler-rt -lbase -lm + -lunwind-elf -lcompiler-rt -lbase -lm @chmod -x $@ %.o: $(KSUPPORT_DIRECTORY)/%.c diff --git a/artiq/firmware/libbacktrace_artiq/Cargo.toml b/artiq/firmware/libbacktrace_artiq/Cargo.toml new file mode 100644 index 000000000..afab53124 --- /dev/null +++ b/artiq/firmware/libbacktrace_artiq/Cargo.toml @@ -0,0 +1,8 @@ +[package] +authors = ["M-Labs"] +name = "backtrace_artiq" +version = "0.0.0" + +[lib] +name = "backtrace_artiq" +path = "lib.rs" diff --git a/artiq/firmware/libbacktrace_artiq/lib.rs b/artiq/firmware/libbacktrace_artiq/lib.rs new file mode 100644 index 000000000..cf06c8f5a --- /dev/null +++ b/artiq/firmware/libbacktrace_artiq/lib.rs @@ -0,0 +1,38 @@ +#![feature(libc, panic_unwind, never_type)] +#![allow(non_upper_case_globals, non_camel_case_types)] +#![no_std] + +extern crate unwind; +extern crate libc; + +use unwind as uw; +use libc::c_void; + +type _Unwind_Trace_Fn = extern "C" fn(*mut uw::_Unwind_Context, *mut c_void) + -> uw::_Unwind_Reason_Code; +extern { + fn _Unwind_Backtrace(trace_fn: _Unwind_Trace_Fn, arg: *mut c_void) + -> uw::_Unwind_Reason_Code; +} + +pub fn backtrace(mut f: F) -> Result<(), uw::_Unwind_Reason_Code> + where F: FnMut(usize) -> () +{ + extern fn trace(context: *mut uw::_Unwind_Context, arg: *mut c_void) + -> uw::_Unwind_Reason_Code + where F: FnMut(usize) -> () + { + unsafe { + let step_fn = &mut *(arg as *mut F); + step_fn(uw::_Unwind_GetIP(context)); + uw::_URC_NO_REASON + } + } + + unsafe { + match _Unwind_Backtrace(trace::, &mut f as *mut _ as *mut c_void) { + uw::_URC_NO_REASON => Ok(()), + err => Err(err) + } + } +} diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index 4a820e33d..f9db55dee 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -19,6 +19,7 @@ log = { version = "0.3", default-features = false } alloc_list = { path = "../liballoc_list" } std_artiq = { path = "../libstd_artiq", features = ["alloc", "io_error_alloc"] } logger_artiq = { path = "../liblogger_artiq" } +backtrace_artiq = { path = "../libbacktrace_artiq" } board = { path = "../libboard", features = ["uart_console"] } proto = { path = "../libproto", features = ["log"] } amp = { path = "../libamp" } diff --git a/artiq/firmware/runtime/Makefile b/artiq/firmware/runtime/Makefile index 94cd87cbe..2ec0a033a 100644 --- a/artiq/firmware/runtime/Makefile +++ b/artiq/firmware/runtime/Makefile @@ -1,7 +1,13 @@ include ../include/generated/variables.mak include $(MISOC_DIRECTORY)/software/common.mak -LDFLAGS += -L../libbase +CFLAGS += \ + -I$(LIBUNWIND_DIRECTORY) \ + -I$(LIBUNWIND_DIRECTORY)/../unwinder/include \ + +LDFLAGS += -L../libbase \ + -L../libprintf \ + -L../libunwind RUSTFLAGS += -Cpanic=abort @@ -11,13 +17,17 @@ all: runtime.bin runtime.fbi $(RUSTOUT)/libruntime.a: $(cargo) --manifest-path $(RUNTIME_DIRECTORY)/Cargo.toml -runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o - $(LD) $(LDFLAGS) -T $(RUNTIME_DIRECTORY)/runtime.ld -o $@ $^ +runtime.elf: $(RUSTOUT)/libruntime.a ksupport_data.o glue.o + $(LD) $(LDFLAGS) -T $(RUNTIME_DIRECTORY)/runtime.ld -o $@ $^ \ + -lunwind-bare -lprintf-nofloat --eh-frame-hdr @chmod -x $@ ksupport_data.o: ../ksupport/ksupport.elf $(LD) -r -b binary -o $@ $< +%.o: $(RUNTIME_DIRECTORY)/%.c + $(compile) + %.bin: %.elf $(OBJCOPY) -O binary $< $@ @chmod -x $@ diff --git a/artiq/firmware/runtime/lib.rs b/artiq/firmware/runtime/lib.rs index 61d0dba4f..784a42f45 100644 --- a/artiq/firmware/runtime/lib.rs +++ b/artiq/firmware/runtime/lib.rs @@ -14,6 +14,7 @@ extern crate alloc_list; #[macro_use] extern crate std_artiq as std; extern crate logger_artiq; +extern crate backtrace_artiq; #[macro_use] extern crate board; extern crate proto; @@ -231,7 +232,9 @@ pub extern fn exception_handler(vect: u32, _regs: *const u32, pc: u32, ea: u32) #[no_mangle] pub extern fn abort() { - panic!("aborted") + println!("aborted"); + + loop {} } #[no_mangle] @@ -239,6 +242,11 @@ pub extern fn abort() { pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! { println!("panic at {}:{}: {}", file, line, args); + println!("backtrace:"); + let _ = backtrace_artiq::backtrace(|ip| { + println!("{:#08x}", ip); + }); + if config::read_str("panic_reboot", |r| r == Ok("1")) { println!("rebooting..."); unsafe { board::boot::reboot() } @@ -248,11 +256,3 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u3 loop {} } } - -// Allow linking with crates that are built as -Cpanic=unwind even if we use -Cpanic=abort. -// This is never called. -#[allow(non_snake_case)] -#[no_mangle] -pub extern fn _Unwind_Resume() -> ! { - loop {} -} diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index 026ec9186..1d21c61fb 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -20,6 +20,21 @@ SECTIONS _etext = .; } > runtime + .eh_frame : + { + __eh_frame_start = .; + KEEP(*(.eh_frame)) + __eh_frame_end = .; + } > runtime + + .eh_frame_hdr : + { + KEEP(*(.eh_frame_hdr)) + } > runtime + + __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; + __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + /* https://sourceware.org/bugzilla/show_bug.cgi?id=20475 */ .got : { @@ -79,10 +94,4 @@ SECTIONS . = ORIGIN(runtime) + LENGTH(runtime); _eheap = .; } > runtime - - /DISCARD/ : - { - *(.eh_frame) - *(.gcc_except_table) - } } diff --git a/conda/artiq-dev/meta.yaml b/conda/artiq-dev/meta.yaml index 91fffb4bf..b93946398 100644 --- a/conda/artiq-dev/meta.yaml +++ b/conda/artiq-dev/meta.yaml @@ -15,7 +15,7 @@ requirements: - python >=3.5.3,<3.6 - setuptools 33.1.1 - migen 0.6.dev py35_50+git82b06ee - - misoc 0.8.dev py35_15+git5c201712 + - misoc 0.8.dev py35_30+gitd95f4edb - jesd204b 0.4 - binutils-or1k-linux >=2.27 - llvm-or1k