diff --git a/src/aarch64/cache.rs b/src/aarch64/cache.rs
index 04637d6..4b207ea 100644
--- a/src/aarch64/cache.rs
+++ b/src/aarch64/cache.rs
@@ -1,18 +1,23 @@
-use core::ops::Deref;
-
 use super::unwind_rule::*;
 use crate::cache::*;
 
 /// The unwinder cache type for [`UnwinderAarch64`](super::UnwinderAarch64).
-pub struct CacheAarch64<D: Deref<Target = [u8]>, P: AllocationPolicy<D> = MayAllocateDuringUnwind>(
-    pub Cache<D, UnwindRuleAarch64, P>,
+pub struct CacheAarch64<P: AllocationPolicy = MayAllocateDuringUnwind>(
+    pub Cache<UnwindRuleAarch64, P>,
 );
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> CacheAarch64<D, P> {
+impl CacheAarch64<MayAllocateDuringUnwind> {
     /// Create a new cache.
     pub fn new() -> Self {
         Self(Cache::new())
     }
+}
+
+impl<P: AllocationPolicy> CacheAarch64<P> {
+    /// Create a new cache.
+    pub fn new_in() -> Self {
+        Self(Cache::new())
+    }
 
     /// Returns a snapshot of the cache usage statistics.
     pub fn stats(&self) -> CacheStats {
@@ -20,8 +25,8 @@ impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> CacheAarch64<D, P> {
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Default for CacheAarch64<D, P> {
+impl<P: AllocationPolicy> Default for CacheAarch64<P> {
     fn default() -> Self {
-        Self::new()
+        Self::new_in()
     }
 }
diff --git a/src/aarch64/dwarf.rs b/src/aarch64/dwarf.rs
index 0f3ea17..c3ea10a 100644
--- a/src/aarch64/dwarf.rs
+++ b/src/aarch64/dwarf.rs
@@ -1,5 +1,6 @@
 use gimli::{
-    AArch64, CfaRule, Encoding, EvaluationStorage, Reader, ReaderOffset, Register, RegisterRule, UnwindContextStorage, UnwindSection, UnwindTableRow
+    AArch64, CfaRule, Encoding, EvaluationStorage, Reader, ReaderOffset, Register, RegisterRule,
+    UnwindContextStorage, UnwindSection, UnwindTableRow,
 };
 
 use super::{arch::ArchAarch64, unwind_rule::UnwindRuleAarch64, unwindregs::UnwindRegsAarch64};
@@ -23,9 +24,9 @@ impl DwarfUnwindRegs for UnwindRegsAarch64 {
 }
 
 impl DwarfUnwinding for ArchAarch64 {
-    fn unwind_frame<F, R, S>(
+    fn unwind_frame<F, R, UCS, ES>(
         section: &impl UnwindSection<R>,
-        unwind_info: &UnwindTableRow<R::Offset, S>,
+        unwind_info: &UnwindTableRow<R::Offset, UCS>,
         encoding: Encoding,
         regs: &mut Self::UnwindRegs,
         is_first_frame: bool,
@@ -34,7 +35,8 @@ impl DwarfUnwinding for ArchAarch64 {
     where
         F: FnMut(u64) -> Result<u64, ()>,
         R: Reader,
-        S: UnwindContextStorage<R::Offset> + EvaluationStorage<R>,
+        UCS: UnwindContextStorage<R::Offset>,
+        ES: EvaluationStorage<R>,
     {
         let cfa_rule = unwind_info.cfa();
         let fp_rule = unwind_info.register(AArch64::X29);
@@ -48,7 +50,7 @@ impl DwarfUnwinding for ArchAarch64 {
             }
         }
 
-        let cfa = eval_cfa_rule::<R, _, S>(section, cfa_rule, encoding, regs)
+        let cfa = eval_cfa_rule::<R, _, ES>(section, cfa_rule, encoding, regs)
             .ok_or(DwarfUnwinderError::CouldNotRecoverCfa)?;
 
         let lr = regs.lr();
@@ -59,19 +61,27 @@ impl DwarfUnwinding for ArchAarch64 {
             if cfa <= sp {
                 return Err(DwarfUnwinderError::StackPointerMovedBackwards);
             }
-            let fp = eval_register_rule::<R, F, _, S>(section, fp_rule, cfa, encoding, fp, regs, read_stack)
-                .ok_or(DwarfUnwinderError::CouldNotRecoverFramePointer)?;
-            let lr = eval_register_rule::<R, F, _, S>(section, lr_rule, cfa, encoding, lr, regs, read_stack)
-                .ok_or(DwarfUnwinderError::CouldNotRecoverReturnAddress)?;
+            let fp = eval_register_rule::<R, F, _, ES>(
+                section, fp_rule, cfa, encoding, fp, regs, read_stack,
+            )
+            .ok_or(DwarfUnwinderError::CouldNotRecoverFramePointer)?;
+            let lr = eval_register_rule::<R, F, _, ES>(
+                section, lr_rule, cfa, encoding, lr, regs, read_stack,
+            )
+            .ok_or(DwarfUnwinderError::CouldNotRecoverReturnAddress)?;
             (fp, lr)
         } else {
             // For the first frame, be more lenient when encountering errors.
             // TODO: Find evidence of what this gives us. I think on macOS the prologue often has Unknown register rules
             // and we only encounter prologues for the first frame.
-            let fp = eval_register_rule::<R, F, _, S>(section, fp_rule, cfa, encoding, fp, regs, read_stack)
-                .unwrap_or(fp);
-            let lr = eval_register_rule::<R, F, _, S>(section, lr_rule, cfa, encoding, lr, regs, read_stack)
-                .unwrap_or(lr);
+            let fp = eval_register_rule::<R, F, _, ES>(
+                section, fp_rule, cfa, encoding, fp, regs, read_stack,
+            )
+            .unwrap_or(fp);
+            let lr = eval_register_rule::<R, F, _, ES>(
+                section, lr_rule, cfa, encoding, lr, regs, read_stack,
+            )
+            .unwrap_or(lr);
             (fp, lr)
         };
 
diff --git a/src/aarch64/unwinder.rs b/src/aarch64/unwinder.rs
index 417eaef..575b0f5 100644
--- a/src/aarch64/unwinder.rs
+++ b/src/aarch64/unwinder.rs
@@ -13,27 +13,26 @@ use super::{ArchAarch64, CacheAarch64, UnwindRegsAarch64};
 ///
 ///  - `D`: The type for unwind section data in the modules. See [`Module`].
 /// -  `P`: The [`AllocationPolicy`].
-pub struct UnwinderAarch64<
-    D: Deref<Target = [u8]>,
-    P: AllocationPolicy<D> = MayAllocateDuringUnwind,
->(UnwinderInternal<D, ArchAarch64, P>);
+pub struct UnwinderAarch64<D: Deref<Target = [u8]>, P: AllocationPolicy = MayAllocateDuringUnwind>(
+    UnwinderInternal<D, ArchAarch64, P>,
+);
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Default for UnwinderAarch64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> Default for UnwinderAarch64<D, P> {
     fn default() -> Self {
         Self::new()
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> UnwinderAarch64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> UnwinderAarch64<D, P> {
     /// Create an unwinder for a process.
     pub fn new() -> Self {
         Self(UnwinderInternal::new())
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Unwinder for UnwinderAarch64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> Unwinder for UnwinderAarch64<D, P> {
     type UnwindRegs = UnwindRegsAarch64;
-    type Cache = CacheAarch64<D, P>;
+    type Cache = CacheAarch64<P>;
     type Module = Module<D>;
 
     fn add_module(&mut self, module: Module<D>) {
@@ -52,7 +51,7 @@ impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Unwinder for UnwinderAarch
         &self,
         address: FrameAddress,
         regs: &mut UnwindRegsAarch64,
-        cache: &mut CacheAarch64<D, P>,
+        cache: &mut CacheAarch64<P>,
         read_stack: &mut F,
     ) -> Result<Option<u64>, Error>
     where
diff --git a/src/arcdata.rs b/src/arcdata.rs
deleted file mode 100644
index 090532a..0000000
--- a/src/arcdata.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use alloc::sync::Arc;
-use core::{fmt::Debug, ops::Deref};
-
-pub type ArcDataReader<D> = gimli::EndianReader<gimli::LittleEndian, ArcData<D>>;
-
-pub struct ArcData<D: Deref<Target = [u8]>>(pub Arc<D>);
-
-impl<D: Deref<Target = [u8]>> Deref for ArcData<D> {
-    type Target = [u8];
-
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-impl<D: Deref<Target = [u8]>> Clone for ArcData<D> {
-    fn clone(&self) -> Self {
-        Self(self.0.clone())
-    }
-}
-
-impl<D: Deref<Target = [u8]>> Debug for ArcData<D> {
-    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
-        f.debug_tuple("ArcData").field(&self.0.as_ptr()).finish()
-    }
-}
-
-// Safety: See the implementation for Arc. ArcData just wraps Arc, cloning ArcData just clones Arc.
-unsafe impl<D: Deref<Target = [u8]>> gimli::StableDeref for ArcData<D> {}
-unsafe impl<D: Deref<Target = [u8]>> gimli::CloneStableDeref for ArcData<D> {}
diff --git a/src/cache.rs b/src/cache.rs
index 2bd99e5..1c7a61f 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -1,18 +1,14 @@
-use core::ops::Deref;
-
 use alloc::boxed::Box;
 
 use crate::{rule_cache::RuleCache, unwind_rule::UnwindRule};
 
-use super::arcdata::ArcDataReader;
-
 pub use crate::rule_cache::CacheStats;
 
 /// A trait which lets you opt into allocation-free unwinding. The two implementations of
 /// this trait are [`MustNotAllocateDuringUnwind`] and [`MayAllocateDuringUnwind`].
-pub trait AllocationPolicy<D: Deref<Target = [u8]>> {
-    type GimliStorage: gimli::UnwindContextStorage<usize>
-        + gimli::EvaluationStorage<ArcDataReader<D>>;
+pub trait AllocationPolicy {
+    type GimliUnwindContextStorage<R: gimli::ReaderOffset>: gimli::UnwindContextStorage<R>;
+    type GimliEvaluationStorage<R: gimli::Reader>: gimli::EvaluationStorage<R>;
 }
 
 /// Require allocation-free unwinding. This is one of the two [`AllocationPolicy`]
@@ -40,8 +36,9 @@ impl<R: gimli::Reader> gimli::EvaluationStorage<R> for StoreOnStack {
     type Result = [gimli::Piece<R>; 1];
 }
 
-impl<D: Deref<Target = [u8]>> AllocationPolicy<D> for MustNotAllocateDuringUnwind {
-    type GimliStorage = StoreOnStack;
+impl AllocationPolicy for MustNotAllocateDuringUnwind {
+    type GimliUnwindContextStorage<R: gimli::ReaderOffset> = StoreOnStack;
+    type GimliEvaluationStorage<R: gimli::Reader> = StoreOnStack;
 }
 
 /// Allow allocation during unwinding. This is one of the two [`AllocationPolicy`]
@@ -50,8 +47,9 @@ impl<D: Deref<Target = [u8]>> AllocationPolicy<D> for MustNotAllocateDuringUnwin
 /// This is the preferred policy because it saves memory and places no limitations on
 /// DWARF CFI evaluation.
 pub struct MayAllocateDuringUnwind;
-impl<D: Deref<Target = [u8]>> AllocationPolicy<D> for MayAllocateDuringUnwind {
-    type GimliStorage = gimli::StoreOnHeap;
+impl AllocationPolicy for MayAllocateDuringUnwind {
+    type GimliUnwindContextStorage<R: gimli::ReaderOffset> = gimli::StoreOnHeap;
+    type GimliEvaluationStorage<R: gimli::Reader> = gimli::StoreOnHeap;
 }
 
 /// The unwinder cache. This needs to be created upfront before unwinding. During
@@ -61,16 +59,13 @@ impl<D: Deref<Target = [u8]>> AllocationPolicy<D> for MayAllocateDuringUnwind {
 ///
 /// The cache stores unwind rules for addresses it has seen before, and it stores the
 /// unwind context which gimli needs for DWARF CFI evaluation.
-pub struct Cache<
-    D: Deref<Target = [u8]>,
-    R: UnwindRule,
-    P: AllocationPolicy<D> = MayAllocateDuringUnwind,
-> {
-    pub(crate) gimli_unwind_context: Box<gimli::UnwindContext<usize, P::GimliStorage>>,
+pub struct Cache<R: UnwindRule, P: AllocationPolicy = MayAllocateDuringUnwind> {
+    pub(crate) gimli_unwind_context:
+        Box<gimli::UnwindContext<usize, P::GimliUnwindContextStorage<usize>>>,
     pub(crate) rule_cache: RuleCache<R>,
 }
 
-impl<D: Deref<Target = [u8]>, R: UnwindRule, P: AllocationPolicy<D>> Cache<D, R, P> {
+impl<R: UnwindRule, P: AllocationPolicy> Cache<R, P> {
     pub fn new() -> Self {
         Self {
             gimli_unwind_context: Box::new(gimli::UnwindContext::new_in()),
@@ -79,7 +74,7 @@ impl<D: Deref<Target = [u8]>, R: UnwindRule, P: AllocationPolicy<D>> Cache<D, R,
     }
 }
 
-impl<D: Deref<Target = [u8]>, R: UnwindRule, P: AllocationPolicy<D>> Default for Cache<D, R, P> {
+impl<R: UnwindRule, P: AllocationPolicy> Default for Cache<R, P> {
     fn default() -> Self {
         Self::new()
     }
diff --git a/src/dwarf.rs b/src/dwarf.rs
index 62cfa43..90214d7 100644
--- a/src/dwarf.rs
+++ b/src/dwarf.rs
@@ -57,9 +57,9 @@ pub enum ConversionError {
 }
 
 pub trait DwarfUnwinding: Arch {
-    fn unwind_frame<F, R, S>(
+    fn unwind_frame<F, R, UCS, ES>(
         section: &impl UnwindSection<R>,
-        unwind_info: &UnwindTableRow<R::Offset, S>,
+        unwind_info: &UnwindTableRow<R::Offset, UCS>,
         encoding: Encoding,
         regs: &mut Self::UnwindRegs,
         is_first_frame: bool,
@@ -68,7 +68,8 @@ pub trait DwarfUnwinding: Arch {
     where
         F: FnMut(u64) -> Result<u64, ()>,
         R: Reader,
-        S: UnwindContextStorage<R::Offset> + EvaluationStorage<R>;
+        UCS: UnwindContextStorage<R::Offset>,
+        ES: EvaluationStorage<R>;
 
     fn rule_if_uncovered_by_fde() -> Self::UnwindRule;
 }
@@ -82,29 +83,25 @@ pub struct DwarfUnwinder<
     'a,
     R: Reader,
     A: DwarfUnwinding + ?Sized,
-    S: UnwindContextStorage<R::Offset>,
+    UCS: UnwindContextStorage<R::Offset>,
 > {
     unwind_section_data: R,
     unwind_section_type: UnwindSectionType,
     eh_frame_hdr: Option<ParsedEhFrameHdr<EndianSlice<'a, R::Endian>>>,
-    unwind_context: &'a mut UnwindContext<R::Offset, S>,
+    unwind_context: &'a mut UnwindContext<R::Offset, UCS>,
     base_svma: u64,
     bases: BaseAddresses,
     _arch: PhantomData<A>,
 }
 
-impl<
-        'a,
-        R: Reader,
-        A: DwarfUnwinding,
-        S: UnwindContextStorage<R::Offset> + EvaluationStorage<R>,
-    > DwarfUnwinder<'a, R, A, S>
+impl<'a, R: Reader, A: DwarfUnwinding, UCS: UnwindContextStorage<R::Offset>>
+    DwarfUnwinder<'a, R, A, UCS>
 {
     pub fn new(
         unwind_section_data: R,
         unwind_section_type: UnwindSectionType,
         eh_frame_hdr_data: Option<&'a [u8]>,
-        unwind_context: &'a mut UnwindContext<R::Offset, S>,
+        unwind_context: &'a mut UnwindContext<R::Offset, UCS>,
         bases: BaseAddresses,
         base_svma: u64,
     ) -> Self {
@@ -138,7 +135,7 @@ impl<
         fde_offset.0.into_u64().try_into().ok()
     }
 
-    pub fn unwind_frame_with_fde<F>(
+    pub fn unwind_frame_with_fde<F, ES>(
         &mut self,
         regs: &mut A::UnwindRegs,
         is_first_frame: bool,
@@ -148,6 +145,7 @@ impl<
     ) -> Result<UnwindResult<A::UnwindRule>, DwarfUnwinderError>
     where
         F: FnMut(u64) -> Result<u64, ()>,
+        ES: EvaluationStorage<R>,
     {
         let lookup_svma = self.base_svma + rel_lookup_address as u64;
         let unwind_section_data = self.unwind_section_data.clone();
@@ -160,7 +158,7 @@ impl<
                     return Ok(UnwindResult::ExecRule(A::rule_if_uncovered_by_fde()));
                 }
                 let (unwind_info, encoding) = unwind_info?;
-                A::unwind_frame::<F, R, S>(
+                A::unwind_frame::<F, R, UCS, ES>(
                     &eh_frame,
                     unwind_info,
                     encoding,
@@ -177,7 +175,7 @@ impl<
                     return Ok(UnwindResult::ExecRule(A::rule_if_uncovered_by_fde()));
                 }
                 let (unwind_info, encoding) = unwind_info?;
-                A::unwind_frame::<F, R, S>(
+                A::unwind_frame::<F, R, UCS, ES>(
                     &debug_frame,
                     unwind_info,
                     encoding,
@@ -194,7 +192,7 @@ impl<
         unwind_section: &US,
         lookup_svma: u64,
         fde_offset: u32,
-    ) -> Result<(&UnwindTableRow<R::Offset, S>, Encoding), DwarfUnwinderError> {
+    ) -> Result<(&UnwindTableRow<R::Offset, UCS>, Encoding), DwarfUnwinderError> {
         let fde = unwind_section.fde_from_offset(
             &self.bases,
             US::Offset::from(R::Offset::from_u32(fde_offset)),
diff --git a/src/lib.rs b/src/lib.rs
index 82610c4..737235c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -116,7 +116,6 @@
 extern crate alloc;
 
 mod add_signed;
-mod arcdata;
 mod arch;
 mod cache;
 mod code_address;
@@ -148,7 +147,7 @@ pub use unwinder::{
 
 /// The unwinder cache for the native CPU architecture.
 #[cfg(target_arch = "aarch64")]
-pub type CacheNative<D, P> = aarch64::CacheAarch64<D, P>;
+pub type CacheNative<P> = aarch64::CacheAarch64<P>;
 /// The unwind registers type for the native CPU architecture.
 #[cfg(target_arch = "aarch64")]
 pub type UnwindRegsNative = aarch64::UnwindRegsAarch64;
@@ -158,7 +157,7 @@ pub type UnwinderNative<D, P> = aarch64::UnwinderAarch64<D, P>;
 
 /// The unwinder cache for the native CPU architecture.
 #[cfg(target_arch = "x86_64")]
-pub type CacheNative<D, P> = x86_64::CacheX86_64<D, P>;
+pub type CacheNative<P> = x86_64::CacheX86_64<P>;
 /// The unwind registers type for the native CPU architecture.
 #[cfg(target_arch = "x86_64")]
 pub type UnwindRegsNative = x86_64::UnwindRegsX86_64;
diff --git a/src/unwinder.rs b/src/unwinder.rs
index d16b63d..e6a2471 100644
--- a/src/unwinder.rs
+++ b/src/unwinder.rs
@@ -2,9 +2,8 @@ use alloc::string::String;
 use alloc::sync::Arc;
 use alloc::vec::Vec;
 use fallible_iterator::FallibleIterator;
-use gimli::{EndianReader, LittleEndian};
+use gimli::{EndianSlice, LittleEndian};
 
-use crate::arcdata::ArcData;
 use crate::arch::Arch;
 use crate::cache::{AllocationPolicy, Cache};
 use crate::dwarf::{DwarfCfiIndex, DwarfUnwinder, DwarfUnwinding, UnwindSectionType};
@@ -223,7 +222,7 @@ cfg_if::cfg_if! {
     }
 }
 
-pub struct UnwinderInternal<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> {
+pub struct UnwinderInternal<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy> {
     /// sorted by avma_range.start
     modules: Vec<Module<D>>,
     /// Incremented every time modules is changed.
@@ -232,7 +231,7 @@ pub struct UnwinderInternal<D: Deref<Target = [u8]>, A: Unwinding, P: Allocation
     _allocation_policy: PhantomData<P>,
 }
 
-impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> Default
+impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy> Default
     for UnwinderInternal<D, A, P>
 {
     fn default() -> Self {
@@ -240,7 +239,7 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> Default
     }
 }
 
-impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInternal<D, A, P> {
+impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy> UnwinderInternal<D, A, P> {
     pub fn new() -> Self {
         Self {
             modules: Vec::new(),
@@ -317,7 +316,7 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
         &self,
         address: FrameAddress,
         regs: &mut A::UnwindRegs,
-        cache: &mut Cache<D, A::UnwindRule, P>,
+        cache: &mut Cache<A::UnwindRule, P>,
         read_stack: &mut F,
         callback: G,
     ) -> Result<Option<u64>, Error>
@@ -328,7 +327,7 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
             FrameAddress,
             u32,
             &mut A::UnwindRegs,
-            &mut Cache<D, A::UnwindRule, P>,
+            &mut Cache<A::UnwindRule, P>,
             &mut F,
         ) -> Result<UnwindResult<A::UnwindRule>, UnwinderError>,
     {
@@ -375,7 +374,7 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
         &self,
         address: FrameAddress,
         regs: &mut A::UnwindRegs,
-        cache: &mut Cache<D, A::UnwindRule, P>,
+        cache: &mut Cache<A::UnwindRule, P>,
         read_stack: &mut F,
     ) -> Result<Option<u64>, Error>
     where
@@ -389,7 +388,7 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
         address: FrameAddress,
         rel_lookup_address: u32,
         regs: &mut A::UnwindRegs,
-        cache: &mut Cache<D, A::UnwindRule, P>,
+        cache: &mut Cache<A::UnwindRule, P>,
         read_stack: &mut F,
     ) -> Result<UnwindResult<A::UnwindRule>, UnwinderError>
     where
@@ -440,18 +439,19 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
                     CuiUnwindResult::ExecRule(rule) => UnwindResult::ExecRule(rule),
                     CuiUnwindResult::NeedDwarf(fde_offset) => {
                         let eh_frame_data = match eh_frame {
-                            Some(data) => ArcData(data.clone()),
+                            Some(data) => &***data,
                             None => return Err(UnwinderError::NoDwarfData),
                         };
-                        let mut dwarf_unwinder = DwarfUnwinder::<_, A, P::GimliStorage>::new(
-                            EndianReader::new(eh_frame_data, LittleEndian),
-                            UnwindSectionType::EhFrame,
-                            None,
-                            &mut cache.gimli_unwind_context,
-                            base_addresses.clone(),
-                            module.base_svma,
-                        );
-                        dwarf_unwinder.unwind_frame_with_fde(
+                        let mut dwarf_unwinder =
+                            DwarfUnwinder::<_, A, P::GimliUnwindContextStorage<_>>::new(
+                                EndianSlice::new(eh_frame_data, LittleEndian),
+                                UnwindSectionType::EhFrame,
+                                None,
+                                &mut cache.gimli_unwind_context,
+                                base_addresses.clone(),
+                                module.base_svma,
+                            );
+                        dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
                             regs,
                             is_first_frame,
                             rel_lookup_address,
@@ -467,19 +467,19 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
                 base_addresses,
             } => {
                 let eh_frame_hdr_data = &eh_frame_hdr[..];
-                let eh_frame_data = ArcData(eh_frame.clone());
-                let mut dwarf_unwinder = DwarfUnwinder::<_, A, P::GimliStorage>::new(
-                    EndianReader::new(eh_frame_data, LittleEndian),
-                    UnwindSectionType::EhFrame,
-                    Some(eh_frame_hdr_data),
-                    &mut cache.gimli_unwind_context,
-                    base_addresses.clone(),
-                    module.base_svma,
-                );
+                let mut dwarf_unwinder =
+                    DwarfUnwinder::<_, A, P::GimliUnwindContextStorage<_>>::new(
+                        EndianSlice::new(eh_frame, LittleEndian),
+                        UnwindSectionType::EhFrame,
+                        Some(eh_frame_hdr_data),
+                        &mut cache.gimli_unwind_context,
+                        base_addresses.clone(),
+                        module.base_svma,
+                    );
                 let fde_offset = dwarf_unwinder
                     .get_fde_offset_for_relative_address(rel_lookup_address)
                     .ok_or(UnwinderError::EhFrameHdrCouldNotFindAddress)?;
-                dwarf_unwinder.unwind_frame_with_fde(
+                dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
                     regs,
                     is_first_frame,
                     rel_lookup_address,
@@ -492,19 +492,19 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
                 eh_frame,
                 base_addresses,
             } => {
-                let eh_frame_data = ArcData(eh_frame.clone());
-                let mut dwarf_unwinder = DwarfUnwinder::<_, A, P::GimliStorage>::new(
-                    EndianReader::new(eh_frame_data, LittleEndian),
-                    UnwindSectionType::EhFrame,
-                    None,
-                    &mut cache.gimli_unwind_context,
-                    base_addresses.clone(),
-                    module.base_svma,
-                );
+                let mut dwarf_unwinder =
+                    DwarfUnwinder::<_, A, P::GimliUnwindContextStorage<_>>::new(
+                        EndianSlice::new(eh_frame, LittleEndian),
+                        UnwindSectionType::EhFrame,
+                        None,
+                        &mut cache.gimli_unwind_context,
+                        base_addresses.clone(),
+                        module.base_svma,
+                    );
                 let fde_offset = index
                     .fde_offset_for_relative_address(rel_lookup_address)
                     .ok_or(UnwinderError::DwarfCfiIndexCouldNotFindAddress)?;
-                dwarf_unwinder.unwind_frame_with_fde(
+                dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
                     regs,
                     is_first_frame,
                     rel_lookup_address,
@@ -517,19 +517,19 @@ impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy<D>> UnwinderInte
                 debug_frame,
                 base_addresses,
             } => {
-                let debug_frame_data = ArcData(debug_frame.clone());
-                let mut dwarf_unwinder = DwarfUnwinder::<_, A, P::GimliStorage>::new(
-                    EndianReader::new(debug_frame_data, LittleEndian),
-                    UnwindSectionType::DebugFrame,
-                    None,
-                    &mut cache.gimli_unwind_context,
-                    base_addresses.clone(),
-                    module.base_svma,
-                );
+                let mut dwarf_unwinder =
+                    DwarfUnwinder::<_, A, P::GimliUnwindContextStorage<_>>::new(
+                        EndianSlice::new(debug_frame, LittleEndian),
+                        UnwindSectionType::DebugFrame,
+                        None,
+                        &mut cache.gimli_unwind_context,
+                        base_addresses.clone(),
+                        module.base_svma,
+                    );
                 let fde_offset = index
                     .fde_offset_for_relative_address(rel_lookup_address)
                     .ok_or(UnwinderError::DwarfCfiIndexCouldNotFindAddress)?;
-                dwarf_unwinder.unwind_frame_with_fde(
+                dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
                     regs,
                     is_first_frame,
                     rel_lookup_address,
diff --git a/src/x86_64/cache.rs b/src/x86_64/cache.rs
index e499580..fa3abdf 100644
--- a/src/x86_64/cache.rs
+++ b/src/x86_64/cache.rs
@@ -1,18 +1,23 @@
-use core::ops::Deref;
-
 use super::unwind_rule::*;
 use crate::cache::*;
 
 /// The unwinder cache type for [`UnwinderX86_64`](super::UnwinderX86_64).
-pub struct CacheX86_64<D: Deref<Target = [u8]>, P: AllocationPolicy<D> = MayAllocateDuringUnwind>(
-    pub Cache<D, UnwindRuleX86_64, P>,
+pub struct CacheX86_64<P: AllocationPolicy = MayAllocateDuringUnwind>(
+    pub Cache<UnwindRuleX86_64, P>,
 );
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> CacheX86_64<D, P> {
+impl CacheX86_64<MayAllocateDuringUnwind> {
     /// Create a new cache.
     pub fn new() -> Self {
         Self(Cache::new())
     }
+}
+
+impl<P: AllocationPolicy> CacheX86_64<P> {
+    /// Create a new cache.
+    pub fn new_in() -> Self {
+        Self(Cache::new())
+    }
 
     /// Returns a snapshot of the cache usage statistics.
     pub fn stats(&self) -> CacheStats {
@@ -20,8 +25,8 @@ impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> CacheX86_64<D, P> {
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Default for CacheX86_64<D, P> {
+impl<P: AllocationPolicy> Default for CacheX86_64<P> {
     fn default() -> Self {
-        Self::new()
+        Self::new_in()
     }
 }
diff --git a/src/x86_64/dwarf.rs b/src/x86_64/dwarf.rs
index becc57c..12fd80a 100644
--- a/src/x86_64/dwarf.rs
+++ b/src/x86_64/dwarf.rs
@@ -22,9 +22,9 @@ impl DwarfUnwindRegs for UnwindRegsX86_64 {
 }
 
 impl DwarfUnwinding for ArchX86_64 {
-    fn unwind_frame<F, R, S>(
+    fn unwind_frame<F, R, UCS, ES>(
         section: &impl UnwindSection<R>,
-        unwind_info: &UnwindTableRow<R::Offset, S>,
+        unwind_info: &UnwindTableRow<R::Offset, UCS>,
         encoding: Encoding,
         regs: &mut Self::UnwindRegs,
         is_first_frame: bool,
@@ -33,7 +33,8 @@ impl DwarfUnwinding for ArchX86_64 {
     where
         F: FnMut(u64) -> Result<u64, ()>,
         R: Reader,
-        S: UnwindContextStorage<R::Offset> + EvaluationStorage<R>,
+        UCS: UnwindContextStorage<R::Offset>,
+        ES: EvaluationStorage<R>,
     {
         let cfa_rule = unwind_info.cfa();
         let bp_rule = unwind_info.register(X86_64::RBP);
@@ -47,18 +48,19 @@ impl DwarfUnwinding for ArchX86_64 {
             }
         }
 
-        let cfa = eval_cfa_rule::<R, _, S>(section, cfa_rule, encoding, regs)
+        let cfa = eval_cfa_rule::<R, _, ES>(section, cfa_rule, encoding, regs)
             .ok_or(DwarfUnwinderError::CouldNotRecoverCfa)?;
 
         let ip = regs.ip();
         let bp = regs.bp();
         let sp = regs.sp();
 
-        let new_bp =
-            eval_register_rule::<R, F, _, S>(section, bp_rule, cfa, encoding, bp, regs, read_stack)
-                .unwrap_or(bp);
+        let new_bp = eval_register_rule::<R, F, _, ES>(
+            section, bp_rule, cfa, encoding, bp, regs, read_stack,
+        )
+        .unwrap_or(bp);
 
-        let return_address = match eval_register_rule::<R, F, _, S>(
+        let return_address = match eval_register_rule::<R, F, _, ES>(
             section, ra_rule, cfa, encoding, ip, regs, read_stack,
         ) {
             Some(ra) => ra,
diff --git a/src/x86_64/unwinder.rs b/src/x86_64/unwinder.rs
index c54cb72..1619a62 100644
--- a/src/x86_64/unwinder.rs
+++ b/src/x86_64/unwinder.rs
@@ -15,26 +15,26 @@ use crate::FrameAddress;
 ///
 ///  - `D`: The type for unwind section data in the modules. See [`Module`].
 /// -  `P`: The [`AllocationPolicy`].
-pub struct UnwinderX86_64<D: Deref<Target = [u8]>, P: AllocationPolicy<D> = MayAllocateDuringUnwind>(
+pub struct UnwinderX86_64<D: Deref<Target = [u8]>, P: AllocationPolicy = MayAllocateDuringUnwind>(
     UnwinderInternal<D, ArchX86_64, P>,
 );
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Default for UnwinderX86_64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> Default for UnwinderX86_64<D, P> {
     fn default() -> Self {
         Self::new()
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> UnwinderX86_64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> UnwinderX86_64<D, P> {
     /// Create an unwinder for a process.
     pub fn new() -> Self {
         Self(UnwinderInternal::new())
     }
 }
 
-impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Unwinder for UnwinderX86_64<D, P> {
+impl<D: Deref<Target = [u8]>, P: AllocationPolicy> Unwinder for UnwinderX86_64<D, P> {
     type UnwindRegs = UnwindRegsX86_64;
-    type Cache = CacheX86_64<D, P>;
+    type Cache = CacheX86_64<P>;
     type Module = Module<D>;
 
     fn add_module(&mut self, module: Module<D>) {
@@ -53,7 +53,7 @@ impl<D: Deref<Target = [u8]>, P: AllocationPolicy<D>> Unwinder for UnwinderX86_6
         &self,
         address: FrameAddress,
         regs: &mut UnwindRegsX86_64,
-        cache: &mut CacheX86_64<D, P>,
+        cache: &mut CacheX86_64<P>,
         read_stack: &mut F,
     ) -> Result<Option<u64>, Error>
     where
diff --git a/tests/integration_tests/linux.rs b/tests/integration_tests/linux.rs
index 680ac7e..c4b691f 100644
--- a/tests/integration_tests/linux.rs
+++ b/tests/integration_tests/linux.rs
@@ -9,7 +9,7 @@ use super::common;
 
 #[test]
 fn test_plt_cfa_expr() {
-    let mut cache = CacheX86_64::<_>::new();
+    let mut cache = CacheX86_64::new();
     let mut unwinder = UnwinderX86_64::new();
     common::add_object(
         &mut unwinder,