framehop/
error.rs

1use crate::dwarf::DwarfUnwinderError;
2#[cfg(feature = "macho")]
3use crate::macho::CompactUnwindInfoUnwinderError;
4#[cfg(feature = "pe")]
5use crate::pe::PeUnwinderError;
6
7/// The error type used in this crate.
8#[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}