Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lookup.rs   Sprache: unbekannt

 
use core::marker::PhantomData;

use crate::common::{DebugInfoOffset, Format};
use crate::read::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset};

// The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have
// similar structures. They consist of a header with metadata and an offset into the
// .debug_info section for the entire compilation unit, and a series
// of following entries that list addresses (for .debug_aranges) or names
// (for .debug_pubnames and .debug_pubtypes) that are covered.
//
// Because these three tables all have similar structures, we abstract out some of
// the parsing mechanics.

pub trait LookupParser<R: Reader> {
    /// The type of the produced header.
    type Header;
    /// The type of the produced entry.
    type Entry;

    /// Parse a header from `input`. Returns a tuple of `input` sliced to contain just the entries
    /// corresponding to this header (without the header itself), and the parsed representation of
    /// the header itself.
    fn parse_header(input: &mut R) -> Result<(R, Self::Header)>;

    /// Parse a single entry from `input`. Returns either a parsed representation of the entry
    /// or None if `input` is exhausted.
    fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>>;
}

#[derive(Clone, Debug)]
pub struct DebugLookup<R, Parser>
where
    R: Reader,
    Parser: LookupParser<R>,
{
    input_buffer: R,
    phantom: PhantomData<Parser>,
}

impl<R, Parser> From<R> for DebugLookup<R, Parser>
where
    R: Reader,
    Parser: LookupParser<R>,
{
    fn from(input_buffer: R) -> Self {
        DebugLookup {
            input_buffer,
            phantom: PhantomData,
        }
    }
}

impl<R, Parser> DebugLookup<R, Parser>
where
    R: Reader,
    Parser: LookupParser<R>,
{
    pub fn items(&self) -> LookupEntryIter<R, Parser> {
        LookupEntryIter {
            current_set: None,
            remaining_input: self.input_buffer.clone(),
        }
    }

    pub fn reader(&self) -> &R {
        &self.input_buffer
    }
}

#[derive(Clone, Debug)]
pub struct LookupEntryIter<R, Parser>
where
    R: Reader,
    Parser: LookupParser<R>,
{
    current_set: Option<(R, Parser::Header)>, // Only none at the very beginning and end.
    remaining_input: R,
}

impl<R, Parser> LookupEntryIter<R, Parser>
where
    R: Reader,
    Parser: LookupParser<R>,
{
    /// Advance the iterator and return the next entry.
    ///
    /// Returns the newly parsed entry as `Ok(Some(Parser::Entry))`. Returns
    /// `Ok(None)` when iteration is complete and all entries have already been
    /// parsed and yielded. If an error occurs while parsing the next entry,
    /// then this error is returned as `Err(e)`, and all subsequent calls return
    /// `Ok(None)`.
    ///
    /// Can be [used with `FallibleIterator`](./index.html#using-with-fallibleiterator).
    pub fn next(&mut self) -> Result<Option<Parser::Entry>> {
        loop {
            if let Some((ref mut input, ref header)) = self.current_set {
                if !input.is_empty() {
                    match Parser::parse_entry(input, header) {
                        Ok(Some(entry)) => return Ok(Some(entry)),
                        Ok(None) => {}
                        Err(e) => {
                            input.empty();
                            self.remaining_input.empty();
                            return Err(e);
                        }
                    }
                }
            }
            if self.remaining_input.is_empty() {
                self.current_set = None;
                return Ok(None);
            }
            match Parser::parse_header(&mut self.remaining_input) {
                Ok(set) => {
                    self.current_set = Some(set);
                }
                Err(e) => {
                    self.current_set = None;
                    self.remaining_input.empty();
                    return Err(e);
                }
            }
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PubStuffHeader<T = usize> {
    format: Format,
    length: T,
    version: u16,
    unit_offset: DebugInfoOffset<T>,
    unit_length: T,
}

pub trait PubStuffEntry<R: Reader> {
    fn new(
        die_offset: UnitOffset<R::Offset>,
        name: R,
        unit_header_offset: DebugInfoOffset<R::Offset>,
    ) -> Self;
}

#[derive(Clone, Debug)]
pub struct PubStuffParser<R, Entry>
where
    R: Reader,
    Entry: PubStuffEntry<R>,
{
    // This struct is never instantiated.
    phantom: PhantomData<(R, Entry)>,
}

impl<R, Entry> LookupParser<R> for PubStuffParser<R, Entry>
where
    R: Reader,
    Entry: PubStuffEntry<R>,
{
    type Header = PubStuffHeader<R::Offset>;
    type Entry = Entry;

    /// Parse an pubthings set header. Returns a tuple of the
    /// pubthings to be parsed for this set, and the newly created PubThingHeader struct.
    fn parse_header(input: &mut R) -> Result<(R, Self::Header)> {
        let (length, format) = input.read_initial_length()?;
        let mut rest = input.split(length)?;

        let version = rest.read_u16()?;
        if version != 2 {
            return Err(Error::UnknownVersion(u64::from(version)));
        }

        let unit_offset = parse_debug_info_offset(&mut rest, format)?;
        let unit_length = rest.read_length(format)?;

        let header = PubStuffHeader {
            format,
            length,
            version,
            unit_offset,
            unit_length,
        };
        Ok((rest, header))
    }

    /// Parse a single pubthing. Return `None` for the null pubthing, `Some` for an actual pubthing.
    fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>> {
        let offset = input.read_offset(header.format)?;
        if offset.into_u64() == 0 {
            input.empty();
            Ok(None)
        } else {
            let name = input.read_null_terminated_slice()?;
            Ok(Some(Self::Entry::new(
                UnitOffset(offset),
                name,
                header.unit_offset,
            )))
        }
    }
}

[ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge