Skip to content

Commit

Permalink
Avoid use of unsafe for Vec storage
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Nov 3, 2021
1 parent fdd7ee4 commit e468488
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 191 deletions.
61 changes: 53 additions & 8 deletions src/read/cfi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use core::iter::FromIterator;
use core::mem;
use core::num::Wrapping;

use super::util::{ArrayLike, ArrayVec};
use super::util::{ArrayLike, ArrayLikeSealed, ArrayLikeStorage};
use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId};
use crate::constants::{self, DwEhPe};
use crate::endianity::Endianity;
Expand Down Expand Up @@ -1821,12 +1821,12 @@ impl<R: Reader> UnwindContextStorage<R> for StoreOnHeap {
/// # unreachable!()
/// # }
/// ```
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone)]
pub struct UnwindContext<R: Reader, A: UnwindContextStorage<R> = StoreOnHeap> {
// 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<A::Stack>,
stack: <A::Stack as ArrayLikeSealed>::Storage,

// 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
Expand All @@ -1841,7 +1841,10 @@ pub struct UnwindContext<R: Reader, A: UnwindContextStorage<R> = StoreOnHeap> {
is_initialized: bool,
}

impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindContext<R, S> {
impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindContext<R, S>
where
<S::Stack as ArrayLikeSealed>::Storage: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnwindContext")
.field("stack", &self.stack)
Expand All @@ -1851,6 +1854,25 @@ impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindContext<R, S> {
}
}

impl<R: Reader, S: UnwindContextStorage<R>> PartialEq for UnwindContext<R, S>
where
<S::Stack as ArrayLikeSealed>::Storage: PartialEq,
R: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.stack == other.stack
&& self.initial_rule == other.initial_rule
&& self.is_initialized == other.is_initialized
}
}

impl<R: Reader, S: UnwindContextStorage<R>> Eq for UnwindContext<R, S>
where
<S::Stack as ArrayLikeSealed>::Storage: Eq,
R: Eq,
{
}

impl<R: Reader, A: UnwindContextStorage<R>> Default for UnwindContext<R, A> {
fn default() -> Self {
Self::new_in()
Expand Down Expand Up @@ -2044,7 +2066,6 @@ impl<R: Reader, A: UnwindContextStorage<R>> UnwindContext<R, A> {
/// > the ones above them. The whole table can be represented quite compactly by
/// > 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<R> = StoreOnHeap> {
code_alignment_factor: Wrapping<u64>,
data_alignment_factor: Wrapping<i64>,
Expand All @@ -2056,6 +2077,24 @@ pub struct UnwindTable<'a, 'ctx, R: Reader, A: UnwindContextStorage<R> = StoreOn
ctx: &'ctx mut UnwindContext<R, A>,
}

impl<'a, 'ctx, R: Reader, S: UnwindContextStorage<R>> Debug for UnwindTable<'a, 'ctx, R, S>
where
<S::Stack as ArrayLikeSealed>::Storage: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnwindTable")
.field("code_alignment_factor", &self.code_alignment_factor)
.field("data_alignment_factor", &self.data_alignment_factor)
.field("next_start_address", &self.next_start_address)
.field("last_end_address", &self.last_end_address)
.field("returned_last_row", &self.returned_last_row)
.field("current_row_valid", &self.current_row_valid)
.field("instructions", &self.instructions)
.field("ctx", &self.ctx)
.finish()
}
}

/// # Signal Safe Methods
///
/// These methods are guaranteed not to allocate, acquire locks, or perform any
Expand Down Expand Up @@ -2357,10 +2396,13 @@ impl<'a, 'ctx, R: Reader, A: UnwindContextStorage<R>> UnwindTable<'a, 'ctx, R, A
// - 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<R: Reader, S: UnwindContextStorage<R> = StoreOnHeap> {
rules: ArrayVec<S::Rules>,
rules: <S::Rules as ArrayLikeSealed>::Storage,
}

impl<R: Reader, S: UnwindContextStorage<R>> Debug for RegisterRuleMap<R, S> {
impl<R: Reader, S: UnwindContextStorage<R>> Debug for RegisterRuleMap<R, S>
where
<S::Rules as ArrayLikeSealed>::Storage: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("RegisterRuleMap")
.field("rules", &self.rules)
Expand Down Expand Up @@ -2507,7 +2549,10 @@ pub struct UnwindTableRow<R: Reader, S: UnwindContextStorage<R> = StoreOnHeap> {
registers: RegisterRuleMap<R, S>,
}

impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindTableRow<R, S> {
impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindTableRow<R, S>
where
<S::Rules as ArrayLikeSealed>::Storage: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnwindTableRow")
.field("start_address", &self.start_address)
Expand Down
39 changes: 31 additions & 8 deletions src/read/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
#[cfg(feature = "read")]
use alloc::vec::Vec;
use core::fmt;
use core::mem;

use super::util::{ArrayLike, ArrayVec};
use super::util::{ArrayLike, ArrayLikeSealed, ArrayLikeStorage};
use crate::common::{DebugAddrIndex, DebugInfoOffset, Encoding, Register};
use crate::constants;
use crate::read::{Error, Reader, ReaderOffset, Result, StoreOnHeap, UnitOffset, Value, ValueType};
Expand Down Expand Up @@ -1089,7 +1090,6 @@ impl<R: Reader> EvaluationStorage<R> for StoreOnHeap {
/// let result = eval.result();
/// println!("{:?}", result);
/// ```
#[derive(Debug)]
pub struct Evaluation<R: Reader, S: EvaluationStorage<R> = StoreOnHeap> {
bytecode: R,
encoding: Encoding,
Expand All @@ -1104,20 +1104,43 @@ pub struct Evaluation<R: Reader, S: EvaluationStorage<R> = StoreOnHeap> {
addr_mask: u64,

// The stack.
stack: ArrayVec<S::Stack>,
stack: <S::Stack as ArrayLikeSealed>::Storage,

// The next operation to decode and evaluate.
pc: R,

// If we see a DW_OP_call* operation, the previous PC and bytecode
// is stored here while evaluating the subroutine.
expression_stack: ArrayVec<S::ExpressionStack>,
expression_stack: <S::ExpressionStack as ArrayLikeSealed>::Storage,

result: <S::Result as ArrayLikeSealed>::Storage,
}

result: ArrayVec<S::Result>,
impl<R: Reader, S: EvaluationStorage<R>> fmt::Debug for Evaluation<R, S>
where
<S::Stack as ArrayLikeSealed>::Storage: fmt::Debug,
<S::ExpressionStack as ArrayLikeSealed>::Storage: fmt::Debug,
<S::Result as ArrayLikeSealed>::Storage: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Evaluation")
.field("bytecode", &self.bytecode)
.field("encoding", &self.encoding)
.field("object_address", &self.object_address)
.field("max_iterations", &self.max_iterations)
.field("iteration", &self.iteration)
.field("state", &self.state)
.field("addr_mask", &self.addr_mask)
.field("stack", &self.stack)
.field("pc", &self.pc)
.field("expression_stack", &self.expression_stack)
.field("result", &self.result)
.finish()
}
}

#[cfg(feature = "read")]
impl<R: Reader> Evaluation<R> {
impl<R: Reader> Evaluation<R, StoreOnHeap> {
/// Create a new DWARF expression evaluator.
///
/// The new evaluator is created without an initial value, without
Expand All @@ -1132,7 +1155,7 @@ impl<R: Reader> Evaluation<R> {
/// Panics if this `Evaluation` has not been driven to completion.
pub fn result(self) -> Vec<Piece<R>> {
match self.state {
EvaluationState::Complete => self.result.into_vec(),
EvaluationState::Complete => self.result,
_ => {
panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
}
Expand Down Expand Up @@ -1258,7 +1281,7 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
if index >= len {
return Err(Error::NotEnoughStackItems);
}
let value = self.stack[len - index - 1];
let value = *self.stack.get(len - index - 1).unwrap();
self.push(value)?;
}
Operation::Swap => {
Expand Down
Loading

0 comments on commit e468488

Please sign in to comment.