diff --git a/src/read/cfi.rs b/src/read/cfi.rs index 5aa88468..fa8de805 100644 --- a/src/read/cfi.rs +++ b/src/read/cfi.rs @@ -459,20 +459,21 @@ impl<'a, R: Reader + 'a> EhHdrTable<'a, R> { /// /// You must provide a function to get the associated CIE. See /// `PartialFrameDescriptionEntry::parse` for more information. - pub fn unwind_info_for_address<'ctx, F, A: UnwindContextStorage>( + pub fn unwind_info_for_address<'ctx, F, S>( &self, frame: &EhFrame, bases: &BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, address: u64, get_cie: F, - ) -> Result<&'ctx UnwindTableRow> + ) -> Result<&'ctx UnwindTableRow> where F: FnMut( &EhFrame, &BaseAddresses, EhFrameOffset, ) -> Result>, + S: UnwindContextStorage, { let fde = self.fde_for_address(frame, bases, address, get_cie)?; fde.unwind_info_for_address(frame, bases, ctx, address) @@ -778,15 +779,16 @@ pub trait UnwindSection: Clone + Debug + _UnwindSectionPrivate { /// # } /// ``` #[inline] - fn unwind_info_for_address<'ctx, F, A: UnwindContextStorage>( + fn unwind_info_for_address<'ctx, F, S>( &self, bases: &BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, address: u64, get_cie: F, - ) -> Result<&'ctx UnwindTableRow> + ) -> Result<&'ctx UnwindTableRow> where F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result>, + S: UnwindContextStorage, { let fde = self.fde_for_address(bases, address, get_cie)?; fde.unwind_info_for_address(self, bases, ctx, address) @@ -1734,12 +1736,16 @@ impl FrameDescriptionEntry { /// Return the table of unwind information for this FDE. #[inline] - pub fn rows<'a, 'ctx, Section: UnwindSection, A: UnwindContextStorage>( + pub fn rows<'a, 'ctx, Section, S>( &self, section: &'a Section, bases: &'a BaseAddresses, - ctx: &'ctx mut UnwindContext, - ) -> Result> { + ctx: &'ctx mut UnwindContext, + ) -> Result> + where + Section: UnwindSection, + S: UnwindContextStorage, + { UnwindTable::new(section, bases, ctx, self) } @@ -1749,17 +1755,17 @@ impl FrameDescriptionEntry { /// context in the form `Ok((unwind_info, context))`. If not found, /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or /// CFI evaluation fails, the error is returned. - pub fn unwind_info_for_address< - 'ctx, - Section: UnwindSection, - A: UnwindContextStorage, - >( + pub fn unwind_info_for_address<'ctx, Section, S>( &self, section: &Section, bases: &BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, address: u64, - ) -> Result<&'ctx UnwindTableRow> { + ) -> Result<&'ctx UnwindTableRow> + where + Section: UnwindSection, + S: UnwindContextStorage, + { let mut table = self.rows(section, bases, ctx)?; while let Some(row) = table.next_row()? { if row.contains(address) { @@ -1970,11 +1976,15 @@ impl UnwindContextStorage for StoreOnHeap { /// # } /// ``` #[derive(Clone, PartialEq, Eq)] -pub struct UnwindContext = StoreOnHeap> { +pub struct UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ // Stack of rows. The last row is the row currently being built by the // program. There is always at least one row. The vast majority of CFI // programs will only ever have one row on the stack. - stack: ArrayVec, + stack: ArrayVec, // If we are evaluating an FDE's instructions, then `is_initialized` will be // `true`. If `initial_rule` is `Some`, then the initial register rules are either @@ -1989,7 +1999,11 @@ pub struct UnwindContext = StoreOnHe is_initialized: bool, } -impl> Debug for UnwindContext { +impl Debug for UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("UnwindContext") .field("stack", &self.stack) @@ -1999,7 +2013,11 @@ impl> Debug for UnwindContext } } -impl> Default for UnwindContext { +impl Default for UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn default() -> Self { Self::new_in() } @@ -2017,7 +2035,11 @@ impl UnwindContext { /// /// These methods are guaranteed not to allocate, acquire locks, or perform any /// other signal-unsafe operations, if an non-allocating storage is used. -impl> UnwindContext { +impl UnwindContext +where + T: ReaderOffset, + S: UnwindContextStorage, +{ /// Construct a new call frame unwinding context. pub fn new_in() -> Self { let mut ctx = UnwindContext { @@ -2058,11 +2080,11 @@ impl> UnwindContext { self.is_initialized = false; } - fn row(&self) -> &UnwindTableRow { + fn row(&self) -> &UnwindTableRow { self.stack.last().unwrap() } - fn row_mut(&mut self) -> &mut UnwindTableRow { + fn row_mut(&mut self) -> &mut UnwindTableRow { self.stack.last_mut().unwrap() } @@ -2196,7 +2218,11 @@ impl> UnwindContext { /// > recording just the differences starting at the beginning address of each /// > subroutine in the program. #[derive(Debug)] -pub struct UnwindTable<'a, 'ctx, R: Reader, A: UnwindContextStorage = StoreOnHeap> { +pub struct UnwindTable<'a, 'ctx, R, S = StoreOnHeap> +where + R: Reader, + S: UnwindContextStorage, +{ code_alignment_factor: Wrapping, data_alignment_factor: Wrapping, next_start_address: u64, @@ -2204,20 +2230,24 @@ pub struct UnwindTable<'a, 'ctx, R: Reader, A: UnwindContextStorage = returned_last_row: bool, current_row_valid: bool, instructions: CallFrameInstructionIter<'a, R>, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, } /// # Signal Safe Methods /// /// These methods are guaranteed not to allocate, acquire locks, or perform any /// other signal-unsafe operations. -impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'ctx, R, A> { +impl<'a, 'ctx, R, S> UnwindTable<'a, 'ctx, R, S> +where + R: Reader, + S: UnwindContextStorage, +{ /// Construct a new `UnwindTable` for the given /// `FrameDescriptionEntry`'s CFI unwinding program. pub fn new>( section: &'a Section, bases: &'a BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, fde: &FrameDescriptionEntry, ) -> Result { ctx.initialize(section, bases, fde.cie())?; @@ -2227,7 +2257,7 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'c fn new_for_fde>( section: &'a Section, bases: &'a BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, fde: &FrameDescriptionEntry, ) -> Self { assert!(ctx.stack.len() >= 1); @@ -2246,7 +2276,7 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'c fn new_for_cie>( section: &'a Section, bases: &'a BaseAddresses, - ctx: &'ctx mut UnwindContext, + ctx: &'ctx mut UnwindContext, cie: &CommonInformationEntry, ) -> Self { assert!(ctx.stack.len() >= 1); @@ -2267,7 +2297,7 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'c /// /// Unfortunately, this cannot be used with `FallibleIterator` because of /// the restricted lifetime of the yielded item. - pub fn next_row(&mut self) -> Result>> { + pub fn next_row(&mut self) -> Result>> { assert!(self.ctx.stack.len() >= 1); self.ctx.set_start_address(self.next_start_address); self.current_row_valid = false; @@ -2300,7 +2330,7 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'c } /// Returns the current row with the lifetime of the context. - pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow> { + pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow> { if self.current_row_valid { Some(self.ctx.row()) } else { @@ -2519,11 +2549,19 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage> UnwindTable<'a, 'c // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-aarch64/dwarf-config.h#L32 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-arm/dwarf-config.h#L31 // - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-mips/dwarf-config.h#L31 -struct RegisterRuleMap = StoreOnHeap> { +struct RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ rules: ArrayVec, } -impl> Debug for RegisterRuleMap { +impl Debug for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RegisterRuleMap") .field("rules", &self.rules) @@ -2531,7 +2569,11 @@ impl> Debug for RegisterRuleMap> Clone for RegisterRuleMap { +impl Clone for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn clone(&self) -> Self { Self { rules: self.rules.clone(), @@ -2539,7 +2581,11 @@ impl> Clone for RegisterRuleMap> Default for RegisterRuleMap { +impl Default for RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn default() -> Self { RegisterRuleMap { rules: Default::default(), @@ -2551,7 +2597,11 @@ impl> Default for RegisterRuleMap> RegisterRuleMap { +impl RegisterRuleMap +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn is_default(&self) -> bool { self.rules.is_empty() } @@ -2599,10 +2649,10 @@ impl> RegisterRuleMap { } } -impl<'a, R, S: UnwindContextStorage> FromIterator<&'a (Register, RegisterRule)> - for RegisterRuleMap +impl<'a, R, S> FromIterator<&'a (Register, RegisterRule)> for RegisterRuleMap where R: 'a + ReaderOffset, + S: UnwindContextStorage, { fn from_iter(iter: T) -> Self where @@ -2620,9 +2670,10 @@ where } } -impl> PartialEq for RegisterRuleMap +impl PartialEq for RegisterRuleMap where T: ReaderOffset + PartialEq, + S: UnwindContextStorage, { fn eq(&self, rhs: &Self) -> bool { for &(reg, ref rule) in &*self.rules { @@ -2643,7 +2694,12 @@ where } } -impl> Eq for RegisterRuleMap where T: ReaderOffset + Eq {} +impl Eq for RegisterRuleMap +where + T: ReaderOffset + Eq, + S: UnwindContextStorage, +{ +} /// An unordered iterator for register rules. #[derive(Debug, Clone)] @@ -2662,7 +2718,11 @@ impl<'iter, T: ReaderOffset> Iterator for RegisterRuleIter<'iter, T> { /// A row in the virtual unwind table that describes how to find the values of /// the registers in the *previous* frame for a range of PC addresses. #[derive(PartialEq, Eq)] -pub struct UnwindTableRow = StoreOnHeap> { +pub struct UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ start_address: u64, end_address: u64, saved_args_size: u64, @@ -2670,7 +2730,11 @@ pub struct UnwindTableRow = StoreOnH registers: RegisterRuleMap, } -impl> Debug for UnwindTableRow { +impl Debug for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("UnwindTableRow") .field("start_address", &self.start_address) @@ -2682,7 +2746,11 @@ impl> Debug for UnwindTableRow } } -impl> Clone for UnwindTableRow { +impl Clone for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn clone(&self) -> Self { Self { start_address: self.start_address, @@ -2694,7 +2762,11 @@ impl> Clone for UnwindTableRow } } -impl> Default for UnwindTableRow { +impl Default for UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn default() -> Self { UnwindTableRow { start_address: 0, @@ -2706,7 +2778,11 @@ impl> Default for UnwindTableRow> UnwindTableRow { +impl UnwindTableRow +where + T: ReaderOffset, + S: UnwindContextStorage, +{ fn is_default(&self) -> bool { self.start_address == 0 && self.end_address == 0 @@ -3472,10 +3548,11 @@ impl UnwindExpression { /// /// The offset and length were previously validated when the /// `UnwindExpression` was created, so this should not fail. - pub fn get, S: UnwindSection>( - &self, - section: &S, - ) -> Result> { + pub fn get(&self, section: &S) -> Result> + where + R: Reader, + S: UnwindSection, + { let input = &mut section.section().clone(); input.skip(self.offset)?; let data = input.split(self.length)?;