aboutsummaryrefslogtreecommitdiff
path: root/vendor/gimli/src/read/abbrev.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/gimli/src/read/abbrev.rs
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/gimli/src/read/abbrev.rs')
-rw-r--r--vendor/gimli/src/read/abbrev.rs1102
1 files changed, 0 insertions, 1102 deletions
diff --git a/vendor/gimli/src/read/abbrev.rs b/vendor/gimli/src/read/abbrev.rs
deleted file mode 100644
index 1162583..0000000
--- a/vendor/gimli/src/read/abbrev.rs
+++ /dev/null
@@ -1,1102 +0,0 @@
-//! Functions for parsing DWARF debugging abbreviations.
-
-use alloc::collections::btree_map;
-use alloc::sync::Arc;
-use alloc::vec::Vec;
-use core::convert::TryFrom;
-use core::fmt::{self, Debug};
-use core::iter::FromIterator;
-use core::ops::Deref;
-
-use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
-use crate::constants;
-use crate::endianity::Endianity;
-use crate::read::{
- DebugInfoUnitHeadersIter, EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader,
-};
-
-/// The `DebugAbbrev` struct represents the abbreviations describing
-/// `DebuggingInformationEntry`s' attribute names and forms found in the
-/// `.debug_abbrev` section.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct DebugAbbrev<R> {
- debug_abbrev_section: R,
-}
-
-impl<'input, Endian> DebugAbbrev<EndianSlice<'input, Endian>>
-where
- Endian: Endianity,
-{
- /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev`
- /// section.
- ///
- /// It is the caller's responsibility to read the `.debug_abbrev` 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::{DebugAbbrev, LittleEndian};
- ///
- /// # let buf = [0x00, 0x01, 0x02, 0x03];
- /// # let read_debug_abbrev_section_somehow = || &buf;
- /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
- /// ```
- pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self {
- Self::from(EndianSlice::new(debug_abbrev_section, endian))
- }
-}
-
-impl<R: Reader> DebugAbbrev<R> {
- /// Parse the abbreviations at the given `offset` within this
- /// `.debug_abbrev` section.
- ///
- /// The `offset` should generally be retrieved from a unit header.
- pub fn abbreviations(
- &self,
- debug_abbrev_offset: DebugAbbrevOffset<R::Offset>,
- ) -> Result<Abbreviations> {
- let input = &mut self.debug_abbrev_section.clone();
- input.skip(debug_abbrev_offset.0)?;
- Abbreviations::parse(input)
- }
-}
-
-impl<T> DebugAbbrev<T> {
- /// Create a `DebugAbbrev` 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::DebugAbbrev<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) -> DebugAbbrev<R>
- where
- F: FnMut(&'a T) -> R,
- {
- borrow(&self.debug_abbrev_section).into()
- }
-}
-
-impl<R> Section<R> for DebugAbbrev<R> {
- fn id() -> SectionId {
- SectionId::DebugAbbrev
- }
-
- fn reader(&self) -> &R {
- &self.debug_abbrev_section
- }
-}
-
-impl<R> From<R> for DebugAbbrev<R> {
- fn from(debug_abbrev_section: R) -> Self {
- DebugAbbrev {
- debug_abbrev_section,
- }
- }
-}
-
-/// The strategy to use for caching abbreviations.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum AbbreviationsCacheStrategy {
- /// Cache abbreviations that are used more than once.
- ///
- /// This is useful if the units in the `.debug_info` section will be parsed only once.
- Duplicates,
- /// Cache all abbreviations.
- ///
- /// This is useful if the units in the `.debug_info` section will be parsed more than once.
- All,
-}
-
-/// A cache of previously parsed `Abbreviations`.
-#[derive(Debug, Default)]
-pub struct AbbreviationsCache {
- abbreviations: btree_map::BTreeMap<u64, Result<Arc<Abbreviations>>>,
-}
-
-impl AbbreviationsCache {
- /// Create an empty abbreviations cache.
- pub fn new() -> Self {
- Self::default()
- }
-
- /// Parse abbreviations and store them in the cache.
- ///
- /// This will iterate over the given units to determine the abbreviations
- /// offsets. Any existing cache entries are discarded.
- ///
- /// Errors during parsing abbreviations are also stored in the cache.
- /// Errors during iterating over the units are ignored.
- pub fn populate<R: Reader>(
- &mut self,
- strategy: AbbreviationsCacheStrategy,
- debug_abbrev: &DebugAbbrev<R>,
- mut units: DebugInfoUnitHeadersIter<R>,
- ) {
- let mut offsets = Vec::new();
- match strategy {
- AbbreviationsCacheStrategy::Duplicates => {
- while let Ok(Some(unit)) = units.next() {
- offsets.push(unit.debug_abbrev_offset());
- }
- offsets.sort_unstable_by_key(|offset| offset.0);
- let mut prev_offset = R::Offset::from_u8(0);
- let mut count = 0;
- offsets.retain(|offset| {
- if count == 0 || prev_offset != offset.0 {
- prev_offset = offset.0;
- count = 1;
- } else {
- count += 1;
- }
- count == 2
- });
- }
- AbbreviationsCacheStrategy::All => {
- while let Ok(Some(unit)) = units.next() {
- offsets.push(unit.debug_abbrev_offset());
- }
- offsets.sort_unstable_by_key(|offset| offset.0);
- offsets.dedup();
- }
- }
- self.abbreviations = offsets
- .into_iter()
- .map(|offset| {
- (
- offset.0.into_u64(),
- debug_abbrev.abbreviations(offset).map(Arc::new),
- )
- })
- .collect();
- }
-
- /// Set an entry in the abbreviations cache.
- ///
- /// This is only required if you want to manually populate the cache.
- pub fn set<R: Reader>(
- &mut self,
- offset: DebugAbbrevOffset<R::Offset>,
- abbreviations: Arc<Abbreviations>,
- ) {
- self.abbreviations
- .insert(offset.0.into_u64(), Ok(abbreviations));
- }
-
- /// Parse the abbreviations at the given offset.
- ///
- /// This uses the cache if possible, but does not update it.
- pub fn get<R: Reader>(
- &self,
- debug_abbrev: &DebugAbbrev<R>,
- offset: DebugAbbrevOffset<R::Offset>,
- ) -> Result<Arc<Abbreviations>> {
- match self.abbreviations.get(&offset.0.into_u64()) {
- Some(entry) => entry.clone(),
- None => debug_abbrev.abbreviations(offset).map(Arc::new),
- }
- }
-}
-
-/// A set of type abbreviations.
-///
-/// Construct an `Abbreviations` instance with the
-/// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations)
-/// method.
-#[derive(Debug, Default, Clone)]
-pub struct Abbreviations {
- vec: Vec<Abbreviation>,
- map: btree_map::BTreeMap<u64, Abbreviation>,
-}
-
-impl Abbreviations {
- /// Construct a new, empty set of abbreviations.
- fn empty() -> Abbreviations {
- Abbreviations {
- vec: Vec::new(),
- map: btree_map::BTreeMap::new(),
- }
- }
-
- /// Insert an abbreviation into the set.
- ///
- /// Returns `Ok` if it is the first abbreviation in the set with its code,
- /// `Err` if the code is a duplicate and there already exists an
- /// abbreviation in the set with the given abbreviation's code.
- fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> {
- let code_usize = abbrev.code as usize;
- if code_usize as u64 == abbrev.code {
- // Optimize for sequential abbreviation codes by storing them
- // in a Vec, as long as the map doesn't already contain them.
- // A potential further optimization would be to allow some
- // holes in the Vec, but there's no need for that yet.
- if code_usize - 1 < self.vec.len() {
- return Err(());
- } else if code_usize - 1 == self.vec.len() {
- if !self.map.is_empty() && self.map.contains_key(&abbrev.code) {
- return Err(());
- } else {
- self.vec.push(abbrev);
- return Ok(());
- }
- }
- }
- match self.map.entry(abbrev.code) {
- btree_map::Entry::Occupied(_) => Err(()),
- btree_map::Entry::Vacant(entry) => {
- entry.insert(abbrev);
- Ok(())
- }
- }
- }
-
- /// Get the abbreviation associated with the given code.
- #[inline]
- pub fn get(&self, code: u64) -> Option<&Abbreviation> {
- if let Ok(code) = usize::try_from(code) {
- let index = code.checked_sub(1)?;
- if index < self.vec.len() {
- return Some(&self.vec[index]);
- }
- }
-
- self.map.get(&code)
- }
-
- /// Parse a series of abbreviations, terminated by a null abbreviation.
- fn parse<R: Reader>(input: &mut R) -> Result<Abbreviations> {
- let mut abbrevs = Abbreviations::empty();
-
- while let Some(abbrev) = Abbreviation::parse(input)? {
- if abbrevs.insert(abbrev).is_err() {
- return Err(Error::DuplicateAbbreviationCode);
- }
- }
-
- Ok(abbrevs)
- }
-}
-
-/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
-/// its code, tag type, whether it has children, and its set of attributes.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Abbreviation {
- code: u64,
- tag: constants::DwTag,
- has_children: constants::DwChildren,
- attributes: Attributes,
-}
-
-impl Abbreviation {
- /// Construct a new `Abbreviation`.
- ///
- /// ### Panics
- ///
- /// Panics if `code` is `0`.
- pub(crate) fn new(
- code: u64,
- tag: constants::DwTag,
- has_children: constants::DwChildren,
- attributes: Attributes,
- ) -> Abbreviation {
- assert_ne!(code, 0);
- Abbreviation {
- code,
- tag,
- has_children,
- attributes,
- }
- }
-
- /// Get this abbreviation's code.
- #[inline]
- pub fn code(&self) -> u64 {
- self.code
- }
-
- /// Get this abbreviation's tag.
- #[inline]
- pub fn tag(&self) -> constants::DwTag {
- self.tag
- }
-
- /// Return true if this abbreviation's type has children, false otherwise.
- #[inline]
- pub fn has_children(&self) -> bool {
- self.has_children == constants::DW_CHILDREN_yes
- }
-
- /// Get this abbreviation's attributes.
- #[inline]
- pub fn attributes(&self) -> &[AttributeSpecification] {
- &self.attributes[..]
- }
-
- /// Parse an abbreviation's tag.
- fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
- let val = input.read_uleb128_u16()?;
- if val == 0 {
- Err(Error::AbbreviationTagZero)
- } else {
- Ok(constants::DwTag(val))
- }
- }
-
- /// Parse an abbreviation's "does the type have children?" byte.
- fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> {
- let val = input.read_u8()?;
- let val = constants::DwChildren(val);
- if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
- Ok(val)
- } else {
- Err(Error::BadHasChildren)
- }
- }
-
- /// Parse a series of attribute specifications, terminated by a null attribute
- /// specification.
- fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
- let mut attrs = Attributes::new();
-
- while let Some(attr) = AttributeSpecification::parse(input)? {
- attrs.push(attr);
- }
-
- Ok(attrs)
- }
-
- /// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
- /// for an actual abbreviation.
- fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> {
- let code = input.read_uleb128()?;
- if code == 0 {
- return Ok(None);
- }
-
- let tag = Self::parse_tag(input)?;
- let has_children = Self::parse_has_children(input)?;
- let attributes = Self::parse_attributes(input)?;
- let abbrev = Abbreviation::new(code, tag, has_children, attributes);
- Ok(Some(abbrev))
- }
-}
-
-/// A list of attributes found in an `Abbreviation`
-#[derive(Clone)]
-pub(crate) enum Attributes {
- Inline {
- buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
- len: usize,
- },
- Heap(Vec<AttributeSpecification>),
-}
-
-// Length of 5 based on benchmark results for both x86-64 and i686.
-const MAX_ATTRIBUTES_INLINE: usize = 5;
-
-impl Attributes {
- /// Returns a new empty list of attributes
- fn new() -> Attributes {
- let default =
- AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
- Attributes::Inline {
- buf: [default; 5],
- len: 0,
- }
- }
-
- /// Pushes a new value onto this list of attributes.
- fn push(&mut self, attr: AttributeSpecification) {
- match self {
- Attributes::Heap(list) => list.push(attr),
- Attributes::Inline {
- buf,
- len: MAX_ATTRIBUTES_INLINE,
- } => {
- let mut list = buf.to_vec();
- list.push(attr);
- *self = Attributes::Heap(list);
- }
- Attributes::Inline { buf, len } => {
- buf[*len] = attr;
- *len += 1;
- }
- }
- }
-}
-
-impl Debug for Attributes {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (**self).fmt(f)
- }
-}
-
-impl PartialEq for Attributes {
- fn eq(&self, other: &Attributes) -> bool {
- **self == **other
- }
-}
-
-impl Eq for Attributes {}
-
-impl Deref for Attributes {
- type Target = [AttributeSpecification];
- fn deref(&self) -> &[AttributeSpecification] {
- match self {
- Attributes::Inline { buf, len } => &buf[..*len],
- Attributes::Heap(list) => list,
- }
- }
-}
-
-impl FromIterator<AttributeSpecification> for Attributes {
- fn from_iter<I>(iter: I) -> Attributes
- where
- I: IntoIterator<Item = AttributeSpecification>,
- {
- let mut list = Attributes::new();
- for item in iter {
- list.push(item);
- }
- list
- }
-}
-
-impl From<Vec<AttributeSpecification>> for Attributes {
- fn from(list: Vec<AttributeSpecification>) -> Attributes {
- Attributes::Heap(list)
- }
-}
-
-/// The description of an attribute in an abbreviated type. It is a pair of name
-/// and form.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct AttributeSpecification {
- name: constants::DwAt,
- form: constants::DwForm,
- implicit_const_value: i64,
-}
-
-impl AttributeSpecification {
- /// Construct a new `AttributeSpecification` from the given name and form
- /// and implicit const value.
- #[inline]
- pub fn new(
- name: constants::DwAt,
- form: constants::DwForm,
- implicit_const_value: Option<i64>,
- ) -> AttributeSpecification {
- debug_assert!(
- (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some())
- || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none())
- );
- AttributeSpecification {
- name,
- form,
- implicit_const_value: implicit_const_value.unwrap_or(0),
- }
- }
-
- /// Get the attribute's name.
- #[inline]
- pub fn name(&self) -> constants::DwAt {
- self.name
- }
-
- /// Get the attribute's form.
- #[inline]
- pub fn form(&self) -> constants::DwForm {
- self.form
- }
-
- /// Get the attribute's implicit const value.
- #[inline]
- pub fn implicit_const_value(&self) -> Option<i64> {
- if self.form == constants::DW_FORM_implicit_const {
- Some(self.implicit_const_value)
- } else {
- None
- }
- }
-
- /// Return the size of the attribute, in bytes.
- ///
- /// Note that because some attributes are variably sized, the size cannot
- /// always be known without parsing, in which case we return `None`.
- pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> {
- get_attribute_size(self.form, header.encoding()).map(usize::from)
- }
-
- /// Parse an attribute's form.
- fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> {
- let val = input.read_uleb128_u16()?;
- if val == 0 {
- Err(Error::AttributeFormZero)
- } else {
- Ok(constants::DwForm(val))
- }
- }
-
- /// Parse an attribute specification. Returns `None` for the null attribute
- /// specification, `Some` for an actual attribute specification.
- fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
- let name = input.read_uleb128_u16()?;
- if name == 0 {
- // Parse the null attribute specification.
- let form = input.read_uleb128_u16()?;
- return if form == 0 {
- Ok(None)
- } else {
- Err(Error::ExpectedZero)
- };
- }
-
- let name = constants::DwAt(name);
- let form = Self::parse_form(input)?;
- let implicit_const_value = if form == constants::DW_FORM_implicit_const {
- Some(input.read_sleb128()?)
- } else {
- None
- };
- let spec = AttributeSpecification::new(name, form, implicit_const_value);
- Ok(Some(spec))
- }
-}
-
-#[inline]
-pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> {
- match form {
- constants::DW_FORM_addr => Some(encoding.address_size),
-
- constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0),
-
- constants::DW_FORM_data1
- | constants::DW_FORM_flag
- | constants::DW_FORM_strx1
- | constants::DW_FORM_ref1
- | constants::DW_FORM_addrx1 => Some(1),
-
- constants::DW_FORM_data2
- | constants::DW_FORM_ref2
- | constants::DW_FORM_addrx2
- | constants::DW_FORM_strx2 => Some(2),
-
- constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3),
-
- constants::DW_FORM_data4
- | constants::DW_FORM_ref_sup4
- | constants::DW_FORM_ref4
- | constants::DW_FORM_strx4
- | constants::DW_FORM_addrx4 => Some(4),
-
- constants::DW_FORM_data8
- | constants::DW_FORM_ref8
- | constants::DW_FORM_ref_sig8
- | constants::DW_FORM_ref_sup8 => Some(8),
-
- constants::DW_FORM_data16 => Some(16),
-
- constants::DW_FORM_sec_offset
- | constants::DW_FORM_GNU_ref_alt
- | constants::DW_FORM_strp
- | constants::DW_FORM_strp_sup
- | constants::DW_FORM_GNU_strp_alt
- | constants::DW_FORM_line_strp => Some(encoding.format.word_size()),
-
- constants::DW_FORM_ref_addr => {
- // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
- // has the same size as an address on the target system. This was changed
- // in DWARF version 3.
- Some(if encoding.version == 2 {
- encoding.address_size
- } else {
- encoding.format.word_size()
- })
- }
-
- // Variably sized forms.
- constants::DW_FORM_block
- | constants::DW_FORM_block1
- | constants::DW_FORM_block2
- | constants::DW_FORM_block4
- | constants::DW_FORM_exprloc
- | constants::DW_FORM_ref_udata
- | constants::DW_FORM_string
- | constants::DW_FORM_sdata
- | constants::DW_FORM_udata
- | constants::DW_FORM_indirect => None,
-
- // We don't know the size of unknown forms.
- _ => None,
- }
-}
-
-#[cfg(test)]
-pub mod tests {
- use super::*;
- use crate::constants;
- use crate::endianity::LittleEndian;
- use crate::read::{EndianSlice, Error};
- use crate::test_util::GimliSectionMethods;
- #[cfg(target_pointer_width = "32")]
- use core::u32;
- use test_assembler::Section;
-
- pub trait AbbrevSectionMethods {
- fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self;
- fn abbrev_null(self) -> Self;
- fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self;
- fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self;
- fn abbrev_attr_null(self) -> Self;
- }
-
- impl AbbrevSectionMethods for Section {
- fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
- self.uleb(code).uleb(tag.0.into()).D8(children.0)
- }
-
- fn abbrev_null(self) -> Self {
- self.D8(0)
- }
-
- fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
- self.uleb(name.0.into()).uleb(form.0.into())
- }
-
- fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
- self.uleb(name.0.into())
- .uleb(constants::DW_FORM_implicit_const.0.into())
- .sleb(value)
- }
-
- fn abbrev_attr_null(self) -> Self {
- self.D8(0).D8(0)
- }
- }
-
- #[test]
- fn test_debug_abbrev_ok() {
- let extra_start = [1, 2, 3, 4];
- let expected_rest = [5, 6, 7, 8];
- #[rustfmt::skip]
- let buf = Section::new()
- .append_bytes(&extra_start)
- .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
- .abbrev_attr_null()
- .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
- .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
- .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
- .abbrev_attr_null()
- .abbrev_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
-
- let abbrev1 = Abbreviation::new(
- 1,
- constants::DW_TAG_compile_unit,
- constants::DW_CHILDREN_yes,
- vec![
- AttributeSpecification::new(
- constants::DW_AT_producer,
- constants::DW_FORM_strp,
- None,
- ),
- AttributeSpecification::new(
- constants::DW_AT_language,
- constants::DW_FORM_data2,
- None,
- ),
- ]
- .into(),
- );
-
- let abbrev2 = Abbreviation::new(
- 2,
- constants::DW_TAG_subprogram,
- constants::DW_CHILDREN_no,
- vec![AttributeSpecification::new(
- constants::DW_AT_name,
- constants::DW_FORM_string,
- None,
- )]
- .into(),
- );
-
- let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
- let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len());
- let abbrevs = debug_abbrev
- .abbreviations(debug_abbrev_offset)
- .expect("Should parse abbreviations");
- assert_eq!(abbrevs.get(1), Some(&abbrev1));
- assert_eq!(abbrevs.get(2), Some(&abbrev2));
- }
-
- #[test]
- fn test_abbreviations_insert() {
- fn abbrev(code: u16) -> Abbreviation {
- Abbreviation::new(
- code.into(),
- constants::DwTag(code),
- constants::DW_CHILDREN_no,
- vec![].into(),
- )
- }
-
- fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
- let abbrev = abbrevs.get(code.into()).unwrap();
- assert_eq!(abbrev.tag(), constants::DwTag(code));
- }
-
- // Sequential insert.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(1)).unwrap();
- abbrevs.insert(abbrev(2)).unwrap();
- assert_eq!(abbrevs.vec.len(), 2);
- assert!(abbrevs.map.is_empty());
- assert_abbrev(&abbrevs, 1);
- assert_abbrev(&abbrevs, 2);
-
- // Out of order insert.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(2)).unwrap();
- abbrevs.insert(abbrev(3)).unwrap();
- assert!(abbrevs.vec.is_empty());
- assert_abbrev(&abbrevs, 2);
- assert_abbrev(&abbrevs, 3);
-
- // Mixed order insert.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(1)).unwrap();
- abbrevs.insert(abbrev(3)).unwrap();
- abbrevs.insert(abbrev(2)).unwrap();
- assert_eq!(abbrevs.vec.len(), 2);
- assert_abbrev(&abbrevs, 1);
- assert_abbrev(&abbrevs, 2);
- assert_abbrev(&abbrevs, 3);
-
- // Duplicate code in vec.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(1)).unwrap();
- abbrevs.insert(abbrev(2)).unwrap();
- assert_eq!(abbrevs.insert(abbrev(1)), Err(()));
- assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
-
- // Duplicate code in map when adding to map.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(2)).unwrap();
- assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
-
- // Duplicate code in map when adding to vec.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(2)).unwrap();
- abbrevs.insert(abbrev(1)).unwrap();
- assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
-
- // 32-bit usize conversions.
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(2)).unwrap();
- }
-
- #[test]
- #[cfg(target_pointer_width = "32")]
- fn test_abbreviations_insert_32() {
- fn abbrev(code: u64) -> Abbreviation {
- Abbreviation::new(
- code,
- constants::DwTag(code as u16),
- constants::DW_CHILDREN_no,
- vec![].into(),
- )
- }
-
- fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
- let abbrev = abbrevs.get(code).unwrap();
- assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
- }
-
- let mut abbrevs = Abbreviations::empty();
- abbrevs.insert(abbrev(1)).unwrap();
-
- let wrap_code = (u32::MAX as u64 + 1) + 1;
- // `get` should not treat the wrapped code as `1`.
- assert_eq!(abbrevs.get(wrap_code), None);
- // `insert` should not treat the wrapped code as `1`.
- abbrevs.insert(abbrev(wrap_code)).unwrap();
- assert_abbrev(&abbrevs, 1);
- assert_abbrev(&abbrevs, wrap_code);
- }
-
- #[test]
- fn test_parse_abbreviations_ok() {
- let expected_rest = [1, 2, 3, 4];
- #[rustfmt::skip]
- let buf = Section::new()
- .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
- .abbrev_attr_null()
- .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
- .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
- .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
- .abbrev_attr_null()
- .abbrev_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
- let rest = &mut EndianSlice::new(&*buf, LittleEndian);
-
- let abbrev1 = Abbreviation::new(
- 1,
- constants::DW_TAG_compile_unit,
- constants::DW_CHILDREN_yes,
- vec![
- AttributeSpecification::new(
- constants::DW_AT_producer,
- constants::DW_FORM_strp,
- None,
- ),
- AttributeSpecification::new(
- constants::DW_AT_language,
- constants::DW_FORM_data2,
- None,
- ),
- ]
- .into(),
- );
-
- let abbrev2 = Abbreviation::new(
- 2,
- constants::DW_TAG_subprogram,
- constants::DW_CHILDREN_no,
- vec![AttributeSpecification::new(
- constants::DW_AT_name,
- constants::DW_FORM_string,
- None,
- )]
- .into(),
- );
-
- let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
- assert_eq!(abbrevs.get(1), Some(&abbrev1));
- assert_eq!(abbrevs.get(2), Some(&abbrev2));
- assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
- }
-
- #[test]
- fn test_parse_abbreviations_duplicate() {
- let expected_rest = [1, 2, 3, 4];
- #[rustfmt::skip]
- let buf = Section::new()
- .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
- .abbrev_attr_null()
- .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
- .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
- .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
- .abbrev_attr_null()
- .abbrev_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
- let buf = &mut EndianSlice::new(&*buf, LittleEndian);
-
- match Abbreviations::parse(buf) {
- Err(Error::DuplicateAbbreviationCode) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_parse_abbreviation_tag_ok() {
- let buf = [0x01, 0x02];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
- assert_eq!(tag, constants::DW_TAG_array_type);
- assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
- }
-
- #[test]
- fn test_parse_abbreviation_tag_zero() {
- let buf = [0x00];
- let buf = &mut EndianSlice::new(&buf, LittleEndian);
- match Abbreviation::parse_tag(buf) {
- Err(Error::AbbreviationTagZero) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_parse_abbreviation_has_children() {
- let buf = [0x00, 0x01, 0x02];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
- assert_eq!(val, constants::DW_CHILDREN_no);
- let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
- assert_eq!(val, constants::DW_CHILDREN_yes);
- match Abbreviation::parse_has_children(rest) {
- Err(Error::BadHasChildren) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_parse_abbreviation_ok() {
- let expected_rest = [0x01, 0x02, 0x03, 0x04];
- let buf = Section::new()
- .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
- .abbrev_attr_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
- let rest = &mut EndianSlice::new(&*buf, LittleEndian);
-
- let expect = Some(Abbreviation::new(
- 1,
- constants::DW_TAG_subprogram,
- constants::DW_CHILDREN_no,
- vec![AttributeSpecification::new(
- constants::DW_AT_name,
- constants::DW_FORM_string,
- None,
- )]
- .into(),
- ));
-
- let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
- assert_eq!(abbrev, expect);
- assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
- }
-
- #[test]
- fn test_parse_abbreviation_implicit_const_ok() {
- let expected_rest = [0x01, 0x02, 0x03, 0x04];
- let buf = Section::new()
- .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr_implicit_const(constants::DW_AT_name, -42)
- .abbrev_attr_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
- let rest = &mut EndianSlice::new(&*buf, LittleEndian);
-
- let expect = Some(Abbreviation::new(
- 1,
- constants::DW_TAG_subprogram,
- constants::DW_CHILDREN_no,
- vec![AttributeSpecification::new(
- constants::DW_AT_name,
- constants::DW_FORM_implicit_const,
- Some(-42),
- )]
- .into(),
- ));
-
- let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
- assert_eq!(abbrev, expect);
- assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
- }
-
- #[test]
- fn test_parse_abbreviation_implicit_const_no_const() {
- let buf = Section::new()
- .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
- .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const)
- .get_contents()
- .unwrap();
- let buf = &mut EndianSlice::new(&*buf, LittleEndian);
-
- match Abbreviation::parse(buf) {
- Err(Error::UnexpectedEof(_)) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- }
- }
-
- #[test]
- fn test_parse_null_abbreviation_ok() {
- let expected_rest = [0x01, 0x02, 0x03, 0x04];
- let buf = Section::new()
- .abbrev_null()
- .append_bytes(&expected_rest)
- .get_contents()
- .unwrap();
- let rest = &mut EndianSlice::new(&*buf, LittleEndian);
-
- let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
- assert!(abbrev.is_none());
- assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
- }
-
- #[test]
- fn test_parse_attribute_form_ok() {
- let buf = [0x01, 0x02];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let tag = AttributeSpecification::parse_form(rest).expect("Should parse form");
- assert_eq!(tag, constants::DW_FORM_addr);
- assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
- }
-
- #[test]
- fn test_parse_attribute_form_zero() {
- let buf = [0x00];
- let buf = &mut EndianSlice::new(&buf, LittleEndian);
- match AttributeSpecification::parse_form(buf) {
- Err(Error::AttributeFormZero) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_parse_null_attribute_specification_ok() {
- let buf = [0x00, 0x00, 0x01];
- let rest = &mut EndianSlice::new(&buf, LittleEndian);
- let attr =
- AttributeSpecification::parse(rest).expect("Should parse null attribute specification");
- assert!(attr.is_none());
- assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian));
- }
-
- #[test]
- fn test_parse_attribute_specifications_name_zero() {
- let buf = [0x00, 0x01, 0x00, 0x00];
- let buf = &mut EndianSlice::new(&buf, LittleEndian);
- match AttributeSpecification::parse(buf) {
- Err(Error::ExpectedZero) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_parse_attribute_specifications_form_zero() {
- let buf = [0x01, 0x00, 0x00, 0x00];
- let buf = &mut EndianSlice::new(&buf, LittleEndian);
- match AttributeSpecification::parse(buf) {
- Err(Error::AttributeFormZero) => {}
- otherwise => panic!("Unexpected result: {:?}", otherwise),
- };
- }
-
- #[test]
- fn test_get_abbrev_zero() {
- let mut abbrevs = Abbreviations::empty();
- abbrevs
- .insert(Abbreviation::new(
- 1,
- constants::DwTag(1),
- constants::DW_CHILDREN_no,
- vec![].into(),
- ))
- .unwrap();
- assert!(abbrevs.get(0).is_none());
- }
-}