aboutsummaryrefslogtreecommitdiff
path: root/vendor/gimli/src/read/aranges.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gimli/src/read/aranges.rs')
-rw-r--r--vendor/gimli/src/read/aranges.rs660
1 files changed, 0 insertions, 660 deletions
diff --git a/vendor/gimli/src/read/aranges.rs b/vendor/gimli/src/read/aranges.rs
deleted file mode 100644
index 83159b6..0000000
--- a/vendor/gimli/src/read/aranges.rs
+++ /dev/null
@@ -1,660 +0,0 @@
-use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
-use crate::endianity::Endianity;
-use crate::read::{EndianSlice, Error, Range, Reader, ReaderOffset, Result, Section};
-
-/// The `DebugAranges` struct represents the DWARF address range information
-/// found in the `.debug_aranges` section.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct DebugAranges<R> {
- section: R,
-}
-
-impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
-where
- Endian: Endianity,
-{
- /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
- /// section.
- ///
- /// It is the caller's responsibility to read the `.debug_aranges` section and
- /// present it as a `&[u8]` slice. That means using some ELF loader on
- /// Linux, a Mach-O loader on macOS, etc.
- ///
- /// ```
- /// use gimli::{DebugAranges, LittleEndian};
- ///
- /// # let buf = [];
- /// # let read_debug_aranges_section = || &buf;
- /// let debug_aranges =
- /// DebugAranges::new(read_debug_aranges_section(), LittleEndian);
- /// ```
- pub fn new(section: &'input [u8], endian: Endian) -> Self {
- DebugAranges {
- section: EndianSlice::new(section, endian),
- }
- }
-}
-
-impl<R: Reader> DebugAranges<R> {
- /// Iterate the sets of entries in the `.debug_aranges` section.
- ///
- /// Each set of entries belongs to a single unit.
- pub fn headers(&self) -> ArangeHeaderIter<R> {
- ArangeHeaderIter {
- input: self.section.clone(),
- offset: DebugArangesOffset(R::Offset::from_u8(0)),
- }
- }
-
- /// Get the header at the given offset.
- pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
- let mut input = self.section.clone();
- input.skip(offset.0)?;
- ArangeHeader::parse(&mut input, offset)
- }
-}
-
-impl<T> DebugAranges<T> {
- /// Create a `DebugAranges` section that references the data in `self`.
- ///
- /// This is useful when `R` implements `Reader` but `T` does not.
- ///
- /// ## Example Usage
- ///
- /// ```rust,no_run
- /// # let load_section = || unimplemented!();
- /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
- /// let owned_section: gimli::DebugAranges<Vec<u8>> = load_section();
- /// // Create a reference to the DWARF section.
- /// let section = owned_section.borrow(|section| {
- /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
- /// });
- /// ```
- pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
- where
- F: FnMut(&'a T) -> R,
- {
- borrow(&self.section).into()
- }
-}
-
-impl<R> Section<R> for DebugAranges<R> {
- fn id() -> SectionId {
- SectionId::DebugAranges
- }
-
- fn reader(&self) -> &R {
- &self.section
- }
-}
-
-impl<R> From<R> for DebugAranges<R> {
- fn from(section: R) -> Self {
- DebugAranges { section }
- }
-}
-
-/// An iterator over the headers of a `.debug_aranges` section.
-#[derive(Clone, Debug)]
-pub struct ArangeHeaderIter<R: Reader> {
- input: R,
- offset: DebugArangesOffset<R::Offset>,
-}
-
-impl<R: Reader> ArangeHeaderIter<R> {
- /// Advance the iterator to the next header.
- pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
- if self.input.is_empty() {
- return Ok(None);
- }
-
- let len = self.input.len();
- match ArangeHeader::parse(&mut self.input, self.offset) {
- Ok(header) => {
- self.offset.0 += len - self.input.len();
- Ok(Some(header))
- }
- Err(e) => {
- self.input.empty();
- Err(e)
- }
- }
- }
-}
-
-#[cfg(feature = "fallible-iterator")]
-impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
- type Item = ArangeHeader<R>;
- type Error = Error;
-
- fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
- ArangeHeaderIter::next(self)
- }
-}
-
-/// A header for a set of entries in the `.debug_arange` section.
-///
-/// These entries all belong to a single unit.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
-where
- R: Reader<Offset = Offset>,
- Offset: ReaderOffset,
-{
- offset: DebugArangesOffset<Offset>,
- encoding: Encoding,
- length: Offset,
- debug_info_offset: DebugInfoOffset<Offset>,
- segment_size: u8,
- entries: R,
-}
-
-impl<R, Offset> ArangeHeader<R, Offset>
-where
- R: Reader<Offset = Offset>,
- Offset: ReaderOffset,
-{
- fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
- let (length, format) = input.read_initial_length()?;
- let mut rest = input.split(length)?;
-
- // Check the version. The DWARF 5 spec says that this is always 2, but version 3
- // has been observed in the wild, potentially due to a bug; see
- // https://github.com/gimli-rs/gimli/issues/559 for more information.
- // lldb allows versions 2 through 5, possibly by mistake.
- let version = rest.read_u16()?;
- if version != 2 && version != 3 {
- return Err(Error::UnknownVersion(u64::from(version)));
- }
-
- let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
- let address_size = rest.read_u8()?;
- let segment_size = rest.read_u8()?;
-
- // unit_length + version + offset + address_size + segment_size
- let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
-
- // The first tuple following the header in each set begins at an offset that is
- // a multiple of the size of a single tuple (that is, the size of a segment selector
- // plus twice the size of an address).
- let tuple_length = address_size
- .checked_mul(2)
- .and_then(|x| x.checked_add(segment_size))
- .ok_or(Error::InvalidAddressRange)?;
- if tuple_length == 0 {
- return Err(Error::InvalidAddressRange)?;
- }
- let padding = if header_length % tuple_length == 0 {
- 0
- } else {
- tuple_length - header_length % tuple_length
- };
- rest.skip(R::Offset::from_u8(padding))?;
-
- let encoding = Encoding {
- format,
- version,
- address_size,
- // TODO: segment_size
- };
- Ok(ArangeHeader {
- offset,
- encoding,
- length,
- debug_info_offset,
- segment_size,
- entries: rest,
- })
- }
-
- /// Return the offset of this header within the `.debug_aranges` section.
- #[inline]
- pub fn offset(&self) -> DebugArangesOffset<Offset> {
- self.offset
- }
-
- /// Return the length of this set of entries, including the header.
- #[inline]
- pub fn length(&self) -> Offset {
- self.length
- }
-
- /// Return the encoding parameters for this set of entries.
- #[inline]
- pub fn encoding(&self) -> Encoding {
- self.encoding
- }
-
- /// Return the segment size for this set of entries.
- #[inline]
- pub fn segment_size(&self) -> u8 {
- self.segment_size
- }
-
- /// Return the offset into the .debug_info section for this set of arange entries.
- #[inline]
- pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
- self.debug_info_offset
- }
-
- /// Return the arange entries in this set.
- #[inline]
- pub fn entries(&self) -> ArangeEntryIter<R> {
- ArangeEntryIter {
- input: self.entries.clone(),
- encoding: self.encoding,
- segment_size: self.segment_size,
- }
- }
-}
-
-/// An iterator over the aranges from a `.debug_aranges` section.
-///
-/// Can be [used with
-/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
-#[derive(Debug, Clone)]
-pub struct ArangeEntryIter<R: Reader> {
- input: R,
- encoding: Encoding,
- segment_size: u8,
-}
-
-impl<R: Reader> ArangeEntryIter<R> {
- /// Advance the iterator and return the next arange.
- ///
- /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
- /// when iteration is complete and all aranges have already been parsed and
- /// yielded. If an error occurs while parsing the next arange, then this error
- /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
- pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
- if self.input.is_empty() {
- return Ok(None);
- }
-
- match ArangeEntry::parse(&mut self.input, self.encoding, self.segment_size) {
- Ok(Some(entry)) => Ok(Some(entry)),
- Ok(None) => {
- self.input.empty();
- Ok(None)
- }
- Err(e) => {
- self.input.empty();
- Err(e)
- }
- }
- }
-}
-
-#[cfg(feature = "fallible-iterator")]
-impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
- type Item = ArangeEntry;
- type Error = Error;
-
- fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
- ArangeEntryIter::next(self)
- }
-}
-
-/// A single parsed arange.
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct ArangeEntry {
- segment: Option<u64>,
- address: u64,
- length: u64,
-}
-
-impl ArangeEntry {
- /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
- fn parse<R: Reader>(
- input: &mut R,
- encoding: Encoding,
- segment_size: u8,
- ) -> Result<Option<Self>> {
- let address_size = encoding.address_size;
-
- let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
- if tuple_length > input.len() {
- input.empty();
- return Ok(None);
- }
-
- let segment = if segment_size != 0 {
- input.read_address(segment_size)?
- } else {
- 0
- };
- let address = input.read_address(address_size)?;
- let length = input.read_address(address_size)?;
-
- match (segment, address, length) {
- // This is meant to be a null terminator, but in practice it can occur
- // before the end, possibly due to a linker omitting a function and
- // leaving an unrelocated entry.
- (0, 0, 0) => Self::parse(input, encoding, segment_size),
- _ => Ok(Some(ArangeEntry {
- segment: if segment_size != 0 {
- Some(segment)
- } else {
- None
- },
- address,
- length,
- })),
- }
- }
-
- /// Return the segment selector of this arange.
- #[inline]
- pub fn segment(&self) -> Option<u64> {
- self.segment
- }
-
- /// Return the beginning address of this arange.
- #[inline]
- pub fn address(&self) -> u64 {
- self.address
- }
-
- /// Return the length of this arange.
- #[inline]
- pub fn length(&self) -> u64 {
- self.length
- }
-
- /// Return the range.
- #[inline]
- pub fn range(&self) -> Range {
- Range {
- begin: self.address,
- end: self.address.wrapping_add(self.length),
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::common::{DebugInfoOffset, Format};
- use crate::endianity::LittleEndian;
- use crate::read::EndianSlice;
-
- #[test]
- fn test_iterate_headers() {
- #[rustfmt::skip]
- let buf = [
- // 32-bit length = 28.
- 0x1c, 0x00, 0x00, 0x00,
- // Version.
- 0x02, 0x00,
- // Offset.
- 0x01, 0x02, 0x03, 0x04,
- // Address size.
- 0x04,
- // Segment size.
- 0x00,
- // Dummy padding and arange tuples.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- // 32-bit length = 36.
- 0x24, 0x00, 0x00, 0x00,
- // Version.
- 0x02, 0x00,
- // Offset.
- 0x11, 0x12, 0x13, 0x14,
- // Address size.
- 0x04,
- // Segment size.
- 0x00,
- // Dummy padding and arange tuples.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- ];
-
- let debug_aranges = DebugAranges::new(&buf, LittleEndian);
- let mut headers = debug_aranges.headers();
-
- let header = headers
- .next()
- .expect("should parse header ok")
- .expect("should have a header");
- assert_eq!(header.offset(), DebugArangesOffset(0));
- assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
-
- let header = headers
- .next()
- .expect("should parse header ok")
- .expect("should have a header");
- assert_eq!(header.offset(), DebugArangesOffset(0x20));
- assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
- }
-
- #[test]
- fn test_parse_header_ok() {
- #[rustfmt::skip]
- let buf = [
- // 32-bit length = 32.
- 0x20, 0x00, 0x00, 0x00,
- // Version.
- 0x02, 0x00,
- // Offset.
- 0x01, 0x02, 0x03, 0x04,
- // Address size.
- 0x08,
- // Segment size.
- 0x04,
- // Length to here = 12, tuple length = 20.
- // Padding to tuple length multiple = 4.
- 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy arange tuple data.
- 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy next arange.
- 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- ];
-
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
-
- let header =
- ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
-
- assert_eq!(
- *rest,
- EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
- );
- assert_eq!(
- header,
- ArangeHeader {
- offset: DebugArangesOffset(0x10),
- encoding: Encoding {
- format: Format::Dwarf32,
- version: 2,
- address_size: 8,
- },
- length: 0x20,
- debug_info_offset: DebugInfoOffset(0x0403_0201),
- segment_size: 4,
- entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
- }
- );
- }
-
- #[test]
- fn test_parse_header_overflow_error() {
- #[rustfmt::skip]
- let buf = [
- // 32-bit length = 32.
- 0x20, 0x00, 0x00, 0x00,
- // Version.
- 0x02, 0x00,
- // Offset.
- 0x01, 0x02, 0x03, 0x04,
- // Address size.
- 0xff,
- // Segment size.
- 0xff,
- // Length to here = 12, tuple length = 20.
- // Padding to tuple length multiple = 4.
- 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy arange tuple data.
- 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy next arange.
- 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- ];
-
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
-
- let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
- .expect_err("should fail to parse header");
- assert_eq!(error, Error::InvalidAddressRange);
- }
-
- #[test]
- fn test_parse_header_div_by_zero_error() {
- #[rustfmt::skip]
- let buf = [
- // 32-bit length = 32.
- 0x20, 0x00, 0x00, 0x00,
- // Version.
- 0x02, 0x00,
- // Offset.
- 0x01, 0x02, 0x03, 0x04,
- // Address size = 0. Could cause a division by zero if we aren't
- // careful.
- 0x00,
- // Segment size.
- 0x00,
- // Length to here = 12, tuple length = 20.
- // Padding to tuple length multiple = 4.
- 0x10, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy arange tuple data.
- 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- // Dummy next arange.
- 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- ];
-
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
-
- let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
- .expect_err("should fail to parse header");
- assert_eq!(error, Error::InvalidAddressRange);
- }
-
- #[test]
- fn test_parse_entry_ok() {
- let encoding = Encoding {
- format: Format::Dwarf32,
- version: 2,
- address_size: 4,
- };
- let segment_size = 0;
- let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let entry =
- ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
- assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
- assert_eq!(
- entry,
- Some(ArangeEntry {
- segment: None,
- address: 0x0403_0201,
- length: 0x0807_0605,
- })
- );
- }
-
- #[test]
- fn test_parse_entry_segment() {
- let encoding = Encoding {
- format: Format::Dwarf32,
- version: 2,
- address_size: 4,
- };
- let segment_size = 8;
- #[rustfmt::skip]
- let buf = [
- // Segment.
- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- // Address.
- 0x01, 0x02, 0x03, 0x04,
- // Length.
- 0x05, 0x06, 0x07, 0x08,
- // Next tuple.
- 0x09
- ];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let entry =
- ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
- assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
- assert_eq!(
- entry,
- Some(ArangeEntry {
- segment: Some(0x1817_1615_1413_1211),
- address: 0x0403_0201,
- length: 0x0807_0605,
- })
- );
- }
-
- #[test]
- fn test_parse_entry_zero() {
- let encoding = Encoding {
- format: Format::Dwarf32,
- version: 2,
- address_size: 4,
- };
- let segment_size = 0;
- #[rustfmt::skip]
- let buf = [
- // Zero tuple.
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Address.
- 0x01, 0x02, 0x03, 0x04,
- // Length.
- 0x05, 0x06, 0x07, 0x08,
- // Next tuple.
- 0x09
- ];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let entry =
- ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
- assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
- assert_eq!(
- entry,
- Some(ArangeEntry {
- segment: None,
- address: 0x0403_0201,
- length: 0x0807_0605,
- })
- );
- }
-}