diff --git a/src/symbolize/dbghelp.rs b/src/symbolize/dbghelp.rs
index 50d5384f..a2d613aa 100644
--- a/src/symbolize/dbghelp.rs
+++ b/src/symbolize/dbghelp.rs
@@ -18,7 +18,7 @@
 #![allow(bad_style)]
 
 use super::super::{dbghelp, windows::*};
-use super::{BytesOrWideString, ResolveWhat, SymbolName};
+use super::{BytesOrWideString, RawSymbolName, ResolveWhat};
 use core::char;
 use core::ffi::c_void;
 use core::marker;
@@ -47,8 +47,8 @@ pub struct Symbol<'a> {
 }
 
 impl Symbol<'_> {
-    pub fn name(&self) -> Option<SymbolName<'_>> {
-        Some(SymbolName::new(unsafe { &*self.name }))
+    pub fn name_raw(&self) -> Option<RawSymbolName<'_>> {
+        Some(RawSymbolName::new(unsafe { &*self.name }))
     }
 
     pub fn addr(&self) -> Option<*mut c_void> {
diff --git a/src/symbolize/gimli.rs b/src/symbolize/gimli.rs
index 51f1c803..75ac30a4 100644
--- a/src/symbolize/gimli.rs
+++ b/src/symbolize/gimli.rs
@@ -7,8 +7,8 @@ use self::gimli::NativeEndian as Endian;
 use self::mmap::Mmap;
 use self::stash::Stash;
 use super::BytesOrWideString;
+use super::RawSymbolName;
 use super::ResolveWhat;
-use super::SymbolName;
 use addr2line::gimli;
 use core::convert::TryInto;
 use core::mem;
@@ -492,13 +492,13 @@ pub enum Symbol<'a> {
 }
 
 impl Symbol<'_> {
-    pub fn name(&self) -> Option<SymbolName<'_>> {
+    pub fn name_raw(&self) -> Option<RawSymbolName<'_>> {
         match self {
             Symbol::Frame { name, .. } => {
                 let name = name.as_ref()?;
-                Some(SymbolName::new(name))
+                Some(RawSymbolName::new(name))
             }
-            Symbol::Symtab { name, .. } => Some(SymbolName::new(name)),
+            Symbol::Symtab { name, .. } => Some(RawSymbolName::new(name)),
         }
     }
 
diff --git a/src/symbolize/miri.rs b/src/symbolize/miri.rs
index 5b0dc308..b7eb9213 100644
--- a/src/symbolize/miri.rs
+++ b/src/symbolize/miri.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
 
 use super::super::backtrace::miri::{resolve_addr, Frame};
 use super::BytesOrWideString;
-use super::{ResolveWhat, SymbolName};
+use super::{RawSymbolName, ResolveWhat};
 
 pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) {
     let sym = match what {
@@ -25,8 +25,8 @@ pub struct Symbol<'a> {
 }
 
 impl<'a> Symbol<'a> {
-    pub fn name(&self) -> Option<SymbolName<'_>> {
-        Some(SymbolName::new(&self.inner.inner.name))
+    pub fn name_raw(&self) -> Option<RawSymbolName<'_>> {
+        Some(RawSymbolName::new(&self.inner.inner.name))
     }
 
     pub fn addr(&self) -> Option<*mut c_void> {
diff --git a/src/symbolize/mod.rs b/src/symbolize/mod.rs
index b01fe86d..6b9c0fbf 100644
--- a/src/symbolize/mod.rs
+++ b/src/symbolize/mod.rs
@@ -205,7 +205,14 @@ impl Symbol {
     ///   utf-8).
     /// * The raw bytes for the symbol name can be accessed.
     pub fn name(&self) -> Option<SymbolName<'_>> {
-        self.inner.name()
+        self.name_raw().map(|s| s.demangle())
+    }
+
+    /// Returns the raw name of this function.
+    ///
+    /// This is similar to `name` but doesn't do any demangling.
+    pub fn name_raw(&self) -> Option<RawSymbolName<'_>> {
+        self.inner.name_raw()
     }
 
     /// Returns the starting address of this function.
@@ -356,6 +363,42 @@ impl<'a> SymbolName<'a> {
     }
 }
 
+/// A wrapper around the raw, mangled, symbol name.
+pub struct RawSymbolName<'a> {
+    bytes: &'a [u8],
+}
+impl<'a> RawSymbolName<'a> {
+    /// Creates a new raw symbol name from the raw underlying bytes.
+    pub fn new(bytes: &'a [u8]) -> RawSymbolName<'a> {
+        RawSymbolName { bytes }
+    }
+
+    /// Attempt to demangle the symbol name.
+    pub fn demangle(self) -> SymbolName<'a> {
+        SymbolName::new(self.bytes)
+    }
+
+    /// Returns the raw (mangled) symbol name as a `str` if the symbol is valid utf-8.
+    pub fn as_str(&self) -> Option<&'a str> {
+        str::from_utf8(self.bytes).ok()
+    }
+
+    /// Returns the raw symbol name as a list of bytes
+    pub fn as_bytes(&self) -> &'a [u8] {
+        self.bytes
+    }
+}
+impl<'a> fmt::Display for RawSymbolName<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        format_symbol_name(fmt::Display::fmt, self.bytes, f)
+    }
+}
+impl<'a> fmt::Debug for RawSymbolName<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        format_symbol_name(fmt::Debug::fmt, self.bytes, f)
+    }
+}
+
 fn format_symbol_name(
     fmt: fn(&str, &mut fmt::Formatter<'_>) -> fmt::Result,
     mut bytes: &[u8],
diff --git a/src/symbolize/noop.rs b/src/symbolize/noop.rs
index c5333653..f9b5723b 100644
--- a/src/symbolize/noop.rs
+++ b/src/symbolize/noop.rs
@@ -1,7 +1,7 @@
 //! Empty symbolication strategy used to compile for platforms that have no
 //! support.
 
-use super::{BytesOrWideString, ResolveWhat, SymbolName};
+use super::{BytesOrWideString, RawSymbolName, ResolveWhat};
 use core::ffi::c_void;
 use core::marker;
 
@@ -12,7 +12,7 @@ pub struct Symbol<'a> {
 }
 
 impl Symbol<'_> {
-    pub fn name(&self) -> Option<SymbolName<'_>> {
+    pub fn name_raw(&self) -> Option<RawSymbolName<'_>> {
         None
     }