1 use core::cmp::Ordering;
2 use core::marker::PhantomData;
3 
4 use crate::common::{DebugInfoOffset, Encoding, SectionId};
5 use crate::endianity::Endianity;
6 use crate::read::lookup::{DebugLookup, LookupEntryIter, LookupParser};
7 use crate::read::{
8     parse_debug_info_offset, EndianSlice, Error, Reader, ReaderOffset, Result, Section,
9 };
10 
11 #[derive(Debug, Clone, PartialEq, Eq)]
12 struct ArangeHeader<T = usize> {
13     encoding: Encoding,
14     length: T,
15     offset: DebugInfoOffset<T>,
16     segment_size: u8,
17 }
18 
19 /// A single parsed arange.
20 #[derive(Debug, Clone, PartialEq, Eq)]
21 pub struct ArangeEntry<T: Copy = usize> {
22     segment: Option<u64>,
23     address: u64,
24     length: u64,
25     unit_header_offset: DebugInfoOffset<T>,
26 }
27 
28 impl<T: Copy> ArangeEntry<T> {
29     /// Return the segment selector of this arange.
30     #[inline]
segment(&self) -> Option<u64>31     pub fn segment(&self) -> Option<u64> {
32         self.segment
33     }
34 
35     /// Return the beginning address of this arange.
36     #[inline]
address(&self) -> u6437     pub fn address(&self) -> u64 {
38         self.address
39     }
40 
41     /// Return the length of this arange.
42     #[inline]
length(&self) -> u6443     pub fn length(&self) -> u64 {
44         self.length
45     }
46 
47     /// Return the offset into the .debug_info section for this arange.
48     #[inline]
debug_info_offset(&self) -> DebugInfoOffset<T>49     pub fn debug_info_offset(&self) -> DebugInfoOffset<T> {
50         self.unit_header_offset
51     }
52 }
53 
54 impl<T: Copy + Ord> PartialOrd for ArangeEntry<T> {
partial_cmp(&self, other: &ArangeEntry<T>) -> Option<Ordering>55     fn partial_cmp(&self, other: &ArangeEntry<T>) -> Option<Ordering> {
56         Some(self.cmp(other))
57     }
58 }
59 
60 impl<T: Copy + Ord> Ord for ArangeEntry<T> {
cmp(&self, other: &ArangeEntry<T>) -> Ordering61     fn cmp(&self, other: &ArangeEntry<T>) -> Ordering {
62         // The expected comparison, but ignore header.
63         self.segment
64             .cmp(&other.segment)
65             .then(self.address.cmp(&other.address))
66             .then(self.length.cmp(&other.length))
67     }
68 }
69 
70 #[derive(Clone, Debug)]
71 struct ArangeParser<R: Reader> {
72     // This struct is never instantiated.
73     phantom: PhantomData<R>,
74 }
75 
76 impl<R: Reader> LookupParser<R> for ArangeParser<R> {
77     type Header = ArangeHeader<R::Offset>;
78     type Entry = ArangeEntry<R::Offset>;
79 
80     /// Parse an arange set header. Returns a tuple of the aranges to be
81     /// parsed for this set, and the newly created ArangeHeader struct.
parse_header(input: &mut R) -> Result<(R, Self::Header)>82     fn parse_header(input: &mut R) -> Result<(R, Self::Header)> {
83         let (length, format) = input.read_initial_length()?;
84         let mut rest = input.split(length)?;
85 
86         let version = rest.read_u16()?;
87         if version != 2 {
88             return Err(Error::UnknownVersion(u64::from(version)));
89         }
90 
91         let offset = parse_debug_info_offset(&mut rest, format)?;
92         let address_size = rest.read_u8()?;
93         let segment_size = rest.read_u8()?;
94 
95         // unit_length + version + offset + address_size + segment_size
96         let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
97 
98         // The first tuple following the header in each set begins at an offset that is
99         // a multiple of the size of a single tuple (that is, the size of a segment selector
100         // plus twice the size of an address).
101         let tuple_length = address_size
102             .checked_mul(2)
103             .and_then(|x| x.checked_add(segment_size))
104             .ok_or(Error::InvalidAddressRange)?;
105         if tuple_length == 0 {
106             return Err(Error::InvalidAddressRange)?;
107         }
108         let padding = if header_length % tuple_length == 0 {
109             0
110         } else {
111             tuple_length - header_length % tuple_length
112         };
113         rest.skip(R::Offset::from_u8(padding))?;
114 
115         let encoding = Encoding {
116             format,
117             version,
118             address_size,
119             // TODO: segment_size
120         };
121         Ok((
122             rest,
123             ArangeHeader {
124                 encoding,
125                 length,
126                 offset,
127                 segment_size,
128             },
129         ))
130     }
131 
132     /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>>133     fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>> {
134         let address_size = header.encoding.address_size;
135         let segment_size = header.segment_size; // May be zero!
136 
137         let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
138         if tuple_length > input.len() {
139             input.empty();
140             return Ok(None);
141         }
142 
143         let segment = if segment_size != 0 {
144             input.read_address(segment_size)?
145         } else {
146             0
147         };
148         let address = input.read_address(address_size)?;
149         let length = input.read_address(address_size)?;
150 
151         match (segment, address, length) {
152             // There may be multiple sets of tuples, each terminated by a zero tuple.
153             // It's not clear what purpose these zero tuples serve.  For now, we
154             // simply skip them.
155             (0, 0, 0) => Self::parse_entry(input, header),
156             _ => Ok(Some(ArangeEntry {
157                 segment: if segment_size != 0 {
158                     Some(segment)
159                 } else {
160                     None
161                 },
162                 address,
163                 length,
164                 unit_header_offset: header.offset,
165             })),
166         }
167     }
168 }
169 
170 /// The `DebugAranges` struct represents the DWARF address range information
171 /// found in the `.debug_aranges` section.
172 #[derive(Debug, Clone)]
173 pub struct DebugAranges<R: Reader>(DebugLookup<R, ArangeParser<R>>);
174 
175 impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
176 where
177     Endian: Endianity,
178 {
179     /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
180     /// section.
181     ///
182     /// It is the caller's responsibility to read the `.debug_aranges` section and
183     /// present it as a `&[u8]` slice. That means using some ELF loader on
184     /// Linux, a Mach-O loader on OSX, etc.
185     ///
186     /// ```
187     /// use gimli::{DebugAranges, LittleEndian};
188     ///
189     /// # let buf = [];
190     /// # let read_debug_aranges_section = || &buf;
191     /// let debug_aranges =
192     ///     DebugAranges::new(read_debug_aranges_section(), LittleEndian);
193     /// ```
new(debug_aranges_section: &'input [u8], endian: Endian) -> Self194     pub fn new(debug_aranges_section: &'input [u8], endian: Endian) -> Self {
195         Self::from(EndianSlice::new(debug_aranges_section, endian))
196     }
197 }
198 
199 impl<R: Reader> DebugAranges<R> {
200     /// Iterate the aranges in the `.debug_aranges` section.
201     ///
202     /// ```
203     /// use gimli::{DebugAranges, EndianSlice, LittleEndian};
204     ///
205     /// # let buf = [];
206     /// # let read_debug_aranges_section = || &buf;
207     /// let debug_aranges = DebugAranges::new(read_debug_aranges_section(), LittleEndian);
208     ///
209     /// let mut iter = debug_aranges.items();
210     /// while let Some(arange) = iter.next().unwrap() {
211     ///     println!("arange starts at {}, has length {}", arange.address(), arange.length());
212     /// }
213     /// ```
items(&self) -> ArangeEntryIter<R>214     pub fn items(&self) -> ArangeEntryIter<R> {
215         ArangeEntryIter(self.0.items())
216     }
217 }
218 
219 impl<R: Reader> Section<R> for DebugAranges<R> {
id() -> SectionId220     fn id() -> SectionId {
221         SectionId::DebugAranges
222     }
223 
reader(&self) -> &R224     fn reader(&self) -> &R {
225         self.0.reader()
226     }
227 }
228 
229 impl<R: Reader> From<R> for DebugAranges<R> {
from(debug_aranges_section: R) -> Self230     fn from(debug_aranges_section: R) -> Self {
231         DebugAranges(DebugLookup::from(debug_aranges_section))
232     }
233 }
234 
235 /// An iterator over the aranges from a `.debug_aranges` section.
236 ///
237 /// Can be [used with
238 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
239 #[derive(Debug, Clone)]
240 pub struct ArangeEntryIter<R: Reader>(LookupEntryIter<R, ArangeParser<R>>);
241 
242 impl<R: Reader> ArangeEntryIter<R> {
243     /// Advance the iterator and return the next arange.
244     ///
245     /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
246     /// when iteration is complete and all aranges have already been parsed and
247     /// yielded. If an error occurs while parsing the next arange, then this error
248     /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
next(&mut self) -> Result<Option<ArangeEntry<R::Offset>>>249     pub fn next(&mut self) -> Result<Option<ArangeEntry<R::Offset>>> {
250         self.0.next()
251     }
252 }
253 
254 #[cfg(feature = "fallible-iterator")]
255 impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
256     type Item = ArangeEntry<R::Offset>;
257     type Error = Error;
258 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>259     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
260         self.0.next()
261     }
262 }
263 
264 #[cfg(test)]
265 mod tests {
266     use super::*;
267     use crate::common::{DebugInfoOffset, Format};
268     use crate::endianity::LittleEndian;
269     use crate::read::lookup::LookupParser;
270     use crate::read::EndianSlice;
271 
272     #[test]
test_parse_header_ok()273     fn test_parse_header_ok() {
274         #[rustfmt::skip]
275         let buf = [
276             // 32-bit length = 32.
277             0x20, 0x00, 0x00, 0x00,
278             // Version.
279             0x02, 0x00,
280             // Offset.
281             0x01, 0x02, 0x03, 0x04,
282             // Address size.
283             0x08,
284             // Segment size.
285             0x04,
286             // Length to here = 12, tuple length = 20.
287             // Padding to tuple length multiple = 4.
288             0x10, 0x00, 0x00, 0x00,
289             0x00, 0x00, 0x00, 0x00,
290 
291             // Dummy arange tuple data.
292             0x20, 0x00, 0x00, 0x00,
293             0x00, 0x00, 0x00, 0x00,
294             0x00, 0x00, 0x00, 0x00,
295             0x00, 0x00, 0x00, 0x00,
296 
297             // Dummy next arange.
298             0x30, 0x00, 0x00, 0x00,
299             0x00, 0x00, 0x00, 0x00,
300             0x00, 0x00, 0x00, 0x00,
301             0x00, 0x00, 0x00, 0x00,
302         ];
303 
304         let rest = &mut EndianSlice::new(&buf, LittleEndian);
305 
306         let (tuples, header) = ArangeParser::parse_header(rest).expect("should parse header ok");
307 
308         assert_eq!(
309             *rest,
310             EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
311         );
312         assert_eq!(
313             tuples,
314             EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian)
315         );
316         assert_eq!(
317             header,
318             ArangeHeader {
319                 encoding: Encoding {
320                     format: Format::Dwarf32,
321                     version: 2,
322                     address_size: 8,
323                 },
324                 length: 0x20,
325                 offset: DebugInfoOffset(0x0403_0201),
326                 segment_size: 4,
327             }
328         );
329     }
330 
331     #[test]
test_parse_header_overflow_error()332     fn test_parse_header_overflow_error() {
333         #[rustfmt::skip]
334         let buf = [
335             // 32-bit length = 32.
336             0x20, 0x00, 0x00, 0x00,
337             // Version.
338             0x02, 0x00,
339             // Offset.
340             0x01, 0x02, 0x03, 0x04,
341             // Address size.
342             0xff,
343             // Segment size.
344             0xff,
345             // Length to here = 12, tuple length = 20.
346             // Padding to tuple length multiple = 4.
347             0x10, 0x00, 0x00, 0x00,
348             0x00, 0x00, 0x00, 0x00,
349 
350             // Dummy arange tuple data.
351             0x20, 0x00, 0x00, 0x00,
352             0x00, 0x00, 0x00, 0x00,
353             0x00, 0x00, 0x00, 0x00,
354             0x00, 0x00, 0x00, 0x00,
355 
356             // Dummy next arange.
357             0x30, 0x00, 0x00, 0x00,
358             0x00, 0x00, 0x00, 0x00,
359             0x00, 0x00, 0x00, 0x00,
360             0x00, 0x00, 0x00, 0x00,
361         ];
362 
363         let rest = &mut EndianSlice::new(&buf, LittleEndian);
364 
365         let error = ArangeParser::parse_header(rest).expect_err("should fail to parse header");
366         assert_eq!(error, Error::InvalidAddressRange);
367     }
368 
369     #[test]
test_parse_header_div_by_zero_error()370     fn test_parse_header_div_by_zero_error() {
371         #[rustfmt::skip]
372         let buf = [
373             // 32-bit length = 32.
374             0x20, 0x00, 0x00, 0x00,
375             // Version.
376             0x02, 0x00,
377             // Offset.
378             0x01, 0x02, 0x03, 0x04,
379             // Address size = 0. Could cause a division by zero if we aren't
380             // careful.
381             0x00,
382             // Segment size.
383             0x00,
384             // Length to here = 12, tuple length = 20.
385             // Padding to tuple length multiple = 4.
386             0x10, 0x00, 0x00, 0x00,
387             0x00, 0x00, 0x00, 0x00,
388 
389             // Dummy arange tuple data.
390             0x20, 0x00, 0x00, 0x00,
391             0x00, 0x00, 0x00, 0x00,
392             0x00, 0x00, 0x00, 0x00,
393             0x00, 0x00, 0x00, 0x00,
394 
395             // Dummy next arange.
396             0x30, 0x00, 0x00, 0x00,
397             0x00, 0x00, 0x00, 0x00,
398             0x00, 0x00, 0x00, 0x00,
399             0x00, 0x00, 0x00, 0x00,
400         ];
401 
402         let rest = &mut EndianSlice::new(&buf, LittleEndian);
403 
404         let error = ArangeParser::parse_header(rest).expect_err("should fail to parse header");
405         assert_eq!(error, Error::InvalidAddressRange);
406     }
407 
408     #[test]
test_parse_entry_ok()409     fn test_parse_entry_ok() {
410         let header = ArangeHeader {
411             encoding: Encoding {
412                 format: Format::Dwarf32,
413                 version: 2,
414                 address_size: 4,
415             },
416             length: 0,
417             offset: DebugInfoOffset(0),
418             segment_size: 0,
419         };
420         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
421         let rest = &mut EndianSlice::new(&buf, LittleEndian);
422         let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok");
423         assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
424         assert_eq!(
425             entry,
426             Some(ArangeEntry {
427                 segment: None,
428                 address: 0x0403_0201,
429                 length: 0x0807_0605,
430                 unit_header_offset: header.offset,
431             })
432         );
433     }
434 
435     #[test]
test_parse_entry_segment()436     fn test_parse_entry_segment() {
437         let header = ArangeHeader {
438             encoding: Encoding {
439                 format: Format::Dwarf32,
440                 version: 2,
441                 address_size: 4,
442             },
443             length: 0,
444             offset: DebugInfoOffset(0),
445             segment_size: 8,
446         };
447         #[rustfmt::skip]
448         let buf = [
449             // Segment.
450             0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
451             // Address.
452             0x01, 0x02, 0x03, 0x04,
453             // Length.
454             0x05, 0x06, 0x07, 0x08,
455             // Next tuple.
456             0x09
457         ];
458         let rest = &mut EndianSlice::new(&buf, LittleEndian);
459         let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok");
460         assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
461         assert_eq!(
462             entry,
463             Some(ArangeEntry {
464                 segment: Some(0x1817_1615_1413_1211),
465                 address: 0x0403_0201,
466                 length: 0x0807_0605,
467                 unit_header_offset: header.offset,
468             })
469         );
470     }
471 
472     #[test]
test_parse_entry_zero()473     fn test_parse_entry_zero() {
474         let header = ArangeHeader {
475             encoding: Encoding {
476                 format: Format::Dwarf32,
477                 version: 2,
478                 address_size: 4,
479             },
480             length: 0,
481             offset: DebugInfoOffset(0),
482             segment_size: 0,
483         };
484         #[rustfmt::skip]
485         let buf = [
486             // Zero tuple.
487             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488             // Address.
489             0x01, 0x02, 0x03, 0x04,
490             // Length.
491             0x05, 0x06, 0x07, 0x08,
492             // Next tuple.
493             0x09
494         ];
495         let rest = &mut EndianSlice::new(&buf, LittleEndian);
496         let entry = ArangeParser::parse_entry(rest, &header).expect("should parse entry ok");
497         assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
498         assert_eq!(
499             entry,
500             Some(ArangeEntry {
501                 segment: None,
502                 address: 0x0403_0201,
503                 length: 0x0807_0605,
504                 unit_header_offset: header.offset,
505             })
506         );
507     }
508 }
509