1use crate::dwarf::DwarfUnwinderError;
2#[cfg(feature = "macho")]
3use crate::macho::CompactUnwindInfoUnwinderError;
4#[cfg(feature = "pe")]
5use crate::pe::PeUnwinderError;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Error {
10 CouldNotReadStack(u64),
11 FramepointerUnwindingMovedBackwards,
12 DidNotAdvance,
13 IntegerOverflow,
14 ReturnAddressIsNull,
15}
16
17impl core::fmt::Display for Error {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 match self {
20 Self::CouldNotReadStack(addr) => write!(f, "Could not read stack memory at 0x{addr:x}"),
21 Self::FramepointerUnwindingMovedBackwards => {
22 write!(f, "Frame pointer unwinding moved backwards")
23 }
24 Self::DidNotAdvance => write!(
25 f,
26 "Neither the code address nor the stack pointer changed, would loop"
27 ),
28 Self::IntegerOverflow => write!(f, "Unwinding caused integer overflow"),
29 Self::ReturnAddressIsNull => write!(f, "Return address is null"),
30 }
31 }
32}
33
34#[cfg(feature = "std")]
35impl std::error::Error for Error {}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum UnwinderError {
39 #[cfg(feature = "macho")]
40 CompactUnwindInfo(CompactUnwindInfoUnwinderError),
41 Dwarf(DwarfUnwinderError),
42 #[cfg(feature = "pe")]
43 Pe(PeUnwinderError),
44 #[cfg(feature = "macho")]
45 NoDwarfData,
46 NoModuleUnwindData,
47 EhFrameHdrCouldNotFindAddress,
48 DwarfCfiIndexCouldNotFindAddress,
49}
50
51impl core::fmt::Display for UnwinderError {
52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53 match self {
54 #[cfg(feature = "macho")]
55 Self::CompactUnwindInfo(err) => {
56 write!(f, "Compact Unwind Info unwinding failed: {err}")
57 }
58 Self::Dwarf(err) => write!(f, "DWARF unwinding failed: {err}"),
59 #[cfg(feature = "pe")]
60 Self::Pe(err) => write!(f, "PE unwinding failed: {err}"),
61 #[cfg(feature = "macho")]
62 Self::NoDwarfData => write!(
63 f,
64 "__unwind_info referred to DWARF FDE but we do not have __eh_frame data"
65 ),
66 Self::NoModuleUnwindData => {
67 write!(f, "No unwind data for the module containing the address")
68 }
69 Self::EhFrameHdrCouldNotFindAddress => write!(
70 f,
71 ".eh_frame_hdr was not successful in looking up the address in the table"
72 ),
73 Self::DwarfCfiIndexCouldNotFindAddress => write!(
74 f,
75 "Failed to look up the address in the DwarfCfiIndex search table"
76 ),
77 }
78 }
79}
80
81impl From<DwarfUnwinderError> for UnwinderError {
82 fn from(e: DwarfUnwinderError) -> Self {
83 Self::Dwarf(e)
84 }
85}
86
87#[cfg(feature = "pe")]
88impl From<PeUnwinderError> for UnwinderError {
89 fn from(e: PeUnwinderError) -> Self {
90 Self::Pe(e)
91 }
92}
93
94#[cfg(feature = "macho")]
95impl From<CompactUnwindInfoUnwinderError> for UnwinderError {
96 fn from(e: CompactUnwindInfoUnwinderError) -> Self {
97 match e {
98 CompactUnwindInfoUnwinderError::BadDwarfUnwinding(e) => UnwinderError::Dwarf(e),
99 e => UnwinderError::CompactUnwindInfo(e),
100 }
101 }
102}
103
104#[cfg(feature = "std")]
105impl std::error::Error for UnwinderError {
106 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
107 match self {
108 #[cfg(feature = "macho")]
109 Self::CompactUnwindInfo(e) => Some(e),
110 Self::Dwarf(e) => Some(e),
111 #[cfg(feature = "pe")]
112 Self::Pe(e) => Some(e),
113 _ => None,
114 }
115 }
116}