use std::error::Error as StdError;
use std::fmt;
pub(crate) type Result<T> = std::result::Result<T, Error>;
pub trait AsDynError<'a> {
fn as_dyn_error(&self) -> &(dyn StdError + 'a);
}
impl<'a, T: StdError + 'a> AsDynError<'a> for T {
#[inline]
fn as_dyn_error(&self) -> &(dyn StdError + 'a) {
self
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
ReadInput(std::io::Error),
ParseFileKind(object::Error),
ParseObjectFile(object::Error),
ParseArchiveFile(object::Error),
ParseArchiveMember(object::Error),
InvalidInputKind,
DecompressData(object::Error),
NamelessSection(object::Error, usize),
RelocationWithInvalidSymbol(String, usize),
MultipleRelocations(String, usize),
UnsupportedRelocation(String, usize),
MissingDwoName(u64),
NoCompilationUnits,
NoDie,
TopLevelDieNotUnit,
MissingRequiredSection(&'static str),
ParseUnitAbbreviations(gimli::read::Error),
ParseUnitAttribute(gimli::read::Error),
ParseUnitHeader(gimli::read::Error),
ParseUnit(gimli::read::Error),
IncompatibleIndexVersion(String, u16, u16),
OffsetAtIndex(gimli::read::Error, u64),
StrAtOffset(gimli::read::Error, usize),
ParseIndex(gimli::read::Error, String),
UnitNotInIndex(u64),
RowNotInIndex(gimli::read::Error, u32),
SectionNotInRow,
EmptyUnit(u64),
MultipleDebugInfoSection,
MultipleDebugTypesSection,
NotSplitUnit,
DuplicateUnit(u64),
MissingReferencedUnit(u64),
NoOutputObjectCreated,
MixedInputEncodings,
Io(std::io::Error),
ObjectRead(object::Error),
ObjectWrite(object::write::Error),
GimliRead(gimli::read::Error),
GimliWrite(gimli::write::Error),
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::ReadInput(source) => Some(source.as_dyn_error()),
Error::ParseFileKind(source) => Some(source.as_dyn_error()),
Error::ParseObjectFile(source) => Some(source.as_dyn_error()),
Error::ParseArchiveFile(source) => Some(source.as_dyn_error()),
Error::ParseArchiveMember(source) => Some(source.as_dyn_error()),
Error::InvalidInputKind => None,
Error::DecompressData(source) => Some(source.as_dyn_error()),
Error::NamelessSection(source, _) => Some(source.as_dyn_error()),
Error::RelocationWithInvalidSymbol(_, _) => None,
Error::MultipleRelocations(_, _) => None,
Error::UnsupportedRelocation(_, _) => None,
Error::MissingDwoName(_) => None,
Error::NoCompilationUnits => None,
Error::NoDie => None,
Error::TopLevelDieNotUnit => None,
Error::MissingRequiredSection(_) => None,
Error::ParseUnitAbbreviations(source) => Some(source.as_dyn_error()),
Error::ParseUnitAttribute(source) => Some(source.as_dyn_error()),
Error::ParseUnitHeader(source) => Some(source.as_dyn_error()),
Error::ParseUnit(source) => Some(source.as_dyn_error()),
Error::IncompatibleIndexVersion(_, _, _) => None,
Error::OffsetAtIndex(source, _) => Some(source.as_dyn_error()),
Error::StrAtOffset(source, _) => Some(source.as_dyn_error()),
Error::ParseIndex(source, _) => Some(source.as_dyn_error()),
Error::UnitNotInIndex(_) => None,
Error::RowNotInIndex(source, _) => Some(source.as_dyn_error()),
Error::SectionNotInRow => None,
Error::EmptyUnit(_) => None,
Error::MultipleDebugInfoSection => None,
Error::MultipleDebugTypesSection => None,
Error::NotSplitUnit => None,
Error::DuplicateUnit(_) => None,
Error::MissingReferencedUnit(_) => None,
Error::NoOutputObjectCreated => None,
Error::MixedInputEncodings => None,
Error::Io(transparent) => StdError::source(transparent.as_dyn_error()),
Error::ObjectRead(transparent) => StdError::source(transparent.as_dyn_error()),
Error::ObjectWrite(transparent) => StdError::source(transparent.as_dyn_error()),
Error::GimliRead(transparent) => StdError::source(transparent.as_dyn_error()),
Error::GimliWrite(transparent) => StdError::source(transparent.as_dyn_error()),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::ReadInput(_) => write!(f, "Failed to read input file"),
Error::ParseFileKind(_) => write!(f, "Failed to parse input file kind"),
Error::ParseObjectFile(_) => write!(f, "Failed to parse input object file"),
Error::ParseArchiveFile(_) => write!(f, "Failed to parse input archive file"),
Error::ParseArchiveMember(_) => write!(f, "Failed to parse archive member"),
Error::InvalidInputKind => write!(f, "Input is not an archive or elf object"),
Error::DecompressData(_) => write!(f, "Failed to decompress compressed section"),
Error::NamelessSection(_, offset) => {
write!(f, "Section without name at offset 0x{:08x}", offset)
}
Error::RelocationWithInvalidSymbol(section, offset) => write!(
f,
"Relocation with invalid symbol for section `{}` at offset 0x{:08x}",
section, offset
),
Error::MultipleRelocations(section, offset) => write!(
f,
"Multiple relocations for section `{}` at offset 0x{:08x}",
section, offset
),
Error::UnsupportedRelocation(section, offset) => write!(
f,
"Unsupported relocation for section {} at offset 0x{:08x}",
section, offset
),
Error::MissingDwoName(id) => {
write!(f, "Missing path attribute to DWARF object (0x{:08x})", id)
}
Error::NoCompilationUnits => {
write!(f, "Input object has no compilation units")
}
Error::NoDie => {
write!(f, "No top-level debugging information entry in compilation/type unit")
}
Error::TopLevelDieNotUnit => {
write!(f, "Top-level debugging information entry is not a compilation/type unit")
}
Error::MissingRequiredSection(section) => {
write!(f, "Input object missing required section `{}`", section)
}
Error::ParseUnitAbbreviations(_) => write!(f, "Failed to parse unit abbreviations"),
Error::ParseUnitAttribute(_) => write!(f, "Failed to parse unit attribute"),
Error::ParseUnitHeader(_) => write!(f, "Failed to parse unit header"),
Error::ParseUnit(_) => write!(f, "Failed to parse unit"),
Error::IncompatibleIndexVersion(section, format, actual) => {
write!(
f,
"Incompatible `{}` index version: found version {}, expected version {}",
section, actual, format
)
}
Error::OffsetAtIndex(_, index) => {
write!(f, "Read offset at index {} of `.debug_str_offsets.dwo` section", index)
}
Error::StrAtOffset(_, offset) => {
write!(f, "Read string at offset 0x{:08x} of `.debug_str.dwo` section", offset)
}
Error::ParseIndex(_, section) => {
write!(f, "Failed to parse `{}` index section", section)
}
Error::UnitNotInIndex(unit) => {
write!(f, "Unit 0x{0:08x} from input package is not in its index", unit)
}
Error::RowNotInIndex(_, row) => {
write!(f, "Row {0} found in index's hash table not present in index", row)
}
Error::SectionNotInRow => write!(f, "Section not found in unit's row in index"),
Error::EmptyUnit(unit) => {
write!(f, "Unit 0x{:08x} in input DWARF object with no data", unit)
}
Error::MultipleDebugInfoSection => {
write!(f, "Multiple `.debug_info.dwo` sections")
}
Error::MultipleDebugTypesSection => {
write!(f, "Multiple `.debug_types.dwo` sections in a package")
}
Error::NotSplitUnit => {
write!(f, "Regular compilation unit in object (missing dwo identifier)")
}
Error::DuplicateUnit(unit) => {
write!(f, "Duplicate split compilation unit (0x{:08x})", unit)
}
Error::MissingReferencedUnit(unit) => {
write!(f, "Unit 0x{:08x} referenced by executable was not found", unit)
}
Error::NoOutputObjectCreated => write!(f, "No output object was created from inputs"),
Error::MixedInputEncodings => write!(f, "Input objects haved mixed encodings"),
Error::Io(e) => fmt::Display::fmt(e, f),
Error::ObjectRead(e) => fmt::Display::fmt(e, f),
Error::ObjectWrite(e) => fmt::Display::fmt(e, f),
Error::GimliRead(e) => fmt::Display::fmt(e, f),
Error::GimliWrite(e) => fmt::Display::fmt(e, f),
}
}
}
impl From<std::io::Error> for Error {
fn from(source: std::io::Error) -> Self {
Error::Io(source)
}
}
impl From<object::Error> for Error {
fn from(source: object::Error) -> Self {
Error::ObjectRead(source)
}
}
impl From<object::write::Error> for Error {
fn from(source: object::write::Error) -> Self {
Error::ObjectWrite(source)
}
}
impl From<gimli::read::Error> for Error {
fn from(source: gimli::read::Error) -> Self {
Error::GimliRead(source)
}
}
impl From<gimli::write::Error> for Error {
fn from(source: gimli::write::Error) -> Self {
Error::GimliWrite(source)
}
}