1use crate::common::{DebugAddrBase, DebugAddrIndex, DebugAddrOffset, Encoding, SectionId};
2use crate::read::{Error, Reader, ReaderOffset, Result, Section};
3
4#[derive(Debug, Default, Clone, Copy)]
6pub struct DebugAddr<R> {
7 section: R,
8}
9
10impl<R: Reader> DebugAddr<R> {
11 pub fn get_address(
26 &self,
27 address_size: u8,
28 base: DebugAddrBase<R::Offset>,
29 index: DebugAddrIndex<R::Offset>,
30 ) -> Result<u64> {
31 let input = &mut self.section.clone();
32 input.skip(base.0)?;
33 input.skip(R::Offset::from_u64(
34 index.0.into_u64() * u64::from(address_size),
35 )?)?;
36 input.read_address(address_size)
37 }
38
39 pub fn headers(&self) -> AddrHeaderIter<R> {
43 AddrHeaderIter {
44 input: self.section.clone(),
45 offset: DebugAddrOffset(R::Offset::from_u8(0)),
46 }
47 }
48}
49
50impl<T> DebugAddr<T> {
51 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
57 where
58 F: FnMut(&'a T) -> R,
59 {
60 borrow(&self.section).into()
61 }
62}
63
64impl<R> Section<R> for DebugAddr<R> {
65 fn id() -> SectionId {
66 SectionId::DebugAddr
67 }
68
69 fn reader(&self) -> &R {
70 &self.section
71 }
72}
73
74impl<R> From<R> for DebugAddr<R> {
75 fn from(section: R) -> Self {
76 DebugAddr { section }
77 }
78}
79
80#[derive(Clone, Debug)]
82pub struct AddrHeaderIter<R: Reader> {
83 input: R,
84 offset: DebugAddrOffset<R::Offset>,
85}
86
87impl<R: Reader> AddrHeaderIter<R> {
88 pub fn next(&mut self) -> Result<Option<AddrHeader<R>>> {
90 if self.input.is_empty() {
91 return Ok(None);
92 }
93
94 let len = self.input.len();
95 match AddrHeader::parse(&mut self.input, self.offset) {
96 Ok(header) => {
97 self.offset.0 += len - self.input.len();
98 Ok(Some(header))
99 }
100 Err(e) => {
101 self.input.empty();
102 Err(e)
103 }
104 }
105 }
106}
107
108#[cfg(feature = "fallible-iterator")]
109impl<R: Reader> fallible_iterator::FallibleIterator for AddrHeaderIter<R> {
110 type Item = AddrHeader<R>;
111 type Error = Error;
112
113 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
114 AddrHeaderIter::next(self)
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct AddrHeader<R, Offset = <R as Reader>::Offset>
123where
124 R: Reader<Offset = Offset>,
125 Offset: ReaderOffset,
126{
127 offset: DebugAddrOffset<Offset>,
128 encoding: Encoding,
129 length: Offset,
130 entries: R,
131}
132
133impl<R, Offset> AddrHeader<R, Offset>
134where
135 R: Reader<Offset = Offset>,
136 Offset: ReaderOffset,
137{
138 fn parse(input: &mut R, offset: DebugAddrOffset<Offset>) -> Result<Self> {
139 let (length, format) = input.read_initial_length()?;
140 let mut rest = input.split(length)?;
141
142 let version = rest.read_u16()?;
144 if version != 5 {
145 return Err(Error::UnknownVersion(u64::from(version)));
146 }
147
148 let address_size = rest.read_address_size()?;
149 let segment_size = rest.read_u8()?;
150 if segment_size != 0 {
151 return Err(Error::UnsupportedSegmentSize);
152 }
153
154 let header_length = format.initial_length_size() + 2 + 1 + 1;
156
157 let tuple_length = address_size;
161 if tuple_length == 0 {
162 return Err(Error::UnsupportedAddressSize(address_size));
163 }
164 let padding = if header_length % tuple_length == 0 {
165 0
166 } else {
167 tuple_length - header_length % tuple_length
168 };
169 rest.skip(R::Offset::from_u8(padding))?;
170
171 let encoding = Encoding {
172 format,
173 version,
174 address_size,
175 };
176 Ok(AddrHeader {
177 offset,
178 encoding,
179 length,
180 entries: rest,
181 })
182 }
183
184 #[inline]
186 pub fn offset(&self) -> DebugAddrOffset<Offset> {
187 self.offset
188 }
189
190 #[inline]
192 pub fn length(&self) -> Offset {
193 self.length
194 }
195
196 #[inline]
198 pub fn encoding(&self) -> Encoding {
199 self.encoding
200 }
201
202 #[inline]
204 pub fn entries(&self) -> AddrEntryIter<R> {
205 AddrEntryIter {
206 input: self.entries.clone(),
207 encoding: self.encoding,
208 }
209 }
210}
211
212#[derive(Debug, Clone)]
217pub struct AddrEntryIter<R: Reader> {
218 input: R,
219 encoding: Encoding,
220}
221
222impl<R: Reader> AddrEntryIter<R> {
223 pub fn next(&mut self) -> Result<Option<u64>> {
230 if self.input.is_empty() {
231 return Ok(None);
232 }
233
234 match self.input.read_address(self.encoding.address_size) {
235 Ok(entry) => Ok(Some(entry)),
236 Err(e) => {
237 self.input.empty();
238 Err(e)
239 }
240 }
241 }
242}
243
244#[cfg(feature = "fallible-iterator")]
245impl<R: Reader> fallible_iterator::FallibleIterator for AddrEntryIter<R> {
246 type Item = u64;
247 type Error = Error;
248
249 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
250 AddrEntryIter::next(self)
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use crate::read::EndianSlice;
258 use crate::test_util::GimliSectionMethods;
259 use crate::{Format, LittleEndian};
260 use test_assembler::{Endian, Label, LabelMaker, Section};
261
262 #[test]
263 fn test_get_address() {
264 for format in [Format::Dwarf32, Format::Dwarf64] {
265 for address_size in [4, 8] {
266 let zero = Label::new();
267 let length = Label::new();
268 let start = Label::new();
269 let first = Label::new();
270 let end = Label::new();
271 let mut section = Section::with_endian(Endian::Little)
272 .mark(&zero)
273 .initial_length(format, &length, &start)
274 .D16(5)
275 .D8(address_size)
276 .D8(0)
277 .mark(&first);
278 for i in 0..20 {
279 section = section.word(address_size, 1000 + i);
280 }
281 section = section.mark(&end);
282 length.set_const((&end - &start) as u64);
283
284 let section = section.get_contents().unwrap();
285 let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian));
286 let base = DebugAddrBase((&first - &zero) as usize);
287
288 assert_eq!(
289 debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
290 Ok(1000)
291 );
292 assert_eq!(
293 debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
294 Ok(1019)
295 );
296 }
297 }
298 }
299
300 #[test]
301 fn test_iterator() {
302 let length = Label::new();
303 let start = Label::new();
304 let end = Label::new();
305 let mut section = Section::with_endian(Endian::Little)
307 .initial_length(Format::Dwarf32, &length, &start)
308 .D16(5) .D8(4) .D8(0) .word(4, 0x12345678)
312 .word(4, 0xdeadbeef)
313 .mark(&end);
314 length.set_const((&end - &start) as u64);
315 let length = Label::new();
317 let start = Label::new();
318 let end = Label::new();
319 section = section
320 .initial_length(Format::Dwarf64, &length, &start)
321 .D16(5) .D8(8) .D8(0) .word(8, 0x123456789abcdef0)
325 .word(8, 0xdeadbeefdeadbeef)
326 .mark(&end);
327 length.set_const((&end - &start) as u64);
328 let section = section.get_contents().unwrap();
329 let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian));
330 let mut iter = debug_addr.headers();
331 let first_header = iter.next().unwrap().unwrap();
332 let first_encoding = first_header.encoding();
333 assert_eq!(first_encoding.address_size, 4);
334 assert_eq!(first_encoding.format, Format::Dwarf32);
335 assert_eq!(first_encoding.version, 5);
336 assert_eq!(first_header.length(), 12);
337 let mut first_entries = first_header.entries();
338 assert_eq!(first_entries.next(), Ok(Some(0x12345678)));
339 assert_eq!(first_entries.next(), Ok(Some(0xdeadbeef)));
340 assert_eq!(first_entries.next(), Ok(None));
341 let second_header = iter.next().unwrap().unwrap();
342 let second_encoding = second_header.encoding();
343 assert_eq!(second_encoding.address_size, 8);
344 assert_eq!(second_encoding.format, Format::Dwarf64);
345 assert_eq!(second_encoding.version, 5);
346 assert_eq!(second_header.length(), 20);
347 let mut second_entries = second_header.entries();
348 assert_eq!(second_entries.next(), Ok(Some(0x123456789abcdef0)));
349 assert_eq!(second_entries.next(), Ok(Some(0xdeadbeefdeadbeef)));
350 assert_eq!(second_entries.next(), Ok(None));
351 assert_eq!(iter.next(), Ok(None));
352 }
353}