summaryrefslogtreecommitdiff
path: root/vendor/gimli/src/read/addr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gimli/src/read/addr.rs')
-rw-r--r--vendor/gimli/src/read/addr.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/vendor/gimli/src/read/addr.rs b/vendor/gimli/src/read/addr.rs
new file mode 100644
index 0000000..593f9fe
--- /dev/null
+++ b/vendor/gimli/src/read/addr.rs
@@ -0,0 +1,128 @@
+use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
+use crate::read::{Reader, ReaderOffset, Result, Section};
+
+/// The raw contents of the `.debug_addr` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugAddr<R> {
+ section: R,
+}
+
+impl<R: Reader> DebugAddr<R> {
+ // TODO: add an iterator over the sets of addresses in the section.
+ // This is not needed for common usage of the section though.
+
+ /// Returns the address at the given `base` and `index`.
+ ///
+ /// A set of addresses in the `.debug_addr` section consists of a header
+ /// followed by a series of addresses.
+ ///
+ /// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
+ /// This is an offset that points to the first address following the header.
+ ///
+ /// The `index` is the value of a `DW_FORM_addrx` attribute.
+ ///
+ /// The `address_size` must be the size of the address for the compilation unit.
+ /// This value must also match the header. However, note that we do not parse the
+ /// header to validate this, since locating the header is unreliable, and the GNU
+ /// extensions do not emit it.
+ pub fn get_address(
+ &self,
+ address_size: u8,
+ base: DebugAddrBase<R::Offset>,
+ index: DebugAddrIndex<R::Offset>,
+ ) -> Result<u64> {
+ let input = &mut self.section.clone();
+ input.skip(base.0)?;
+ input.skip(R::Offset::from_u64(
+ index.0.into_u64() * u64::from(address_size),
+ )?)?;
+ input.read_address(address_size)
+ }
+}
+
+impl<T> DebugAddr<T> {
+ /// Create a `DebugAddr` 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::DebugAddr<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) -> DebugAddr<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.section).into()
+ }
+}
+
+impl<R> Section<R> for DebugAddr<R> {
+ fn id() -> SectionId {
+ SectionId::DebugAddr
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugAddr<R> {
+ fn from(section: R) -> Self {
+ DebugAddr { section }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::read::EndianSlice;
+ use crate::test_util::GimliSectionMethods;
+ use crate::{Format, LittleEndian};
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_get_address() {
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ for address_size in vec![4, 8] {
+ let zero = Label::new();
+ let length = Label::new();
+ let start = Label::new();
+ let first = Label::new();
+ let end = Label::new();
+ let mut section = Section::with_endian(Endian::Little)
+ .mark(&zero)
+ .initial_length(format, &length, &start)
+ .D16(5)
+ .D8(address_size)
+ .D8(0)
+ .mark(&first);
+ for i in 0..20 {
+ section = section.word(address_size, 1000 + i);
+ }
+ section = section.mark(&end);
+ length.set_const((&end - &start) as u64);
+
+ let section = section.get_contents().unwrap();
+ let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
+ let base = DebugAddrBase((&first - &zero) as usize);
+
+ assert_eq!(
+ debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
+ Ok(1000)
+ );
+ assert_eq!(
+ debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
+ Ok(1019)
+ );
+ }
+ }
+ }
+}