From d5136d47bdf4afb5860bf0e291a0607cd8c23218 Mon Sep 17 00:00:00 2001 From: Ryan Slawson Date: Wed, 27 Nov 2024 19:12:02 +0100 Subject: [PATCH] Attempting to capture panics with GDB. --- .../data/gdb/smoltcp-hitl-prog.gdb | 21 ++++++- firmware-binaries/.cargo/config.toml | 7 ++- firmware-binaries/Cargo.lock | 56 ++++++++++++++++++- .../examples/smoltcp_client/Cargo.toml | 26 +++++++-- .../examples/smoltcp_client/src/main.rs | 16 ++---- firmware-support/Cargo.lock | 55 ++++++++++++++++++ firmware-support/Cargo.toml | 2 +- firmware-support/gdb-trace/Cargo.toml | 13 +++++ firmware-support/gdb-trace/src/lib.rs | 29 ++++++++++ 9 files changed, 200 insertions(+), 25 deletions(-) create mode 100644 firmware-support/gdb-trace/Cargo.toml create mode 100644 firmware-support/gdb-trace/src/lib.rs diff --git a/bittide-instances/data/gdb/smoltcp-hitl-prog.gdb b/bittide-instances/data/gdb/smoltcp-hitl-prog.gdb index bf75249d8..48f27d73d 100644 --- a/bittide-instances/data/gdb/smoltcp-hitl-prog.gdb +++ b/bittide-instances/data/gdb/smoltcp-hitl-prog.gdb @@ -1,9 +1,24 @@ # SPDX-FileCopyrightText: 2024 Google LLC # # SPDX-License-Identifier: Apache-2.0 +set logging file ./_build/hitl/gdb-out.log +set logging overwrite on +set logging enabled on file "./_build/cargo/firmware-binaries/riscv32imc-unknown-none-elf/release/smoltcp_client" -target extended-remote :3333 -# Load binary on CPU and start execution +break core::panicking::panic +break ExceptionHandler +break rust_begin_unwind +break smoltcp_client::gdb_panic + +target extended-remote :3333 load -start + +define hook-stop +printf "!!! program stopped executing !!!" +i r +bt +quit 1 +end + +continue diff --git a/firmware-binaries/.cargo/config.toml b/firmware-binaries/.cargo/config.toml index 3333601fa..df43ff189 100644 --- a/firmware-binaries/.cargo/config.toml +++ b/firmware-binaries/.cargo/config.toml @@ -4,7 +4,12 @@ [build] target = "riscv32imc-unknown-none-elf" -rustflags = ["-C", "target-feature=+f"] +rustflags = [ + "-C", "target-feature=+f", + # XXX: These two seem to be ignored + "-C", "force-frame-pointers=yes", + "-C", "force-unwind-tables=yes" +] target-dir = "../_build/cargo/firmware-binaries" [unstable] diff --git a/firmware-binaries/Cargo.lock b/firmware-binaries/Cargo.lock index 7a80c484d..6bd92fb84 100644 --- a/firmware-binaries/Cargo.lock +++ b/firmware-binaries/Cargo.lock @@ -132,12 +132,25 @@ dependencies = [ "void", ] +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "fdt" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" +[[package]] +name = "gdb-trace" +version = "0.1.0" +dependencies = [ + "riscv 0.12.1", +] + [[package]] name = "hash32" version = "0.2.1" @@ -239,6 +252,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "proc-macro2" version = "1.0.91" @@ -324,9 +343,39 @@ checksum = "aa3145d2fae3778b1e31ec2e827b228bdc6abd9b74bb5705ba46dcb82069bc4f" dependencies = [ "bit_field", "critical-section", - "embedded-hal", + "embedded-hal 0.2.7", ] +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + [[package]] name = "riscv-rt" version = "0.11.0" @@ -334,7 +383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "102c52c89defde24dedf9ac077cc69df77b85aa2400dd2d5aad6eea6a6a5c089" dependencies = [ "r0", - "riscv", + "riscv 0.10.1", "riscv-rt-macros", "riscv-target", ] @@ -399,9 +448,10 @@ name = "smoltcp_client" version = "0.1.0" dependencies = [ "bittide-sys", + "gdb-trace", "heapless 0.8.0", "log", - "riscv", + "riscv 0.10.1", "riscv-rt", "smoltcp", "ufmt", diff --git a/firmware-binaries/examples/smoltcp_client/Cargo.toml b/firmware-binaries/examples/smoltcp_client/Cargo.toml index a708c1dfb..d658ed34c 100644 --- a/firmware-binaries/examples/smoltcp_client/Cargo.toml +++ b/firmware-binaries/examples/smoltcp_client/Cargo.toml @@ -12,10 +12,26 @@ authors = ["Google LLC"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bittide-sys = { path = "../../../firmware-support/bittide-sys" } -riscv-rt = "0.11.0" riscv = "^0.10" -heapless = { version = "0.8", default-features = false} -smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp.git", rev = "dc08e0b42e668c331bb2b6f8d80016301d0efe03", default-features = false, features = ["medium-ethernet", "proto-ipv4", "socket-tcp", "socket-dhcpv4"] } +riscv-rt = "0.11.0" ufmt = "0.2.0" -log = {version = "0.4.21", features = ["max_level_off", "release_max_level_info"]} + +[dependencies.bittide-sys] +path = "../../../firmware-support/bittide-sys" + +[dependencies.gdb-trace] +path = "../../../firmware-support/gdb-trace" + +[dependencies.heapless] +version = "0.8" +default-features = false + +[dependencies.log] +version = "0.4.21" +features = ["max_level_off", "release_max_level_info"] + +[dependencies.smoltcp] +git = "https://github.com/smoltcp-rs/smoltcp.git" +rev = "dc08e0b42e668c331bb2b6f8d80016301d0efe03" +default-features = false +features = ["medium-ethernet", "proto-ipv4", "socket-tcp", "socket-dhcpv4"] diff --git a/firmware-binaries/examples/smoltcp_client/src/main.rs b/firmware-binaries/examples/smoltcp_client/src/main.rs index ef4e83380..fd39b64de 100644 --- a/firmware-binaries/examples/smoltcp_client/src/main.rs +++ b/firmware-binaries/examples/smoltcp_client/src/main.rs @@ -42,6 +42,10 @@ const CHUNK_SIZE: usize = 4096; const SERVER_IP: IpAddress = IpAddress::v4(10, 0, 0, 1); const SERVER_PORT: u16 = 1234; +gdb_trace::gdb_panic! { + unsafe { Uart::new(UART_ADDR) } +} + // See https://github.com/bittide/bittide-hardware/issues/681 #[allow(static_mut_refs)] #[cfg_attr(not(test), entry)] @@ -178,18 +182,6 @@ fn exception_handler(_trap_frame: &riscv_rt::TrapFrame) -> ! { } } -#[panic_handler] -fn panic_handler(info: &core::panic::PanicInfo) -> ! { - let mut uart = unsafe { Uart::new(UART_ADDR) }; - - uwriteln!(uart, "Panicked!").unwrap(); - info!("error: {}\n", info); - uwriteln!(uart, "Looping forever now").unwrap(); - loop { - continue; - } -} - fn update_dhcp(iface: &mut Interface, socket: &mut dhcpv4::Socket) { let event = socket.poll(); match event { diff --git a/firmware-support/Cargo.lock b/firmware-support/Cargo.lock index e31b8b01d..e75d3b4a4 100644 --- a/firmware-support/Cargo.lock +++ b/firmware-support/Cargo.lock @@ -91,6 +91,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "errno" version = "0.3.9" @@ -129,6 +141,13 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "gdb-trace" +version = "0.1.0" +dependencies = [ + "riscv", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -265,6 +284,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -363,6 +388,36 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + [[package]] name = "rustix" version = "0.38.41" diff --git a/firmware-support/Cargo.toml b/firmware-support/Cargo.toml index f1a0233d3..d003e152d 100644 --- a/firmware-support/Cargo.toml +++ b/firmware-support/Cargo.toml @@ -4,6 +4,6 @@ [workspace] members = [ - "bittide-sys", + "bittide-sys", "gdb-trace", ] resolver = "2" diff --git a/firmware-support/gdb-trace/Cargo.toml b/firmware-support/gdb-trace/Cargo.toml new file mode 100644 index 000000000..674b66146 --- /dev/null +++ b/firmware-support/gdb-trace/Cargo.toml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2022 Google LLC +# +# SPDX-License-Identifier: CC0-1.0 + +[package] +name = "gdb-trace" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +riscv = "0.12.1" diff --git a/firmware-support/gdb-trace/src/lib.rs b/firmware-support/gdb-trace/src/lib.rs new file mode 100644 index 000000000..27803ed5a --- /dev/null +++ b/firmware-support/gdb-trace/src/lib.rs @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2022 Google LLC +// +// SPDX-License-Identifier: Apache-2.0 + +#![no_std] + +use core::{fmt::Write, panic::PanicInfo}; + +/// Internal function for a GDB panic handler. It disables interrupts and attemps to write +/// the panic info to the provided write-able interface. It's expected that the user will +/// be running a GDB process and set a breakpoint to the panic handler so that the output +/// can be read. +#[allow(clippy::empty_loop)] +pub fn gdb_panic_internal(writer: &mut W, info: &PanicInfo) -> ! { + riscv::interrupt::machine::disable(); + writeln!(writer, "{:?}", info).unwrap(); + loop {} +} + +#[macro_export] +macro_rules! gdb_panic { + ($writer:expr) => { + #[panic_handler] + fn gdb_panic(info: &::core::panic::PanicInfo) -> ! { + let mut writer = $writer; + $crate::gdb_panic_internal(&mut writer, info); + } + }; +}