summaryrefslogtreecommitdiffstats
path: root/vendor/gimli/src/read/abbrev.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gimli/src/read/abbrev.rs')
-rw-r--r--vendor/gimli/src/read/abbrev.rs129
1 files changed, 111 insertions, 18 deletions
diff --git a/vendor/gimli/src/read/abbrev.rs b/vendor/gimli/src/read/abbrev.rs
index 1a24835a7..54f5cf8e5 100644
--- a/vendor/gimli/src/read/abbrev.rs
+++ b/vendor/gimli/src/read/abbrev.rs
@@ -1,6 +1,7 @@
//! 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};
@@ -10,7 +11,8 @@ use core::ops::Deref;
use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
use crate::constants;
use crate::endianity::Endianity;
-use crate::read::{EndianSlice, Error, Reader, Result, Section, UnitHeader};
+use crate::read::lazy::LazyArc;
+use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader};
/// The `DebugAbbrev` struct represents the abbreviations describing
/// `DebuggingInformationEntry`s' attribute names and forms found in the
@@ -100,6 +102,38 @@ impl<R> From<R> for DebugAbbrev<R> {
}
}
+/// A cache of previously parsed `Abbreviations`.
+///
+/// Currently this only caches the abbreviations for offset 0,
+/// since this is a common case in which abbreviations are reused.
+/// This strategy may change in future if there is sufficient need.
+#[derive(Debug, Default)]
+pub struct AbbreviationsCache {
+ abbreviations: LazyArc<Abbreviations>,
+}
+
+impl AbbreviationsCache {
+ /// Create an empty abbreviations cache.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Parse the abbreviations at the given offset.
+ ///
+ /// This uses or updates the cache as required.
+ pub fn get<R: Reader>(
+ &self,
+ debug_abbrev: &DebugAbbrev<R>,
+ offset: DebugAbbrevOffset<R::Offset>,
+ ) -> Result<Arc<Abbreviations>> {
+ if offset.0 != R::Offset::from_u8(0) {
+ return debug_abbrev.abbreviations(offset).map(Arc::new);
+ }
+ self.abbreviations
+ .get(|| debug_abbrev.abbreviations(offset))
+ }
+}
+
/// A set of type abbreviations.
///
/// Construct an `Abbreviations` instance with the
@@ -310,7 +344,7 @@ impl Attributes {
/// Pushes a new value onto this list of attributes.
fn push(&mut self, attr: AttributeSpecification) {
match self {
- Attributes::Heap(list) => return list.push(attr),
+ Attributes::Heap(list) => list.push(attr),
Attributes::Inline {
buf,
len: MAX_ATTRIBUTES_INLINE,
@@ -329,13 +363,13 @@ impl Attributes {
impl Debug for Attributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (&**self).fmt(f)
+ (**self).fmt(f)
}
}
impl PartialEq for Attributes {
fn eq(&self, other: &Attributes) -> bool {
- &**self == &**other
+ **self == **other
}
}
@@ -360,7 +394,7 @@ impl FromIterator<AttributeSpecification> for Attributes {
for item in iter {
list.push(item);
}
- return list;
+ list
}
}
@@ -470,8 +504,7 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
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_implicit_const | constants::DW_FORM_flag_present => Some(0),
constants::DW_FORM_data1
| constants::DW_FORM_flag
@@ -497,7 +530,7 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
| constants::DW_FORM_ref_sig8
| constants::DW_FORM_ref_sup8 => Some(8),
- constants::DW_FORM_data16 => Some(16),
+ constants::DW_FORM_data16 => Some(16),
constants::DW_FORM_sec_offset
| constants::DW_FORM_GNU_ref_alt
@@ -518,16 +551,16 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
}
// 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 |
+ 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,
@@ -993,4 +1026,64 @@ pub mod tests {
.unwrap();
assert!(abbrevs.get(0).is_none());
}
+
+ #[test]
+ fn abbreviations_cache() {
+ #[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_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()
+ .get_contents()
+ .unwrap();
+
+ let abbrev1 = 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 abbrev2 = 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 debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
+ let cache = AbbreviationsCache::new();
+ let abbrevs1 = cache.get(&debug_abbrev, DebugAbbrevOffset(0)).unwrap();
+ assert_eq!(abbrevs1.get(1), Some(&abbrev1));
+ let abbrevs2 = cache.get(&debug_abbrev, DebugAbbrevOffset(8)).unwrap();
+ assert_eq!(abbrevs2.get(1), Some(&abbrev2));
+ let abbrevs3 = cache.get(&debug_abbrev, DebugAbbrevOffset(0)).unwrap();
+ assert_eq!(abbrevs3.get(1), Some(&abbrev1));
+
+ assert!(!Arc::ptr_eq(&abbrevs1, &abbrevs2));
+ assert!(Arc::ptr_eq(&abbrevs1, &abbrevs3));
+ }
}