diff --git a/Cargo.toml b/Cargo.toml
index e1ba8a00ca263efeb4d48cccb53bdbacc5182439..9f573ee780ad062c853c111b2e49172e7324b4b7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 [dependencies]
+anyhow = "1.0"
 serde = { version = "1", features = ["derive"] }
 serde_json = "1.0"
 gimli = "0.16"
diff --git a/src/main.rs b/src/main.rs
index 6fadc6b5adb200c40c8a942f6aeead3624026515..8c87687be91b063aafd35fb9c6e4914abec00322 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,76 +1,15 @@
 // Based on the gimli 0.16.1 dwarfdump.rs example
-// Allow clippy lints when building without clippy.
+use anyhow::{anyhow, Result};
 use fallible_iterator::FallibleIterator;
 use gimli::{Endianity, Reader};
 use object::Object;
 use serde::Serialize;
 use std::borrow::{Borrow, Cow};
-use std::error;
-use std::fmt::{self, Debug};
 use std::fs;
-use std::io;
 use std::path::PathBuf;
-use std::result;
 use structopt::StructOpt;
 use typed_arena::Arena;
 
-#[derive(Debug)]
-pub enum Error {
-    GimliError(gimli::Error),
-    IoError(io::Error),
-    MissingDIE,
-    Message(String),
-    SerdeError(serde_json::Error),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
-        match self {
-            Error::GimliError(err) => write!(f, "Gimli error: {}", err),
-            Error::IoError(e) => write!(f, "I/O error: {}", e),
-            Error::MissingDIE => write!(f, "Expected a DIE but none was found"),
-            Error::Message(m) => write!(f, "Error: {}", m),
-            Error::SerdeError(err) => write!(f, "Serde error: {}", err),
-        }
-    }
-}
-
-impl error::Error for Error {
-    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
-        match *self {
-            Error::GimliError(ref err) => Some(err),
-            Error::SerdeError(ref err) => Some(err),
-            _ => None,
-        }
-    }
-}
-
-impl From<gimli::Error> for Error {
-    fn from(err: gimli::Error) -> Self {
-        Error::GimliError(err)
-    }
-}
-
-impl From<io::Error> for Error {
-    fn from(e: io::Error) -> Self {
-        Error::IoError(e)
-    }
-}
-
-impl From<&str> for Error {
-    fn from(m: &str) -> Self {
-        Error::Message(m.to_owned())
-    }
-}
-
-impl From<serde_json::Error> for Error {
-    fn from(e: serde_json::Error) -> Self {
-        Error::SerdeError(e)
-    }
-}
-
-pub type Result<T> = result::Result<T, Error>;
-
 fn list_file<E: Endianity>(file: &object::File, endian: E) -> Result<Vec<Unit>> {
     let arena = Arena::new();
 
@@ -140,13 +79,13 @@ fn list_entries<R: Reader>(
                 .and_then(|attr| attr.string_value(debug_str))
                 .map::<Result<String>, _>(|s| Ok(s.to_string()?.into_owned()))
                 .transpose()?
-                .ok_or("Missing DW_AT_comp_dir")?;
+                .ok_or_else(|| anyhow!("Missing DW_AT_comp_dir"))?;
             let comp_name = entry
                 .attr(gimli::DW_AT_name)?
                 .and_then(|attr| attr.string_value(debug_str))
                 .map::<Result<String>, _>(|s| Ok(s.to_string()?.into_owned()))
                 .transpose()?
-                .ok_or("Missing DW_AT_name")?;
+                .ok_or_else(|| anyhow!("Missing DW_AT_name"))?;
 
             v.push(Unit {
                 comp_dir,
@@ -178,7 +117,7 @@ fn main() -> Result<()> {
     let opt = Opt::from_args();
     let file = fs::File::open(&opt.file)?;
     let file = unsafe { memmap::Mmap::map(&file) }?;
-    let file = object::File::parse(&*file)?;
+    let file = object::File::parse(&*file).map_err( | e | anyhow!(e))?;
 
     let endian = if file.is_little_endian() {
         gimli::RunTimeEndian::Little
@@ -204,6 +143,7 @@ fn main() -> Result<()> {
     } else {
         units
     };
+
     let d = Data {
         file: opt.file,
         units,