1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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(§ion, 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(§ion, 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)
);
}
}
}
}
|