Skip to content

Commit

Permalink
Add read-core feature gate (#596)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbdd0121 authored Oct 13, 2021
1 parent 80010ee commit 7a3aeef
Show file tree
Hide file tree
Showing 13 changed files with 110 additions and 34 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ jobs:
steps:
- uses: actions/checkout@v2
- run: cargo test --no-default-features
# Ensure gimli can be built without alloc.
- run: cargo check --no-default-features --features read-core
- run: cargo test --no-default-features --features read
- run: cargo test --no-default-features --features read,fallible-iterator
- run: cargo test --no-default-features --features read,std
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ test-assembler = "0.1.3"
typed-arena = "2"

[features]
read = []
endian-reader = ["stable_deref_trait"]
read-core = []
read = ["read-core"]
endian-reader = ["read", "stable_deref_trait"]
write = ["indexmap"]
std = ["fallible-iterator/std", "stable_deref_trait/std"]
default = ["read", "write", "std", "fallible-iterator", "endian-reader"]
Expand Down
11 changes: 8 additions & 3 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,14 @@ macro_rules! dw {
if let Some(s) = self.static_string() {
f.pad(s)
} else {
f.pad(&format!("Unknown {}: {}",
stringify!($struct_name),
self.0))
#[cfg(feature = "read")]
{
f.pad(&format!("Unknown {}: {}", stringify!($struct_name), self.0))
}
#[cfg(not(feature = "read"))]
{
write!(f, "Unknown {}: {}", stringify!($struct_name), self.0)
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/leb128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
//! ```
const CONTINUATION_BIT: u8 = 1 << 7;
#[cfg(feature = "read")]
#[cfg(feature = "read-core")]
const SIGN_BIT: u8 = 1 << 6;

#[inline]
Expand All @@ -62,7 +62,7 @@ fn low_bits_of_u64(val: u64) -> u8 {

/// A module for reading signed and unsigned integers that have been LEB128
/// encoded.
#[cfg(feature = "read")]
#[cfg(feature = "read-core")]
pub mod read {
use super::{low_bits_of_byte, CONTINUATION_BIT, SIGN_BIT};
use crate::read::{Error, Reader, Result};
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#![no_std]

#[allow(unused_imports)]
#[cfg(any(feature = "read", feature = "write"))]
#[macro_use]
extern crate alloc;

Expand All @@ -62,10 +63,10 @@ pub use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian, Run

pub mod leb128;

#[cfg(feature = "read")]
#[cfg(feature = "read-core")]
pub mod read;
// For backwards compat.
#[cfg(feature = "read")]
#[cfg(feature = "read-core")]
pub use crate::read::*;

#[cfg(feature = "write")]
Expand Down
13 changes: 11 additions & 2 deletions src/read/cfi.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(feature = "read")]
use alloc::vec::Vec;

use core::cmp::{Ord, Ordering};
Expand Down Expand Up @@ -1738,8 +1739,13 @@ impl<R: Reader> FrameDescriptionEntry<R> {

/// Specification of what storage should be used for [`UnwindContext`].
///
/// Normally you would only need to use [`StoreOnHeap`], which places the stack
/// on the heap using [`Vec`]. This is the default storage type parameter for [`UnwindContext`].
#[cfg_attr(
feature = "read",
doc = "
Normally you would only need to use [`StoreOnHeap`], which places the stack
on the heap using [`Vec`]. This is the default storage type parameter for [`UnwindContext`].
"
)]
///
/// If you need to avoid [`UnwindContext`] from allocating memory, e.g. for signal safety,
/// you can provide you own storage specification:
Expand Down Expand Up @@ -1780,8 +1786,10 @@ pub trait UnwindContextStorage<R: Reader>: Sized {
type Stack: ArrayLike<Item = UnwindTableRow<R, Self>>;
}

#[cfg(feature = "read")]
const MAX_RULES: usize = 192;

#[cfg(feature = "read")]
impl<R: Reader> UnwindContextStorage<R> for StoreOnHeap {
type Rules = [(Register, RegisterRule<R>); MAX_RULES];
type Stack = Vec<UnwindTableRow<R, Self>>;
Expand Down Expand Up @@ -1849,6 +1857,7 @@ impl<R: Reader, A: UnwindContextStorage<R>> Default for UnwindContext<R, A> {
}
}

#[cfg(feature = "read")]
impl<R: Reader> UnwindContext<R> {
/// Construct a new call frame unwinding context.
pub fn new() -> Self {
Expand Down
11 changes: 11 additions & 0 deletions src/read/endian_slice.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Working with byte slices that have an associated endianity.
#[cfg(feature = "read")]
use alloc::borrow::Cow;
#[cfg(feature = "read")]
use alloc::string::String;
use core::ops::{Deref, Index, Range, RangeFrom, RangeTo};
use core::str;
Expand Down Expand Up @@ -82,6 +84,7 @@ where

/// Converts the slice to a string, including invalid characters,
/// using `String::from_utf8_lossy`.
#[cfg(feature = "read")]
#[inline]
pub fn to_string_lossy(&self) -> Cow<'input, str> {
String::from_utf8_lossy(self.slice)
Expand Down Expand Up @@ -284,11 +287,18 @@ where
Ok(EndianSlice::new(slice, self.endian))
}

#[cfg(not(feature = "read"))]
fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
super::reader::seal_if_no_alloc::Sealed
}

#[cfg(feature = "read")]
#[inline]
fn to_slice(&self) -> Result<Cow<[u8]>> {
Ok(self.slice.into())
}

#[cfg(feature = "read")]
#[inline]
fn to_string(&self) -> Result<Cow<str>> {
match str::from_utf8(self.slice) {
Expand All @@ -297,6 +307,7 @@ where
}
}

#[cfg(feature = "read")]
#[inline]
fn to_string_lossy(&self) -> Result<Cow<str>> {
Ok(String::from_utf8_lossy(self.slice))
Expand Down
17 changes: 17 additions & 0 deletions src/read/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ pub use self::addr::*;
mod cfi;
pub use self::cfi::*;

#[cfg(feature = "read")]
mod dwarf;
#[cfg(feature = "read")]
pub use self::dwarf::*;

mod endian_slice;
Expand All @@ -200,7 +202,9 @@ pub use self::endian_reader::*;
mod reader;
pub use self::reader::*;

#[cfg(feature = "read")]
mod abbrev;
#[cfg(feature = "read")]
pub use self::abbrev::*;

mod aranges;
Expand All @@ -209,23 +213,30 @@ pub use self::aranges::*;
mod index;
pub use self::index::*;

#[cfg(feature = "read")]
mod line;
#[cfg(feature = "read")]
pub use self::line::*;

mod lists;

mod loclists;
pub use self::loclists::*;

#[cfg(feature = "read")]
mod lookup;

mod op;
pub use self::op::*;

#[cfg(feature = "read")]
mod pubnames;
#[cfg(feature = "read")]
pub use self::pubnames::*;

#[cfg(feature = "read")]
mod pubtypes;
#[cfg(feature = "read")]
pub use self::pubtypes::*;

mod rnglists;
Expand All @@ -234,7 +245,13 @@ pub use self::rnglists::*;
mod str;
pub use self::str::*;

/// An offset into the current compilation or type unit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct UnitOffset<T = usize>(pub T);

#[cfg(feature = "read")]
mod unit;
#[cfg(feature = "read")]
pub use self::unit::*;

mod value;
Expand Down
41 changes: 24 additions & 17 deletions src/read/op.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Functions for parsing and evaluating DWARF expressions.
#[cfg(feature = "read")]
use alloc::vec::Vec;
use core::mem;

Expand Down Expand Up @@ -938,6 +939,7 @@ impl<R: Reader> Expression<R> {
/// let mut eval = expression.evaluation(unit.encoding());
/// let mut result = eval.evaluate().unwrap();
/// ```
#[cfg(feature = "read")]
#[inline]
pub fn evaluation(self, encoding: Encoding) -> Evaluation<R> {
Evaluation::new(self.0, encoding)
Expand Down Expand Up @@ -982,8 +984,13 @@ impl<R: Reader> OperationIter<R> {

/// Specification of what storage should be used for [`Evaluation`].
///
/// Normally you would only need to use [`StoreOnHeap`], which places the stacks and the results
/// on the heap using [`Vec`]. This is the default storage type parameter for [`Evaluation`].
#[cfg_attr(
feature = "read",
doc = "
Normally you would only need to use [`StoreOnHeap`], which places the stacks and the results
on the heap using [`Vec`]. This is the default storage type parameter for [`Evaluation`].
"
)]
///
/// If you need to avoid [`Evaluation`] from allocating memory, e.g. for signal safety,
/// you can provide you own storage specification:
Expand Down Expand Up @@ -1030,6 +1037,7 @@ pub trait EvaluationStorage<R: Reader> {
type Result: ArrayLike<Item = Piece<R>>;
}

#[cfg(feature = "read")]
impl<R: Reader> EvaluationStorage<R> for StoreOnHeap {
type Stack = Vec<Value>;
type ExpressionStack = Vec<(R, R)>;
Expand Down Expand Up @@ -1108,6 +1116,7 @@ pub struct Evaluation<R: Reader, S: EvaluationStorage<R> = StoreOnHeap> {
result: ArrayVec<S::Result>,
}

#[cfg(feature = "read")]
impl<R: Reader> Evaluation<R> {
/// Create a new DWARF expression evaluator.
///
Expand All @@ -1116,6 +1125,19 @@ impl<R: Reader> Evaluation<R> {
pub fn new(bytecode: R, encoding: Encoding) -> Self {
Self::new_in(bytecode, encoding)
}

/// Get the result of this `Evaluation`.
///
/// # Panics
/// 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(),
_ => {
panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
}
}
}
}

impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
Expand Down Expand Up @@ -1956,21 +1978,6 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
}
}

impl<R: Reader> Evaluation<R, StoreOnHeap> {
/// Get the result of this `Evaluation`.
///
/// # Panics
/// 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(),
_ => {
panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
}
}
}
}

#[cfg(test)]
// Tests require leb128::write.
#[cfg(feature = "write")]
Expand Down
19 changes: 19 additions & 0 deletions src/read/reader.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(feature = "read")]
use alloc::borrow::Cow;
use core::convert::TryInto;
use core::fmt::Debug;
Expand Down Expand Up @@ -186,6 +187,12 @@ impl ReaderOffset for usize {
}
}

#[cfg(not(feature = "read"))]
pub(crate) mod seal_if_no_alloc {
#[derive(Debug)]
pub struct Sealed;
}

/// A trait for reading the data from a DWARF section.
///
/// All read operations advance the section offset of the reader
Expand Down Expand Up @@ -251,12 +258,22 @@ pub trait Reader: Debug + Clone {
/// `len` bytes, and `self` is advanced so that it reads the remainder.
fn split(&mut self, len: Self::Offset) -> Result<Self>;

/// This trait cannot be implemented if "read" feature is not enabled.
///
/// `Reader` trait has a few methods that depend on `alloc` crate.
/// Disallowing `Reader` trait implementation prevents a crate that only depends on
/// "read-core" from being broken if another crate depending on `gimli` enables
/// "read" feature.
#[cfg(not(feature = "read"))]
fn cannot_implement() -> seal_if_no_alloc::Sealed;

/// Return all remaining data as a clone-on-write slice.
///
/// The slice will be borrowed where possible, but some readers may
/// always return an owned vector.
///
/// Does not advance the reader.
#[cfg(feature = "read")]
fn to_slice(&self) -> Result<Cow<[u8]>>;

/// Convert all remaining data to a clone-on-write string.
Expand All @@ -267,6 +284,7 @@ pub trait Reader: Debug + Clone {
/// Does not advance the reader.
///
/// Returns an error if the data contains invalid characters.
#[cfg(feature = "read")]
fn to_string(&self) -> Result<Cow<str>>;

/// Convert all remaining data to a clone-on-write string, including invalid characters.
Expand All @@ -275,6 +293,7 @@ pub trait Reader: Debug + Clone {
/// always return an owned string.
///
/// Does not advance the reader.
#[cfg(feature = "read")]
fn to_string_lossy(&self) -> Result<Cow<str>>;

/// Read exactly `buf.len()` bytes into `buf`.
Expand Down
6 changes: 1 addition & 5 deletions src/read/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::constants;
use crate::endianity::Endianity;
use crate::read::{
Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
Expression, Reader, ReaderOffset, Result, Section,
Expression, Reader, ReaderOffset, Result, Section, UnitOffset,
};

impl<T: ReaderOffset> DebugTypesOffset<T> {
Expand Down Expand Up @@ -52,10 +52,6 @@ impl<T: ReaderOffset> DebugInfoOffset<T> {
}
}

/// An offset into the current compilation or type unit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct UnitOffset<T = usize>(pub T);

impl<T: ReaderOffset> UnitOffset<T> {
/// Convert an offset to be relative to the start of the .debug_info section,
/// instead of relative to the start of the given unit. Returns None if the
Expand Down
Loading

0 comments on commit 7a3aeef

Please sign in to comment.