blob: 6723b42228125e434c699cc26c2390015e6d9a77 [file] [log] [blame]
use crate::common::{DebugInfoOffset, SectionId};
use crate::endianity::Endianity;
use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser};
use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset};
/// A single parsed pubtype.
#[derive(Debug, Clone)]
pub struct PubTypesEntry<R: Reader> {
unit_header_offset: DebugInfoOffset<R::Offset>,
die_offset: UnitOffset<R::Offset>,
name: R,
}
impl<R: Reader> PubTypesEntry<R> {
/// Returns the name of the type this entry refers to.
pub fn name(&self) -> &R {
&self.name
}
/// Returns the offset into the .debug_info section for the header of the compilation unit
/// which contains the type with this name.
pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> {
self.unit_header_offset
}
/// Returns the offset into the compilation unit for the debugging information entry which
/// the type with this name.
pub fn die_offset(&self) -> UnitOffset<R::Offset> {
self.die_offset
}
}
impl<R: Reader> PubStuffEntry<R> for PubTypesEntry<R> {
fn new(
die_offset: UnitOffset<R::Offset>,
name: R,
unit_header_offset: DebugInfoOffset<R::Offset>,
) -> Self {
PubTypesEntry {
unit_header_offset,
die_offset,
name,
}
}
}
/// The `DebugPubTypes` struct represents the DWARF public types information
/// found in the `.debug_info` section.
#[derive(Debug, Clone)]
pub struct DebugPubTypes<R: Reader>(DebugLookup<R, PubStuffParser<R, PubTypesEntry<R>>>);
impl<'input, Endian> DebugPubTypes<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugPubTypes` instance from the data in the `.debug_pubtypes`
/// section.
///
/// It is the caller's responsibility to read the `.debug_pubtypes` 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::{DebugPubTypes, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubtypes_somehow = || &buf;
/// let debug_pubtypes =
/// DebugPubTypes::new(read_debug_pubtypes_somehow(), LittleEndian);
/// ```
pub fn new(debug_pubtypes_section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(debug_pubtypes_section, endian))
}
}
impl<R: Reader> DebugPubTypes<R> {
/// Iterate the pubtypes in the `.debug_pubtypes` section.
///
/// ```
/// use gimli::{DebugPubTypes, EndianSlice, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubtypes_section_somehow = || &buf;
/// let debug_pubtypes =
/// DebugPubTypes::new(read_debug_pubtypes_section_somehow(), LittleEndian);
///
/// let mut iter = debug_pubtypes.items();
/// while let Some(pubtype) = iter.next().unwrap() {
/// println!("pubtype {} found!", pubtype.name().to_string_lossy());
/// }
/// ```
pub fn items(&self) -> PubTypesEntryIter<R> {
PubTypesEntryIter(self.0.items())
}
}
impl<R: Reader> Section<R> for DebugPubTypes<R> {
fn id() -> SectionId {
SectionId::DebugPubTypes
}
fn reader(&self) -> &R {
self.0.reader()
}
}
impl<R: Reader> From<R> for DebugPubTypes<R> {
fn from(debug_pubtypes_section: R) -> Self {
DebugPubTypes(DebugLookup::from(debug_pubtypes_section))
}
}
/// An iterator over the pubtypes from a `.debug_pubtypes` section.
///
/// Can be [used with
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
#[derive(Debug, Clone)]
pub struct PubTypesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubTypesEntry<R>>>);
impl<R: Reader> PubTypesEntryIter<R> {
/// Advance the iterator and return the next pubtype.
///
/// Returns the newly parsed pubtype as `Ok(Some(pubtype))`. Returns
/// `Ok(None)` when iteration is complete and all pubtypes have already been
/// parsed and yielded. If an error occurs while parsing the next pubtype,
/// then this error is returned as `Err(e)`, and all subsequent calls return
/// `Ok(None)`.
pub fn next(&mut self) -> Result<Option<PubTypesEntry<R>>> {
self.0.next()
}
}
#[cfg(feature = "fallible-iterator")]
impl<R: Reader> fallible_iterator::FallibleIterator for PubTypesEntryIter<R> {
type Item = PubTypesEntry<R>;
type Error = crate::read::Error;
fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
self.0.next()
}
}