/// The `DebugAranges` struct represents the DWARF address range information /// found in the `.debug_aranges` section. #[derive(Debug, Default, Clone, Copy)] pubstruct 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); /// ``` pubfn 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. pubfn headers(&self) -> ArangeHeaderIter<R> {
ArangeHeaderIter {
input: self.section.clone(),
offset: DebugArangesOffset(R::Offset::from_u8(0)),
}
}
/// Get the header at the given offset. pubfn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> { letmut 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. /// /// Used by `DwarfSections::borrow`. pubfn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R> where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
/// An iterator over the headers of a `.debug_aranges` section. #[derive(Clone, Debug)] pubstruct ArangeHeaderIter<R: Reader> {
input: R,
offset: DebugArangesOffset<R::Offset>,
}
impl<R: Reader> ArangeHeaderIter<R> { /// Advance the iterator to the next header. pubfn next(&mutself) -> Result<Option<ArangeHeader<R>>> { ifself.input.is_empty() { return Ok(None);
}
let len = self.input.len(); match ArangeHeader::parse(&mutself.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;
/// 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)] pubstruct 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,
}
// 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()?;
// 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))?;
/// Return the offset of this header within the `.debug_aranges` section. #[inline] pubfn offset(&self) -> DebugArangesOffset<Offset> { self.offset
}
/// Return the length of this set of entries, including the header. #[inline] pubfn length(&self) -> Offset { self.length
}
/// Return the encoding parameters for this set of entries. #[inline] pubfn encoding(&self) -> Encoding { self.encoding
}
/// Return the segment size for this set of entries. #[inline] pubfn segment_size(&self) -> u8 { self.segment_size
}
/// Return the offset into the .debug_info section for this set of arange entries. #[inline] pubfn debug_info_offset(&self) -> DebugInfoOffset<Offset> { self.debug_info_offset
}
/// Return the arange entries in this set. #[inline] pubfn 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)] pubstruct 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)`. pubfn next(&mutself) -> Result<Option<ArangeEntry>> { ifself.input.is_empty() { return Ok(None);
}
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] pubfn segment(&self) -> Option<u64> { self.segment
}
/// Return the beginning address of this arange. #[inline] pubfn address(&self) -> u64 { self.address
}
/// Return the length of this arange. #[inline] pubfn length(&self) -> u64 { self.length
}
/// Return the range. #[inline] pubfn range(&self) -> Range {
Range {
begin: self.address,
end: self.address.wrapping_add(self.length),
}
}
}
#[cfg(test)] mod tests { usesuper::*; usecrate::common::{DebugInfoOffset, Format}; usecrate::endianity::LittleEndian; usecrate::read::EndianSlice;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.