From 5a8e7cdc1075b07e1f65711e7aa118b350f22a21 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 12:59:54 +0100 Subject: [PATCH 01/10] ref(wasm): Switch to error with kind --- symbolic-debuginfo/src/wasm.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/symbolic-debuginfo/src/wasm.rs b/symbolic-debuginfo/src/wasm.rs index 4fe7b2304..092477782 100644 --- a/symbolic-debuginfo/src/wasm.rs +++ b/symbolic-debuginfo/src/wasm.rs @@ -1,5 +1,6 @@ //! Support for WASM Objects (WebAssembly). use std::borrow::Cow; +use std::error::Error; use std::fmt; use thiserror::Error; @@ -11,12 +12,22 @@ use crate::dwarf::{Dwarf, DwarfDebugSession, DwarfError, DwarfSection, Endian}; use crate::private::Parse; /// An error when dealing with [`WasmObject`](struct.WasmObject.html). -#[non_exhaustive] #[derive(Debug, Error)] -pub enum WasmError { - /// The module cannot be parsed. - #[error("invalid WASM file")] - BadObject, +#[error("invalid WASM file")] +pub struct WasmError { + #[source] + source: Option>, +} + +impl WasmError { + /// Creates a new WASM error from an arbitrary error payload. + fn new(source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { source } + } } /// Wasm object container (.wasm), used for executables and debug @@ -37,10 +48,7 @@ impl<'data> WasmObject<'data> { /// Tries to parse a WASM from the given slice. pub fn parse(data: &'data [u8]) -> Result { - let wasm_module = match walrus::Module::from_buffer(data) { - Ok(module) => module, - Err(_) => return Err(WasmError::BadObject), - }; + let wasm_module = walrus::Module::from_buffer(data).map_err(WasmError::new)?; // we need to parse the file a second time to get the offset to the // code section as walrus does not expose that yet. From 2c45e955952f92169304e45842a69d60acfbf599 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 13:56:03 +0100 Subject: [PATCH 02/10] ref(sourcebundle): Switch to error with kind --- symbolic-debuginfo/src/sourcebundle.rs | 96 ++++++++++++++++++-------- 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/symbolic-debuginfo/src/sourcebundle.rs b/symbolic-debuginfo/src/sourcebundle.rs index b47d9e7d7..4fde96c14 100644 --- a/symbolic-debuginfo/src/sourcebundle.rs +++ b/symbolic-debuginfo/src/sourcebundle.rs @@ -36,6 +36,7 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::error::Error; use std::fmt; use std::fs::{File, OpenOptions}; use std::io::{BufReader, BufWriter, Read, Seek, Write}; @@ -47,7 +48,7 @@ use parking_lot::Mutex; use regex::Regex; use serde::{Deserialize, Serialize}; use thiserror::Error; -use zip::{result::ZipError, write::FileOptions, ZipWriter}; +use zip::{write::FileOptions, ZipWriter}; use symbolic_common::{Arch, AsSelf, CodeId, DebugId}; @@ -71,33 +72,67 @@ lazy_static::lazy_static! { static ref SANE_PATH_RE: Regex = Regex::new(r#":?[/\\]+"#).unwrap(); } -/// An error returned when handling [`SourceBundle`](struct.SourceBundle.html). +/// The error type for [`SourceBundleError`]. #[non_exhaustive] -#[derive(Debug, Error)] -pub enum SourceBundleError { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum SourceBundleErrorKind { /// The source bundle container is damanged. - #[error("malformed zip archive")] - BadZip(#[source] ZipError), + BadZip, /// An error when reading/writing the manifest. - #[error("failed to read/write source bundle manifest")] - BadManifest(#[source] serde_json::Error), + BadManifest, /// The `Object` contains invalid data and cannot be converted. - #[error("malformed debug info file")] - BadDebugFile(#[source] Box), + BadDebugFile, /// Generic error when writing a source bundle, most likely IO. - #[error("failed to write source bundle")] - WriteFailed(#[source] ZipError), + WriteFailed, +} + +impl fmt::Display for SourceBundleErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::BadZip => write!(f, "malformed zip archive"), + Self::BadManifest => write!(f, "failed to read/write source bundle manifest"), + Self::BadDebugFile => write!(f, "malformed debug info file"), + Self::WriteFailed => write!(f, "failed to write source bundle"), + } + } +} + +/// An error returned when handling [`SourceBundle`](struct.SourceBundle.html). +#[derive(Debug, Error)] +#[error("{kind}")] +pub struct SourceBundleError { + kind: SourceBundleErrorKind, + #[source] + source: Option>, } impl SourceBundleError { - fn bad_debug_file(err: E) -> Self + /// Creates a new SourceBundle error from a known kind of error as well as an arbitrary error + /// payload. + /// + /// This function is used to generically create source bundle errors which do not originate from + /// `symbolic` itself. The `source` argument is an arbitrary payload which will be contained in + /// this [`CfiError`]. + pub fn new(kind: SourceBundleErrorKind, source: E) -> Self where - E: std::error::Error + Send + Sync + 'static, + E: Into>, { - SourceBundleError::BadDebugFile(Box::new(err)) + let source = Some(source.into()); + Self { kind, source } + } + + /// Returns the corresponding [`SourceBundleErrorKind`] for this error. + pub fn kind(&self) -> SourceBundleErrorKind { + self.kind + } +} + +impl From for SourceBundleError { + fn from(kind: SourceBundleErrorKind) -> Self { + Self { kind, source: None } } } @@ -317,12 +352,12 @@ impl<'data> SourceBundle<'data> { /// Tries to parse a `SourceBundle` from the given slice. pub fn parse(data: &'data [u8]) -> Result, SourceBundleError> { let mut archive = zip::read::ZipArchive::new(std::io::Cursor::new(data)) - .map_err(SourceBundleError::BadZip)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadZip, e))?; let manifest_file = archive .by_name("manifest.json") - .map_err(SourceBundleError::BadZip)?; - let manifest = - serde_json::from_reader(manifest_file).map_err(SourceBundleError::BadManifest)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadZip, e))?; + let manifest = serde_json::from_reader(manifest_file) + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadManifest, e))?; Ok(SourceBundle { manifest: Arc::new(manifest), archive: Arc::new(Mutex::new(archive)), @@ -598,11 +633,11 @@ impl<'data> SourceBundleDebugSession<'data> { let mut archive = self.archive.lock(); let mut file = archive .by_name(zip_path) - .map_err(SourceBundleError::BadZip)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadZip, e))?; let mut source_content = String::new(); file.read_to_string(&mut source_content) - .map_err(|e| SourceBundleError::BadZip(ZipError::Io(e)))?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadZip, e))?; Ok(Some(source_content)) } @@ -724,7 +759,7 @@ where let header = SourceBundleHeader::default(); writer .write_all(header.as_bytes()) - .map_err(|e| SourceBundleError::WriteFailed(ZipError::Io(e)))?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; Ok(SourceBundleWriter { manifest: SourceBundleManifest::new(), @@ -822,9 +857,9 @@ where self.writer .start_file(unique_path.clone(), FileOptions::default()) - .map_err(SourceBundleError::WriteFailed)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; std::io::copy(&mut file, &mut self.writer) - .map_err(|e| SourceBundleError::WriteFailed(ZipError::Io(e)))?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; self.manifest.files.insert(unique_path, info); Ok(()) @@ -870,7 +905,7 @@ where let mut files_handled = BTreeSet::new(); let session = object .debug_session() - .map_err(SourceBundleError::bad_debug_file)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadDebugFile, e))?; self.set_attribute("arch", object.arch().to_string()); self.set_attribute("debug_id", object.debug_id().to_string()); @@ -880,7 +915,8 @@ where } for file_result in session.files() { - let file = file_result.map_err(SourceBundleError::bad_debug_file)?; + let file = file_result + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadDebugFile, e))?; let filename = file.abs_path_str(); if files_handled.contains(&filename) { @@ -917,7 +953,7 @@ where self.write_manifest()?; self.writer .finish() - .map_err(SourceBundleError::WriteFailed)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; self.finished = true; Ok(()) } @@ -953,10 +989,10 @@ where fn write_manifest(&mut self) -> Result<(), SourceBundleError> { self.writer .start_file(MANIFEST_PATH, FileOptions::default()) - .map_err(SourceBundleError::WriteFailed)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; serde_json::to_writer(&mut self.writer, &self.manifest) - .map_err(SourceBundleError::BadManifest)?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::BadManifest, e))?; Ok(()) } @@ -977,7 +1013,7 @@ impl SourceBundleWriter> { .create(true) .truncate(true) .open(path) - .map_err(|e| SourceBundleError::WriteFailed(ZipError::Io(e)))?; + .map_err(|e| SourceBundleError::new(SourceBundleErrorKind::WriteFailed, e))?; Self::start(BufWriter::new(file)) } From 5a8612147d7bdd1a77fef5b28f2a8972fb832180 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:03:39 +0100 Subject: [PATCH 03/10] ref(pe): Switch to error with kind --- symbolic-debuginfo/src/pe.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/symbolic-debuginfo/src/pe.rs b/symbolic-debuginfo/src/pe.rs index a25f5d017..84138da9c 100644 --- a/symbolic-debuginfo/src/pe.rs +++ b/symbolic-debuginfo/src/pe.rs @@ -1,11 +1,12 @@ //! Support for Portable Executables, an extension of COFF used on Windows. use std::borrow::Cow; +use std::error::Error; use std::fmt; use std::io::Cursor; use std::marker::PhantomData; -use goblin::{error::Error as GoblinError, pe}; +use goblin::pe; use thiserror::Error; use symbolic_common::{Arch, AsSelf, CodeId, DebugId, Uuid}; @@ -16,13 +17,23 @@ use crate::private::Parse; pub use goblin::pe::exception::*; pub use goblin::pe::section_table::SectionTable; -/// An error when dealing with [`PeObject`](struct.PeObject.html). -#[non_exhaustive] +/// An error when dealing with [`PEObject`](struct.PEObject.html). #[derive(Debug, Error)] -pub enum PeError { - /// The data in the PE file could not be parsed. - #[error("invalid PE file")] - BadObject(#[from] GoblinError), +#[error("invalid PE file")] +pub struct PeError { + #[source] + source: Option>, +} + +impl PeError { + /// Creates a new PE error from an arbitrary error payload. + fn new(source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { source } + } } /// Detects if the PE is a packer stub. @@ -66,7 +77,7 @@ impl<'data> PeObject<'data> { /// Tries to parse a PE object from the given slice. pub fn parse(data: &'data [u8]) -> Result { - let pe = pe::PE::parse(data).map_err(PeError::BadObject)?; + let pe = pe::PE::parse(data).map_err(PeError::new)?; let is_stub = is_pe_stub(&pe); Ok(PeObject { pe, data, is_stub }) } From 4c230961da63270fc5b2451900947c01a6b80a47 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:12:01 +0100 Subject: [PATCH 04/10] ref(pdb): Switch to error with kind --- symbolic-debuginfo/src/pdb.rs | 72 ++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/symbolic-debuginfo/src/pdb.rs b/symbolic-debuginfo/src/pdb.rs index 275f86891..2577ae260 100644 --- a/symbolic-debuginfo/src/pdb.rs +++ b/symbolic-debuginfo/src/pdb.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::collections::btree_map::{BTreeMap, Entry}; +use std::error::Error; use std::fmt; use std::io::Cursor; use std::sync::Arc; @@ -32,21 +33,72 @@ const MAGIC_BIG: &[u8] = b"Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\x00\x00\x00" #[doc(hidden)] pub use pdb; -/// An error when dealing with [`PdbObject`](struct.PdbObject.html). +/// The error type for [`PdbError`]. #[non_exhaustive] -#[derive(Debug, Error)] -pub enum PdbError { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PdbErrorKind { /// The PDB file is corrupted. See the cause for more information. - #[error("invalid pdb file")] - BadObject(#[from] pdb::Error), + BadObject, /// An inline record was encountered without an inlining parent. - #[error("unexpected inline function without parent")] UnexpectedInline, - /// Formatting of a type name failed - #[error("failed to format type name")] - FormattingFailed(#[from] fmt::Error), + /// Formatting of a type name failed. + FormattingFailed, +} + +impl fmt::Display for PdbErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::BadObject => write!(f, "invalid pdb file"), + Self::UnexpectedInline => write!(f, "unexpected inline function without parent"), + Self::FormattingFailed => write!(f, "failed to format type name"), + } + } +} + +/// An error when dealing with [`PdbObject`](struct.PdbObject.html). +#[derive(Debug, Error)] +#[error("{kind}")] +pub struct PdbError { + kind: PdbErrorKind, + #[source] + source: Option>, +} + +impl PdbError { + /// Creates a new PDB error from a known kind of error as well as an arbitrary error + /// payload. + fn new(kind: PdbErrorKind, source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { kind, source } + } + + /// Returns the corresponding [`PdbErrorKind`] for this error. + pub fn kind(&self) -> PdbErrorKind { + self.kind + } +} + +impl From for PdbError { + fn from(kind: PdbErrorKind) -> Self { + Self { kind, source: None } + } +} + +impl From for PdbError { + fn from(e: pdb::Error) -> Self { + Self::new(PdbErrorKind::BadObject, e) + } +} + +impl From for PdbError { + fn from(e: fmt::Error) -> Self { + Self::new(PdbErrorKind::FormattingFailed, e) + } } /// Program Database, the debug companion format on Windows. @@ -1058,7 +1110,7 @@ impl<'s> Unit<'s> { let parent_offset = proc_offsets .last() .map(|&(_, offset)| offset) - .ok_or(PdbError::UnexpectedInline)?; + .ok_or(PdbErrorKind::UnexpectedInline)?; // We can assume that inlinees will be listed in the inlinee table. If missing, // skip silently instead of erroring out. Missing a single inline function is From fa4438ecb1ebc28a9af29f9616fb375128cad61b Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:16:25 +0100 Subject: [PATCH 05/10] ref(macho): Switch to error with kind --- symbolic-debuginfo/src/macho.rs | 35 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/symbolic-debuginfo/src/macho.rs b/symbolic-debuginfo/src/macho.rs index 8f50b0e20..faeffae22 100644 --- a/symbolic-debuginfo/src/macho.rs +++ b/symbolic-debuginfo/src/macho.rs @@ -1,10 +1,11 @@ //! Support for Mach Objects, used on macOS and iOS. use std::borrow::Cow; +use std::error::Error; use std::fmt; use std::io::Cursor; -use goblin::{error::Error as GoblinError, mach}; +use goblin::mach; use smallvec::SmallVec; use thiserror::Error; @@ -15,12 +16,22 @@ use crate::dwarf::{Dwarf, DwarfDebugSession, DwarfError, DwarfSection, Endian}; use crate::private::{MonoArchive, MonoArchiveObjects, Parse}; /// An error when dealing with [`MachObject`](struct.MachObject.html). -#[non_exhaustive] #[derive(Debug, Error)] -pub enum MachError { - /// The data in the MachO file could not be parsed. - #[error("invalid MachO file")] - BadObject(#[from] GoblinError), +#[error("invalid MachO file")] +pub struct MachError { + #[source] + source: Option>, +} + +impl MachError { + /// Creates a new MachO error from an arbitrary error payload. + fn new(source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { source } + } } /// Mach Object containers, used for executables and debug companions on macOS and iOS. @@ -40,7 +51,9 @@ impl<'d> MachObject<'d> { /// Tries to parse a MachO from the given slice. pub fn parse(data: &'d [u8]) -> Result { - Ok(mach::MachO::parse(data, 0).map(|macho| MachObject { macho, data })?) + mach::MachO::parse(data, 0) + .map(|macho| MachObject { macho, data }) + .map_err(MachError::new) } /// The container file format, which is always `FileFormat::MachO`. @@ -455,7 +468,7 @@ impl<'d, 'a> Iterator for FatMachObjectIterator<'d, 'a> { let end = ((arch.offset + arch.size) as usize).min(self.data.len()); Some(MachObject::parse(&self.data[start..end])) } - Some(Err(error)) => Some(Err(MachError::BadObject(error))), + Some(Err(error)) => Some(Err(MachError::new(error))), None => None, } } @@ -487,7 +500,9 @@ impl<'d> FatMachO<'d> { /// Tries to parse a fat MachO container from the given slice. pub fn parse(data: &'d [u8]) -> Result { - Ok(mach::MultiArch::new(data).map(|fat| FatMachO { fat, data })?) + mach::MultiArch::new(data) + .map(|fat| FatMachO { fat, data }) + .map_err(MachError::new) } /// Returns an iterator over objects in this container. @@ -510,7 +525,7 @@ impl<'d> FatMachO<'d> { /// be parsed. pub fn object_by_index(&self, index: usize) -> Result>, MachError> { let arch = match self.fat.iter_arches().nth(index) { - Some(arch) => arch?, + Some(arch) => arch.map_err(MachError::new)?, None => return Ok(None), }; From 59a0484a7ce905991f857a26312eef57907b5e02 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:18:03 +0100 Subject: [PATCH 06/10] ref(elf): Switch to error with kind --- symbolic-debuginfo/src/elf.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/symbolic-debuginfo/src/elf.rs b/symbolic-debuginfo/src/elf.rs index 06c016144..0ad961da9 100644 --- a/symbolic-debuginfo/src/elf.rs +++ b/symbolic-debuginfo/src/elf.rs @@ -1,6 +1,7 @@ //! Support for the Executable and Linkable Format, used on Linux. use std::borrow::Cow; +use std::error::Error; use std::fmt; use std::io::Cursor; @@ -39,12 +40,22 @@ const EF_MIPS_ABI_EABI64: u32 = 0x0000_4000; const MIPS_64_FLAGS: u32 = EF_MIPS_ABI_O64 | EF_MIPS_ABI_EABI64; /// An error when dealing with [`ElfObject`](struct.ElfObject.html). -#[non_exhaustive] #[derive(Debug, Error)] -pub enum ElfError { - /// The data in the ELF file could not be parsed. - #[error("invalid ELF file")] - BadObject(#[from] GoblinError), +#[error("invalid ELF file")] +pub struct ElfError { + #[source] + source: Option>, +} + +impl ElfError { + /// Creates a new ELF error from an arbitrary error payload. + fn new(source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { source } + } } /// Executable and Linkable Format, used for executables and libraries on Linux. @@ -64,7 +75,9 @@ impl<'data> ElfObject<'data> { /// Tries to parse an ELF object from the given slice. pub fn parse(data: &'data [u8]) -> Result { - Ok(elf::Elf::parse(data).map(|elf| ElfObject { elf, data })?) + elf::Elf::parse(data) + .map(|elf| ElfObject { elf, data }) + .map_err(ElfError::new) } /// The container file format, which is always `FileFormat::Elf`. From 8f47deb5149a9c21cc83ee2395c25a94d26ddea6 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:27:18 +0100 Subject: [PATCH 07/10] ref(breakpad): Switch to error with kind --- symbolic-debuginfo/src/breakpad.rs | 96 +++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/symbolic-debuginfo/src/breakpad.rs b/symbolic-debuginfo/src/breakpad.rs index 1777ab89c..ece55391c 100644 --- a/symbolic-debuginfo/src/breakpad.rs +++ b/symbolic-debuginfo/src/breakpad.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::BTreeMap; +use std::error::Error; use std::fmt; use std::str; @@ -32,27 +33,78 @@ const BREAKPAD_HEADER_CAP: usize = 320; /// Placeholder used for missing function or symbol names. const UNKNOWN_NAME: &str = ""; -/// An error when dealing with [`BreakpadObject`](struct.BreakpadObject.html). +/// The error type for [`BreakpadError`]. #[non_exhaustive] -#[derive(Debug, Error)] -pub enum BreakpadError { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BreakpadErrorKind { /// The symbol header (`MODULE` record) is missing. - #[error("missing breakpad symbol header")] InvalidMagic, /// A part of the file is not encoded in valid UTF-8. - #[error("bad utf-8 sequence")] - BadEncoding(#[from] str::Utf8Error), + BadEncoding, /// A record violates the Breakpad symbol syntax. - #[error(transparent)] - BadSyntax(#[from] pest::error::Error), + BadSyntax, /// Parsing of a record failed. - #[error("{0}")] Parse(&'static str), } +impl fmt::Display for BreakpadErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidMagic => write!(f, "missing breakpad symbol header"), + Self::BadEncoding => write!(f, "bad utf-8 sequence"), + Self::BadSyntax => write!(f, "invalid syntax"), + Self::Parse(field) => write!(f, "{}", field), + } + } +} + +/// An error when dealing with [`BreakpadObject`](struct.BreakpadObject.html). +#[derive(Debug, Error)] +#[error("{kind}")] +pub struct BreakpadError { + kind: BreakpadErrorKind, + #[source] + source: Option>, +} + +impl BreakpadError { + /// Creates a new Breakpad error from a known kind of error as well as an arbitrary error + /// payload. + fn new(kind: BreakpadErrorKind, source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { kind, source } + } + + /// Returns the corresponding [`BreakpadErrorKind`] for this error. + pub fn kind(&self) -> BreakpadErrorKind { + self.kind + } +} + +impl From for BreakpadError { + fn from(kind: BreakpadErrorKind) -> Self { + Self { kind, source: None } + } +} + +impl From for BreakpadError { + fn from(e: str::Utf8Error) -> Self { + Self::new(BreakpadErrorKind::BadEncoding, e) + } +} + +impl From> for BreakpadError { + fn from(e: pest::error::Error) -> Self { + Self::new(BreakpadErrorKind::BadSyntax, e) + } +} + // TODO(ja): Test the parser /// A [module record], constituting the header of a Breakpad file. @@ -134,7 +186,7 @@ impl<'d> BreakpadInfoRecord<'d> { } } - Err(BreakpadError::Parse("unknown INFO record")) + Err(BreakpadErrorKind::Parse("unknown INFO record").into()) } fn code_info_from_pair(pair: pest::iterators::Pair<'d, Rule>) -> Result { @@ -230,7 +282,7 @@ impl<'d> BreakpadFileRecord<'d> { match pair.as_rule() { Rule::file_id => { record.id = u64::from_str_radix(pair.as_str(), 10) - .map_err(|_| BreakpadError::Parse("file identifier"))?; + .map_err(|_| BreakpadErrorKind::Parse("file identifier"))?; } Rule::name => record.name = pair.as_str(), _ => unreachable!(), @@ -306,11 +358,11 @@ impl<'d> BreakpadPublicRecord<'d> { Rule::multiple => record.multiple = true, Rule::addr => { record.address = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("symbol address"))?; + .map_err(|_| BreakpadErrorKind::Parse("symbol address"))?; } Rule::param_size => { record.parameter_size = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("symbol parameter size"))?; + .map_err(|_| BreakpadErrorKind::Parse("symbol parameter size"))?; } Rule::name => record.name = pair.as_str(), _ => unreachable!(), @@ -395,15 +447,15 @@ impl<'d> BreakpadFuncRecord<'d> { Rule::multiple => record.multiple = true, Rule::addr => { record.address = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("function address"))?; + .map_err(|_| BreakpadErrorKind::Parse("function address"))?; } Rule::size => { record.size = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("function size"))?; + .map_err(|_| BreakpadErrorKind::Parse("function size"))?; } Rule::param_size => { record.parameter_size = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("function parameter size"))?; + .map_err(|_| BreakpadErrorKind::Parse("function parameter size"))?; } Rule::name => record.name = pair.as_str(), _ => unreachable!(), @@ -518,11 +570,11 @@ impl BreakpadLineRecord { match pair.as_rule() { Rule::addr => { record.address = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("line address"))?; + .map_err(|_| BreakpadErrorKind::Parse("line address"))?; } Rule::size => { record.size = u64::from_str_radix(pair.as_str(), 16) - .map_err(|_| BreakpadError::Parse("line size"))?; + .map_err(|_| BreakpadErrorKind::Parse("line size"))?; } Rule::line_num => { // NB: Breakpad does not allow negative line numbers and even tests that the @@ -530,11 +582,11 @@ impl BreakpadLineRecord { // been observed at least for ELF files, so handle them gracefully. record.line = i32::from_str_radix(pair.as_str(), 10) .map(|line| u64::from(line as u32)) - .map_err(|_| BreakpadError::Parse("line number"))?; + .map_err(|_| BreakpadErrorKind::Parse("line number"))?; } Rule::file_id => { record.file_id = u64::from_str_radix(pair.as_str(), 10) - .map_err(|_| BreakpadError::Parse("file number"))?; + .map_err(|_| BreakpadErrorKind::Parse("file number"))?; } _ => unreachable!(), } @@ -768,11 +820,11 @@ impl<'data> BreakpadObject<'data> { id: module .id .parse() - .map_err(|_| BreakpadError::Parse("module id"))?, + .map_err(|_| BreakpadErrorKind::Parse("module id"))?, arch: module .arch .parse() - .map_err(|_| BreakpadError::Parse("module architecture"))?, + .map_err(|_| BreakpadErrorKind::Parse("module architecture"))?, module, data, }) From 42c5cb8bfd6ef29b4ebec28d212841ad9fb56776 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:32:52 +0100 Subject: [PATCH 08/10] ref(dwarf): Switch to error with kind --- symbolic-debuginfo/src/dwarf.rs | 74 +++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/symbolic-debuginfo/src/dwarf.rs b/symbolic-debuginfo/src/dwarf.rs index 338971f48..6507a97ec 100644 --- a/symbolic-debuginfo/src/dwarf.rs +++ b/symbolic-debuginfo/src/dwarf.rs @@ -8,6 +8,7 @@ //! [`MachObject`]: ../macho/struct.MachObject.html use std::borrow::Cow; +use std::error::Error; use std::fmt; use std::marker::PhantomData; use std::ops::{Deref, RangeBounds}; @@ -51,29 +52,76 @@ fn offset(addr: u64, offset: i64) -> u64 { (addr as i64).wrapping_sub(offset as i64) as u64 } -/// An error handling [`DWARF`](trait.Dwarf.html) debugging information. +/// The error type for [`DwarfError`]. #[non_exhaustive] -#[derive(Debug, Error)] -pub enum DwarfError { +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum DwarfErrorKind { /// A compilation unit referenced by index does not exist. - #[error("compilation unit for offset {0} does not exist")] InvalidUnitRef(usize), /// A file record referenced by index does not exist. - #[error("referenced file {0} does not exist")] InvalidFileRef(u64), /// An inline record was encountered without an inlining parent. - #[error("unexpected inline function without parent")] UnexpectedInline, /// The debug_ranges of a function are invalid. - #[error("function with inverted address range")] InvertedFunctionRange, /// The DWARF file is corrupted. See the cause for more information. - #[error("corrupted dwarf debug data")] - CorruptedData(#[from] GimliError), + CorruptedData, +} + +impl fmt::Display for DwarfErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidUnitRef(offset) => { + write!(f, "compilation unit for offset {} does not exist", offset) + } + Self::InvalidFileRef(id) => write!(f, "referenced file {} does not exist", id), + Self::UnexpectedInline => write!(f, "unexpected inline function without parent"), + Self::InvertedFunctionRange => write!(f, "function with inverted address range"), + Self::CorruptedData => write!(f, "corrupted dwarf debug data"), + } + } +} + +/// An error handling [`DWARF`](trait.Dwarf.html) debugging information. +#[derive(Debug, Error)] +#[error("{kind}")] +pub struct DwarfError { + kind: DwarfErrorKind, + #[source] + source: Option>, +} + +impl DwarfError { + /// Creates a new DWARF error from a known kind of error as well as an arbitrary error + /// payload. + fn new(kind: DwarfErrorKind, source: E) -> Self + where + E: Into>, + { + let source = Some(source.into()); + Self { kind, source } + } + + /// Returns the corresponding [`DwarfErrorKind`] for this error. + pub fn kind(&self) -> DwarfErrorKind { + self.kind + } +} + +impl From for DwarfError { + fn from(kind: DwarfErrorKind) -> Self { + Self { kind, source: None } + } +} + +impl From for DwarfError { + fn from(e: GimliError) -> Self { + Self::new(DwarfErrorKind::CorruptedData, e) + } } /// DWARF section information including its data. @@ -525,7 +573,7 @@ impl<'d, 'a> DwarfUnit<'d, 'a> { if low_pc > high_pc { // TODO: consider swallowing errors here? - return Err(DwarfError::InvertedFunctionRange); + return Err(DwarfErrorKind::InvertedFunctionRange.into()); } range_buf.push(Range { @@ -737,7 +785,7 @@ impl<'d, 'a> DwarfUnit<'d, 'a> { // indicates invalid debug information. let parent = match stack.peek_mut() { Some(parent) => parent, - None => return Err(DwarfError::UnexpectedInline), + None => return Err(DwarfErrorKind::UnexpectedInline.into()), }; // Make sure there is correct line information for the call site of this inlined @@ -1076,7 +1124,7 @@ impl<'d> DwarfInfo<'d> { let index = match search_result { Ok(index) => index, - Err(0) => return Err(DwarfError::InvalidUnitRef(offset.0)), + Err(0) => return Err(DwarfErrorKind::InvalidUnitRef(offset.0).into()), Err(next_index) => next_index - 1, }; @@ -1087,7 +1135,7 @@ impl<'d> DwarfInfo<'d> { } } - Err(DwarfError::InvalidUnitRef(offset.0)) + Err(DwarfErrorKind::InvalidUnitRef(offset.0).into()) } /// Returns an iterator over all compilation units. From cbddabc46b905c9adc23b8c3c570a8d2047b1668 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 14:52:00 +0100 Subject: [PATCH 09/10] ref(object): Switch to error with kind --- symbolic-cabi/src/core.rs | 34 +----- symbolic-debuginfo/src/object.rs | 178 +++++++++++++++++++------------ 2 files changed, 110 insertions(+), 102 deletions(-) diff --git a/symbolic-cabi/src/core.rs b/symbolic-cabi/src/core.rs index 67b7186f7..5048f6ca4 100644 --- a/symbolic-cabi/src/core.rs +++ b/symbolic-cabi/src/core.rs @@ -247,42 +247,14 @@ impl SymbolicErrorCode { } use symbolic::debuginfo::{ - dwarf::DwarfError, ObjectError, UnknownFileFormatError, UnknownObjectKindError, + ObjectError, UnknownFileFormatError, UnknownObjectKindError, }; if error.downcast_ref::().is_some() { return SymbolicErrorCode::UnknownObjectKindError; } else if error.downcast_ref::().is_some() { return SymbolicErrorCode::UnknownFileFormatError; - } else if let Some(error) = error.downcast_ref::() { - return match error { - ObjectError::UnsupportedObject => { - SymbolicErrorCode::ObjectErrorUnsupportedObject - } - ObjectError::Breakpad(_) => SymbolicErrorCode::ObjectErrorBadBreakpadObject, - ObjectError::Elf(_) => SymbolicErrorCode::ObjectErrorBadElfObject, - ObjectError::MachO(_) => SymbolicErrorCode::ObjectErrorBadMachOObject, - ObjectError::Pdb(_) => SymbolicErrorCode::ObjectErrorBadPdbObject, - ObjectError::Pe(_) => SymbolicErrorCode::ObjectErrorBadPeObject, - ObjectError::Wasm(_) => SymbolicErrorCode::ObjectErrorBadWasmObject, - ObjectError::Dwarf(ref e) => match e { - DwarfError::InvalidUnitRef(_) => { - SymbolicErrorCode::DwarfErrorInvalidUnitRef - } - DwarfError::InvalidFileRef(_) => { - SymbolicErrorCode::DwarfErrorInvalidFileRef - } - DwarfError::UnexpectedInline => { - SymbolicErrorCode::DwarfErrorUnexpectedInline - } - DwarfError::InvertedFunctionRange => { - SymbolicErrorCode::DwarfErrorInvertedFunctionRange - } - DwarfError::CorruptedData(_) => SymbolicErrorCode::DwarfErrorCorruptedData, - _ => SymbolicErrorCode::DwarfErrorUnknown, - }, - ObjectError::SourceBundle(_) => SymbolicErrorCode::ObjectErrorBadSourceBundle, - _ => SymbolicErrorCode::ObjectErrorUnknown, - }; + } else if error.downcast_ref::().is_some() { + return SymbolicErrorCode::ObjectErrorUnknown; } use symbolic::minidump::cfi::{CfiError, CfiErrorKind}; diff --git a/symbolic-debuginfo/src/object.rs b/symbolic-debuginfo/src/object.rs index 06c072721..02f524d3d 100644 --- a/symbolic-debuginfo/src/object.rs +++ b/symbolic-debuginfo/src/object.rs @@ -1,9 +1,10 @@ //! Generic wrappers over various object file formats. use std::borrow::Cow; +use std::error::Error; +use std::fmt; use goblin::Hint; -use thiserror::Error; use symbolic_common::{Arch, AsSelf, CodeId, DebugId}; @@ -49,58 +50,75 @@ macro_rules! map_inner { macro_rules! map_result { ($value:expr, $from:tt($pat:pat) => $to:tt($expr:expr)) => { match $value { - $from::Breakpad($pat) => $expr.map($to::Breakpad).map_err(ObjectError::Breakpad), - $from::Elf($pat) => $expr.map($to::Elf).map_err(ObjectError::Elf), - $from::MachO($pat) => $expr.map($to::MachO).map_err(ObjectError::MachO), - $from::Pdb($pat) => $expr.map($to::Pdb).map_err(ObjectError::Pdb), - $from::Pe($pat) => $expr.map($to::Pe).map_err(ObjectError::Pe), + $from::Breakpad($pat) => $expr.map($to::Breakpad).map_err(ObjectError::transparent), + $from::Elf($pat) => $expr.map($to::Elf).map_err(ObjectError::transparent), + $from::MachO($pat) => $expr.map($to::MachO).map_err(ObjectError::transparent), + $from::Pdb($pat) => $expr.map($to::Pdb).map_err(ObjectError::transparent), + $from::Pe($pat) => $expr.map($to::Pe).map_err(ObjectError::transparent), $from::SourceBundle($pat) => $expr .map($to::SourceBundle) - .map_err(ObjectError::SourceBundle), - $from::Wasm($pat) => $expr.map($to::Wasm).map_err(ObjectError::Wasm), + .map_err(ObjectError::transparent), + $from::Wasm($pat) => $expr.map($to::Wasm).map_err(ObjectError::transparent), } }; } -/// An error when dealing with any kind of [`Object`](enum.Object.html). -#[non_exhaustive] -#[derive(Debug, Error)] -pub enum ObjectError { +/// Internal representation of the object error type. +#[derive(Debug)] +enum ObjectErrorRepr { /// The object file format is not supported. - #[error("unsupported object file format")] UnsupportedObject, - /// An error in a Breakpad ASCII symbol. - #[error("failed to process breakpad file")] - Breakpad(#[from] BreakpadError), - - /// An error in an ELF file. - #[error("failed to process elf file")] - Elf(#[from] ElfError), + /// A transparent error from the inner object file type. + Transparent(Box), +} - /// An error in a Mach object. - #[error("failed to process macho file")] - MachO(#[from] MachError), +/// An error when dealing with any kind of [`Object`](enum.Object.html). +pub struct ObjectError { + repr: ObjectErrorRepr, +} - /// An error in a Program Database. - #[error("failed to process pdb file")] - Pdb(#[from] PdbError), +impl ObjectError { + /// Creates a new object error with the given representation. + fn new(repr: ObjectErrorRepr) -> Self { + Self { repr } + } - /// An error in a Portable Executable. - #[error("failed to process pe file")] - Pe(#[from] PeError), + /// Creates a new object error from an arbitrary error payload. + fn transparent(source: E) -> Self + where + E: Into>, + { + let repr = ObjectErrorRepr::Transparent(source.into()); + Self { repr } + } +} - /// An error in DWARF debugging information. - #[error("failed to process dwarf info")] - Dwarf(#[from] DwarfError), +impl fmt::Debug for ObjectError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.repr { + ObjectErrorRepr::Transparent(ref inner) => inner.fmt(f), + _ => self.repr.fmt(f), + } + } +} - /// An error in source bundles. - #[error("failed to process source bundle")] - SourceBundle(#[from] SourceBundleError), +impl fmt::Display for ObjectError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.repr { + ObjectErrorRepr::UnsupportedObject => write!(f, "unsupported object file format"), + ObjectErrorRepr::Transparent(ref inner) => inner.fmt(f), + } + } +} - /// An error in a WASM file. - #[error("failed to process wasm file")] - Wasm(#[from] WasmError), +impl Error for ObjectError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self.repr { + ObjectErrorRepr::UnsupportedObject => None, + ObjectErrorRepr::Transparent(ref inner) => inner.source(), + } + } } /// Tries to infer the object type from the start of the given buffer. @@ -173,7 +191,7 @@ impl<'data> Object<'data> { pub fn parse(data: &'data [u8]) -> Result { macro_rules! parse_object { ($kind:ident, $file:ident, $data:expr) => { - Object::$kind($file::parse(data).map_err(ObjectError::$kind)?) + Object::$kind($file::parse(data).map_err(ObjectError::transparent)?) }; }; @@ -185,7 +203,9 @@ impl<'data> Object<'data> { FileFormat::Pe => parse_object!(Pe, PeObject, data), FileFormat::SourceBundle => parse_object!(SourceBundle, SourceBundle, data), FileFormat::Wasm => parse_object!(Wasm, WasmObject, data), - FileFormat::Unknown => return Err(ObjectError::UnsupportedObject), + FileFormat::Unknown => { + return Err(ObjectError::new(ObjectErrorRepr::UnsupportedObject)) + } }; Ok(object) @@ -274,31 +294,31 @@ impl<'data> Object<'data> { Object::Breakpad(ref o) => o .debug_session() .map(ObjectDebugSession::Breakpad) - .map_err(ObjectError::Breakpad), + .map_err(ObjectError::transparent), Object::Elf(ref o) => o .debug_session() .map(ObjectDebugSession::Dwarf) - .map_err(ObjectError::Dwarf), + .map_err(ObjectError::transparent), Object::MachO(ref o) => o .debug_session() .map(ObjectDebugSession::Dwarf) - .map_err(ObjectError::Dwarf), + .map_err(ObjectError::transparent), Object::Pdb(ref o) => o .debug_session() .map(ObjectDebugSession::Pdb) - .map_err(ObjectError::Pdb), + .map_err(ObjectError::transparent), Object::Pe(ref o) => o .debug_session() .map(ObjectDebugSession::Pe) - .map_err(ObjectError::Pe), + .map_err(ObjectError::transparent), Object::SourceBundle(ref o) => o .debug_session() .map(ObjectDebugSession::SourceBundle) - .map_err(ObjectError::SourceBundle), + .map_err(ObjectError::transparent), Object::Wasm(ref o) => o .debug_session() .map(ObjectDebugSession::Dwarf) - .map_err(ObjectError::Dwarf), + .map_err(ObjectError::transparent), } } @@ -432,13 +452,19 @@ impl<'d> ObjectDebugSession<'d> { pub fn source_by_path(&self, path: &str) -> Result>, ObjectError> { match *self { ObjectDebugSession::Breakpad(ref s) => { - s.source_by_path(path).map_err(ObjectError::Breakpad) + s.source_by_path(path).map_err(ObjectError::transparent) + } + ObjectDebugSession::Dwarf(ref s) => { + s.source_by_path(path).map_err(ObjectError::transparent) + } + ObjectDebugSession::Pdb(ref s) => { + s.source_by_path(path).map_err(ObjectError::transparent) + } + ObjectDebugSession::Pe(ref s) => { + s.source_by_path(path).map_err(ObjectError::transparent) } - ObjectDebugSession::Dwarf(ref s) => s.source_by_path(path).map_err(ObjectError::Dwarf), - ObjectDebugSession::Pdb(ref s) => s.source_by_path(path).map_err(ObjectError::Pdb), - ObjectDebugSession::Pe(ref s) => s.source_by_path(path).map_err(ObjectError::Pe), ObjectDebugSession::SourceBundle(ref s) => { - s.source_by_path(path).map_err(ObjectError::SourceBundle) + s.source_by_path(path).map_err(ObjectError::transparent) } } } @@ -478,13 +504,19 @@ impl<'s> Iterator for ObjectFunctionIterator<'s> { fn next(&mut self) -> Option { match *self { ObjectFunctionIterator::Breakpad(ref mut i) => { - Some(i.next()?.map_err(ObjectError::Breakpad)) + Some(i.next()?.map_err(ObjectError::transparent)) + } + ObjectFunctionIterator::Dwarf(ref mut i) => { + Some(i.next()?.map_err(ObjectError::transparent)) + } + ObjectFunctionIterator::Pdb(ref mut i) => { + Some(i.next()?.map_err(ObjectError::transparent)) + } + ObjectFunctionIterator::Pe(ref mut i) => { + Some(i.next()?.map_err(ObjectError::transparent)) } - ObjectFunctionIterator::Dwarf(ref mut i) => Some(i.next()?.map_err(ObjectError::Dwarf)), - ObjectFunctionIterator::Pdb(ref mut i) => Some(i.next()?.map_err(ObjectError::Pdb)), - ObjectFunctionIterator::Pe(ref mut i) => Some(i.next()?.map_err(ObjectError::Pe)), ObjectFunctionIterator::SourceBundle(ref mut i) => { - Some(i.next()?.map_err(ObjectError::SourceBundle)) + Some(i.next()?.map_err(ObjectError::transparent)) } } } @@ -507,13 +539,15 @@ impl<'s> Iterator for ObjectFileIterator<'s> { fn next(&mut self) -> Option { match *self { ObjectFileIterator::Breakpad(ref mut i) => { - Some(i.next()?.map_err(ObjectError::Breakpad)) + Some(i.next()?.map_err(ObjectError::transparent)) + } + ObjectFileIterator::Dwarf(ref mut i) => { + Some(i.next()?.map_err(ObjectError::transparent)) } - ObjectFileIterator::Dwarf(ref mut i) => Some(i.next()?.map_err(ObjectError::Dwarf)), - ObjectFileIterator::Pdb(ref mut i) => Some(i.next()?.map_err(ObjectError::Pdb)), - ObjectFileIterator::Pe(ref mut i) => Some(i.next()?.map_err(ObjectError::Pe)), + ObjectFileIterator::Pdb(ref mut i) => Some(i.next()?.map_err(ObjectError::transparent)), + ObjectFileIterator::Pe(ref mut i) => Some(i.next()?.map_err(ObjectError::transparent)), ObjectFileIterator::SourceBundle(ref mut i) => { - Some(i.next()?.map_err(ObjectError::SourceBundle)) + Some(i.next()?.map_err(ObjectError::transparent)) } } } @@ -577,14 +611,16 @@ impl<'d> Archive<'d> { FileFormat::MachO => { let inner = MachArchive::parse(data) .map(ArchiveInner::MachO) - .map_err(ObjectError::MachO)?; + .map_err(ObjectError::transparent)?; Archive(inner) } FileFormat::Pdb => Archive(ArchiveInner::Pdb(MonoArchive::new(data))), FileFormat::Pe => Archive(ArchiveInner::Pe(MonoArchive::new(data))), FileFormat::SourceBundle => Archive(ArchiveInner::SourceBundle(MonoArchive::new(data))), FileFormat::Wasm => Archive(ArchiveInner::Wasm(MonoArchive::new(data))), - FileFormat::Unknown => return Err(ObjectError::UnsupportedObject), + FileFormat::Unknown => { + return Err(ObjectError::new(ObjectErrorRepr::UnsupportedObject)) + } }; Ok(archive) @@ -623,31 +659,31 @@ impl<'d> Archive<'d> { ArchiveInner::Breakpad(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::Breakpad)) - .map_err(ObjectError::Breakpad), + .map_err(ObjectError::transparent), ArchiveInner::Elf(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::Elf)) - .map_err(ObjectError::Elf), + .map_err(ObjectError::transparent), ArchiveInner::MachO(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::MachO)) - .map_err(ObjectError::MachO), + .map_err(ObjectError::transparent), ArchiveInner::Pdb(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::Pdb)) - .map_err(ObjectError::Pdb), + .map_err(ObjectError::transparent), ArchiveInner::Pe(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::Pe)) - .map_err(ObjectError::Pe), + .map_err(ObjectError::transparent), ArchiveInner::SourceBundle(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::SourceBundle)) - .map_err(ObjectError::SourceBundle), + .map_err(ObjectError::transparent), ArchiveInner::Wasm(ref a) => a .object_by_index(index) .map(|opt| opt.map(Object::Wasm)) - .map_err(ObjectError::Wasm), + .map_err(ObjectError::transparent), } } From fc34f8c7a22d048395f449ce36e21ddb49b46432 Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Mon, 30 Nov 2020 15:42:24 +0100 Subject: [PATCH 10/10] ref: Disambiguate fmt calls --- symbolic-debuginfo/src/object.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/symbolic-debuginfo/src/object.rs b/symbolic-debuginfo/src/object.rs index 02f524d3d..99b985c9e 100644 --- a/symbolic-debuginfo/src/object.rs +++ b/symbolic-debuginfo/src/object.rs @@ -97,8 +97,8 @@ impl ObjectError { impl fmt::Debug for ObjectError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.repr { - ObjectErrorRepr::Transparent(ref inner) => inner.fmt(f), - _ => self.repr.fmt(f), + ObjectErrorRepr::Transparent(ref inner) => fmt::Debug::fmt(inner, f), + _ => fmt::Debug::fmt(&self.repr, f), } } } @@ -107,7 +107,7 @@ impl fmt::Display for ObjectError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.repr { ObjectErrorRepr::UnsupportedObject => write!(f, "unsupported object file format"), - ObjectErrorRepr::Transparent(ref inner) => inner.fmt(f), + ObjectErrorRepr::Transparent(ref inner) => fmt::Display::fmt(inner, f), } } }