diff --git a/Cargo.lock b/Cargo.lock
index e1b5ea30f50..7f627e2ce6e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5892,6 +5892,18 @@ dependencies = [
  "compiler_builtins",
  "core",
  "libc",
+ "unwinding",
+]
+
+[[package]]
+name = "unwinding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
+dependencies = [
+ "compiler_builtins",
+ "gimli",
+ "rustc-std-workspace-core",
 ]
 
 [[package]]
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
index a263e5d5cde..ed0591ad918 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
@@ -14,7 +14,7 @@ pub fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+a,+c".into(),
-            panic_strategy: PanicStrategy::Abort,
+            panic_strategy: PanicStrategy::Unwind,
             relocation_model: RelocModel::Static,
             ..Default::default()
         },
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 9363fde5de2..7a0bae34642 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -49,6 +49,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(any(
         all(target_family = "windows", target_env = "gnu"),
         target_os = "psp",
+        target_os = "xous",
         target_os = "solid_asp3",
         all(target_family = "unix", not(target_os = "espidf")),
         all(target_vendor = "fortanix", target_env = "sgx"),
diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs
index 386a399f532..0fff53f1887 100644
--- a/library/std/src/sys/personality/mod.rs
+++ b/library/std/src/sys/personality/mod.rs
@@ -28,6 +28,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(any(
         all(target_family = "windows", target_env = "gnu"),
         target_os = "psp",
+        target_os = "xous",
         target_os = "solid_asp3",
         all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")),
         all(target_vendor = "fortanix", target_env = "sgx"),
diff --git a/library/std/src/sys/xous/os.rs b/library/std/src/sys/xous/os.rs
index 3d19fa4b31a..8d2eaee8aa6 100644
--- a/library/std/src/sys/xous/os.rs
+++ b/library/std/src/sys/xous/os.rs
@@ -7,6 +7,28 @@ use crate::marker::PhantomData;
 use crate::os::xous::ffi::Error as XousError;
 use crate::path::{self, PathBuf};
 
+#[cfg(not(test))]
+#[cfg(feature = "panic_unwind")]
+mod eh_unwinding {
+    pub(crate) struct EhFrameFinder(usize /* eh_frame */);
+    pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0);
+    impl EhFrameFinder {
+        pub(crate) unsafe fn init(&mut self, eh_frame: usize) {
+            unsafe {
+                EH_FRAME_SETTINGS.0 = eh_frame;
+            }
+        }
+    }
+    unsafe impl unwind::EhFrameFinder for EhFrameFinder {
+        fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
+            Some(unwind::FrameInfo {
+                text_base: None,
+                kind: unwind::FrameInfoKind::EhFrame(self.0),
+            })
+        }
+    }
+}
+
 #[cfg(not(test))]
 mod c_compat {
     use crate::os::xous::ffi::exit;
@@ -20,7 +42,12 @@ mod c_compat {
     }
 
     #[no_mangle]
-    pub extern "C" fn _start() {
+    pub extern "C" fn _start(eh_frame: usize) {
+        #[cfg(feature = "panic_unwind")]
+        unsafe {
+            super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame);
+            unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
+        }
         exit(unsafe { main() });
     }
 
diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml
index 9aa552ed81a..b7418d1189c 100644
--- a/library/unwind/Cargo.toml
+++ b/library/unwind/Cargo.toml
@@ -15,10 +15,13 @@ doc = false
 
 [dependencies]
 core = { path = "../core" }
-libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = false }
+libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
 compiler_builtins = "0.1.0"
 cfg-if = "1.0"
 
+[target.'cfg(target_os = "xous")'.dependencies]
+unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
+
 [features]
 
 # Only applies for Linux and Fuchsia targets
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 335bded71c1..eeee98f754e 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -26,6 +26,9 @@ cfg_if::cfg_if! {
     ))] {
         mod libunwind;
         pub use libunwind::*;
+    } else if #[cfg(target_os = "xous")] {
+        mod unwinding;
+        pub use unwinding::*;
     } else {
         // no unwinder on the system!
         // - wasm32 (not emscripten, which is "unix" family)
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index dba64aa74ce..1b5f6f9dde3 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -103,7 +103,10 @@ pub type _Unwind_Exception_Cleanup_Fn =
 // and RFC 2841
 #[cfg_attr(
     any(
-        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        all(
+            feature = "llvm-libunwind",
+            any(target_os = "fuchsia", target_os = "linux", target_os = "xous")
+        ),
         all(target_os = "windows", target_env = "gnu", target_abi = "llvm")
     ),
     link(name = "unwind", kind = "static", modifiers = "-bundle")
@@ -134,7 +137,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
     pub use _Unwind_Action::*;
 
     #[cfg_attr(
-        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
         link(name = "unwind", kind = "static", modifiers = "-bundle")
     )]
     extern "C" {
@@ -192,7 +195,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
     pub const UNWIND_IP_REG: c_int = 15;
 
     #[cfg_attr(
-        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
         link(name = "unwind", kind = "static", modifiers = "-bundle")
     )]
     extern "C" {
@@ -258,14 +261,14 @@ cfg_if::cfg_if! {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
     #[cfg_attr(
-        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
         link(name = "unwind", kind = "static", modifiers = "-bundle")
     )]
     extern "C-unwind" {
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
     #[cfg_attr(
-        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")),
         link(name = "unwind", kind = "static", modifiers = "-bundle")
     )]
     extern "C" {
diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs
new file mode 100644
index 00000000000..1a4187b2220
--- /dev/null
+++ b/library/unwind/src/unwinding.rs
@@ -0,0 +1,105 @@
+#![allow(nonstandard_style)]
+
+use libc::{c_int, c_void};
+
+#[repr(C)]
+#[derive(Copy, Clone, PartialEq)]
+pub enum _Unwind_Action {
+    _UA_SEARCH_PHASE = 1,
+    _UA_CLEANUP_PHASE = 2,
+    _UA_HANDLER_FRAME = 4,
+    _UA_FORCE_UNWIND = 8,
+    _UA_END_OF_STACK = 16,
+}
+pub use _Unwind_Action::*;
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum _Unwind_Reason_Code {
+    _URC_NO_REASON = 0,
+    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+    _URC_FATAL_PHASE2_ERROR = 2,
+    _URC_FATAL_PHASE1_ERROR = 3,
+    _URC_NORMAL_STOP = 4,
+    _URC_END_OF_STACK = 5,
+    _URC_HANDLER_FOUND = 6,
+    _URC_INSTALL_CONTEXT = 7,
+    _URC_CONTINUE_UNWIND = 8,
+    _URC_FAILURE = 9, // used only by ARM EHABI
+}
+pub use _Unwind_Reason_Code::*;
+
+pub use unwinding::abi::UnwindContext;
+pub use unwinding::abi::UnwindException;
+pub enum _Unwind_Context {}
+
+pub use unwinding::custom_eh_frame_finder::{
+    set_custom_eh_frame_finder, EhFrameFinder, FrameInfo, FrameInfoKind,
+};
+
+pub type _Unwind_Exception_Class = u64;
+pub type _Unwind_Word = *const u8;
+pub type _Unwind_Ptr = *const u8;
+
+pub const unwinder_private_data_size: usize = core::mem::size_of::<UnwindException>()
+    - core::mem::size_of::<_Unwind_Exception_Class>()
+    - core::mem::size_of::<_Unwind_Exception_Cleanup_Fn>();
+
+pub type _Unwind_Exception_Cleanup_Fn =
+    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
+
+#[repr(C)]
+pub struct _Unwind_Exception {
+    pub exception_class: _Unwind_Exception_Class,
+    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
+    pub private: [_Unwind_Word; unwinder_private_data_size],
+}
+
+pub unsafe fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_GetDataRelBase(ctx) as _Unwind_Ptr
+}
+
+pub unsafe fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_GetTextRelBase(ctx) as _Unwind_Ptr
+}
+
+pub unsafe fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_GetRegionStart(ctx) as _Unwind_Ptr
+}
+
+pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_SetGR(ctx, reg_index, value as usize)
+}
+
+pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_SetIP(ctx, value as usize)
+}
+
+pub unsafe fn _Unwind_GetIPInfo(
+    ctx: *mut _Unwind_Context,
+    ip_before_insn: *mut c_int,
+) -> _Unwind_Word {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    let ip_before_insn = unsafe { &mut *(ip_before_insn as *mut c_int) };
+    unsafe { &*(unwinding::abi::_Unwind_GetIPInfo(ctx, ip_before_insn) as _Unwind_Word) }
+}
+
+pub unsafe fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void {
+    let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) };
+    unwinding::abi::_Unwind_GetLanguageSpecificData(ctx)
+}
+
+pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
+    let exception = unsafe { &mut *(exception as *mut UnwindException) };
+    unsafe { core::mem::transmute(unwinding::abi::_Unwind_RaiseException(exception)) }
+}
+
+pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) {
+    let exception = unsafe { &mut *(exception as *mut UnwindException) };
+    unsafe { unwinding::abi::_Unwind_DeleteException(exception) }
+}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 6baf2e21604..b38d5436477 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -372,6 +372,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "unicode-security",
     "unicode-width",
     "unicode-xid",
+    "unwinding",
     "valuable",
     "version_check",
     "wasi",