Skip to content

Commit

Permalink
Merge pull request #36 from afranchuk/remove-thiserror
Browse files Browse the repository at this point in the history
Remove thiserror and thiserror-no-std.
  • Loading branch information
mstange authored Jun 4, 2024
2 parents a5afb61 + 0cf2e75 commit 4d4d538
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 97 deletions.
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ exclude = ["/.github", "/.vscode", "/tests", "/fixtures", "/big-fixtures"]
[dependencies]
gimli = { version = "0.30", default-features = false, features = ["read"] }
object = { version = "0.36", default-features = false, features = ["read_core"], optional = true }
thiserror-no-std = "2.0.2"
thiserror = { version = "1.0.0", optional = true }
macho-unwind-info = { version = "0.4.0", optional = true }
pe-unwind-info = { version = "0.2.1", optional = true }
fallible-iterator = "0.3.0"
Expand All @@ -27,7 +25,7 @@ cfg-if = "1.0.0"
default = ["std", "macho", "pe"]
macho = ["macho-unwind-info"]
pe = ["pe-unwind-info"]
std = ["arrayvec/std", "thiserror", "gimli/std"]
std = ["arrayvec/std", "gimli/std"]

[dev-dependencies]
object = "0.36"
Expand Down
89 changes: 62 additions & 27 deletions src/dwarf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,47 @@ pub(crate) use gimli::BaseAddresses;

use crate::{arch::Arch, unwind_result::UnwindResult, ModuleSectionInfo};

#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(not(feature = "std"), derive(thiserror_no_std::Error))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DwarfUnwinderError {
#[error("Could not get the FDE for the supplied offset: {0}")]
FdeFromOffsetFailed(#[source] gimli::Error),

#[error("Could not find DWARF unwind info for the requested address: {0}")]
UnwindInfoForAddressFailed(#[source] gimli::Error),

#[error("Stack pointer moved backwards")]
FdeFromOffsetFailed(gimli::Error),
UnwindInfoForAddressFailed(gimli::Error),
StackPointerMovedBackwards,

#[error("Did not advance")]
DidNotAdvance,

#[error("Could not recover the CFA")]
CouldNotRecoverCfa,

#[error("Could not recover the return address")]
CouldNotRecoverReturnAddress,

#[error("Could not recover the frame pointer")]
CouldNotRecoverFramePointer,
}

impl core::fmt::Display for DwarfUnwinderError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::FdeFromOffsetFailed(err) => {
write!(f, "Could not get the FDE for the supplied offset: {err}")
}
Self::UnwindInfoForAddressFailed(err) => write!(
f,
"Could not find DWARF unwind info for the requested address: {err}"
),
Self::StackPointerMovedBackwards => write!(f, "Stack pointer moved backwards"),
Self::DidNotAdvance => write!(f, "Did not advance"),
Self::CouldNotRecoverCfa => write!(f, "Could not recover the CFA"),
Self::CouldNotRecoverReturnAddress => write!(f, "Could not recover the return address"),
Self::CouldNotRecoverFramePointer => write!(f, "Could not recover the frame pointer"),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for DwarfUnwinderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::FdeFromOffsetFailed(e) => Some(e),
Self::UnwindInfoForAddressFailed(e) => Some(e),
_ => None,
}
}
}

#[derive(Clone, Debug)]
pub enum ConversionError {
CfaIsExpression,
Expand Down Expand Up @@ -232,23 +247,43 @@ pub(crate) fn base_addresses_for_sections<D>(
.set_got(start_addr(&[b"__got", b".got"]))
}

#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(not(feature = "std"), derive(thiserror_no_std::Error))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DwarfCfiIndexError {
#[error("EhFrame processing failed: {0}")]
Gimli(#[from] gimli::Error),

#[error("Could not subtract base address to create relative pc")]
Gimli(gimli::Error),
CouldNotSubtractBaseAddress,

#[error("Relative address did not fit into u32")]
RelativeAddressTooBig,

#[error("FDE offset did not fit into u32")]
FdeOffsetTooBig,
}

impl core::fmt::Display for DwarfCfiIndexError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Gimli(e) => write!(f, "EhFrame processing failed: {e}"),
Self::CouldNotSubtractBaseAddress => {
write!(f, "Could not subtract base address to create relative pc")
}
Self::RelativeAddressTooBig => write!(f, "Relative address did not fit into u32"),
Self::FdeOffsetTooBig => write!(f, "FDE offset did not fit into u32"),
}
}
}

impl From<gimli::Error> for DwarfCfiIndexError {
fn from(e: gimli::Error) -> Self {
Self::Gimli(e)
}
}

#[cfg(feature = "std")]
impl std::error::Error for DwarfCfiIndexError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Gimli(e) => Some(e),
_ => None,
}
}
}

/// A binary search table for eh_frame FDEs. We generate this whenever a module
/// without eh_frame_hdr is added.
pub struct DwarfCfiIndex {
Expand Down
109 changes: 80 additions & 29 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,92 @@ use crate::macho::CompactUnwindInfoUnwinderError;
use crate::pe::PeUnwinderError;

/// The error type used in this crate.
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(not(feature = "std"), derive(thiserror_no_std::Error))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
#[error("Could not read stack memory at 0x{0:x}")]
CouldNotReadStack(u64),

#[error("Frame pointer unwinding moved backwards")]
FramepointerUnwindingMovedBackwards,

#[error("Neither the code address nor the stack pointer changed, would loop")]
DidNotAdvance,

#[error("Unwinding caused integer overflow")]
IntegerOverflow,

#[error("Return address is null")]
ReturnAddressIsNull,
}

#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(not(feature = "std"), derive(thiserror_no_std::Error))]
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::CouldNotReadStack(addr) => write!(f, "Could not read stack memory at 0x{addr:x}"),
Self::FramepointerUnwindingMovedBackwards => {
write!(f, "Frame pointer unwinding moved backwards")
}
Self::DidNotAdvance => write!(
f,
"Neither the code address nor the stack pointer changed, would loop"
),
Self::IntegerOverflow => write!(f, "Unwinding caused integer overflow"),
Self::ReturnAddressIsNull => write!(f, "Return address is null"),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnwinderError {
#[cfg(feature = "macho")]
#[error("Compact Unwind Info unwinding failed: {0}")]
CompactUnwindInfo(#[source] CompactUnwindInfoUnwinderError),

#[error("DWARF unwinding failed: {0}")]
Dwarf(#[from] DwarfUnwinderError),

CompactUnwindInfo(CompactUnwindInfoUnwinderError),
Dwarf(DwarfUnwinderError),
#[cfg(feature = "pe")]
#[error("PE unwinding failed: {0}")]
Pe(#[from] PeUnwinderError),

Pe(PeUnwinderError),
#[cfg(feature = "macho")]
#[error("__unwind_info referred to DWARF FDE but we do not have __eh_frame data")]
NoDwarfData,

#[error("No unwind data for the module containing the address")]
NoModuleUnwindData,

#[error(".eh_frame_hdr was not successful in looking up the address in the table")]
EhFrameHdrCouldNotFindAddress,

#[error("Failed to look up the address in the DwarfCfiIndex search table")]
DwarfCfiIndexCouldNotFindAddress,
}

impl core::fmt::Display for UnwinderError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "macho")]
Self::CompactUnwindInfo(err) => {
write!(f, "Compact Unwind Info unwinding failed: {err}")
}
Self::Dwarf(err) => write!(f, "DWARF unwinding failed: {err}"),
#[cfg(feature = "pe")]
Self::Pe(err) => write!(f, "PE unwinding failed: {err}"),
#[cfg(feature = "macho")]
Self::NoDwarfData => write!(
f,
"__unwind_info referred to DWARF FDE but we do not have __eh_frame data"
),
Self::NoModuleUnwindData => {
write!(f, "No unwind data for the module containing the address")
}
Self::EhFrameHdrCouldNotFindAddress => write!(
f,
".eh_frame_hdr was not successful in looking up the address in the table"
),
Self::DwarfCfiIndexCouldNotFindAddress => write!(
f,
"Failed to look up the address in the DwarfCfiIndex search table"
),
}
}
}

impl From<DwarfUnwinderError> for UnwinderError {
fn from(e: DwarfUnwinderError) -> Self {
Self::Dwarf(e)
}
}

#[cfg(feature = "pe")]
impl From<PeUnwinderError> for UnwinderError {
fn from(e: PeUnwinderError) -> Self {
Self::Pe(e)
}
}

#[cfg(feature = "macho")]
impl From<CompactUnwindInfoUnwinderError> for UnwinderError {
fn from(e: CompactUnwindInfoUnwinderError) -> Self {
Expand All @@ -63,3 +100,17 @@ impl From<CompactUnwindInfoUnwinderError> for UnwinderError {
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for UnwinderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
#[cfg(feature = "macho")]
Self::CompactUnwindInfo(e) => Some(e),
Self::Dwarf(e) => Some(e),
#[cfg(feature = "pe")]
Self::Pe(e) => Some(e),
_ => None,
}
}
}
74 changes: 45 additions & 29 deletions src/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,66 @@ use crate::dwarf::DwarfUnwinderError;
use crate::{arch::Arch, unwind_rule::UnwindRule};
use macho_unwind_info::UnwindInfo;

#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(not(feature = "std"), derive(thiserror_no_std::Error))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompactUnwindInfoUnwinderError {
#[error("Bad __unwind_info format: {0}")]
BadFormat(#[from] macho_unwind_info::Error),

#[error("Address 0x{0:x} outside of the range covered by __unwind_info")]
BadFormat(macho_unwind_info::Error),
AddressOutsideRange(u32),

#[error("Encountered a non-leaf function which was marked as frameless.")]
CallerCannotBeFrameless,

#[error("No unwind info (null opcode) for this function in __unwind_info")]
FunctionHasNoInfo,

#[error("rbp offset from the stack pointer divided by 8 does not fit into i16")]
BpOffsetDoesNotFit,

#[error("Unrecognized __unwind_info opcode kind {0}")]
BadOpcodeKind(u8),

#[error("DWARF unwinding failed: {0}")]
BadDwarfUnwinding(#[from] DwarfUnwinderError),

#[error("Don't have the function bytes to look up the offset for frameless function with indirect stack offset")]
BadDwarfUnwinding(DwarfUnwinderError),
NoTextBytesToLookUpIndirectStackOffset,

#[error("Stack offset not found inside the bounds of the text bytes")]
IndirectStackOffsetOutOfBounds,

#[error("Stack adjust addition overflowed")]
StackAdjustOverflow,

#[error("Stack size does not fit into the rule representation")]
StackSizeDoesNotFit,

#[error("A caller had its address in the __stubs section")]
StubFunctionCannotBeCaller,

#[error("Encountered invalid unwind entry")]
InvalidFrameless,
}

impl core::fmt::Display for CompactUnwindInfoUnwinderError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::BadFormat(err) => write!(f, "Bad __unwind_info format: {err}"),
Self::AddressOutsideRange(addr) => write!(f, "Address 0x{addr:x} outside of the range covered by __unwind_info"),
Self::CallerCannotBeFrameless => write!(f, "Encountered a non-leaf function which was marked as frameless."),
Self::FunctionHasNoInfo => write!(f, "No unwind info (null opcode) for this function in __unwind_info"),
Self::BpOffsetDoesNotFit => write!(f, "rbp offset from the stack pointer divided by 8 does not fit into i16"),
Self::BadOpcodeKind(kind) => write!(f, "Unrecognized __unwind_info opcode kind {kind}"),
Self::BadDwarfUnwinding(err) => write!(f, "DWARF unwinding failed: {err}"),
Self::NoTextBytesToLookUpIndirectStackOffset => write!(f, "Don't have the function bytes to look up the offset for frameless function with indirect stack offset"),
Self::IndirectStackOffsetOutOfBounds => write!(f, "Stack offset not found inside the bounds of the text bytes"),
Self::StackAdjustOverflow => write!(f, "Stack adjust addition overflowed"),
Self::StackSizeDoesNotFit => write!(f, "Stack size does not fit into the rule representation"),
Self::StubFunctionCannotBeCaller => write!(f, "A caller had its address in the __stubs section"),
Self::InvalidFrameless => write!(f, "Encountered invalid unwind entry"),
}
}
}

impl From<macho_unwind_info::Error> for CompactUnwindInfoUnwinderError {
fn from(e: macho_unwind_info::Error) -> Self {
Self::BadFormat(e)
}
}

impl From<DwarfUnwinderError> for CompactUnwindInfoUnwinderError {
fn from(e: DwarfUnwinderError) -> Self {
Self::BadDwarfUnwinding(e)
}
}

#[cfg(feature = "std")]
impl std::error::Error for CompactUnwindInfoUnwinderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::BadFormat(e) => Some(e),
Self::BadDwarfUnwinding(e) => Some(e),
_ => None,
}
}
}

#[derive(Clone, Debug)]
pub enum CuiUnwindResult<R: UnwindRule> {
ExecRule(R),
Expand Down
Loading

0 comments on commit 4d4d538

Please sign in to comment.