1 //! Functions for parsing DWARF `.debug_info` and `.debug_types` sections.
2
3 use core::cell::Cell;
4 use core::ops::{Range, RangeFrom, RangeTo};
5 use core::{u16, u8};
6
7 use crate::common::{
8 DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
9 DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
10 DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
11 DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, Encoding, Format,
12 LocationListsOffset, RangeListsOffset, SectionId,
13 };
14 use crate::constants;
15 use crate::endianity::Endianity;
16 use crate::read::{
17 Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
18 Expression, Reader, ReaderOffset, Result, Section,
19 };
20
21 impl<T: ReaderOffset> DebugTypesOffset<T> {
22 /// Convert an offset to be relative to the start of the given unit,
23 /// instead of relative to the start of the .debug_types section.
24 /// Returns `None` if the offset is not within the unit entries.
to_unit_offset<R>(&self, unit: &TypeUnitHeader<R>) -> Option<UnitOffset<T>> where R: Reader<Offset = T>,25 pub fn to_unit_offset<R>(&self, unit: &TypeUnitHeader<R>) -> Option<UnitOffset<T>>
26 where
27 R: Reader<Offset = T>,
28 {
29 let offset = match self.0.checked_sub(unit.offset.0) {
30 Some(offset) => UnitOffset(offset),
31 None => return None,
32 };
33 if !unit.header.is_valid_offset(offset) {
34 return None;
35 }
36 Some(offset)
37 }
38 }
39
40 impl<T: ReaderOffset> DebugInfoOffset<T> {
41 /// Convert an offset to be relative to the start of the given unit,
42 /// instead of relative to the start of the .debug_info section.
43 /// Returns `None` if the offset is not within this unit entries.
to_unit_offset<R>(&self, unit: &CompilationUnitHeader<R>) -> Option<UnitOffset<T>> where R: Reader<Offset = T>,44 pub fn to_unit_offset<R>(&self, unit: &CompilationUnitHeader<R>) -> Option<UnitOffset<T>>
45 where
46 R: Reader<Offset = T>,
47 {
48 let offset = match self.0.checked_sub(unit.offset.0) {
49 Some(offset) => UnitOffset(offset),
50 None => return None,
51 };
52 if !unit.header.is_valid_offset(offset) {
53 return None;
54 }
55 Some(offset)
56 }
57 }
58
59 /// An offset into the current compilation or type unit.
60 #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
61 pub struct UnitOffset<T = usize>(pub T);
62
63 impl<T: ReaderOffset> UnitOffset<T> {
64 /// Convert an offset to be relative to the start of the .debug_info section,
65 /// instead of relative to the start of the given compilation unit.
to_debug_info_offset<R>(&self, unit: &CompilationUnitHeader<R>) -> DebugInfoOffset<T> where R: Reader<Offset = T>,66 pub fn to_debug_info_offset<R>(&self, unit: &CompilationUnitHeader<R>) -> DebugInfoOffset<T>
67 where
68 R: Reader<Offset = T>,
69 {
70 DebugInfoOffset(unit.offset.0 + self.0)
71 }
72
73 /// Convert an offset to be relative to the start of the .debug_types section,
74 /// instead of relative to the start of the given type unit.
to_debug_types_offset<R>(&self, unit: &TypeUnitHeader<R>) -> DebugTypesOffset<T> where R: Reader<Offset = T>,75 pub fn to_debug_types_offset<R>(&self, unit: &TypeUnitHeader<R>) -> DebugTypesOffset<T>
76 where
77 R: Reader<Offset = T>,
78 {
79 DebugTypesOffset(unit.offset.0 + self.0)
80 }
81 }
82
83 /// The `DebugInfo` struct represents the DWARF debugging information found in
84 /// the `.debug_info` section.
85 #[derive(Debug, Default, Clone, Copy)]
86 pub struct DebugInfo<R> {
87 debug_info_section: R,
88 }
89
90 impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
91 where
92 Endian: Endianity,
93 {
94 /// Construct a new `DebugInfo` instance from the data in the `.debug_info`
95 /// section.
96 ///
97 /// It is the caller's responsibility to read the `.debug_info` section and
98 /// present it as a `&[u8]` slice. That means using some ELF loader on
99 /// Linux, a Mach-O loader on OSX, etc.
100 ///
101 /// ```
102 /// use gimli::{DebugInfo, LittleEndian};
103 ///
104 /// # let buf = [0x00, 0x01, 0x02, 0x03];
105 /// # let read_debug_info_section_somehow = || &buf;
106 /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
107 /// ```
new(debug_info_section: &'input [u8], endian: Endian) -> Self108 pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
109 Self::from(EndianSlice::new(debug_info_section, endian))
110 }
111 }
112
113 impl<R: Reader> DebugInfo<R> {
114 /// Iterate the compilation- and partial-units in this
115 /// `.debug_info` section.
116 ///
117 /// ```
118 /// use gimli::{DebugInfo, LittleEndian};
119 ///
120 /// # let buf = [];
121 /// # let read_debug_info_section_somehow = || &buf;
122 /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
123 ///
124 /// let mut iter = debug_info.units();
125 /// while let Some(unit) = iter.next().unwrap() {
126 /// println!("unit's length is {}", unit.unit_length());
127 /// }
128 /// ```
129 ///
130 /// Can be [used with
131 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
units(&self) -> CompilationUnitHeadersIter<R>132 pub fn units(&self) -> CompilationUnitHeadersIter<R> {
133 CompilationUnitHeadersIter {
134 input: self.debug_info_section.clone(),
135 offset: DebugInfoOffset(R::Offset::from_u8(0)),
136 }
137 }
138
139 /// Get the CompilationUnitHeader located at offset from this .debug_info section.
140 ///
141 ///
header_from_offset( &self, offset: DebugInfoOffset<R::Offset>, ) -> Result<CompilationUnitHeader<R>>142 pub fn header_from_offset(
143 &self,
144 offset: DebugInfoOffset<R::Offset>,
145 ) -> Result<CompilationUnitHeader<R>> {
146 let input = &mut self.debug_info_section.clone();
147 input.skip(offset.0)?;
148 CompilationUnitHeader::parse(input, offset)
149 }
150 }
151
152 impl<T> DebugInfo<T> {
153 /// Create a `DebugInfo` section that references the data in `self`.
154 ///
155 /// This is useful when `R` implements `Reader` but `T` does not.
156 ///
157 /// ## Example Usage
158 ///
159 /// ```rust,no_run
160 /// # let load_section = || unimplemented!();
161 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
162 /// let owned_section: gimli::DebugInfo<Vec<u8>> = load_section();
163 /// // Create a reference to the DWARF section.
164 /// let section = owned_section.borrow(|section| {
165 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
166 /// });
167 /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R> where F: FnMut(&'a T) -> R,168 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
169 where
170 F: FnMut(&'a T) -> R,
171 {
172 borrow(&self.debug_info_section).into()
173 }
174 }
175
176 impl<R> Section<R> for DebugInfo<R> {
id() -> SectionId177 fn id() -> SectionId {
178 SectionId::DebugInfo
179 }
180
reader(&self) -> &R181 fn reader(&self) -> &R {
182 &self.debug_info_section
183 }
184 }
185
186 impl<R> From<R> for DebugInfo<R> {
from(debug_info_section: R) -> Self187 fn from(debug_info_section: R) -> Self {
188 DebugInfo { debug_info_section }
189 }
190 }
191
192 /// An iterator over the compilation- and partial-units of a section.
193 ///
194 /// See the [documentation on
195 /// `DebugInfo::units`](./struct.DebugInfo.html#method.units) for more detail.
196 #[derive(Clone, Debug)]
197 pub struct CompilationUnitHeadersIter<R: Reader> {
198 input: R,
199 offset: DebugInfoOffset<R::Offset>,
200 }
201
202 impl<R: Reader> CompilationUnitHeadersIter<R> {
203 /// Advance the iterator to the next unit header.
next(&mut self) -> Result<Option<CompilationUnitHeader<R>>>204 pub fn next(&mut self) -> Result<Option<CompilationUnitHeader<R>>> {
205 if self.input.is_empty() {
206 Ok(None)
207 } else {
208 let len = self.input.len();
209 match CompilationUnitHeader::parse(&mut self.input, self.offset) {
210 Ok(header) => {
211 self.offset.0 += len - self.input.len();
212 Ok(Some(header))
213 }
214 Err(e) => {
215 self.input.empty();
216 Err(e)
217 }
218 }
219 }
220 }
221 }
222
223 #[cfg(feature = "fallible-iterator")]
224 impl<R: Reader> fallible_iterator::FallibleIterator for CompilationUnitHeadersIter<R> {
225 type Item = CompilationUnitHeader<R>;
226 type Error = Error;
227
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>228 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
229 CompilationUnitHeadersIter::next(self)
230 }
231 }
232
233 /// The header of a compilation unit's debugging information.
234 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
235 pub struct CompilationUnitHeader<R, Offset = <R as Reader>::Offset>
236 where
237 R: Reader<Offset = Offset>,
238 Offset: ReaderOffset,
239 {
240 header: UnitHeader<R, Offset>,
241 offset: DebugInfoOffset<Offset>,
242 }
243
244 impl<R, Offset> CompilationUnitHeader<R, Offset>
245 where
246 R: Reader<Offset = Offset>,
247 Offset: ReaderOffset,
248 {
249 /// Construct a new `CompilationUnitHeader`.
new(header: UnitHeader<R, Offset>, offset: DebugInfoOffset<Offset>) -> Self250 pub fn new(header: UnitHeader<R, Offset>, offset: DebugInfoOffset<Offset>) -> Self {
251 CompilationUnitHeader { header, offset }
252 }
253
254 /// Return the `UnitHeader` containing common unit header fields.
header(self) -> UnitHeader<R, Offset>255 pub fn header(self) -> UnitHeader<R, Offset> {
256 self.header
257 }
258
259 /// Return the serialized size of the compilation unit header for the given
260 /// DWARF encoding.
size_of_header(encoding: Encoding) -> usize261 pub fn size_of_header(encoding: Encoding) -> usize {
262 UnitHeader::<R, _>::size_of_header(encoding)
263 }
264
265 /// Get the offset of this compilation unit within the .debug_info section.
offset(&self) -> DebugInfoOffset<R::Offset>266 pub fn offset(&self) -> DebugInfoOffset<R::Offset> {
267 self.offset
268 }
269
270 /// Get the length of the debugging info for this compilation unit, not
271 /// including the byte length of the encoded length itself.
unit_length(&self) -> R::Offset272 pub fn unit_length(&self) -> R::Offset {
273 self.header.unit_length
274 }
275
276 /// Get the length of the debugging info for this compilation unit,
277 /// including the byte length of the encoded length itself.
length_including_self(&self) -> R::Offset278 pub fn length_including_self(&self) -> R::Offset {
279 self.header.length_including_self()
280 }
281
282 /// Return the encoding parameters for this unit.
encoding(&self) -> Encoding283 pub fn encoding(&self) -> Encoding {
284 self.header.encoding
285 }
286
287 /// Get the DWARF version of the debugging info for this compilation unit.
version(&self) -> u16288 pub fn version(&self) -> u16 {
289 self.header.version()
290 }
291
292 /// The offset into the `.debug_abbrev` section for this compilation unit's
293 /// debugging information entries' abbreviations.
debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset>294 pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset> {
295 self.header.debug_abbrev_offset
296 }
297
298 /// The size of addresses (in bytes) in this type-unit.
address_size(&self) -> u8299 pub fn address_size(&self) -> u8 {
300 self.header.address_size()
301 }
302
303 /// Whether this type unit is encoded in 64- or 32-bit DWARF.
format(&self) -> Format304 pub fn format(&self) -> Format {
305 self.header.format()
306 }
307
308 /// The serialized size of the header for this compilation unit.
header_size(&self) -> R::Offset309 pub fn header_size(&self) -> R::Offset {
310 self.header.header_size()
311 }
312
313 /// Read the `DebuggingInformationEntry` at the given offset.
entry<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<R::Offset>, ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>>314 pub fn entry<'me, 'abbrev>(
315 &'me self,
316 abbreviations: &'abbrev Abbreviations,
317 offset: UnitOffset<R::Offset>,
318 ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>> {
319 self.header.entry(abbreviations, offset)
320 }
321
322 /// Navigate this compilation unit's `DebuggingInformationEntry`s.
entries<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, ) -> EntriesCursor<'abbrev, 'me, R>323 pub fn entries<'me, 'abbrev>(
324 &'me self,
325 abbreviations: &'abbrev Abbreviations,
326 ) -> EntriesCursor<'abbrev, 'me, R> {
327 self.header.entries(abbreviations)
328 }
329
330 /// Navigate this compilation unit's `DebuggingInformationEntry`s
331 /// starting at the given offset.
entries_at_offset<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<R::Offset>, ) -> Result<EntriesCursor<'abbrev, 'me, R>>332 pub fn entries_at_offset<'me, 'abbrev>(
333 &'me self,
334 abbreviations: &'abbrev Abbreviations,
335 offset: UnitOffset<R::Offset>,
336 ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
337 self.header.entries_at_offset(abbreviations, offset)
338 }
339
340 /// Navigate this compilation unit's `DebuggingInformationEntry`s as a tree
341 /// starting at the given offset.
entries_tree<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesTree<'abbrev, 'me, R>>342 pub fn entries_tree<'me, 'abbrev>(
343 &'me self,
344 abbreviations: &'abbrev Abbreviations,
345 offset: Option<UnitOffset<R::Offset>>,
346 ) -> Result<EntriesTree<'abbrev, 'me, R>> {
347 self.header.entries_tree(abbreviations, offset)
348 }
349
350 /// Read the raw data that defines the Debugging Information Entries.
entries_raw<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesRaw<'abbrev, 'me, R>>351 pub fn entries_raw<'me, 'abbrev>(
352 &'me self,
353 abbreviations: &'abbrev Abbreviations,
354 offset: Option<UnitOffset<R::Offset>>,
355 ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
356 self.header.entries_raw(abbreviations, offset)
357 }
358
359 /// Parse this compilation unit's abbreviations.
360 ///
361 /// ```
362 /// use gimli::DebugAbbrev;
363 /// # use gimli::{DebugInfo, LittleEndian};
364 /// # let info_buf = [
365 /// # // Comilation unit header
366 /// #
367 /// # // 32-bit unit length = 25
368 /// # 0x19, 0x00, 0x00, 0x00,
369 /// # // Version 4
370 /// # 0x04, 0x00,
371 /// # // debug_abbrev_offset
372 /// # 0x00, 0x00, 0x00, 0x00,
373 /// # // Address size
374 /// # 0x04,
375 /// #
376 /// # // DIEs
377 /// #
378 /// # // Abbreviation code
379 /// # 0x01,
380 /// # // Attribute of form DW_FORM_string = "foo\0"
381 /// # 0x66, 0x6f, 0x6f, 0x00,
382 /// #
383 /// # // Children
384 /// #
385 /// # // Abbreviation code
386 /// # 0x01,
387 /// # // Attribute of form DW_FORM_string = "foo\0"
388 /// # 0x66, 0x6f, 0x6f, 0x00,
389 /// #
390 /// # // Children
391 /// #
392 /// # // Abbreviation code
393 /// # 0x01,
394 /// # // Attribute of form DW_FORM_string = "foo\0"
395 /// # 0x66, 0x6f, 0x6f, 0x00,
396 /// #
397 /// # // Children
398 /// #
399 /// # // End of children
400 /// # 0x00,
401 /// #
402 /// # // End of children
403 /// # 0x00,
404 /// #
405 /// # // End of children
406 /// # 0x00,
407 /// # ];
408 /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
409 /// #
410 /// # let abbrev_buf = [
411 /// # // Code
412 /// # 0x01,
413 /// # // DW_TAG_subprogram
414 /// # 0x2e,
415 /// # // DW_CHILDREN_yes
416 /// # 0x01,
417 /// # // Begin attributes
418 /// # // Attribute name = DW_AT_name
419 /// # 0x03,
420 /// # // Attribute form = DW_FORM_string
421 /// # 0x08,
422 /// # // End attributes
423 /// # 0x00,
424 /// # 0x00,
425 /// # // Null terminator
426 /// # 0x00
427 /// # ];
428 /// #
429 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
430 ///
431 /// let unit = get_some_unit();
432 ///
433 /// # let read_debug_abbrev_section_somehow = || &abbrev_buf;
434 /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
435 /// let abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
436 /// ```
abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations>437 pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
438 self.header.abbreviations(debug_abbrev)
439 }
440
441 /// Parse a compilation unit header.
parse( input: &mut R, offset: DebugInfoOffset<R::Offset>, ) -> Result<CompilationUnitHeader<R>>442 fn parse(
443 input: &mut R,
444 offset: DebugInfoOffset<R::Offset>,
445 ) -> Result<CompilationUnitHeader<R>> {
446 let header = parse_unit_header(input)?;
447 Ok(CompilationUnitHeader { header, offset })
448 }
449 }
450
451 /// Parse the unit type from the compilation unit header.
parse_compilation_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt>452 fn parse_compilation_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt> {
453 let val = input.read_u8()?;
454 Ok(constants::DwUt(val))
455 }
456
457 /// Parse the `debug_abbrev_offset` in the compilation unit header.
parse_debug_abbrev_offset<R: Reader>( input: &mut R, format: Format, ) -> Result<DebugAbbrevOffset<R::Offset>>458 fn parse_debug_abbrev_offset<R: Reader>(
459 input: &mut R,
460 format: Format,
461 ) -> Result<DebugAbbrevOffset<R::Offset>> {
462 input.read_offset(format).map(DebugAbbrevOffset)
463 }
464
465 /// Parse the `debug_info_offset` in the arange header.
parse_debug_info_offset<R: Reader>( input: &mut R, format: Format, ) -> Result<DebugInfoOffset<R::Offset>>466 pub(crate) fn parse_debug_info_offset<R: Reader>(
467 input: &mut R,
468 format: Format,
469 ) -> Result<DebugInfoOffset<R::Offset>> {
470 input.read_offset(format).map(DebugInfoOffset)
471 }
472
473 /// The common fields for the headers of compilation units and
474 /// type units.
475 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
476 pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
477 where
478 R: Reader<Offset = Offset>,
479 Offset: ReaderOffset,
480 {
481 encoding: Encoding,
482 unit_length: Offset,
483 debug_abbrev_offset: DebugAbbrevOffset<Offset>,
484 entries_buf: R,
485 }
486
487 /// Static methods.
488 impl<R, Offset> UnitHeader<R, Offset>
489 where
490 R: Reader<Offset = Offset>,
491 Offset: ReaderOffset,
492 {
493 /// Construct a new `UnitHeader`.
new( encoding: Encoding, unit_length: R::Offset, debug_abbrev_offset: DebugAbbrevOffset<R::Offset>, entries_buf: R, ) -> Self494 pub fn new(
495 encoding: Encoding,
496 unit_length: R::Offset,
497 debug_abbrev_offset: DebugAbbrevOffset<R::Offset>,
498 entries_buf: R,
499 ) -> Self {
500 UnitHeader {
501 encoding,
502 unit_length,
503 debug_abbrev_offset,
504 entries_buf,
505 }
506 }
507
508 /// Return the serialized size of the common unit header for the given
509 /// DWARF format.
size_of_header(encoding: Encoding) -> usize510 pub fn size_of_header(encoding: Encoding) -> usize {
511 let unit_length_size = encoding.format.initial_length_size() as usize;
512 let version_size = 2;
513 let debug_abbrev_offset_size = encoding.format.word_size() as usize;
514 let address_size_size = 1;
515 let unit_type_size = if encoding.version == 5 { 1 } else { 0 };
516
517 unit_length_size
518 + version_size
519 + debug_abbrev_offset_size
520 + address_size_size
521 + unit_type_size
522 }
523 }
524
525 /// Instance methods.
526 impl<R, Offset> UnitHeader<R, Offset>
527 where
528 R: Reader<Offset = Offset>,
529 Offset: ReaderOffset,
530 {
531 /// Get the length of the debugging info for this compilation unit, not
532 /// including the byte length of the encoded length itself.
unit_length(&self) -> R::Offset533 pub fn unit_length(&self) -> R::Offset {
534 self.unit_length
535 }
536
537 /// Get the length of the debugging info for this compilation unit,
538 /// including the byte length of the encoded length itself.
length_including_self(&self) -> R::Offset539 pub fn length_including_self(&self) -> R::Offset {
540 R::Offset::from_u8(self.format().initial_length_size()) + self.unit_length
541 }
542
543 /// Return the encoding parameters for this unit.
encoding(&self) -> Encoding544 pub fn encoding(&self) -> Encoding {
545 self.encoding
546 }
547
548 /// Get the DWARF version of the debugging info for this compilation unit.
version(&self) -> u16549 pub fn version(&self) -> u16 {
550 self.encoding.version
551 }
552
553 /// The offset into the `.debug_abbrev` section for this compilation unit's
554 /// debugging information entries' abbreviations.
debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset>555 pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset> {
556 self.debug_abbrev_offset
557 }
558
559 /// The size of addresses (in bytes) in this compilation unit.
address_size(&self) -> u8560 pub fn address_size(&self) -> u8 {
561 self.encoding.address_size
562 }
563
564 /// Whether this compilation unit is encoded in 64- or 32-bit DWARF.
format(&self) -> Format565 pub fn format(&self) -> Format {
566 self.encoding.format
567 }
568
569 /// The serialized size of the header for this compilation unit.
header_size(&self) -> R::Offset570 pub fn header_size(&self) -> R::Offset {
571 self.length_including_self() - self.entries_buf.len()
572 }
573
is_valid_offset(&self, offset: UnitOffset<R::Offset>) -> bool574 pub(crate) fn is_valid_offset(&self, offset: UnitOffset<R::Offset>) -> bool {
575 let size_of_header = self.header_size();
576 if offset.0 < size_of_header {
577 return false;
578 }
579
580 let relative_to_entries_buf = offset.0 - size_of_header;
581 relative_to_entries_buf < self.entries_buf.len()
582 }
583
584 /// Get the underlying bytes for the supplied range.
range(&self, idx: Range<UnitOffset<R::Offset>>) -> Result<R>585 pub fn range(&self, idx: Range<UnitOffset<R::Offset>>) -> Result<R> {
586 if !self.is_valid_offset(idx.start) {
587 return Err(Error::OffsetOutOfBounds);
588 }
589 if !self.is_valid_offset(idx.end) {
590 return Err(Error::OffsetOutOfBounds);
591 }
592 assert!(idx.start <= idx.end);
593 let size_of_header = self.header_size();
594 let start = idx.start.0 - size_of_header;
595 let end = idx.end.0 - size_of_header;
596 let mut input = self.entries_buf.clone();
597 input.skip(start)?;
598 input.truncate(end - start)?;
599 Ok(input)
600 }
601
602 /// Get the underlying bytes for the supplied range.
range_from(&self, idx: RangeFrom<UnitOffset<R::Offset>>) -> Result<R>603 pub fn range_from(&self, idx: RangeFrom<UnitOffset<R::Offset>>) -> Result<R> {
604 if !self.is_valid_offset(idx.start) {
605 return Err(Error::OffsetOutOfBounds);
606 }
607 let start = idx.start.0 - self.header_size();
608 let mut input = self.entries_buf.clone();
609 input.skip(start)?;
610 Ok(input)
611 }
612
613 /// Get the underlying bytes for the supplied range.
range_to(&self, idx: RangeTo<UnitOffset<R::Offset>>) -> Result<R>614 pub fn range_to(&self, idx: RangeTo<UnitOffset<R::Offset>>) -> Result<R> {
615 if !self.is_valid_offset(idx.end) {
616 return Err(Error::OffsetOutOfBounds);
617 }
618 let end = idx.end.0 - self.header_size();
619 let mut input = self.entries_buf.clone();
620 input.truncate(end)?;
621 Ok(input)
622 }
623
624 /// Read the `DebuggingInformationEntry` at the given offset.
entry<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<R::Offset>, ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>>625 pub fn entry<'me, 'abbrev>(
626 &'me self,
627 abbreviations: &'abbrev Abbreviations,
628 offset: UnitOffset<R::Offset>,
629 ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>> {
630 let mut input = self.range_from(offset..)?;
631 let entry = DebuggingInformationEntry::parse(&mut input, self, abbreviations)?;
632 entry.ok_or(Error::NoEntryAtGivenOffset)
633 }
634
635 /// Navigate this unit's `DebuggingInformationEntry`s.
entries<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, ) -> EntriesCursor<'abbrev, 'me, R>636 pub fn entries<'me, 'abbrev>(
637 &'me self,
638 abbreviations: &'abbrev Abbreviations,
639 ) -> EntriesCursor<'abbrev, 'me, R> {
640 EntriesCursor {
641 unit: self,
642 input: self.entries_buf.clone(),
643 abbreviations,
644 cached_current: None,
645 delta_depth: 0,
646 }
647 }
648
649 /// Navigate this compilation unit's `DebuggingInformationEntry`s
650 /// starting at the given offset.
entries_at_offset<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<R::Offset>, ) -> Result<EntriesCursor<'abbrev, 'me, R>>651 pub fn entries_at_offset<'me, 'abbrev>(
652 &'me self,
653 abbreviations: &'abbrev Abbreviations,
654 offset: UnitOffset<R::Offset>,
655 ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
656 let input = self.range_from(offset..)?;
657 Ok(EntriesCursor {
658 unit: self,
659 input,
660 abbreviations,
661 cached_current: None,
662 delta_depth: 0,
663 })
664 }
665
666 /// Navigate this unit's `DebuggingInformationEntry`s as a tree
667 /// starting at the given offset.
entries_tree<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesTree<'abbrev, 'me, R>>668 pub fn entries_tree<'me, 'abbrev>(
669 &'me self,
670 abbreviations: &'abbrev Abbreviations,
671 offset: Option<UnitOffset<R::Offset>>,
672 ) -> Result<EntriesTree<'abbrev, 'me, R>> {
673 let input = match offset {
674 Some(offset) => self.range_from(offset..)?,
675 None => self.entries_buf.clone(),
676 };
677 Ok(EntriesTree::new(input, self, abbreviations))
678 }
679
680 /// Read the raw data that defines the Debugging Information Entries.
entries_raw<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesRaw<'abbrev, 'me, R>>681 pub fn entries_raw<'me, 'abbrev>(
682 &'me self,
683 abbreviations: &'abbrev Abbreviations,
684 offset: Option<UnitOffset<R::Offset>>,
685 ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
686 let input = match offset {
687 Some(offset) => self.range_from(offset..)?,
688 None => self.entries_buf.clone(),
689 };
690 Ok(EntriesRaw {
691 input,
692 unit: self,
693 abbreviations,
694 depth: 0,
695 })
696 }
697
698 /// Parse this unit's abbreviations.
abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations>699 pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
700 debug_abbrev.abbreviations(self.debug_abbrev_offset())
701 }
702 }
703
704 /// Parse a compilation unit header.
parse_unit_header<R: Reader>(input: &mut R) -> Result<UnitHeader<R>>705 fn parse_unit_header<R: Reader>(input: &mut R) -> Result<UnitHeader<R>> {
706 let (unit_length, format) = input.read_initial_length()?;
707 let mut rest = input.split(unit_length)?;
708
709 let version = rest.read_u16()?;
710 let offset;
711 let address_size;
712 // DWARF 1 was very different, and is obsolete, so isn't supported by this
713 // reader.
714 if 2 <= version && version <= 4 {
715 offset = parse_debug_abbrev_offset(&mut rest, format)?;
716 address_size = rest.read_u8()?;
717 } else if version == 5 {
718 let unit_type = parse_compilation_unit_type(&mut rest)?;
719 if unit_type != constants::DW_UT_compile {
720 return Err(Error::UnsupportedUnitType);
721 }
722 address_size = rest.read_u8()?;
723 offset = parse_debug_abbrev_offset(&mut rest, format)?;
724 } else {
725 return Err(Error::UnknownVersion(u64::from(version)));
726 }
727 let encoding = Encoding {
728 format,
729 version,
730 address_size,
731 };
732
733 Ok(UnitHeader::new(encoding, unit_length, offset, rest))
734 }
735
736 /// A Debugging Information Entry (DIE).
737 ///
738 /// DIEs have a set of attributes and optionally have children DIEs as well.
739 #[derive(Clone, Debug)]
740 pub struct DebuggingInformationEntry<'abbrev, 'unit, R, Offset = <R as Reader>::Offset>
741 where
742 R: Reader<Offset = Offset>,
743 Offset: ReaderOffset,
744 {
745 offset: UnitOffset<Offset>,
746 attrs_slice: R,
747 attrs_len: Cell<Option<Offset>>,
748 abbrev: &'abbrev Abbreviation,
749 unit: &'unit UnitHeader<R, Offset>,
750 }
751
752 impl<'abbrev, 'unit, R, Offset> DebuggingInformationEntry<'abbrev, 'unit, R, Offset>
753 where
754 R: Reader<Offset = Offset>,
755 Offset: ReaderOffset,
756 {
757 /// Construct a new `DebuggingInformationEntry`.
new( offset: UnitOffset<Offset>, attrs_slice: R, abbrev: &'abbrev Abbreviation, unit: &'unit UnitHeader<R, Offset>, ) -> Self758 pub fn new(
759 offset: UnitOffset<Offset>,
760 attrs_slice: R,
761 abbrev: &'abbrev Abbreviation,
762 unit: &'unit UnitHeader<R, Offset>,
763 ) -> Self {
764 DebuggingInformationEntry {
765 offset,
766 attrs_slice,
767 attrs_len: Cell::new(None),
768 abbrev,
769 unit,
770 }
771 }
772
773 /// Get this entry's code.
code(&self) -> u64774 pub fn code(&self) -> u64 {
775 self.abbrev.code()
776 }
777
778 /// Get this entry's offset.
offset(&self) -> UnitOffset<R::Offset>779 pub fn offset(&self) -> UnitOffset<R::Offset> {
780 self.offset
781 }
782
783 /// Get this entry's `DW_TAG_whatever` tag.
784 ///
785 /// ```
786 /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
787 /// # let info_buf = [
788 /// # // Comilation unit header
789 /// #
790 /// # // 32-bit unit length = 12
791 /// # 0x0c, 0x00, 0x00, 0x00,
792 /// # // Version 4
793 /// # 0x04, 0x00,
794 /// # // debug_abbrev_offset
795 /// # 0x00, 0x00, 0x00, 0x00,
796 /// # // Address size
797 /// # 0x04,
798 /// #
799 /// # // DIEs
800 /// #
801 /// # // Abbreviation code
802 /// # 0x01,
803 /// # // Attribute of form DW_FORM_string = "foo\0"
804 /// # 0x66, 0x6f, 0x6f, 0x00,
805 /// # ];
806 /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
807 /// # let abbrev_buf = [
808 /// # // Code
809 /// # 0x01,
810 /// # // DW_TAG_subprogram
811 /// # 0x2e,
812 /// # // DW_CHILDREN_no
813 /// # 0x00,
814 /// # // Begin attributes
815 /// # // Attribute name = DW_AT_name
816 /// # 0x03,
817 /// # // Attribute form = DW_FORM_string
818 /// # 0x08,
819 /// # // End attributes
820 /// # 0x00,
821 /// # 0x00,
822 /// # // Null terminator
823 /// # 0x00
824 /// # ];
825 /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
826 /// # let unit = debug_info.units().next().unwrap().unwrap();
827 /// # let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
828 /// # let mut cursor = unit.entries(&abbrevs);
829 /// # let (_, entry) = cursor.next_dfs().unwrap().unwrap();
830 /// # let mut get_some_entry = || entry;
831 /// let entry = get_some_entry();
832 ///
833 /// match entry.tag() {
834 /// gimli::DW_TAG_subprogram =>
835 /// println!("this entry contains debug info about a function"),
836 /// gimli::DW_TAG_inlined_subroutine =>
837 /// println!("this entry contains debug info about a particular instance of inlining"),
838 /// gimli::DW_TAG_variable =>
839 /// println!("this entry contains debug info about a local variable"),
840 /// gimli::DW_TAG_formal_parameter =>
841 /// println!("this entry contains debug info about a function parameter"),
842 /// otherwise =>
843 /// println!("this entry is some other kind of data: {:?}", otherwise),
844 /// };
845 /// ```
tag(&self) -> constants::DwTag846 pub fn tag(&self) -> constants::DwTag {
847 self.abbrev.tag()
848 }
849
850 /// Return true if this entry's type can have children, false otherwise.
has_children(&self) -> bool851 pub fn has_children(&self) -> bool {
852 self.abbrev.has_children()
853 }
854
855 /// Iterate over this entry's set of attributes.
856 ///
857 /// ```
858 /// use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
859 ///
860 /// // Read the `.debug_info` section.
861 ///
862 /// # let info_buf = [
863 /// # // Comilation unit header
864 /// #
865 /// # // 32-bit unit length = 12
866 /// # 0x0c, 0x00, 0x00, 0x00,
867 /// # // Version 4
868 /// # 0x04, 0x00,
869 /// # // debug_abbrev_offset
870 /// # 0x00, 0x00, 0x00, 0x00,
871 /// # // Address size
872 /// # 0x04,
873 /// #
874 /// # // DIEs
875 /// #
876 /// # // Abbreviation code
877 /// # 0x01,
878 /// # // Attribute of form DW_FORM_string = "foo\0"
879 /// # 0x66, 0x6f, 0x6f, 0x00,
880 /// # ];
881 /// # let read_debug_info_section_somehow = || &info_buf;
882 /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
883 ///
884 /// // Get the data about the first compilation unit out of the `.debug_info`.
885 ///
886 /// let unit = debug_info.units().next()
887 /// .expect("Should have at least one compilation unit")
888 /// .expect("and it should parse ok");
889 ///
890 /// // Read the `.debug_abbrev` section and parse the
891 /// // abbreviations for our compilation unit.
892 ///
893 /// # let abbrev_buf = [
894 /// # // Code
895 /// # 0x01,
896 /// # // DW_TAG_subprogram
897 /// # 0x2e,
898 /// # // DW_CHILDREN_no
899 /// # 0x00,
900 /// # // Begin attributes
901 /// # // Attribute name = DW_AT_name
902 /// # 0x03,
903 /// # // Attribute form = DW_FORM_string
904 /// # 0x08,
905 /// # // End attributes
906 /// # 0x00,
907 /// # 0x00,
908 /// # // Null terminator
909 /// # 0x00
910 /// # ];
911 /// # let read_debug_abbrev_section_somehow = || &abbrev_buf;
912 /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
913 /// let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
914 ///
915 /// // Get the first entry from that compilation unit.
916 ///
917 /// let mut cursor = unit.entries(&abbrevs);
918 /// let (_, entry) = cursor.next_dfs()
919 /// .expect("Should parse next entry")
920 /// .expect("Should have at least one entry");
921 ///
922 /// // Finally, print the first entry's attributes.
923 ///
924 /// let mut attrs = entry.attrs();
925 /// while let Some(attr) = attrs.next().unwrap() {
926 /// println!("Attribute name = {:?}", attr.name());
927 /// println!("Attribute value = {:?}", attr.value());
928 /// }
929 /// ```
930 ///
931 /// Can be [used with
932 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R>933 pub fn attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R> {
934 AttrsIter {
935 input: self.attrs_slice.clone(),
936 attributes: self.abbrev.attributes(),
937 entry: self,
938 }
939 }
940
941 /// Find the first attribute in this entry which has the given name,
942 /// and return it. Returns `Ok(None)` if no attribute is found.
attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>>943 pub fn attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>> {
944 let mut attrs = self.attrs();
945 while let Some(attr) = attrs.next()? {
946 if attr.name() == name {
947 return Ok(Some(attr));
948 }
949 }
950 Ok(None)
951 }
952
953 /// Find the first attribute in this entry which has the given name,
954 /// and return its raw value. Returns `Ok(None)` if no attribute is found.
attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>>955 pub fn attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
956 self.attr(name)
957 .map(|attr| attr.map(|attr| attr.raw_value()))
958 }
959
960 /// Find the first attribute in this entry which has the given name,
961 /// and return its normalized value. Returns `Ok(None)` if no
962 /// attribute is found.
attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>>963 pub fn attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
964 self.attr(name).map(|attr| attr.map(|attr| attr.value()))
965 }
966
967 /// Return the input buffer after the last attribute.
968 #[allow(clippy::inline_always)]
969 #[inline(always)]
after_attrs(&self) -> Result<R>970 fn after_attrs(&self) -> Result<R> {
971 if let Some(attrs_len) = self.attrs_len.get() {
972 let mut input = self.attrs_slice.clone();
973 input.skip(attrs_len)?;
974 Ok(input)
975 } else {
976 let mut attrs = self.attrs();
977 while let Some(_) = attrs.next()? {}
978 Ok(attrs.input)
979 }
980 }
981
982 /// Use the `DW_AT_sibling` attribute to find the input buffer for the
983 /// next sibling. Returns `None` if the attribute is missing or invalid.
sibling(&self) -> Option<R>984 fn sibling(&self) -> Option<R> {
985 let attr = self.attr_value(constants::DW_AT_sibling);
986 if let Ok(Some(AttributeValue::UnitRef(offset))) = attr {
987 if offset.0 > self.offset.0 {
988 if let Ok(input) = self.unit.range_from(offset..) {
989 return Some(input);
990 }
991 }
992 }
993 None
994 }
995
996 /// Parse an entry. Returns `Ok(None)` for null entries.
997 #[allow(clippy::inline_always)]
998 #[inline(always)]
parse( input: &mut R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations, ) -> Result<Option<Self>>999 fn parse(
1000 input: &mut R,
1001 unit: &'unit UnitHeader<R>,
1002 abbreviations: &'abbrev Abbreviations,
1003 ) -> Result<Option<Self>> {
1004 let offset = unit.header_size() + input.offset_from(&unit.entries_buf);
1005 let code = input.read_uleb128()?;
1006 if code == 0 {
1007 return Ok(None);
1008 };
1009 let abbrev = abbreviations.get(code).ok_or(Error::UnknownAbbreviation)?;
1010 Ok(Some(DebuggingInformationEntry {
1011 offset: UnitOffset(offset),
1012 attrs_slice: input.clone(),
1013 attrs_len: Cell::new(None),
1014 abbrev,
1015 unit,
1016 }))
1017 }
1018 }
1019
1020 /// The value of an attribute in a `DebuggingInformationEntry`.
1021 //
1022 // Set the discriminant size so that all variants use the same alignment
1023 // for their data. This gives better code generation in `parse_attribute`.
1024 #[repr(u64)]
1025 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
1026 pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
1027 where
1028 R: Reader<Offset = Offset>,
1029 Offset: ReaderOffset,
1030 {
1031 /// "Refers to some location in the address space of the described program."
1032 Addr(u64),
1033
1034 /// A slice of an arbitrary number of bytes.
1035 Block(R),
1036
1037 /// A one byte constant data value. How to interpret the byte depends on context.
1038 ///
1039 /// From section 7 of the standard: "Depending on context, it may be a
1040 /// signed integer, an unsigned integer, a floating-point constant, or
1041 /// anything else."
1042 Data1(u8),
1043
1044 /// A two byte constant data value. How to interpret the bytes depends on context.
1045 ///
1046 /// These bytes have been converted from `R::Endian`. This may need to be reversed
1047 /// if this was not required.
1048 ///
1049 /// From section 7 of the standard: "Depending on context, it may be a
1050 /// signed integer, an unsigned integer, a floating-point constant, or
1051 /// anything else."
1052 Data2(u16),
1053
1054 /// A four byte constant data value. How to interpret the bytes depends on context.
1055 ///
1056 /// These bytes have been converted from `R::Endian`. This may need to be reversed
1057 /// if this was not required.
1058 ///
1059 /// From section 7 of the standard: "Depending on context, it may be a
1060 /// signed integer, an unsigned integer, a floating-point constant, or
1061 /// anything else."
1062 Data4(u32),
1063
1064 /// An eight byte constant data value. How to interpret the bytes depends on context.
1065 ///
1066 /// These bytes have been converted from `R::Endian`. This may need to be reversed
1067 /// if this was not required.
1068 ///
1069 /// From section 7 of the standard: "Depending on context, it may be a
1070 /// signed integer, an unsigned integer, a floating-point constant, or
1071 /// anything else."
1072 Data8(u64),
1073
1074 /// A signed integer constant.
1075 Sdata(i64),
1076
1077 /// An unsigned integer constant.
1078 Udata(u64),
1079
1080 /// "The information bytes contain a DWARF expression (see Section 2.5) or
1081 /// location description (see Section 2.6)."
1082 Exprloc(Expression<R>),
1083
1084 /// A boolean that indicates presence or absence of the attribute.
1085 Flag(bool),
1086
1087 /// An offset into another section. Which section this is an offset into
1088 /// depends on context.
1089 SecOffset(Offset),
1090
1091 /// An offset to a set of addresses in the `.debug_addr` section.
1092 DebugAddrBase(DebugAddrBase<Offset>),
1093
1094 /// An index into a set of addresses in the `.debug_addr` section.
1095 DebugAddrIndex(DebugAddrIndex<Offset>),
1096
1097 /// An offset into the current compilation unit.
1098 UnitRef(UnitOffset<Offset>),
1099
1100 /// An offset into the current `.debug_info` section, but possibly a
1101 /// different compilation unit from the current one.
1102 DebugInfoRef(DebugInfoOffset<Offset>),
1103
1104 /// An offset into the `.debug_info` section of the supplementary object file.
1105 DebugInfoRefSup(DebugInfoOffset<Offset>),
1106
1107 /// An offset into the `.debug_line` section.
1108 DebugLineRef(DebugLineOffset<Offset>),
1109
1110 /// An offset into either the `.debug_loc` section or the `.debug_loclists` section.
1111 LocationListsRef(LocationListsOffset<Offset>),
1112
1113 /// An offset to a set of offsets in the `.debug_loclists` section.
1114 DebugLocListsBase(DebugLocListsBase<Offset>),
1115
1116 /// An index into a set of offsets in the `.debug_loclists` section.
1117 DebugLocListsIndex(DebugLocListsIndex<Offset>),
1118
1119 /// An offset into the `.debug_macinfo` section.
1120 DebugMacinfoRef(DebugMacinfoOffset<Offset>),
1121
1122 /// An offset into the `.debug_macro` section.
1123 DebugMacroRef(DebugMacroOffset<Offset>),
1124
1125 /// An offset into the `.debug_ranges` section.
1126 RangeListsRef(RangeListsOffset<Offset>),
1127
1128 /// An offset to a set of offsets in the `.debug_rnglists` section.
1129 DebugRngListsBase(DebugRngListsBase<Offset>),
1130
1131 /// An index into a set of offsets in the `.debug_rnglists` section.
1132 DebugRngListsIndex(DebugRngListsIndex<Offset>),
1133
1134 /// A type signature.
1135 DebugTypesRef(DebugTypeSignature),
1136
1137 /// An offset into the `.debug_str` section.
1138 DebugStrRef(DebugStrOffset<Offset>),
1139
1140 /// An offset into the `.debug_str` section of the supplementary object file.
1141 DebugStrRefSup(DebugStrOffset<Offset>),
1142
1143 /// An offset to a set of entries in the `.debug_str_offsets` section.
1144 DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
1145
1146 /// An index into a set of entries in the `.debug_str_offsets` section.
1147 DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
1148
1149 /// An offset into the `.debug_line_str` section.
1150 DebugLineStrRef(DebugLineStrOffset<Offset>),
1151
1152 /// A slice of bytes representing a string. Does not include a final null byte.
1153 /// Not guaranteed to be UTF-8 or anything like that.
1154 String(R),
1155
1156 /// The value of a `DW_AT_encoding` attribute.
1157 Encoding(constants::DwAte),
1158
1159 /// The value of a `DW_AT_decimal_sign` attribute.
1160 DecimalSign(constants::DwDs),
1161
1162 /// The value of a `DW_AT_endianity` attribute.
1163 Endianity(constants::DwEnd),
1164
1165 /// The value of a `DW_AT_accessibility` attribute.
1166 Accessibility(constants::DwAccess),
1167
1168 /// The value of a `DW_AT_visibility` attribute.
1169 Visibility(constants::DwVis),
1170
1171 /// The value of a `DW_AT_virtuality` attribute.
1172 Virtuality(constants::DwVirtuality),
1173
1174 /// The value of a `DW_AT_language` attribute.
1175 Language(constants::DwLang),
1176
1177 /// The value of a `DW_AT_address_class` attribute.
1178 AddressClass(constants::DwAddr),
1179
1180 /// The value of a `DW_AT_identifier_case` attribute.
1181 IdentifierCase(constants::DwId),
1182
1183 /// The value of a `DW_AT_calling_convention` attribute.
1184 CallingConvention(constants::DwCc),
1185
1186 /// The value of a `DW_AT_inline` attribute.
1187 Inline(constants::DwInl),
1188
1189 /// The value of a `DW_AT_ordering` attribute.
1190 Ordering(constants::DwOrd),
1191
1192 /// An index into the filename entries from the line number information
1193 /// table for the compilation unit containing this value.
1194 FileIndex(u64),
1195 }
1196
1197 /// An attribute in a `DebuggingInformationEntry`, consisting of a name and
1198 /// associated value.
1199 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1200 pub struct Attribute<R: Reader> {
1201 name: constants::DwAt,
1202 value: AttributeValue<R>,
1203 }
1204
1205 impl<R: Reader> Attribute<R> {
1206 /// Get this attribute's name.
name(&self) -> constants::DwAt1207 pub fn name(&self) -> constants::DwAt {
1208 self.name
1209 }
1210
1211 /// Get this attribute's raw value.
raw_value(&self) -> AttributeValue<R>1212 pub fn raw_value(&self) -> AttributeValue<R> {
1213 self.value.clone()
1214 }
1215
1216 /// Get this attribute's normalized value.
1217 ///
1218 /// Attribute values can potentially be encoded in multiple equivalent forms,
1219 /// and may have special meaning depending on the attribute name. This method
1220 /// converts the attribute value to a normalized form based on the attribute
1221 /// name.
1222 ///
1223 /// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings".
1224 #[allow(clippy::cyclomatic_complexity)]
1225 #[allow(clippy::match_same_arms)]
value(&self) -> AttributeValue<R>1226 pub fn value(&self) -> AttributeValue<R> {
1227 // Table 7.5 shows the possible attribute classes for each name.
1228 // Table 7.6 shows the possible attribute classes for each form.
1229 // For each attribute name, we need to match on the form, and
1230 // convert it to one of the classes that is allowed for both
1231 // the name and the form.
1232 //
1233 // The individual class conversions rarely vary for each name,
1234 // so for each class conversion we define a macro that matches
1235 // on the allowed forms for that class.
1236 //
1237 // For some classes, we don't need to do any conversion, so their
1238 // macro is empty. In the future we may want to fill them in to
1239 // provide strict checking of the forms for each class. For now,
1240 // they simply provide a way to document the allowed classes for
1241 // each name.
1242
1243 // DW_FORM_addr
1244 // DW_FORM_addrx
1245 // DW_FORM_addrx1
1246 // DW_FORM_addrx2
1247 // DW_FORM_addrx3
1248 // DW_FORM_addrx4
1249 macro_rules! address {
1250 () => {};
1251 }
1252 // DW_FORM_sec_offset
1253 macro_rules! addrptr {
1254 () => {
1255 if let Some(offset) = self.offset_value() {
1256 return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
1257 }
1258 };
1259 }
1260 // DW_FORM_block
1261 // DW_FORM_block1
1262 // DW_FORM_block2
1263 // DW_FORM_block4
1264 macro_rules! block {
1265 () => {};
1266 }
1267 // DW_FORM_sdata
1268 // DW_FORM_udata
1269 // DW_FORM_data1
1270 // DW_FORM_data2
1271 // DW_FORM_data4
1272 // DW_FORM_data8
1273 // DW_FORM_data16
1274 // DW_FORM_implicit_const
1275 macro_rules! constant {
1276 ($value:ident, $variant:ident) => {
1277 if let Some(value) = self.$value() {
1278 return AttributeValue::$variant(value);
1279 }
1280 };
1281 ($value:ident, $variant:ident, $constant:ident) => {
1282 if let Some(value) = self.$value() {
1283 return AttributeValue::$variant(constants::$constant(value));
1284 }
1285 };
1286 }
1287 // DW_FORM_exprloc
1288 macro_rules! exprloc {
1289 () => {
1290 if let Some(value) = self.exprloc_value() {
1291 return AttributeValue::Exprloc(value);
1292 }
1293 };
1294 }
1295 // DW_FORM_flag
1296 // DW_FORM_flag_present
1297 macro_rules! flag {
1298 () => {};
1299 }
1300 // DW_FORM_sec_offset
1301 macro_rules! lineptr {
1302 () => {
1303 if let Some(offset) = self.offset_value() {
1304 return AttributeValue::DebugLineRef(DebugLineOffset(offset));
1305 }
1306 };
1307 }
1308 // This also covers `loclist` in DWARF version 5.
1309 // DW_FORM_sec_offset
1310 // DW_FORM_loclistx
1311 macro_rules! loclistptr {
1312 () => {
1313 // DebugLocListsIndex is also an allowed form in DWARF version 5.
1314 if let Some(offset) = self.offset_value() {
1315 return AttributeValue::LocationListsRef(LocationListsOffset(offset));
1316 }
1317 };
1318 }
1319 // DW_FORM_sec_offset
1320 macro_rules! loclistsptr {
1321 () => {
1322 if let Some(offset) = self.offset_value() {
1323 return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
1324 }
1325 };
1326 }
1327 // DWARF version <= 4.
1328 // DW_FORM_sec_offset
1329 macro_rules! macinfoptr {
1330 () => {
1331 if let Some(offset) = self.offset_value() {
1332 return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
1333 }
1334 };
1335 }
1336 // DWARF version >= 5.
1337 // DW_FORM_sec_offset
1338 macro_rules! macroptr {
1339 () => {
1340 if let Some(offset) = self.offset_value() {
1341 return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
1342 }
1343 };
1344 }
1345 // DW_FORM_ref_addr
1346 // DW_FORM_ref1
1347 // DW_FORM_ref2
1348 // DW_FORM_ref4
1349 // DW_FORM_ref8
1350 // DW_FORM_ref_udata
1351 // DW_FORM_ref_sig8
1352 // DW_FORM_ref_sup4
1353 // DW_FORM_ref_sup8
1354 macro_rules! reference {
1355 () => {};
1356 }
1357 // This also covers `rnglist` in DWARF version 5.
1358 // DW_FORM_sec_offset
1359 // DW_FORM_rnglistx
1360 macro_rules! rangelistptr {
1361 () => {
1362 // DebugRngListsIndex is also an allowed form in DWARF version 5.
1363 if let Some(offset) = self.offset_value() {
1364 return AttributeValue::RangeListsRef(RangeListsOffset(offset));
1365 }
1366 };
1367 }
1368 // DW_FORM_sec_offset
1369 macro_rules! rnglistsptr {
1370 () => {
1371 if let Some(offset) = self.offset_value() {
1372 return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
1373 }
1374 };
1375 }
1376 // DW_FORM_string
1377 // DW_FORM_strp
1378 // DW_FORM_strx
1379 // DW_FORM_strx1
1380 // DW_FORM_strx2
1381 // DW_FORM_strx3
1382 // DW_FORM_strx4
1383 // DW_FORM_strp_sup
1384 // DW_FORM_line_strp
1385 macro_rules! string {
1386 () => {};
1387 }
1388 // DW_FORM_sec_offset
1389 macro_rules! stroffsetsptr {
1390 () => {
1391 if let Some(offset) = self.offset_value() {
1392 return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
1393 }
1394 };
1395 }
1396
1397 // Perform the allowed class conversions for each attribute name.
1398 match self.name {
1399 constants::DW_AT_sibling => {
1400 reference!();
1401 }
1402 constants::DW_AT_location => {
1403 exprloc!();
1404 loclistptr!();
1405 }
1406 constants::DW_AT_name => {
1407 string!();
1408 }
1409 constants::DW_AT_ordering => {
1410 constant!(u8_value, Ordering, DwOrd);
1411 }
1412 constants::DW_AT_byte_size
1413 | constants::DW_AT_bit_offset
1414 | constants::DW_AT_bit_size => {
1415 constant!(udata_value, Udata);
1416 exprloc!();
1417 reference!();
1418 }
1419 constants::DW_AT_stmt_list => {
1420 lineptr!();
1421 }
1422 constants::DW_AT_low_pc => {
1423 address!();
1424 }
1425 constants::DW_AT_high_pc => {
1426 address!();
1427 constant!(udata_value, Udata);
1428 }
1429 constants::DW_AT_language => {
1430 constant!(u16_value, Language, DwLang);
1431 }
1432 constants::DW_AT_discr => {
1433 reference!();
1434 }
1435 constants::DW_AT_discr_value => {
1436 // constant: depends on type of DW_TAG_variant_part,
1437 // so caller must normalize.
1438 }
1439 constants::DW_AT_visibility => {
1440 constant!(u8_value, Visibility, DwVis);
1441 }
1442 constants::DW_AT_import => {
1443 reference!();
1444 }
1445 constants::DW_AT_string_length => {
1446 exprloc!();
1447 loclistptr!();
1448 reference!();
1449 }
1450 constants::DW_AT_common_reference => {
1451 reference!();
1452 }
1453 constants::DW_AT_comp_dir => {
1454 string!();
1455 }
1456 constants::DW_AT_const_value => {
1457 // TODO: constant: sign depends on DW_AT_type.
1458 block!();
1459 string!();
1460 }
1461 constants::DW_AT_containing_type => {
1462 reference!();
1463 }
1464 constants::DW_AT_default_value => {
1465 // TODO: constant: sign depends on DW_AT_type.
1466 reference!();
1467 flag!();
1468 }
1469 constants::DW_AT_inline => {
1470 constant!(u8_value, Inline, DwInl);
1471 }
1472 constants::DW_AT_is_optional => {
1473 flag!();
1474 }
1475 constants::DW_AT_lower_bound => {
1476 // TODO: constant: sign depends on DW_AT_type.
1477 exprloc!();
1478 reference!();
1479 }
1480 constants::DW_AT_producer => {
1481 string!();
1482 }
1483 constants::DW_AT_prototyped => {
1484 flag!();
1485 }
1486 constants::DW_AT_return_addr => {
1487 exprloc!();
1488 loclistptr!();
1489 }
1490 constants::DW_AT_start_scope => {
1491 // TODO: constant
1492 rangelistptr!();
1493 }
1494 constants::DW_AT_bit_stride => {
1495 constant!(udata_value, Udata);
1496 exprloc!();
1497 reference!();
1498 }
1499 constants::DW_AT_upper_bound => {
1500 // TODO: constant: sign depends on DW_AT_type.
1501 exprloc!();
1502 reference!();
1503 }
1504 constants::DW_AT_abstract_origin => {
1505 reference!();
1506 }
1507 constants::DW_AT_accessibility => {
1508 constant!(u8_value, Accessibility, DwAccess);
1509 }
1510 constants::DW_AT_address_class => {
1511 constant!(udata_value, AddressClass, DwAddr);
1512 }
1513 constants::DW_AT_artificial => {
1514 flag!();
1515 }
1516 constants::DW_AT_base_types => {
1517 reference!();
1518 }
1519 constants::DW_AT_calling_convention => {
1520 constant!(u8_value, CallingConvention, DwCc);
1521 }
1522 constants::DW_AT_count => {
1523 // TODO: constant
1524 exprloc!();
1525 reference!();
1526 }
1527 constants::DW_AT_data_member_location => {
1528 // Constants must be handled before loclistptr so that DW_FORM_data4/8
1529 // are correctly interpreted for DWARF version 4+.
1530 constant!(udata_value, Udata);
1531 exprloc!();
1532 loclistptr!();
1533 }
1534 constants::DW_AT_decl_column => {
1535 constant!(udata_value, Udata);
1536 }
1537 constants::DW_AT_decl_file => {
1538 constant!(udata_value, FileIndex);
1539 }
1540 constants::DW_AT_decl_line => {
1541 constant!(udata_value, Udata);
1542 }
1543 constants::DW_AT_declaration => {
1544 flag!();
1545 }
1546 constants::DW_AT_discr_list => {
1547 block!();
1548 }
1549 constants::DW_AT_encoding => {
1550 constant!(u8_value, Encoding, DwAte);
1551 }
1552 constants::DW_AT_external => {
1553 flag!();
1554 }
1555 constants::DW_AT_frame_base => {
1556 exprloc!();
1557 loclistptr!();
1558 }
1559 constants::DW_AT_friend => {
1560 reference!();
1561 }
1562 constants::DW_AT_identifier_case => {
1563 constant!(u8_value, IdentifierCase, DwId);
1564 }
1565 constants::DW_AT_macro_info => {
1566 macinfoptr!();
1567 }
1568 constants::DW_AT_namelist_item => {
1569 reference!();
1570 }
1571 constants::DW_AT_priority => {
1572 reference!();
1573 }
1574 constants::DW_AT_segment => {
1575 exprloc!();
1576 loclistptr!();
1577 }
1578 constants::DW_AT_specification => {
1579 reference!();
1580 }
1581 constants::DW_AT_static_link => {
1582 exprloc!();
1583 loclistptr!();
1584 }
1585 constants::DW_AT_type => {
1586 reference!();
1587 }
1588 constants::DW_AT_use_location => {
1589 exprloc!();
1590 loclistptr!();
1591 }
1592 constants::DW_AT_variable_parameter => {
1593 flag!();
1594 }
1595 constants::DW_AT_virtuality => {
1596 constant!(u8_value, Virtuality, DwVirtuality);
1597 }
1598 constants::DW_AT_vtable_elem_location => {
1599 exprloc!();
1600 loclistptr!();
1601 }
1602 constants::DW_AT_allocated => {
1603 // TODO: constant
1604 exprloc!();
1605 reference!();
1606 }
1607 constants::DW_AT_associated => {
1608 // TODO: constant
1609 exprloc!();
1610 reference!();
1611 }
1612 constants::DW_AT_data_location => {
1613 exprloc!();
1614 }
1615 constants::DW_AT_byte_stride => {
1616 constant!(udata_value, Udata);
1617 exprloc!();
1618 reference!();
1619 }
1620 constants::DW_AT_entry_pc => {
1621 // TODO: constant
1622 address!();
1623 }
1624 constants::DW_AT_use_UTF8 => {
1625 flag!();
1626 }
1627 constants::DW_AT_extension => {
1628 reference!();
1629 }
1630 constants::DW_AT_ranges => {
1631 rangelistptr!();
1632 }
1633 constants::DW_AT_trampoline => {
1634 address!();
1635 flag!();
1636 reference!();
1637 string!();
1638 }
1639 constants::DW_AT_call_column => {
1640 constant!(udata_value, Udata);
1641 }
1642 constants::DW_AT_call_file => {
1643 constant!(udata_value, FileIndex);
1644 }
1645 constants::DW_AT_call_line => {
1646 constant!(udata_value, Udata);
1647 }
1648 constants::DW_AT_description => {
1649 string!();
1650 }
1651 constants::DW_AT_binary_scale => {
1652 // TODO: constant
1653 }
1654 constants::DW_AT_decimal_scale => {
1655 // TODO: constant
1656 }
1657 constants::DW_AT_small => {
1658 reference!();
1659 }
1660 constants::DW_AT_decimal_sign => {
1661 constant!(u8_value, DecimalSign, DwDs);
1662 }
1663 constants::DW_AT_digit_count => {
1664 // TODO: constant
1665 }
1666 constants::DW_AT_picture_string => {
1667 string!();
1668 }
1669 constants::DW_AT_mutable => {
1670 flag!();
1671 }
1672 constants::DW_AT_threads_scaled => {
1673 flag!();
1674 }
1675 constants::DW_AT_explicit => {
1676 flag!();
1677 }
1678 constants::DW_AT_object_pointer => {
1679 reference!();
1680 }
1681 constants::DW_AT_endianity => {
1682 constant!(u8_value, Endianity, DwEnd);
1683 }
1684 constants::DW_AT_elemental => {
1685 flag!();
1686 }
1687 constants::DW_AT_pure => {
1688 flag!();
1689 }
1690 constants::DW_AT_recursive => {
1691 flag!();
1692 }
1693 constants::DW_AT_signature => {
1694 reference!();
1695 }
1696 constants::DW_AT_main_subprogram => {
1697 flag!();
1698 }
1699 constants::DW_AT_data_bit_offset => {
1700 // TODO: constant
1701 }
1702 constants::DW_AT_const_expr => {
1703 flag!();
1704 }
1705 constants::DW_AT_enum_class => {
1706 flag!();
1707 }
1708 constants::DW_AT_linkage_name => {
1709 string!();
1710 }
1711 constants::DW_AT_string_length_bit_size => {
1712 // TODO: constant
1713 }
1714 constants::DW_AT_string_length_byte_size => {
1715 // TODO: constant
1716 }
1717 constants::DW_AT_rank => {
1718 // TODO: constant
1719 exprloc!();
1720 }
1721 constants::DW_AT_str_offsets_base => {
1722 stroffsetsptr!();
1723 }
1724 constants::DW_AT_addr_base => {
1725 addrptr!();
1726 }
1727 constants::DW_AT_rnglists_base => {
1728 rnglistsptr!();
1729 }
1730 constants::DW_AT_dwo_name => {
1731 string!();
1732 }
1733 constants::DW_AT_reference => {
1734 flag!();
1735 }
1736 constants::DW_AT_rvalue_reference => {
1737 flag!();
1738 }
1739 constants::DW_AT_macros => {
1740 macroptr!();
1741 }
1742 constants::DW_AT_call_all_calls => {
1743 flag!();
1744 }
1745 constants::DW_AT_call_all_source_calls => {
1746 flag!();
1747 }
1748 constants::DW_AT_call_all_tail_calls => {
1749 flag!();
1750 }
1751 constants::DW_AT_call_return_pc => {
1752 address!();
1753 }
1754 constants::DW_AT_call_value => {
1755 exprloc!();
1756 }
1757 constants::DW_AT_call_origin => {
1758 exprloc!();
1759 }
1760 constants::DW_AT_call_parameter => {
1761 reference!();
1762 }
1763 constants::DW_AT_call_pc => {
1764 address!();
1765 }
1766 constants::DW_AT_call_tail_call => {
1767 flag!();
1768 }
1769 constants::DW_AT_call_target => {
1770 exprloc!();
1771 }
1772 constants::DW_AT_call_target_clobbered => {
1773 exprloc!();
1774 }
1775 constants::DW_AT_call_data_location => {
1776 exprloc!();
1777 }
1778 constants::DW_AT_call_data_value => {
1779 exprloc!();
1780 }
1781 constants::DW_AT_noreturn => {
1782 flag!();
1783 }
1784 constants::DW_AT_alignment => {
1785 // TODO: constant
1786 }
1787 constants::DW_AT_export_symbols => {
1788 flag!();
1789 }
1790 constants::DW_AT_deleted => {
1791 flag!();
1792 }
1793 constants::DW_AT_defaulted => {
1794 // TODO: constant
1795 }
1796 constants::DW_AT_loclists_base => {
1797 loclistsptr!();
1798 }
1799 _ => {}
1800 }
1801 self.value.clone()
1802 }
1803
1804 /// Try to convert this attribute's value to a u8.
1805 #[inline]
u8_value(&self) -> Option<u8>1806 pub fn u8_value(&self) -> Option<u8> {
1807 self.value.u8_value()
1808 }
1809
1810 /// Try to convert this attribute's value to a u16.
1811 #[inline]
u16_value(&self) -> Option<u16>1812 pub fn u16_value(&self) -> Option<u16> {
1813 self.value.u16_value()
1814 }
1815
1816 /// Try to convert this attribute's value to an unsigned integer.
1817 #[inline]
udata_value(&self) -> Option<u64>1818 pub fn udata_value(&self) -> Option<u64> {
1819 self.value.udata_value()
1820 }
1821
1822 /// Try to convert this attribute's value to a signed integer.
1823 #[inline]
sdata_value(&self) -> Option<i64>1824 pub fn sdata_value(&self) -> Option<i64> {
1825 self.value.sdata_value()
1826 }
1827
1828 /// Try to convert this attribute's value to an offset.
1829 #[inline]
offset_value(&self) -> Option<R::Offset>1830 pub fn offset_value(&self) -> Option<R::Offset> {
1831 self.value.offset_value()
1832 }
1833
1834 /// Try to convert this attribute's value to an expression or location buffer.
1835 ///
1836 /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1837 /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1838 /// it is encountered in practice.
1839 #[inline]
exprloc_value(&self) -> Option<Expression<R>>1840 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1841 self.value.exprloc_value()
1842 }
1843
1844 /// Try to return this attribute's value as a string slice.
1845 ///
1846 /// If this attribute's value is either an inline `DW_FORM_string` string,
1847 /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1848 /// section, return the attribute's string value as `Some`. Other attribute
1849 /// value forms are returned as `None`.
1850 ///
1851 /// Warning: this function does not handle all possible string forms.
1852 /// Use `Dwarf::attr_string` instead.
1853 #[inline]
string_value(&self, debug_str: &DebugStr<R>) -> Option<R>1854 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1855 self.value.string_value(debug_str)
1856 }
1857
1858 /// Try to return this attribute's value as a string slice.
1859 ///
1860 /// If this attribute's value is either an inline `DW_FORM_string` string,
1861 /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1862 /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1863 /// object file, return the attribute's string value as `Some`. Other attribute
1864 /// value forms are returned as `None`.
1865 ///
1866 /// Warning: this function does not handle all possible string forms.
1867 /// Use `Dwarf::attr_string` instead.
1868 #[inline]
string_value_sup( &self, debug_str: &DebugStr<R>, debug_str_sup: Option<&DebugStr<R>>, ) -> Option<R>1869 pub fn string_value_sup(
1870 &self,
1871 debug_str: &DebugStr<R>,
1872 debug_str_sup: Option<&DebugStr<R>>,
1873 ) -> Option<R> {
1874 self.value.string_value_sup(debug_str, debug_str_sup)
1875 }
1876 }
1877
1878 impl<R, Offset> AttributeValue<R, Offset>
1879 where
1880 R: Reader<Offset = Offset>,
1881 Offset: ReaderOffset,
1882 {
1883 /// Try to convert this attribute's value to a u8.
u8_value(&self) -> Option<u8>1884 pub fn u8_value(&self) -> Option<u8> {
1885 if let Some(value) = self.udata_value() {
1886 if value <= u64::from(u8::MAX) {
1887 return Some(value as u8);
1888 }
1889 }
1890 None
1891 }
1892
1893 /// Try to convert this attribute's value to a u16.
u16_value(&self) -> Option<u16>1894 pub fn u16_value(&self) -> Option<u16> {
1895 if let Some(value) = self.udata_value() {
1896 if value <= u64::from(u16::MAX) {
1897 return Some(value as u16);
1898 }
1899 }
1900 None
1901 }
1902
1903 /// Try to convert this attribute's value to an unsigned integer.
udata_value(&self) -> Option<u64>1904 pub fn udata_value(&self) -> Option<u64> {
1905 Some(match *self {
1906 AttributeValue::Data1(data) => u64::from(data),
1907 AttributeValue::Data2(data) => u64::from(data),
1908 AttributeValue::Data4(data) => u64::from(data),
1909 AttributeValue::Data8(data) => data,
1910 AttributeValue::Udata(data) => data,
1911 AttributeValue::Sdata(data) => {
1912 if data < 0 {
1913 // Maybe we should emit a warning here
1914 return None;
1915 }
1916 data as u64
1917 }
1918 _ => return None,
1919 })
1920 }
1921
1922 /// Try to convert this attribute's value to a signed integer.
sdata_value(&self) -> Option<i64>1923 pub fn sdata_value(&self) -> Option<i64> {
1924 Some(match *self {
1925 AttributeValue::Data1(data) => i64::from(data as i8),
1926 AttributeValue::Data2(data) => i64::from(data as i16),
1927 AttributeValue::Data4(data) => i64::from(data as i32),
1928 AttributeValue::Data8(data) => data as i64,
1929 AttributeValue::Sdata(data) => data,
1930 AttributeValue::Udata(data) => {
1931 if data > i64::max_value() as u64 {
1932 // Maybe we should emit a warning here
1933 return None;
1934 }
1935 data as i64
1936 }
1937 _ => return None,
1938 })
1939 }
1940
1941 /// Try to convert this attribute's value to an offset.
offset_value(&self) -> Option<R::Offset>1942 pub fn offset_value(&self) -> Option<R::Offset> {
1943 // While offsets will be DW_FORM_data4/8 in DWARF version 2/3,
1944 // these have already been converted to `SecOffset.
1945 if let AttributeValue::SecOffset(offset) = *self {
1946 Some(offset)
1947 } else {
1948 None
1949 }
1950 }
1951
1952 /// Try to convert this attribute's value to an expression or location buffer.
1953 ///
1954 /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
1955 /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
1956 /// it is encountered in practice.
exprloc_value(&self) -> Option<Expression<R>>1957 pub fn exprloc_value(&self) -> Option<Expression<R>> {
1958 Some(match *self {
1959 AttributeValue::Block(ref data) => Expression(data.clone()),
1960 AttributeValue::Exprloc(ref data) => data.clone(),
1961 _ => return None,
1962 })
1963 }
1964
1965 /// Try to return this attribute's value as a string slice.
1966 ///
1967 /// If this attribute's value is either an inline `DW_FORM_string` string,
1968 /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1969 /// section, return the attribute's string value as `Some`. Other attribute
1970 /// value forms are returned as `None`.
1971 ///
1972 /// Warning: this function does not handle all possible string forms.
1973 /// Use `Dwarf::attr_string` instead.
string_value(&self, debug_str: &DebugStr<R>) -> Option<R>1974 pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
1975 match *self {
1976 AttributeValue::String(ref string) => Some(string.clone()),
1977 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
1978 _ => None,
1979 }
1980 }
1981
1982 /// Try to return this attribute's value as a string slice.
1983 ///
1984 /// If this attribute's value is either an inline `DW_FORM_string` string,
1985 /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
1986 /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
1987 /// object file, return the attribute's string value as `Some`. Other attribute
1988 /// value forms are returned as `None`.
1989 ///
1990 /// Warning: this function does not handle all possible string forms.
1991 /// Use `Dwarf::attr_string` instead.
string_value_sup( &self, debug_str: &DebugStr<R>, debug_str_sup: Option<&DebugStr<R>>, ) -> Option<R>1992 pub fn string_value_sup(
1993 &self,
1994 debug_str: &DebugStr<R>,
1995 debug_str_sup: Option<&DebugStr<R>>,
1996 ) -> Option<R> {
1997 match *self {
1998 AttributeValue::String(ref string) => Some(string.clone()),
1999 AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
2000 AttributeValue::DebugStrRefSup(offset) => {
2001 debug_str_sup.and_then(|s| s.get_str(offset).ok())
2002 }
2003 _ => None,
2004 }
2005 }
2006 }
2007
length_u8_value<R: Reader>(input: &mut R) -> Result<R>2008 fn length_u8_value<R: Reader>(input: &mut R) -> Result<R> {
2009 let len = input.read_u8().map(R::Offset::from_u8)?;
2010 input.split(len)
2011 }
2012
length_u16_value<R: Reader>(input: &mut R) -> Result<R>2013 fn length_u16_value<R: Reader>(input: &mut R) -> Result<R> {
2014 let len = input.read_u16().map(R::Offset::from_u16)?;
2015 input.split(len)
2016 }
2017
length_u32_value<R: Reader>(input: &mut R) -> Result<R>2018 fn length_u32_value<R: Reader>(input: &mut R) -> Result<R> {
2019 let len = input.read_u32().map(R::Offset::from_u32)?;
2020 input.split(len)
2021 }
2022
length_uleb128_value<R: Reader>(input: &mut R) -> Result<R>2023 fn length_uleb128_value<R: Reader>(input: &mut R) -> Result<R> {
2024 let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
2025 input.split(len)
2026 }
2027
2028 // Return true if the given `name` can be a section offset in DWARF version 2/3.
2029 // This is required to correctly handle relocations.
allow_section_offset(name: constants::DwAt, version: u16) -> bool2030 fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
2031 match name {
2032 constants::DW_AT_location
2033 | constants::DW_AT_stmt_list
2034 | constants::DW_AT_string_length
2035 | constants::DW_AT_return_addr
2036 | constants::DW_AT_start_scope
2037 | constants::DW_AT_frame_base
2038 | constants::DW_AT_macro_info
2039 | constants::DW_AT_macros
2040 | constants::DW_AT_segment
2041 | constants::DW_AT_static_link
2042 | constants::DW_AT_use_location
2043 | constants::DW_AT_vtable_elem_location
2044 | constants::DW_AT_ranges => true,
2045 constants::DW_AT_data_member_location => version == 2 || version == 3,
2046 _ => false,
2047 }
2048 }
2049
parse_attribute<'unit, R: Reader>( input: &mut R, encoding: Encoding, spec: AttributeSpecification, ) -> Result<Attribute<R>>2050 pub(crate) fn parse_attribute<'unit, R: Reader>(
2051 input: &mut R,
2052 encoding: Encoding,
2053 spec: AttributeSpecification,
2054 ) -> Result<Attribute<R>> {
2055 let mut form = spec.form();
2056 loop {
2057 let value = match form {
2058 constants::DW_FORM_indirect => {
2059 let dynamic_form = input.read_uleb128_u16()?;
2060 form = constants::DwForm(dynamic_form);
2061 continue;
2062 }
2063 constants::DW_FORM_addr => {
2064 let addr = input.read_address(encoding.address_size)?;
2065 AttributeValue::Addr(addr)
2066 }
2067 constants::DW_FORM_block1 => {
2068 let block = length_u8_value(input)?;
2069 AttributeValue::Block(block)
2070 }
2071 constants::DW_FORM_block2 => {
2072 let block = length_u16_value(input)?;
2073 AttributeValue::Block(block)
2074 }
2075 constants::DW_FORM_block4 => {
2076 let block = length_u32_value(input)?;
2077 AttributeValue::Block(block)
2078 }
2079 constants::DW_FORM_block => {
2080 let block = length_uleb128_value(input)?;
2081 AttributeValue::Block(block)
2082 }
2083 constants::DW_FORM_data1 => {
2084 let data = input.read_u8()?;
2085 AttributeValue::Data1(data)
2086 }
2087 constants::DW_FORM_data2 => {
2088 let data = input.read_u16()?;
2089 AttributeValue::Data2(data)
2090 }
2091 constants::DW_FORM_data4 => {
2092 // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
2093 // Ensure we handle relocations here.
2094 if encoding.format == Format::Dwarf32
2095 && allow_section_offset(spec.name(), encoding.version)
2096 {
2097 let offset = input.read_offset(Format::Dwarf32)?;
2098 AttributeValue::SecOffset(offset)
2099 } else {
2100 let data = input.read_u32()?;
2101 AttributeValue::Data4(data)
2102 }
2103 }
2104 constants::DW_FORM_data8 => {
2105 // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
2106 // Ensure we handle relocations here.
2107 if encoding.format == Format::Dwarf64
2108 && allow_section_offset(spec.name(), encoding.version)
2109 {
2110 let offset = input.read_offset(Format::Dwarf64)?;
2111 AttributeValue::SecOffset(offset)
2112 } else {
2113 let data = input.read_u64()?;
2114 AttributeValue::Data8(data)
2115 }
2116 }
2117 constants::DW_FORM_data16 => {
2118 let block = input.split(R::Offset::from_u8(16))?;
2119 AttributeValue::Block(block)
2120 }
2121 constants::DW_FORM_udata => {
2122 let data = input.read_uleb128()?;
2123 AttributeValue::Udata(data)
2124 }
2125 constants::DW_FORM_sdata => {
2126 let data = input.read_sleb128()?;
2127 AttributeValue::Sdata(data)
2128 }
2129 constants::DW_FORM_exprloc => {
2130 let block = length_uleb128_value(input)?;
2131 AttributeValue::Exprloc(Expression(block))
2132 }
2133 constants::DW_FORM_flag => {
2134 let present = input.read_u8()?;
2135 AttributeValue::Flag(present != 0)
2136 }
2137 constants::DW_FORM_flag_present => {
2138 // FlagPresent is this weird compile time always true thing that
2139 // isn't actually present in the serialized DIEs, only in the abbreviation.
2140 AttributeValue::Flag(true)
2141 }
2142 constants::DW_FORM_sec_offset => {
2143 let offset = input.read_offset(encoding.format)?;
2144 AttributeValue::SecOffset(offset)
2145 }
2146 constants::DW_FORM_ref1 => {
2147 let reference = input.read_u8().map(R::Offset::from_u8)?;
2148 AttributeValue::UnitRef(UnitOffset(reference))
2149 }
2150 constants::DW_FORM_ref2 => {
2151 let reference = input.read_u16().map(R::Offset::from_u16)?;
2152 AttributeValue::UnitRef(UnitOffset(reference))
2153 }
2154 constants::DW_FORM_ref4 => {
2155 let reference = input.read_u32().map(R::Offset::from_u32)?;
2156 AttributeValue::UnitRef(UnitOffset(reference))
2157 }
2158 constants::DW_FORM_ref8 => {
2159 let reference = input.read_u64().and_then(R::Offset::from_u64)?;
2160 AttributeValue::UnitRef(UnitOffset(reference))
2161 }
2162 constants::DW_FORM_ref_udata => {
2163 let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
2164 AttributeValue::UnitRef(UnitOffset(reference))
2165 }
2166 constants::DW_FORM_ref_addr => {
2167 // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
2168 // has the same size as an address on the target system. This was changed
2169 // in DWARF version 3.
2170 let offset = if encoding.version == 2 {
2171 input.read_sized_offset(encoding.address_size)?
2172 } else {
2173 input.read_offset(encoding.format)?
2174 };
2175 AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
2176 }
2177 constants::DW_FORM_ref_sig8 => {
2178 let signature = input.read_u64()?;
2179 AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
2180 }
2181 constants::DW_FORM_ref_sup4 => {
2182 let offset = input.read_u32().map(R::Offset::from_u32)?;
2183 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2184 }
2185 constants::DW_FORM_ref_sup8 => {
2186 let offset = input.read_u64().and_then(R::Offset::from_u64)?;
2187 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2188 }
2189 constants::DW_FORM_GNU_ref_alt => {
2190 let offset = input.read_offset(encoding.format)?;
2191 AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
2192 }
2193 constants::DW_FORM_string => {
2194 let string = input.read_null_terminated_slice()?;
2195 AttributeValue::String(string)
2196 }
2197 constants::DW_FORM_strp => {
2198 let offset = input.read_offset(encoding.format)?;
2199 AttributeValue::DebugStrRef(DebugStrOffset(offset))
2200 }
2201 constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
2202 let offset = input.read_offset(encoding.format)?;
2203 AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
2204 }
2205 constants::DW_FORM_line_strp => {
2206 let offset = input.read_offset(encoding.format)?;
2207 AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
2208 }
2209 constants::DW_FORM_implicit_const => {
2210 let data = spec
2211 .implicit_const_value()
2212 .ok_or(Error::InvalidImplicitConst)?;
2213 AttributeValue::Sdata(data)
2214 }
2215 constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
2216 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2217 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2218 }
2219 constants::DW_FORM_strx1 => {
2220 let index = input.read_u8().map(R::Offset::from_u8)?;
2221 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2222 }
2223 constants::DW_FORM_strx2 => {
2224 let index = input.read_u16().map(R::Offset::from_u16)?;
2225 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2226 }
2227 constants::DW_FORM_strx3 => {
2228 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2229 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2230 }
2231 constants::DW_FORM_strx4 => {
2232 let index = input.read_u32().map(R::Offset::from_u32)?;
2233 AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
2234 }
2235 constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
2236 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2237 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2238 }
2239 constants::DW_FORM_addrx1 => {
2240 let index = input.read_u8().map(R::Offset::from_u8)?;
2241 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2242 }
2243 constants::DW_FORM_addrx2 => {
2244 let index = input.read_u16().map(R::Offset::from_u16)?;
2245 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2246 }
2247 constants::DW_FORM_addrx3 => {
2248 let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
2249 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2250 }
2251 constants::DW_FORM_addrx4 => {
2252 let index = input.read_u32().map(R::Offset::from_u32)?;
2253 AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
2254 }
2255 constants::DW_FORM_loclistx => {
2256 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2257 AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
2258 }
2259 constants::DW_FORM_rnglistx => {
2260 let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
2261 AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
2262 }
2263 _ => {
2264 return Err(Error::UnknownForm);
2265 }
2266 };
2267 let attr = Attribute {
2268 name: spec.name(),
2269 value,
2270 };
2271 return Ok(attr);
2272 }
2273 }
2274
2275 /// An iterator over a particular entry's attributes.
2276 ///
2277 /// See [the documentation for
2278 /// `DebuggingInformationEntry::attrs()`](./struct.DebuggingInformationEntry.html#method.attrs)
2279 /// for details.
2280 ///
2281 /// Can be [used with
2282 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
2283 #[derive(Clone, Copy, Debug)]
2284 pub struct AttrsIter<'abbrev, 'entry, 'unit, R: Reader> {
2285 input: R,
2286 attributes: &'abbrev [AttributeSpecification],
2287 entry: &'entry DebuggingInformationEntry<'abbrev, 'unit, R>,
2288 }
2289
2290 impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> {
2291 /// Advance the iterator and return the next attribute.
2292 ///
2293 /// Returns `None` when iteration is finished. If an error
2294 /// occurs while parsing the next attribute, then this error
2295 /// is returned, and all subsequent calls return `None`.
2296 #[allow(clippy::inline_always)]
2297 #[inline(always)]
next(&mut self) -> Result<Option<Attribute<R>>>2298 pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
2299 if self.attributes.is_empty() {
2300 // Now that we have parsed all of the attributes, we know where
2301 // either (1) this entry's children start, if the abbreviation says
2302 // this entry has children; or (2) where this entry's siblings
2303 // begin.
2304 if let Some(end) = self.entry.attrs_len.get() {
2305 debug_assert_eq!(end, self.input.offset_from(&self.entry.attrs_slice));
2306 } else {
2307 self.entry
2308 .attrs_len
2309 .set(Some(self.input.offset_from(&self.entry.attrs_slice)));
2310 }
2311
2312 return Ok(None);
2313 }
2314
2315 let spec = self.attributes[0];
2316 let rest_spec = &self.attributes[1..];
2317 match parse_attribute(&mut self.input, self.entry.unit.encoding(), spec) {
2318 Ok(attr) => {
2319 self.attributes = rest_spec;
2320 Ok(Some(attr))
2321 }
2322 Err(e) => {
2323 self.input.empty();
2324 Err(e)
2325 }
2326 }
2327 }
2328 }
2329
2330 #[cfg(feature = "fallible-iterator")]
2331 impl<'abbrev, 'entry, 'unit, R: Reader> fallible_iterator::FallibleIterator
2332 for AttrsIter<'abbrev, 'entry, 'unit, R>
2333 {
2334 type Item = Attribute<R>;
2335 type Error = Error;
2336
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>2337 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
2338 AttrsIter::next(self)
2339 }
2340 }
2341
2342 /// A raw reader of the data that defines the Debugging Information Entries.
2343 ///
2344 /// `EntriesRaw` provides primitives to read the components of Debugging Information
2345 /// Entries (DIEs). A DIE consists of an abbreviation code (read with `read_abbreviation`)
2346 /// followed by a number of attributes (read with `read_attribute`).
2347 /// The user must provide the control flow to read these correctly.
2348 /// In particular, all attributes must always be read before reading another
2349 /// abbreviation code.
2350 ///
2351 /// `EntriesRaw` lacks some features of `EntriesCursor`, such as the ability to skip
2352 /// to the next sibling DIE. However, this also allows it to optimize better, since it
2353 /// does not need to perform the extra bookkeeping required to support these features,
2354 /// and thus it is suitable for cases where performance is important.
2355 ///
2356 /// ## Example Usage
2357 /// ```rust,no_run
2358 /// # fn example() -> Result<(), gimli::Error> {
2359 /// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2360 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2361 /// let unit = get_some_unit();
2362 /// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2363 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2364 /// let abbrevs = get_abbrevs_for_unit(&unit);
2365 ///
2366 /// let mut entries = unit.entries_raw(&abbrevs, None)?;
2367 /// while !entries.is_empty() {
2368 /// let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
2369 /// abbrev
2370 /// } else {
2371 /// // Null entry with no attributes.
2372 /// continue
2373 /// };
2374 /// match abbrev.tag() {
2375 /// gimli::DW_TAG_subprogram => {
2376 /// // Loop over attributes for DIEs we care about.
2377 /// for spec in abbrev.attributes() {
2378 /// let attr = entries.read_attribute(*spec)?;
2379 /// match attr.name() {
2380 /// // Handle attributes.
2381 /// _ => {}
2382 /// }
2383 /// }
2384 /// }
2385 /// _ => {
2386 /// // Skip attributes for DIEs we don't care about.
2387 /// for spec in abbrev.attributes() {
2388 /// entries.read_attribute(*spec)?;
2389 /// }
2390 /// }
2391 /// }
2392 /// }
2393 /// # unreachable!()
2394 /// # }
2395 /// ```
2396 #[derive(Clone, Debug)]
2397 pub struct EntriesRaw<'abbrev, 'unit, R>
2398 where
2399 R: Reader,
2400 {
2401 input: R,
2402 unit: &'unit UnitHeader<R>,
2403 abbreviations: &'abbrev Abbreviations,
2404 depth: isize,
2405 }
2406
2407 impl<'abbrev, 'unit, R: Reader> EntriesRaw<'abbrev, 'unit, R> {
2408 /// Return true if there is no more input.
2409 #[inline]
is_empty(&self) -> bool2410 pub fn is_empty(&self) -> bool {
2411 self.input.is_empty()
2412 }
2413
2414 /// Return the unit offset at which the reader will read next.
2415 ///
2416 /// If you want the offset of the next entry, then this must be called prior to reading
2417 /// the next entry.
next_offset(&self) -> UnitOffset<R::Offset>2418 pub fn next_offset(&self) -> UnitOffset<R::Offset> {
2419 UnitOffset(self.unit.header_size() + self.input.offset_from(&self.unit.entries_buf))
2420 }
2421
2422 /// Return the depth of the next entry.
2423 ///
2424 /// This depth is updated when `read_abbreviation` is called, and is updated
2425 /// based on null entries and the `has_children` field in the abbreviation.
2426 #[inline]
next_depth(&self) -> isize2427 pub fn next_depth(&self) -> isize {
2428 self.depth
2429 }
2430
2431 /// Read an abbreviation code and lookup the corresponding `Abbreviation`.
2432 ///
2433 /// Returns `Ok(None)` for null entries.
2434 #[inline]
read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>>2435 pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
2436 let code = self.input.read_uleb128()?;
2437 if code == 0 {
2438 self.depth -= 1;
2439 return Ok(None);
2440 };
2441 let abbrev = self
2442 .abbreviations
2443 .get(code)
2444 .ok_or(Error::UnknownAbbreviation)?;
2445 if abbrev.has_children() {
2446 self.depth += 1;
2447 }
2448 Ok(Some(abbrev))
2449 }
2450
2451 /// Read an attribute.
2452 #[inline]
read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>>2453 pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
2454 parse_attribute(&mut self.input, self.unit.encoding(), spec)
2455 }
2456 }
2457
2458 /// A cursor into the Debugging Information Entries tree for a compilation unit.
2459 ///
2460 /// The `EntriesCursor` can traverse the DIE tree in DFS order using `next_dfs()`,
2461 /// or skip to the next sibling of the entry the cursor is currently pointing to
2462 /// using `next_sibling()`.
2463 ///
2464 /// It is also possible to traverse the DIE tree at a lower abstraction level
2465 /// using `next_entry()`. This method does not skip over null entries, or provide
2466 /// any indication of the current tree depth. In this case, you must use `current()`
2467 /// to obtain the current entry, and `current().has_children()` to determine if
2468 /// the entry following the current entry will be a sibling or child. `current()`
2469 /// will return `None` if the current entry is a null entry, which signifies the
2470 /// end of the current tree depth.
2471 #[derive(Clone, Debug)]
2472 pub struct EntriesCursor<'abbrev, 'unit, R>
2473 where
2474 R: Reader,
2475 {
2476 input: R,
2477 unit: &'unit UnitHeader<R>,
2478 abbreviations: &'abbrev Abbreviations,
2479 cached_current: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2480 delta_depth: isize,
2481 }
2482
2483 impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> {
2484 /// Get a reference to the entry that the cursor is currently pointing to.
2485 ///
2486 /// If the cursor is not pointing at an entry, or if the current entry is a
2487 /// null entry, then `None` is returned.
2488 #[inline]
current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>2489 pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> {
2490 self.cached_current.as_ref()
2491 }
2492
2493 /// Move the cursor to the next DIE in the tree.
2494 ///
2495 /// Returns `Some` if there is a next entry, even if this entry is null.
2496 /// If there is no next entry, then `None` is returned.
next_entry(&mut self) -> Result<Option<()>>2497 pub fn next_entry(&mut self) -> Result<Option<()>> {
2498 if let Some(ref current) = self.cached_current {
2499 self.input = current.after_attrs()?;
2500 }
2501
2502 if self.input.is_empty() {
2503 self.cached_current = None;
2504 self.delta_depth = 0;
2505 return Ok(None);
2506 }
2507
2508 match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2509 Ok(Some(entry)) => {
2510 self.delta_depth = entry.has_children() as isize;
2511 self.cached_current = Some(entry);
2512 Ok(Some(()))
2513 }
2514 Ok(None) => {
2515 self.delta_depth = -1;
2516 self.cached_current = None;
2517 Ok(Some(()))
2518 }
2519 Err(e) => {
2520 self.input.empty();
2521 self.delta_depth = 0;
2522 self.cached_current = None;
2523 Err(e)
2524 }
2525 }
2526 }
2527
2528 /// Move the cursor to the next DIE in the tree in DFS order.
2529 ///
2530 /// Upon successful movement of the cursor, return the delta traversal
2531 /// depth and the entry:
2532 ///
2533 /// * If we moved down into the previous current entry's children, we get
2534 /// `Some((1, entry))`.
2535 ///
2536 /// * If we moved to the previous current entry's sibling, we get
2537 /// `Some((0, entry))`.
2538 ///
2539 /// * If the previous entry does not have any siblings and we move up to
2540 /// its parent's next sibling, then we get `Some((-1, entry))`. Note that
2541 /// if the parent doesn't have a next sibling, then it could go up to the
2542 /// parent's parent's next sibling and return `Some((-2, entry))`, etc.
2543 ///
2544 /// If there is no next entry, then `None` is returned.
2545 ///
2546 /// Here is an example that finds the first entry in a compilation unit that
2547 /// does not have any children.
2548 ///
2549 /// ```
2550 /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2551 /// # let info_buf = [
2552 /// # // Comilation unit header
2553 /// #
2554 /// # // 32-bit unit length = 25
2555 /// # 0x19, 0x00, 0x00, 0x00,
2556 /// # // Version 4
2557 /// # 0x04, 0x00,
2558 /// # // debug_abbrev_offset
2559 /// # 0x00, 0x00, 0x00, 0x00,
2560 /// # // Address size
2561 /// # 0x04,
2562 /// #
2563 /// # // DIEs
2564 /// #
2565 /// # // Abbreviation code
2566 /// # 0x01,
2567 /// # // Attribute of form DW_FORM_string = "foo\0"
2568 /// # 0x66, 0x6f, 0x6f, 0x00,
2569 /// #
2570 /// # // Children
2571 /// #
2572 /// # // Abbreviation code
2573 /// # 0x01,
2574 /// # // Attribute of form DW_FORM_string = "foo\0"
2575 /// # 0x66, 0x6f, 0x6f, 0x00,
2576 /// #
2577 /// # // Children
2578 /// #
2579 /// # // Abbreviation code
2580 /// # 0x01,
2581 /// # // Attribute of form DW_FORM_string = "foo\0"
2582 /// # 0x66, 0x6f, 0x6f, 0x00,
2583 /// #
2584 /// # // Children
2585 /// #
2586 /// # // End of children
2587 /// # 0x00,
2588 /// #
2589 /// # // End of children
2590 /// # 0x00,
2591 /// #
2592 /// # // End of children
2593 /// # 0x00,
2594 /// # ];
2595 /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2596 /// #
2597 /// # let abbrev_buf = [
2598 /// # // Code
2599 /// # 0x01,
2600 /// # // DW_TAG_subprogram
2601 /// # 0x2e,
2602 /// # // DW_CHILDREN_yes
2603 /// # 0x01,
2604 /// # // Begin attributes
2605 /// # // Attribute name = DW_AT_name
2606 /// # 0x03,
2607 /// # // Attribute form = DW_FORM_string
2608 /// # 0x08,
2609 /// # // End attributes
2610 /// # 0x00,
2611 /// # 0x00,
2612 /// # // Null terminator
2613 /// # 0x00
2614 /// # ];
2615 /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2616 /// #
2617 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2618 ///
2619 /// let unit = get_some_unit();
2620 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2621 /// let abbrevs = get_abbrevs_for_unit(&unit);
2622 ///
2623 /// let mut first_entry_with_no_children = None;
2624 /// let mut cursor = unit.entries(&abbrevs);
2625 ///
2626 /// // Move the cursor to the root.
2627 /// assert!(cursor.next_dfs().unwrap().is_some());
2628 ///
2629 /// // Traverse the DIE tree in depth-first search order.
2630 /// let mut depth = 0;
2631 /// while let Some((delta_depth, current)) = cursor.next_dfs().expect("Should parse next dfs") {
2632 /// // Update depth value, and break out of the loop when we
2633 /// // return to the original starting position.
2634 /// depth += delta_depth;
2635 /// if depth <= 0 {
2636 /// break;
2637 /// }
2638 ///
2639 /// first_entry_with_no_children = Some(current.clone());
2640 /// }
2641 ///
2642 /// println!("The first entry with no children is {:?}",
2643 /// first_entry_with_no_children.unwrap());
2644 /// ```
2645 #[allow(clippy::type_complexity)]
next_dfs( &mut self, ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>>2646 pub fn next_dfs(
2647 &mut self,
2648 ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>> {
2649 let mut delta_depth = self.delta_depth;
2650 loop {
2651 // The next entry should be the one we want.
2652 if self.next_entry()?.is_some() {
2653 if let Some(ref entry) = self.cached_current {
2654 return Ok(Some((delta_depth, entry)));
2655 }
2656
2657 // next_entry() read a null entry.
2658 delta_depth += self.delta_depth;
2659 } else {
2660 return Ok(None);
2661 }
2662 }
2663 }
2664
2665 /// Move the cursor to the next sibling DIE of the current one.
2666 ///
2667 /// Returns `Ok(Some(entry))` when the cursor has been moved to
2668 /// the next sibling, `Ok(None)` when there is no next sibling.
2669 ///
2670 /// The depth of the cursor is never changed if this method returns `Ok`.
2671 /// Once `Ok(None)` is returned, this method will continue to return
2672 /// `Ok(None)` until either `next_entry` or `next_dfs` is called.
2673 ///
2674 /// Here is an example that iterates over all of the direct children of the
2675 /// root entry:
2676 ///
2677 /// ```
2678 /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
2679 /// # let info_buf = [
2680 /// # // Comilation unit header
2681 /// #
2682 /// # // 32-bit unit length = 25
2683 /// # 0x19, 0x00, 0x00, 0x00,
2684 /// # // Version 4
2685 /// # 0x04, 0x00,
2686 /// # // debug_abbrev_offset
2687 /// # 0x00, 0x00, 0x00, 0x00,
2688 /// # // Address size
2689 /// # 0x04,
2690 /// #
2691 /// # // DIEs
2692 /// #
2693 /// # // Abbreviation code
2694 /// # 0x01,
2695 /// # // Attribute of form DW_FORM_string = "foo\0"
2696 /// # 0x66, 0x6f, 0x6f, 0x00,
2697 /// #
2698 /// # // Children
2699 /// #
2700 /// # // Abbreviation code
2701 /// # 0x01,
2702 /// # // Attribute of form DW_FORM_string = "foo\0"
2703 /// # 0x66, 0x6f, 0x6f, 0x00,
2704 /// #
2705 /// # // Children
2706 /// #
2707 /// # // Abbreviation code
2708 /// # 0x01,
2709 /// # // Attribute of form DW_FORM_string = "foo\0"
2710 /// # 0x66, 0x6f, 0x6f, 0x00,
2711 /// #
2712 /// # // Children
2713 /// #
2714 /// # // End of children
2715 /// # 0x00,
2716 /// #
2717 /// # // End of children
2718 /// # 0x00,
2719 /// #
2720 /// # // End of children
2721 /// # 0x00,
2722 /// # ];
2723 /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
2724 /// #
2725 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2726 ///
2727 /// # let abbrev_buf = [
2728 /// # // Code
2729 /// # 0x01,
2730 /// # // DW_TAG_subprogram
2731 /// # 0x2e,
2732 /// # // DW_CHILDREN_yes
2733 /// # 0x01,
2734 /// # // Begin attributes
2735 /// # // Attribute name = DW_AT_name
2736 /// # 0x03,
2737 /// # // Attribute form = DW_FORM_string
2738 /// # 0x08,
2739 /// # // End attributes
2740 /// # 0x00,
2741 /// # 0x00,
2742 /// # // Null terminator
2743 /// # 0x00
2744 /// # ];
2745 /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
2746 /// #
2747 /// let unit = get_some_unit();
2748 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2749 /// let abbrevs = get_abbrevs_for_unit(&unit);
2750 ///
2751 /// let mut cursor = unit.entries(&abbrevs);
2752 ///
2753 /// // Move the cursor to the root.
2754 /// assert!(cursor.next_dfs().unwrap().is_some());
2755 ///
2756 /// // Move the cursor to the root's first child.
2757 /// assert!(cursor.next_dfs().unwrap().is_some());
2758 ///
2759 /// // Iterate the root's children.
2760 /// loop {
2761 /// {
2762 /// let current = cursor.current().expect("Should be at an entry");
2763 /// println!("{:?} is a child of the root", current);
2764 /// }
2765 ///
2766 /// if cursor.next_sibling().expect("Should parse next sibling").is_none() {
2767 /// break;
2768 /// }
2769 /// }
2770 /// ```
next_sibling( &mut self, ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>>2771 pub fn next_sibling(
2772 &mut self,
2773 ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>> {
2774 if self.current().is_none() {
2775 // We're already at the null for the end of the sibling list.
2776 return Ok(None);
2777 }
2778
2779 // Loop until we find an entry at the current level.
2780 let mut depth = 0;
2781 loop {
2782 // Use is_some() and unwrap() to keep borrow checker happy.
2783 if self.current().is_some() && self.current().unwrap().has_children() {
2784 if let Some(sibling_input) = self.current().unwrap().sibling() {
2785 // Fast path: this entry has a DW_AT_sibling
2786 // attribute pointing to its sibling, so jump
2787 // to it (which keeps us at the same depth).
2788 self.input = sibling_input;
2789 self.cached_current = None;
2790 } else {
2791 // This entry has children, so the next entry is
2792 // down one level.
2793 depth += 1;
2794 }
2795 }
2796
2797 if self.next_entry()?.is_none() {
2798 // End of input.
2799 return Ok(None);
2800 }
2801
2802 if depth == 0 {
2803 // Found an entry at the current level.
2804 return Ok(self.current());
2805 }
2806
2807 if self.current().is_none() {
2808 // A null entry means the end of a child list, so we're
2809 // back up a level.
2810 depth -= 1;
2811 }
2812 }
2813 }
2814 }
2815
2816 /// The state information for a tree view of the Debugging Information Entries.
2817 ///
2818 /// The `EntriesTree` can be used to recursively iterate through the DIE
2819 /// tree, following the parent/child relationships. The `EntriesTree` contains
2820 /// shared state for all nodes in the tree, avoiding any duplicate parsing of
2821 /// entries during the traversal.
2822 ///
2823 /// ## Example Usage
2824 /// ```rust,no_run
2825 /// # fn example() -> Result<(), gimli::Error> {
2826 /// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
2827 /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
2828 /// let unit = get_some_unit();
2829 /// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
2830 /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
2831 /// let abbrevs = get_abbrevs_for_unit(&unit);
2832 ///
2833 /// let mut tree = unit.entries_tree(&abbrevs, None)?;
2834 /// let root = tree.root()?;
2835 /// process_tree(root)?;
2836 /// # unreachable!()
2837 /// # }
2838 ///
2839 /// fn process_tree<R>(mut node: gimli::EntriesTreeNode<R>) -> gimli::Result<()>
2840 /// where R: gimli::Reader
2841 /// {
2842 /// {
2843 /// // Examine the entry attributes.
2844 /// let mut attrs = node.entry().attrs();
2845 /// while let Some(attr) = attrs.next()? {
2846 /// }
2847 /// }
2848 /// let mut children = node.children();
2849 /// while let Some(child) = children.next()? {
2850 /// // Recursively process a child.
2851 /// process_tree(child);
2852 /// }
2853 /// Ok(())
2854 /// }
2855 /// ```
2856 #[derive(Clone, Debug)]
2857 pub struct EntriesTree<'abbrev, 'unit, R>
2858 where
2859 R: Reader,
2860 {
2861 root: R,
2862 unit: &'unit UnitHeader<R>,
2863 abbreviations: &'abbrev Abbreviations,
2864 input: R,
2865 entry: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
2866 depth: isize,
2867 }
2868
2869 impl<'abbrev, 'unit, R: Reader> EntriesTree<'abbrev, 'unit, R> {
new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self2870 fn new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self {
2871 let input = root.clone();
2872 EntriesTree {
2873 root,
2874 unit,
2875 abbreviations,
2876 input,
2877 entry: None,
2878 depth: 0,
2879 }
2880 }
2881
2882 /// Returns the root node of the tree.
root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>>2883 pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>> {
2884 self.input = self.root.clone();
2885 self.entry =
2886 DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations)?;
2887 if self.entry.is_none() {
2888 return Err(Error::UnexpectedNull);
2889 }
2890 self.depth = 0;
2891 Ok(EntriesTreeNode::new(self, 1))
2892 }
2893
2894 /// Move the cursor to the next entry at the specified depth.
2895 ///
2896 /// Requires `depth <= self.depth + 1`.
2897 ///
2898 /// Returns `true` if successful.
next(&mut self, depth: isize) -> Result<bool>2899 fn next(&mut self, depth: isize) -> Result<bool> {
2900 if self.depth < depth {
2901 debug_assert_eq!(self.depth + 1, depth);
2902
2903 match self.entry {
2904 Some(ref entry) => {
2905 if !entry.has_children() {
2906 return Ok(false);
2907 }
2908 self.depth += 1;
2909 self.input = entry.after_attrs()?;
2910 }
2911 None => return Ok(false),
2912 }
2913
2914 if self.input.is_empty() {
2915 self.entry = None;
2916 return Ok(false);
2917 }
2918
2919 return match DebuggingInformationEntry::parse(
2920 &mut self.input,
2921 self.unit,
2922 self.abbreviations,
2923 ) {
2924 Ok(entry) => {
2925 self.entry = entry;
2926 Ok(self.entry.is_some())
2927 }
2928 Err(e) => {
2929 self.input.empty();
2930 self.entry = None;
2931 Err(e)
2932 }
2933 };
2934 }
2935
2936 loop {
2937 match self.entry {
2938 Some(ref entry) => {
2939 if entry.has_children() {
2940 if let Some(sibling_input) = entry.sibling() {
2941 // Fast path: this entry has a DW_AT_sibling
2942 // attribute pointing to its sibling, so jump
2943 // to it (which keeps us at the same depth).
2944 self.input = sibling_input;
2945 } else {
2946 // This entry has children, so the next entry is
2947 // down one level.
2948 self.depth += 1;
2949 self.input = entry.after_attrs()?;
2950 }
2951 } else {
2952 // This entry has no children, so next entry is at same depth.
2953 self.input = entry.after_attrs()?;
2954 }
2955 }
2956 None => {
2957 // This entry is a null, so next entry is up one level.
2958 self.depth -= 1;
2959 }
2960 }
2961
2962 if self.input.is_empty() {
2963 self.entry = None;
2964 return Ok(false);
2965 }
2966
2967 match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
2968 Ok(entry) => {
2969 self.entry = entry;
2970 if self.depth == depth {
2971 return Ok(self.entry.is_some());
2972 }
2973 }
2974 Err(e) => {
2975 self.input.empty();
2976 self.entry = None;
2977 return Err(e);
2978 }
2979 }
2980 }
2981 }
2982 }
2983
2984 /// A node in the Debugging Information Entry tree.
2985 ///
2986 /// The root node of a tree can be obtained
2987 /// via [`EntriesTree::root`](./struct.EntriesTree.html#method.root).
2988 #[derive(Debug)]
2989 pub struct EntriesTreeNode<'abbrev, 'unit, 'tree, R: Reader> {
2990 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2991 depth: isize,
2992 }
2993
2994 impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
new( tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, depth: isize, ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R>2995 fn new(
2996 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
2997 depth: isize,
2998 ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
2999 debug_assert!(tree.entry.is_some());
3000 EntriesTreeNode { tree, depth }
3001 }
3002
3003 /// Returns the current entry in the tree.
entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R>3004 pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> {
3005 // We never create a node without an entry.
3006 self.tree.entry.as_ref().unwrap()
3007 }
3008
3009 /// Create an iterator for the children of the current entry.
3010 ///
3011 /// The current entry can no longer be accessed after creating the
3012 /// iterator.
children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R>3013 pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3014 EntriesTreeIter::new(self.tree, self.depth)
3015 }
3016 }
3017
3018 /// An iterator that allows traversal of the children of an
3019 /// `EntriesTreeNode`.
3020 ///
3021 /// The items returned by this iterator are also `EntriesTreeNode`s,
3022 /// which allow recursive traversal of grandchildren, etc.
3023 #[derive(Debug)]
3024 pub struct EntriesTreeIter<'abbrev, 'unit, 'tree, R: Reader> {
3025 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
3026 depth: isize,
3027 empty: bool,
3028 }
3029
3030 impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
new( tree: &'tree mut EntriesTree<'abbrev, 'unit, R>, depth: isize, ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R>3031 fn new(
3032 tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
3033 depth: isize,
3034 ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
3035 EntriesTreeIter {
3036 tree,
3037 depth,
3038 empty: false,
3039 }
3040 }
3041
3042 /// Returns an `EntriesTreeNode` for the next child entry.
3043 ///
3044 /// Returns `None` if there are no more children.
next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>>3045 pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>> {
3046 if self.empty {
3047 Ok(None)
3048 } else if self.tree.next(self.depth)? {
3049 Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
3050 } else {
3051 self.empty = true;
3052 Ok(None)
3053 }
3054 }
3055 }
3056
3057 /// Parse a type unit header's unique type signature. Callers should handle
3058 /// unique-ness checking.
parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature>3059 fn parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature> {
3060 input.read_u64().map(DebugTypeSignature)
3061 }
3062
3063 /// Parse a type unit header's type offset.
parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>>3064 fn parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>> {
3065 input.read_offset(format).map(UnitOffset)
3066 }
3067
3068 /// The `DebugTypes` struct represents the DWARF type information
3069 /// found in the `.debug_types` section.
3070 #[derive(Debug, Default, Clone, Copy)]
3071 pub struct DebugTypes<R> {
3072 debug_types_section: R,
3073 }
3074
3075 impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
3076 where
3077 Endian: Endianity,
3078 {
3079 /// Construct a new `DebugTypes` instance from the data in the `.debug_types`
3080 /// section.
3081 ///
3082 /// It is the caller's responsibility to read the `.debug_types` section and
3083 /// present it as a `&[u8]` slice. That means using some ELF loader on
3084 /// Linux, a Mach-O loader on OSX, etc.
3085 ///
3086 /// ```
3087 /// use gimli::{DebugTypes, LittleEndian};
3088 ///
3089 /// # let buf = [0x00, 0x01, 0x02, 0x03];
3090 /// # let read_debug_types_section_somehow = || &buf;
3091 /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3092 /// ```
new(debug_types_section: &'input [u8], endian: Endian) -> Self3093 pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
3094 Self::from(EndianSlice::new(debug_types_section, endian))
3095 }
3096 }
3097
3098 impl<T> DebugTypes<T> {
3099 /// Create a `DebugTypes` section that references the data in `self`.
3100 ///
3101 /// This is useful when `R` implements `Reader` but `T` does not.
3102 ///
3103 /// ## Example Usage
3104 ///
3105 /// ```rust,no_run
3106 /// # let load_section = || unimplemented!();
3107 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
3108 /// let owned_section: gimli::DebugTypes<Vec<u8>> = load_section();
3109 /// // Create a reference to the DWARF section.
3110 /// let section = owned_section.borrow(|section| {
3111 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
3112 /// });
3113 /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R> where F: FnMut(&'a T) -> R,3114 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
3115 where
3116 F: FnMut(&'a T) -> R,
3117 {
3118 borrow(&self.debug_types_section).into()
3119 }
3120 }
3121
3122 impl<R> Section<R> for DebugTypes<R> {
id() -> SectionId3123 fn id() -> SectionId {
3124 SectionId::DebugTypes
3125 }
3126
reader(&self) -> &R3127 fn reader(&self) -> &R {
3128 &self.debug_types_section
3129 }
3130 }
3131
3132 impl<R> From<R> for DebugTypes<R> {
from(debug_types_section: R) -> Self3133 fn from(debug_types_section: R) -> Self {
3134 DebugTypes {
3135 debug_types_section,
3136 }
3137 }
3138 }
3139
3140 impl<R: Reader> DebugTypes<R> {
3141 /// Iterate the type-units in this `.debug_types` section.
3142 ///
3143 /// ```
3144 /// use gimli::{DebugTypes, LittleEndian};
3145 ///
3146 /// # let buf = [];
3147 /// # let read_debug_types_section_somehow = || &buf;
3148 /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
3149 ///
3150 /// let mut iter = debug_types.units();
3151 /// while let Some(unit) = iter.next().unwrap() {
3152 /// println!("unit's length is {}", unit.unit_length());
3153 /// }
3154 /// ```
3155 ///
3156 /// Can be [used with
3157 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
units(&self) -> TypeUnitHeadersIter<R>3158 pub fn units(&self) -> TypeUnitHeadersIter<R> {
3159 TypeUnitHeadersIter {
3160 input: self.debug_types_section.clone(),
3161 offset: DebugTypesOffset(R::Offset::from_u8(0)),
3162 }
3163 }
3164 }
3165
3166 /// An iterator over the type-units of this `.debug_types` section.
3167 ///
3168 /// See the [documentation on
3169 /// `DebugTypes::units`](./struct.DebugTypes.html#method.units) for
3170 /// more detail.
3171 #[derive(Clone, Debug)]
3172 pub struct TypeUnitHeadersIter<R: Reader> {
3173 input: R,
3174 offset: DebugTypesOffset<R::Offset>,
3175 }
3176
3177 impl<R: Reader> TypeUnitHeadersIter<R> {
3178 /// Advance the iterator to the next type unit header.
next(&mut self) -> Result<Option<TypeUnitHeader<R>>>3179 pub fn next(&mut self) -> Result<Option<TypeUnitHeader<R>>> {
3180 if self.input.is_empty() {
3181 Ok(None)
3182 } else {
3183 let len = self.input.len();
3184 match parse_type_unit_header(&mut self.input, self.offset) {
3185 Ok(header) => {
3186 self.offset.0 += len - self.input.len();
3187 Ok(Some(header))
3188 }
3189 Err(e) => {
3190 self.input.empty();
3191 Err(e)
3192 }
3193 }
3194 }
3195 }
3196 }
3197
3198 #[cfg(feature = "fallible-iterator")]
3199 impl<R: Reader> fallible_iterator::FallibleIterator for TypeUnitHeadersIter<R> {
3200 type Item = TypeUnitHeader<R>;
3201 type Error = Error;
3202
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>3203 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
3204 TypeUnitHeadersIter::next(self)
3205 }
3206 }
3207
3208 /// The header of a type unit's debugging information.
3209 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
3210 pub struct TypeUnitHeader<R, Offset = <R as Reader>::Offset>
3211 where
3212 R: Reader<Offset = Offset>,
3213 Offset: ReaderOffset,
3214 {
3215 header: UnitHeader<R, Offset>,
3216 offset: DebugTypesOffset<Offset>,
3217 type_signature: DebugTypeSignature,
3218 type_offset: UnitOffset<Offset>,
3219 }
3220
3221 impl<R, Offset> TypeUnitHeader<R, Offset>
3222 where
3223 R: Reader<Offset = Offset>,
3224 Offset: ReaderOffset,
3225 {
3226 /// Construct a new `TypeUnitHeader`.
new( header: UnitHeader<R>, offset: DebugTypesOffset<R::Offset>, type_signature: DebugTypeSignature, type_offset: UnitOffset<R::Offset>, ) -> Self3227 fn new(
3228 header: UnitHeader<R>,
3229 offset: DebugTypesOffset<R::Offset>,
3230 type_signature: DebugTypeSignature,
3231 type_offset: UnitOffset<R::Offset>,
3232 ) -> Self {
3233 TypeUnitHeader {
3234 header,
3235 offset,
3236 type_signature,
3237 type_offset,
3238 }
3239 }
3240
3241 /// Return the `UnitHeader` containing common unit fields.
header(self) -> UnitHeader<R, Offset>3242 pub fn header(self) -> UnitHeader<R, Offset> {
3243 self.header
3244 }
3245
3246 /// Return the serialized size of the type-unit header for the given
3247 /// DWARF format.
size_of_header(encoding: Encoding) -> usize3248 pub fn size_of_header(encoding: Encoding) -> usize {
3249 let unit_header_size = UnitHeader::<R, _>::size_of_header(encoding);
3250 let type_signature_size = 8;
3251 let type_offset_size = encoding.format.word_size() as usize;
3252 unit_header_size + type_signature_size + type_offset_size
3253 }
3254
3255 /// Get the offset of this compilation unit within the .debug_info section.
offset(&self) -> DebugTypesOffset<R::Offset>3256 pub fn offset(&self) -> DebugTypesOffset<R::Offset> {
3257 self.offset
3258 }
3259
3260 /// Get the length of the debugging info for this type-unit.
unit_length(&self) -> R::Offset3261 pub fn unit_length(&self) -> R::Offset {
3262 self.header.unit_length
3263 }
3264
3265 /// Get the length of the debugging info for this type-unit,
3266 /// including the byte length of the encoded length itself.
length_including_self(&self) -> R::Offset3267 pub fn length_including_self(&self) -> R::Offset {
3268 self.header.length_including_self()
3269 }
3270
3271 /// Return the encoding parameters for this unit.
encoding(&self) -> Encoding3272 pub fn encoding(&self) -> Encoding {
3273 self.header.encoding
3274 }
3275
3276 /// Get the DWARF version of the debugging info for this type-unit.
version(&self) -> u163277 pub fn version(&self) -> u16 {
3278 self.header.version()
3279 }
3280
3281 /// The offset into the `.debug_abbrev` section for this type-unit's
3282 /// debugging information entries.
debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset>3283 pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<R::Offset> {
3284 self.header.debug_abbrev_offset
3285 }
3286
3287 /// The size of addresses (in bytes) in this type-unit.
address_size(&self) -> u83288 pub fn address_size(&self) -> u8 {
3289 self.header.address_size()
3290 }
3291
3292 /// Whether this type unit is encoded in 64- or 32-bit DWARF.
format(&self) -> Format3293 pub fn format(&self) -> Format {
3294 self.header.format()
3295 }
3296
3297 /// The serialized size of the header for this type-unit.
header_size(&self) -> R::Offset3298 pub fn header_size(&self) -> R::Offset {
3299 self.header.header_size()
3300 }
3301
3302 /// Get the unique type signature for this type unit.
type_signature(&self) -> DebugTypeSignature3303 pub fn type_signature(&self) -> DebugTypeSignature {
3304 self.type_signature
3305 }
3306
3307 /// Get the offset within this type unit where the type is defined.
type_offset(&self) -> UnitOffset<R::Offset>3308 pub fn type_offset(&self) -> UnitOffset<R::Offset> {
3309 self.type_offset
3310 }
3311
3312 /// Navigate this type unit's `DebuggingInformationEntry`s.
entries<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, ) -> EntriesCursor<'abbrev, 'me, R>3313 pub fn entries<'me, 'abbrev>(
3314 &'me self,
3315 abbreviations: &'abbrev Abbreviations,
3316 ) -> EntriesCursor<'abbrev, 'me, R> {
3317 self.header.entries(abbreviations)
3318 }
3319
3320 /// Navigate this type unit's `DebuggingInformationEntry`s
3321 /// starting at the given offset.
entries_at_offset<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: UnitOffset<R::Offset>, ) -> Result<EntriesCursor<'abbrev, 'me, R>>3322 pub fn entries_at_offset<'me, 'abbrev>(
3323 &'me self,
3324 abbreviations: &'abbrev Abbreviations,
3325 offset: UnitOffset<R::Offset>,
3326 ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
3327 self.header.entries_at_offset(abbreviations, offset)
3328 }
3329
3330 /// Navigate this type unit's `DebuggingInformationEntry`s as a tree
3331 /// starting at the given offset.
entries_tree<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesTree<'abbrev, 'me, R>>3332 pub fn entries_tree<'me, 'abbrev>(
3333 &'me self,
3334 abbreviations: &'abbrev Abbreviations,
3335 offset: Option<UnitOffset<R::Offset>>,
3336 ) -> Result<EntriesTree<'abbrev, 'me, R>> {
3337 self.header.entries_tree(abbreviations, offset)
3338 }
3339
3340 /// Read the raw data that defines the Debugging Information Entries.
entries_raw<'me, 'abbrev>( &'me self, abbreviations: &'abbrev Abbreviations, offset: Option<UnitOffset<R::Offset>>, ) -> Result<EntriesRaw<'abbrev, 'me, R>>3341 pub fn entries_raw<'me, 'abbrev>(
3342 &'me self,
3343 abbreviations: &'abbrev Abbreviations,
3344 offset: Option<UnitOffset<R::Offset>>,
3345 ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
3346 self.header.entries_raw(abbreviations, offset)
3347 }
3348
3349 /// Parse this type unit's abbreviations.
3350 ///
3351 /// ```
3352 /// use gimli::DebugAbbrev;
3353 /// # use gimli::{DebugTypes, LittleEndian};
3354 /// # let types_buf = [
3355 /// # // Type unit header
3356 /// #
3357 /// # // 32-bit unit length = 37
3358 /// # 0x25, 0x00, 0x00, 0x00,
3359 /// # // Version 4
3360 /// # 0x04, 0x00,
3361 /// # // debug_abbrev_offset
3362 /// # 0x00, 0x00, 0x00, 0x00,
3363 /// # // Address size
3364 /// # 0x04,
3365 /// # // Type signature
3366 /// # 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3367 /// # // Type offset
3368 /// # 0x01, 0x02, 0x03, 0x04,
3369 /// #
3370 /// # // DIEs
3371 /// #
3372 /// # // Abbreviation code
3373 /// # 0x01,
3374 /// # // Attribute of form DW_FORM_string = "foo\0"
3375 /// # 0x66, 0x6f, 0x6f, 0x00,
3376 /// #
3377 /// # // Children
3378 /// #
3379 /// # // Abbreviation code
3380 /// # 0x01,
3381 /// # // Attribute of form DW_FORM_string = "foo\0"
3382 /// # 0x66, 0x6f, 0x6f, 0x00,
3383 /// #
3384 /// # // Children
3385 /// #
3386 /// # // Abbreviation code
3387 /// # 0x01,
3388 /// # // Attribute of form DW_FORM_string = "foo\0"
3389 /// # 0x66, 0x6f, 0x6f, 0x00,
3390 /// #
3391 /// # // Children
3392 /// #
3393 /// # // End of children
3394 /// # 0x00,
3395 /// #
3396 /// # // End of children
3397 /// # 0x00,
3398 /// #
3399 /// # // End of children
3400 /// # 0x00,
3401 /// # ];
3402 /// # let debug_types = DebugTypes::new(&types_buf, LittleEndian);
3403 /// #
3404 /// # let abbrev_buf = [
3405 /// # // Code
3406 /// # 0x01,
3407 /// # // DW_TAG_subprogram
3408 /// # 0x2e,
3409 /// # // DW_CHILDREN_yes
3410 /// # 0x01,
3411 /// # // Begin attributes
3412 /// # // Attribute name = DW_AT_name
3413 /// # 0x03,
3414 /// # // Attribute form = DW_FORM_string
3415 /// # 0x08,
3416 /// # // End attributes
3417 /// # 0x00,
3418 /// # 0x00,
3419 /// # // Null terminator
3420 /// # 0x00
3421 /// # ];
3422 /// #
3423 /// # let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
3424 ///
3425 /// let unit = get_some_type_unit();
3426 ///
3427 /// # let read_debug_abbrev_section_somehow = || &abbrev_buf;
3428 /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
3429 /// let abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
3430 /// ```
abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations>3431 pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
3432 self.header.abbreviations(debug_abbrev)
3433 }
3434 }
3435
3436 /// Parse a type unit header.
parse_type_unit_header<R: Reader>( input: &mut R, offset: DebugTypesOffset<R::Offset>, ) -> Result<TypeUnitHeader<R>>3437 fn parse_type_unit_header<R: Reader>(
3438 input: &mut R,
3439 offset: DebugTypesOffset<R::Offset>,
3440 ) -> Result<TypeUnitHeader<R>> {
3441 let mut header = parse_unit_header(input)?;
3442 let format = header.format();
3443 let signature = parse_type_signature(&mut header.entries_buf)?;
3444 let type_offset = parse_type_offset(&mut header.entries_buf, format)?;
3445 Ok(TypeUnitHeader::new(header, offset, signature, type_offset))
3446 }
3447
3448 #[cfg(test)]
3449 // Tests require leb128::write.
3450 #[cfg(feature = "write")]
3451 mod tests {
3452 use super::*;
3453 use crate::constants;
3454 use crate::constants::*;
3455 use crate::endianity::{Endianity, LittleEndian};
3456 use crate::leb128;
3457 use crate::read::abbrev::tests::AbbrevSectionMethods;
3458 use crate::read::{
3459 Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
3460 };
3461 use crate::test_util::GimliSectionMethods;
3462 use alloc::vec::Vec;
3463 use core::cell::Cell;
3464 use test_assembler::{Endian, Label, LabelMaker, Section};
3465
3466 // Mixin methods for `Section` to help define binary test data.
3467
3468 trait UnitSectionMethods {
comp_unit<'input, E>( self, unit: &mut CompilationUnitHeader<EndianSlice<'input, E>>, ) -> Self where E: Endianity3469 fn comp_unit<'input, E>(
3470 self,
3471 unit: &mut CompilationUnitHeader<EndianSlice<'input, E>>,
3472 ) -> Self
3473 where
3474 E: Endianity;
type_unit<'input, E>(self, unit: &mut TypeUnitHeader<EndianSlice<'input, E>>) -> Self where E: Endianity3475 fn type_unit<'input, E>(self, unit: &mut TypeUnitHeader<EndianSlice<'input, E>>) -> Self
3476 where
3477 E: Endianity;
unit<'input, E>( self, unit: &mut UnitHeader<EndianSlice<'input, E>>, extra_header: &[u8], ) -> Self where E: Endianity3478 fn unit<'input, E>(
3479 self,
3480 unit: &mut UnitHeader<EndianSlice<'input, E>>,
3481 extra_header: &[u8],
3482 ) -> Self
3483 where
3484 E: Endianity;
die<F>(self, code: u64, attr: F) -> Self where F: Fn(Section) -> Section3485 fn die<F>(self, code: u64, attr: F) -> Self
3486 where
3487 F: Fn(Section) -> Section;
die_null(self) -> Self3488 fn die_null(self) -> Self;
attr_string(self, s: &str) -> Self3489 fn attr_string(self, s: &str) -> Self;
attr_ref1(self, o: u8) -> Self3490 fn attr_ref1(self, o: u8) -> Self;
offset(self, offset: usize, format: Format) -> Self3491 fn offset(self, offset: usize, format: Format) -> Self;
3492 }
3493
3494 impl UnitSectionMethods for Section {
comp_unit<'input, E>( self, unit: &mut CompilationUnitHeader<EndianSlice<'input, E>>, ) -> Self where E: Endianity,3495 fn comp_unit<'input, E>(
3496 self,
3497 unit: &mut CompilationUnitHeader<EndianSlice<'input, E>>,
3498 ) -> Self
3499 where
3500 E: Endianity,
3501 {
3502 unit.offset = DebugInfoOffset(self.size() as usize);
3503 self.unit(&mut unit.header, &[])
3504 }
3505
type_unit<'input, E>(self, unit: &mut TypeUnitHeader<EndianSlice<'input, E>>) -> Self where E: Endianity,3506 fn type_unit<'input, E>(self, unit: &mut TypeUnitHeader<EndianSlice<'input, E>>) -> Self
3507 where
3508 E: Endianity,
3509 {
3510 unit.offset = DebugTypesOffset(self.size() as usize);
3511 let section = Section::with_endian(Endian::Little)
3512 .L64(unit.type_signature.0)
3513 .offset(unit.type_offset.0, unit.header.format());
3514 let extra_header = section.get_contents().unwrap();
3515 self.unit(&mut unit.header, &extra_header)
3516 }
3517
unit<'input, E>( self, unit: &mut UnitHeader<EndianSlice<'input, E>>, extra_header: &[u8], ) -> Self where E: Endianity,3518 fn unit<'input, E>(
3519 self,
3520 unit: &mut UnitHeader<EndianSlice<'input, E>>,
3521 extra_header: &[u8],
3522 ) -> Self
3523 where
3524 E: Endianity,
3525 {
3526 let length = Label::new();
3527 let start = Label::new();
3528 let end = Label::new();
3529
3530 let section = match unit.format() {
3531 Format::Dwarf32 => self.L32(&length),
3532 Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
3533 };
3534
3535 let section = match unit.version() {
3536 2 | 3 | 4 => section
3537 .mark(&start)
3538 .L16(unit.version())
3539 .offset(unit.debug_abbrev_offset.0, unit.format())
3540 .D8(unit.address_size())
3541 .append_bytes(extra_header)
3542 .append_bytes(unit.entries_buf.into())
3543 .mark(&end),
3544 5 => section
3545 .mark(&start)
3546 .L16(unit.version())
3547 .D8(constants::DW_UT_compile.0)
3548 .D8(unit.address_size())
3549 .offset(unit.debug_abbrev_offset.0, unit.format())
3550 .append_bytes(extra_header)
3551 .append_bytes(unit.entries_buf.into())
3552 .mark(&end),
3553 _ => unreachable!(),
3554 };
3555
3556 unit.unit_length = (&end - &start) as usize;
3557 length.set_const(unit.unit_length as u64);
3558
3559 section
3560 }
3561
die<F>(self, code: u64, attr: F) -> Self where F: Fn(Section) -> Section,3562 fn die<F>(self, code: u64, attr: F) -> Self
3563 where
3564 F: Fn(Section) -> Section,
3565 {
3566 let section = self.uleb(code);
3567 attr(section)
3568 }
3569
die_null(self) -> Self3570 fn die_null(self) -> Self {
3571 self.D8(0)
3572 }
3573
attr_string(self, attr: &str) -> Self3574 fn attr_string(self, attr: &str) -> Self {
3575 self.append_bytes(attr.as_bytes()).D8(0)
3576 }
3577
attr_ref1(self, attr: u8) -> Self3578 fn attr_ref1(self, attr: u8) -> Self {
3579 self.D8(attr)
3580 }
3581
offset(self, offset: usize, format: Format) -> Self3582 fn offset(self, offset: usize, format: Format) -> Self {
3583 match format {
3584 Format::Dwarf32 => self.L32(offset as u32),
3585 Format::Dwarf64 => self.L64(offset as u64),
3586 }
3587 }
3588 }
3589
3590 #[test]
test_parse_debug_abbrev_offset_32()3591 fn test_parse_debug_abbrev_offset_32() {
3592 let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3593 let buf = section.get_contents().unwrap();
3594 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3595
3596 match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3597 Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0403_0201)),
3598 otherwise => panic!("Unexpected result: {:?}", otherwise),
3599 };
3600 }
3601
3602 #[test]
test_parse_debug_abbrev_offset_32_incomplete()3603 fn test_parse_debug_abbrev_offset_32_incomplete() {
3604 let buf = [0x01, 0x02];
3605 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3606
3607 match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
3608 Err(Error::UnexpectedEof(_)) => assert!(true),
3609 otherwise => panic!("Unexpected result: {:?}", otherwise),
3610 };
3611 }
3612
3613 #[test]
3614 #[cfg(target_pointer_width = "64")]
test_parse_debug_abbrev_offset_64()3615 fn test_parse_debug_abbrev_offset_64() {
3616 let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3617 let buf = section.get_contents().unwrap();
3618 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3619
3620 match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3621 Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0807_0605_0403_0201)),
3622 otherwise => panic!("Unexpected result: {:?}", otherwise),
3623 };
3624 }
3625
3626 #[test]
test_parse_debug_abbrev_offset_64_incomplete()3627 fn test_parse_debug_abbrev_offset_64_incomplete() {
3628 let buf = [0x01, 0x02];
3629 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3630
3631 match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
3632 Err(Error::UnexpectedEof(_)) => assert!(true),
3633 otherwise => panic!("Unexpected result: {:?}", otherwise),
3634 };
3635 }
3636
3637 #[test]
test_parse_debug_info_offset_32()3638 fn test_parse_debug_info_offset_32() {
3639 let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
3640 let buf = section.get_contents().unwrap();
3641 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3642
3643 match parse_debug_info_offset(buf, Format::Dwarf32) {
3644 Ok(val) => assert_eq!(val, DebugInfoOffset(0x0403_0201)),
3645 otherwise => panic!("Unexpected result: {:?}", otherwise),
3646 };
3647 }
3648
3649 #[test]
test_parse_debug_info_offset_32_incomplete()3650 fn test_parse_debug_info_offset_32_incomplete() {
3651 let buf = [0x01, 0x02];
3652 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3653
3654 match parse_debug_info_offset(buf, Format::Dwarf32) {
3655 Err(Error::UnexpectedEof(_)) => assert!(true),
3656 otherwise => panic!("Unexpected result: {:?}", otherwise),
3657 };
3658 }
3659
3660 #[test]
3661 #[cfg(target_pointer_width = "64")]
test_parse_debug_info_offset_64()3662 fn test_parse_debug_info_offset_64() {
3663 let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
3664 let buf = section.get_contents().unwrap();
3665 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3666
3667 match parse_debug_info_offset(buf, Format::Dwarf64) {
3668 Ok(val) => assert_eq!(val, DebugInfoOffset(0x0807_0605_0403_0201)),
3669 otherwise => panic!("Unexpected result: {:?}", otherwise),
3670 };
3671 }
3672
3673 #[test]
test_parse_debug_info_offset_64_incomplete()3674 fn test_parse_debug_info_offset_64_incomplete() {
3675 let buf = [0x01, 0x02];
3676 let buf = &mut EndianSlice::new(&buf, LittleEndian);
3677
3678 match parse_debug_info_offset(buf, Format::Dwarf64) {
3679 Err(Error::UnexpectedEof(_)) => assert!(true),
3680 otherwise => panic!("Unexpected result: {:?}", otherwise),
3681 };
3682 }
3683
3684 #[test]
3685 #[cfg(target_pointer_width = "64")]
test_units()3686 fn test_units() {
3687 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3688 let mut unit64 = CompilationUnitHeader {
3689 header: UnitHeader {
3690 encoding: Encoding {
3691 format: Format::Dwarf64,
3692 version: 4,
3693 address_size: 8,
3694 },
3695 unit_length: 0,
3696 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3697 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3698 },
3699 offset: DebugInfoOffset(0),
3700 };
3701 let mut unit32 = CompilationUnitHeader {
3702 header: UnitHeader {
3703 encoding: Encoding {
3704 format: Format::Dwarf32,
3705 version: 4,
3706 address_size: 4,
3707 },
3708 unit_length: 0,
3709 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3710 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3711 },
3712 offset: DebugInfoOffset(0),
3713 };
3714 let section = Section::with_endian(Endian::Little)
3715 .comp_unit(&mut unit64)
3716 .comp_unit(&mut unit32);
3717 let buf = section.get_contents().unwrap();
3718
3719 let debug_info = DebugInfo::new(&buf, LittleEndian);
3720 let mut units = debug_info.units();
3721
3722 assert_eq!(units.next(), Ok(Some(unit64)));
3723 assert_eq!(units.next(), Ok(Some(unit32)));
3724 assert_eq!(units.next(), Ok(None));
3725 }
3726
3727 #[test]
test_unit_version_unknown_version()3728 fn test_unit_version_unknown_version() {
3729 let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
3730 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3731
3732 match parse_unit_header(rest) {
3733 Err(Error::UnknownVersion(0xcdab)) => assert!(true),
3734 otherwise => panic!("Unexpected result: {:?}", otherwise),
3735 };
3736
3737 let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
3738 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3739
3740 match parse_unit_header(rest) {
3741 Err(Error::UnknownVersion(1)) => assert!(true),
3742 otherwise => panic!("Unexpected result: {:?}", otherwise),
3743 };
3744 }
3745
3746 #[test]
test_unit_version_incomplete()3747 fn test_unit_version_incomplete() {
3748 let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
3749 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3750
3751 match parse_unit_header(rest) {
3752 Err(Error::UnexpectedEof(_)) => assert!(true),
3753 otherwise => panic!("Unexpected result: {:?}", otherwise),
3754 };
3755 }
3756
3757 #[test]
test_parse_unit_header_32_ok()3758 fn test_parse_unit_header_32_ok() {
3759 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3760 let encoding = Encoding {
3761 format: Format::Dwarf32,
3762 version: 4,
3763 address_size: 4,
3764 };
3765 let mut expected_unit = UnitHeader {
3766 encoding,
3767 unit_length: 0,
3768 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3769 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3770 };
3771 let section = Section::with_endian(Endian::Little)
3772 .unit(&mut expected_unit, &[])
3773 .append_bytes(expected_rest);
3774 let buf = section.get_contents().unwrap();
3775 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3776
3777 assert_eq!(parse_unit_header(rest), Ok(expected_unit));
3778 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3779 }
3780
3781 #[test]
3782 #[cfg(target_pointer_width = "64")]
test_parse_unit_header_64_ok()3783 fn test_parse_unit_header_64_ok() {
3784 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3785 let encoding = Encoding {
3786 format: Format::Dwarf64,
3787 version: 4,
3788 address_size: 8,
3789 };
3790 let mut expected_unit = UnitHeader {
3791 encoding,
3792 unit_length: 0,
3793 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3794 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3795 };
3796 let section = Section::with_endian(Endian::Little)
3797 .unit(&mut expected_unit, &[])
3798 .append_bytes(expected_rest);
3799 let buf = section.get_contents().unwrap();
3800 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3801
3802 assert_eq!(parse_unit_header(rest), Ok(expected_unit));
3803 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3804 }
3805
3806 #[test]
test_parse_v5_unit_header_32_ok()3807 fn test_parse_v5_unit_header_32_ok() {
3808 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3809 let encoding = Encoding {
3810 format: Format::Dwarf32,
3811 version: 5,
3812 address_size: 4,
3813 };
3814 let mut expected_unit = UnitHeader {
3815 encoding,
3816 unit_length: 0,
3817 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3818 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3819 };
3820 let section = Section::with_endian(Endian::Little)
3821 .unit(&mut expected_unit, &[])
3822 .append_bytes(expected_rest);
3823 let buf = section.get_contents().unwrap();
3824 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3825
3826 assert_eq!(parse_unit_header(rest), Ok(expected_unit));
3827 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3828 }
3829
3830 #[test]
3831 #[cfg(target_pointer_width = "64")]
test_parse_v5_unit_header_64_ok()3832 fn test_parse_v5_unit_header_64_ok() {
3833 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3834 let encoding = Encoding {
3835 format: Format::Dwarf64,
3836 version: 5,
3837 address_size: 8,
3838 };
3839 let mut expected_unit = UnitHeader {
3840 encoding,
3841 unit_length: 0,
3842 debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
3843 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3844 };
3845 let section = Section::with_endian(Endian::Little)
3846 .unit(&mut expected_unit, &[])
3847 .append_bytes(expected_rest);
3848 let buf = section.get_contents().unwrap();
3849 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3850
3851 assert_eq!(parse_unit_header(rest), Ok(expected_unit));
3852 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3853 }
3854
3855 #[test]
test_parse_type_offset_32_ok()3856 fn test_parse_type_offset_32_ok() {
3857 let buf = [0x12, 0x34, 0x56, 0x78, 0x00];
3858 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3859
3860 match parse_type_offset(rest, Format::Dwarf32) {
3861 Ok(offset) => {
3862 assert_eq!(rest.len(), 1);
3863 assert_eq!(UnitOffset(0x7856_3412), offset);
3864 }
3865 otherwise => panic!("Unexpected result: {:?}", otherwise),
3866 }
3867 }
3868
3869 #[test]
3870 #[cfg(target_pointer_width = "64")]
test_parse_type_offset_64_ok()3871 fn test_parse_type_offset_64_ok() {
3872 let buf = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00];
3873 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3874
3875 match parse_type_offset(rest, Format::Dwarf64) {
3876 Ok(offset) => {
3877 assert_eq!(rest.len(), 1);
3878 assert_eq!(UnitOffset(0xffde_bc9a_7856_3412), offset);
3879 }
3880 otherwise => panic!("Unexpected result: {:?}", otherwise),
3881 }
3882 }
3883
3884 #[test]
test_parse_type_offset_incomplete()3885 fn test_parse_type_offset_incomplete() {
3886 // Need at least 4 bytes.
3887 let buf = [0xff, 0xff, 0xff];
3888 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3889
3890 match parse_type_offset(rest, Format::Dwarf32) {
3891 Err(Error::UnexpectedEof(_)) => assert!(true),
3892 otherwise => panic!("Unexpected result: {:?}", otherwise),
3893 };
3894 }
3895
3896 #[test]
test_parse_type_unit_header_32_ok()3897 fn test_parse_type_unit_header_32_ok() {
3898 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3899 let encoding = Encoding {
3900 format: Format::Dwarf32,
3901 version: 4,
3902 address_size: 8,
3903 };
3904 let mut expected_unit = TypeUnitHeader {
3905 header: UnitHeader {
3906 encoding,
3907 unit_length: 0,
3908 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3909 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3910 },
3911 offset: DebugTypesOffset(0),
3912 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3913 type_offset: UnitOffset(0x7856_3412),
3914 };
3915 let section = Section::with_endian(Endian::Little)
3916 .type_unit(&mut expected_unit)
3917 .append_bytes(expected_rest);
3918 let buf = section.get_contents().unwrap();
3919 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3920
3921 assert_eq!(
3922 parse_type_unit_header(rest, DebugTypesOffset(0)),
3923 Ok(expected_unit)
3924 );
3925 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3926 }
3927
3928 #[test]
3929 #[cfg(target_pointer_width = "64")]
test_parse_type_unit_header_64_ok()3930 fn test_parse_type_unit_header_64_ok() {
3931 let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
3932 let encoding = Encoding {
3933 format: Format::Dwarf64,
3934 version: 4,
3935 address_size: 8,
3936 };
3937 let mut expected_unit = TypeUnitHeader {
3938 header: UnitHeader {
3939 encoding,
3940 unit_length: 0,
3941 debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
3942 entries_buf: EndianSlice::new(expected_rest, LittleEndian),
3943 },
3944 offset: DebugTypesOffset(0),
3945 type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
3946 type_offset: UnitOffset(0x7856_3412_7856_3412),
3947 };
3948 let section = Section::with_endian(Endian::Little)
3949 .type_unit(&mut expected_unit)
3950 .append_bytes(expected_rest);
3951 let buf = section.get_contents().unwrap();
3952 let rest = &mut EndianSlice::new(&buf, LittleEndian);
3953
3954 assert_eq!(
3955 parse_type_unit_header(rest, DebugTypesOffset(0)),
3956 Ok(expected_unit)
3957 );
3958 assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
3959 }
3960
section_contents<F>(f: F) -> Vec<u8> where F: Fn(Section) -> Section,3961 fn section_contents<F>(f: F) -> Vec<u8>
3962 where
3963 F: Fn(Section) -> Section,
3964 {
3965 f(Section::with_endian(Endian::Little))
3966 .get_contents()
3967 .unwrap()
3968 }
3969
3970 #[test]
test_attribute_value()3971 fn test_attribute_value() {
3972 let mut unit = test_parse_attribute_unit_default();
3973 let endian = unit.entries_buf.endian();
3974
3975 let block_data = &[1, 2, 3, 4];
3976 let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
3977 let block = EndianSlice::new(&buf, endian);
3978
3979 let buf = section_contents(|s| s.L32(0x0102_0304));
3980 let data4 = EndianSlice::new(&buf, endian);
3981
3982 let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
3983 let data8 = EndianSlice::new(&buf, endian);
3984
3985 let tests = [
3986 (
3987 Format::Dwarf32,
3988 2,
3989 constants::DW_AT_data_member_location,
3990 constants::DW_FORM_block,
3991 block,
3992 AttributeValue::Block(EndianSlice::new(block_data, endian)),
3993 AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
3994 ),
3995 (
3996 Format::Dwarf32,
3997 2,
3998 constants::DW_AT_data_member_location,
3999 constants::DW_FORM_data4,
4000 data4,
4001 AttributeValue::SecOffset(0x0102_0304),
4002 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4003 ),
4004 (
4005 Format::Dwarf64,
4006 2,
4007 constants::DW_AT_data_member_location,
4008 constants::DW_FORM_data4,
4009 data4,
4010 AttributeValue::Data4(0x0102_0304),
4011 AttributeValue::Udata(0x0102_0304),
4012 ),
4013 (
4014 Format::Dwarf32,
4015 4,
4016 constants::DW_AT_data_member_location,
4017 constants::DW_FORM_data4,
4018 data4,
4019 AttributeValue::Data4(0x0102_0304),
4020 AttributeValue::Udata(0x0102_0304),
4021 ),
4022 (
4023 Format::Dwarf32,
4024 2,
4025 constants::DW_AT_data_member_location,
4026 constants::DW_FORM_data8,
4027 data8,
4028 AttributeValue::Data8(0x0102_0304_0506_0708),
4029 AttributeValue::Udata(0x0102_0304_0506_0708),
4030 ),
4031 #[cfg(target_pointer_width = "64")]
4032 (
4033 Format::Dwarf64,
4034 2,
4035 constants::DW_AT_data_member_location,
4036 constants::DW_FORM_data8,
4037 data8,
4038 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4039 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4040 ),
4041 (
4042 Format::Dwarf64,
4043 4,
4044 constants::DW_AT_data_member_location,
4045 constants::DW_FORM_data8,
4046 data8,
4047 AttributeValue::Data8(0x0102_0304_0506_0708),
4048 AttributeValue::Udata(0x0102_0304_0506_0708),
4049 ),
4050 (
4051 Format::Dwarf32,
4052 4,
4053 constants::DW_AT_location,
4054 constants::DW_FORM_data4,
4055 data4,
4056 AttributeValue::SecOffset(0x0102_0304),
4057 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
4058 ),
4059 #[cfg(target_pointer_width = "64")]
4060 (
4061 Format::Dwarf64,
4062 4,
4063 constants::DW_AT_location,
4064 constants::DW_FORM_data8,
4065 data8,
4066 AttributeValue::SecOffset(0x0102_0304_0506_0708),
4067 AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
4068 ),
4069 (
4070 Format::Dwarf32,
4071 4,
4072 constants::DW_AT_str_offsets_base,
4073 constants::DW_FORM_sec_offset,
4074 data4,
4075 AttributeValue::SecOffset(0x0102_0304),
4076 AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
4077 ),
4078 (
4079 Format::Dwarf32,
4080 4,
4081 constants::DW_AT_stmt_list,
4082 constants::DW_FORM_sec_offset,
4083 data4,
4084 AttributeValue::SecOffset(0x0102_0304),
4085 AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
4086 ),
4087 (
4088 Format::Dwarf32,
4089 4,
4090 constants::DW_AT_addr_base,
4091 constants::DW_FORM_sec_offset,
4092 data4,
4093 AttributeValue::SecOffset(0x0102_0304),
4094 AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
4095 ),
4096 (
4097 Format::Dwarf32,
4098 4,
4099 constants::DW_AT_rnglists_base,
4100 constants::DW_FORM_sec_offset,
4101 data4,
4102 AttributeValue::SecOffset(0x0102_0304),
4103 AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
4104 ),
4105 (
4106 Format::Dwarf32,
4107 4,
4108 constants::DW_AT_loclists_base,
4109 constants::DW_FORM_sec_offset,
4110 data4,
4111 AttributeValue::SecOffset(0x0102_0304),
4112 AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
4113 ),
4114 ];
4115
4116 for test in tests.iter() {
4117 let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
4118 unit.encoding.format = format;
4119 unit.encoding.version = version;
4120 let spec = AttributeSpecification::new(name, form, None);
4121 let attribute =
4122 parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
4123 assert_eq!(attribute.raw_value(), expect_raw);
4124 assert_eq!(attribute.value(), expect_value);
4125 }
4126 }
4127
4128 #[test]
test_attribute_udata_sdata_value()4129 fn test_attribute_udata_sdata_value() {
4130 #[allow(clippy::type_complexity)]
4131 let tests: &[(
4132 AttributeValue<EndianSlice<LittleEndian>>,
4133 Option<u64>,
4134 Option<i64>,
4135 )] = &[
4136 (AttributeValue::Data1(1), Some(1), Some(1)),
4137 (
4138 AttributeValue::Data1(core::u8::MAX),
4139 Some(u64::from(std::u8::MAX)),
4140 Some(-1),
4141 ),
4142 (AttributeValue::Data2(1), Some(1), Some(1)),
4143 (
4144 AttributeValue::Data2(core::u16::MAX),
4145 Some(u64::from(std::u16::MAX)),
4146 Some(-1),
4147 ),
4148 (AttributeValue::Data4(1), Some(1), Some(1)),
4149 (
4150 AttributeValue::Data4(core::u32::MAX),
4151 Some(u64::from(std::u32::MAX)),
4152 Some(-1),
4153 ),
4154 (AttributeValue::Data8(1), Some(1), Some(1)),
4155 (
4156 AttributeValue::Data8(core::u64::MAX),
4157 Some(core::u64::MAX),
4158 Some(-1),
4159 ),
4160 (AttributeValue::Sdata(1), Some(1), Some(1)),
4161 (AttributeValue::Sdata(-1), None, Some(-1)),
4162 (AttributeValue::Udata(1), Some(1), Some(1)),
4163 (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
4164 ];
4165 for test in tests.iter() {
4166 let (value, expect_udata, expect_sdata) = *test;
4167 let attribute = Attribute {
4168 name: DW_AT_data_member_location,
4169 value,
4170 };
4171 assert_eq!(attribute.udata_value(), expect_udata);
4172 assert_eq!(attribute.sdata_value(), expect_sdata);
4173 }
4174 }
4175
test_parse_attribute_unit<Endian>( address_size: u8, format: Format, endian: Endian, ) -> UnitHeader<EndianSlice<'static, Endian>> where Endian: Endianity,4176 fn test_parse_attribute_unit<Endian>(
4177 address_size: u8,
4178 format: Format,
4179 endian: Endian,
4180 ) -> UnitHeader<EndianSlice<'static, Endian>>
4181 where
4182 Endian: Endianity,
4183 {
4184 let encoding = Encoding {
4185 format,
4186 version: 4,
4187 address_size,
4188 };
4189 UnitHeader::new(
4190 encoding,
4191 7,
4192 DebugAbbrevOffset(0x0807_0605),
4193 EndianSlice::new(&[], endian),
4194 )
4195 }
4196
test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>>4197 fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
4198 test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
4199 }
4200
test_parse_attribute<'input, Endian>( buf: &'input [u8], len: usize, unit: &UnitHeader<EndianSlice<'input, Endian>>, form: constants::DwForm, value: AttributeValue<EndianSlice<'input, Endian>>, ) where Endian: Endianity,4201 fn test_parse_attribute<'input, Endian>(
4202 buf: &'input [u8],
4203 len: usize,
4204 unit: &UnitHeader<EndianSlice<'input, Endian>>,
4205 form: constants::DwForm,
4206 value: AttributeValue<EndianSlice<'input, Endian>>,
4207 ) where
4208 Endian: Endianity,
4209 {
4210 let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
4211
4212 let expect = Attribute {
4213 name: constants::DW_AT_low_pc,
4214 value,
4215 };
4216
4217 let rest = &mut EndianSlice::new(buf, Endian::default());
4218 match parse_attribute(rest, unit.encoding(), spec) {
4219 Ok(attr) => {
4220 assert_eq!(attr, expect);
4221 assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
4222 }
4223 otherwise => {
4224 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4225 }
4226 };
4227 }
4228
4229 #[test]
test_parse_attribute_addr()4230 fn test_parse_attribute_addr() {
4231 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4232 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4233 let form = constants::DW_FORM_addr;
4234 let value = AttributeValue::Addr(0x0403_0201);
4235 test_parse_attribute(&buf, 4, &unit, form, value);
4236 }
4237
4238 #[test]
test_parse_attribute_addr8()4239 fn test_parse_attribute_addr8() {
4240 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
4241 let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4242 let form = constants::DW_FORM_addr;
4243 let value = AttributeValue::Addr(0x0807_0605_0403_0201);
4244 test_parse_attribute(&buf, 8, &unit, form, value);
4245 }
4246
4247 #[test]
test_parse_attribute_block1()4248 fn test_parse_attribute_block1() {
4249 // Length of data (3), three bytes of data, two bytes of left over input.
4250 let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
4251 let unit = test_parse_attribute_unit_default();
4252 let form = constants::DW_FORM_block1;
4253 let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
4254 test_parse_attribute(&buf, 4, &unit, form, value);
4255 }
4256
4257 #[test]
test_parse_attribute_block2()4258 fn test_parse_attribute_block2() {
4259 // Two byte length of data (2), two bytes of data, two bytes of left over input.
4260 let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
4261 let unit = test_parse_attribute_unit_default();
4262 let form = constants::DW_FORM_block2;
4263 let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
4264 test_parse_attribute(&buf, 4, &unit, form, value);
4265 }
4266
4267 #[test]
test_parse_attribute_block4()4268 fn test_parse_attribute_block4() {
4269 // Four byte length of data (2), two bytes of data, no left over input.
4270 let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
4271 let unit = test_parse_attribute_unit_default();
4272 let form = constants::DW_FORM_block4;
4273 let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
4274 test_parse_attribute(&buf, 6, &unit, form, value);
4275 }
4276
4277 #[test]
test_parse_attribute_block()4278 fn test_parse_attribute_block() {
4279 // LEB length of data (2, one byte), two bytes of data, no left over input.
4280 let buf = [0x02, 0x99, 0x99];
4281 let unit = test_parse_attribute_unit_default();
4282 let form = constants::DW_FORM_block;
4283 let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
4284 test_parse_attribute(&buf, 3, &unit, form, value);
4285 }
4286
4287 #[test]
test_parse_attribute_data1()4288 fn test_parse_attribute_data1() {
4289 let buf = [0x03];
4290 let unit = test_parse_attribute_unit_default();
4291 let form = constants::DW_FORM_data1;
4292 let value = AttributeValue::Data1(0x03);
4293 test_parse_attribute(&buf, 1, &unit, form, value);
4294 }
4295
4296 #[test]
test_parse_attribute_data2()4297 fn test_parse_attribute_data2() {
4298 let buf = [0x02, 0x01, 0x0];
4299 let unit = test_parse_attribute_unit_default();
4300 let form = constants::DW_FORM_data2;
4301 let value = AttributeValue::Data2(0x0102);
4302 test_parse_attribute(&buf, 2, &unit, form, value);
4303 }
4304
4305 #[test]
test_parse_attribute_data4()4306 fn test_parse_attribute_data4() {
4307 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4308 let unit = test_parse_attribute_unit_default();
4309 let form = constants::DW_FORM_data4;
4310 let value = AttributeValue::Data4(0x0403_0201);
4311 test_parse_attribute(&buf, 4, &unit, form, value);
4312 }
4313
4314 #[test]
test_parse_attribute_data8()4315 fn test_parse_attribute_data8() {
4316 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4317 let unit = test_parse_attribute_unit_default();
4318 let form = constants::DW_FORM_data8;
4319 let value = AttributeValue::Data8(0x0807_0605_0403_0201);
4320 test_parse_attribute(&buf, 8, &unit, form, value);
4321 }
4322
4323 #[test]
test_parse_attribute_udata()4324 fn test_parse_attribute_udata() {
4325 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4326
4327 let bytes_written = {
4328 let mut writable = &mut buf[..];
4329 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4330 };
4331
4332 let unit = test_parse_attribute_unit_default();
4333 let form = constants::DW_FORM_udata;
4334 let value = AttributeValue::Udata(4097);
4335 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4336 }
4337
4338 #[test]
test_parse_attribute_sdata()4339 fn test_parse_attribute_sdata() {
4340 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4341
4342 let bytes_written = {
4343 let mut writable = &mut buf[..];
4344 leb128::write::signed(&mut writable, -4097).expect("should write ok")
4345 };
4346
4347 let unit = test_parse_attribute_unit_default();
4348 let form = constants::DW_FORM_sdata;
4349 let value = AttributeValue::Sdata(-4097);
4350 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4351 }
4352
4353 #[test]
test_parse_attribute_exprloc()4354 fn test_parse_attribute_exprloc() {
4355 // LEB length of data (2, one byte), two bytes of data, one byte left over input.
4356 let buf = [0x02, 0x99, 0x99, 0x11];
4357 let unit = test_parse_attribute_unit_default();
4358 let form = constants::DW_FORM_exprloc;
4359 let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
4360 test_parse_attribute(&buf, 3, &unit, form, value);
4361 }
4362
4363 #[test]
test_parse_attribute_flag_true()4364 fn test_parse_attribute_flag_true() {
4365 let buf = [0x42];
4366 let unit = test_parse_attribute_unit_default();
4367 let form = constants::DW_FORM_flag;
4368 let value = AttributeValue::Flag(true);
4369 test_parse_attribute(&buf, 1, &unit, form, value);
4370 }
4371
4372 #[test]
test_parse_attribute_flag_false()4373 fn test_parse_attribute_flag_false() {
4374 let buf = [0x00];
4375 let unit = test_parse_attribute_unit_default();
4376 let form = constants::DW_FORM_flag;
4377 let value = AttributeValue::Flag(false);
4378 test_parse_attribute(&buf, 1, &unit, form, value);
4379 }
4380
4381 #[test]
test_parse_attribute_flag_present()4382 fn test_parse_attribute_flag_present() {
4383 let buf = [0x01, 0x02, 0x03, 0x04];
4384 let unit = test_parse_attribute_unit_default();
4385 let form = constants::DW_FORM_flag_present;
4386 let value = AttributeValue::Flag(true);
4387 // DW_FORM_flag_present does not consume any bytes of the input stream.
4388 test_parse_attribute(&buf, 0, &unit, form, value);
4389 }
4390
4391 #[test]
test_parse_attribute_sec_offset_32()4392 fn test_parse_attribute_sec_offset_32() {
4393 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4394 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4395 let form = constants::DW_FORM_sec_offset;
4396 let value = AttributeValue::SecOffset(0x0403_0201);
4397 test_parse_attribute(&buf, 4, &unit, form, value);
4398 }
4399
4400 #[test]
4401 #[cfg(target_pointer_width = "64")]
test_parse_attribute_sec_offset_64()4402 fn test_parse_attribute_sec_offset_64() {
4403 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
4404 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4405 let form = constants::DW_FORM_sec_offset;
4406 let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
4407 test_parse_attribute(&buf, 8, &unit, form, value);
4408 }
4409
4410 #[test]
test_parse_attribute_ref1()4411 fn test_parse_attribute_ref1() {
4412 let buf = [0x03];
4413 let unit = test_parse_attribute_unit_default();
4414 let form = constants::DW_FORM_ref1;
4415 let value = AttributeValue::UnitRef(UnitOffset(3));
4416 test_parse_attribute(&buf, 1, &unit, form, value);
4417 }
4418
4419 #[test]
test_parse_attribute_ref2()4420 fn test_parse_attribute_ref2() {
4421 let buf = [0x02, 0x01, 0x0];
4422 let unit = test_parse_attribute_unit_default();
4423 let form = constants::DW_FORM_ref2;
4424 let value = AttributeValue::UnitRef(UnitOffset(258));
4425 test_parse_attribute(&buf, 2, &unit, form, value);
4426 }
4427
4428 #[test]
test_parse_attribute_ref4()4429 fn test_parse_attribute_ref4() {
4430 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4431 let unit = test_parse_attribute_unit_default();
4432 let form = constants::DW_FORM_ref4;
4433 let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
4434 test_parse_attribute(&buf, 4, &unit, form, value);
4435 }
4436
4437 #[test]
4438 #[cfg(target_pointer_width = "64")]
test_parse_attribute_ref8()4439 fn test_parse_attribute_ref8() {
4440 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4441 let unit = test_parse_attribute_unit_default();
4442 let form = constants::DW_FORM_ref8;
4443 let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
4444 test_parse_attribute(&buf, 8, &unit, form, value);
4445 }
4446
4447 #[test]
test_parse_attribute_ref_sup4()4448 fn test_parse_attribute_ref_sup4() {
4449 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4450 let unit = test_parse_attribute_unit_default();
4451 let form = constants::DW_FORM_ref_sup4;
4452 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4453 test_parse_attribute(&buf, 4, &unit, form, value);
4454 }
4455
4456 #[test]
4457 #[cfg(target_pointer_width = "64")]
test_parse_attribute_ref_sup8()4458 fn test_parse_attribute_ref_sup8() {
4459 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4460 let unit = test_parse_attribute_unit_default();
4461 let form = constants::DW_FORM_ref_sup8;
4462 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4463 test_parse_attribute(&buf, 8, &unit, form, value);
4464 }
4465
4466 #[test]
test_parse_attribute_refudata()4467 fn test_parse_attribute_refudata() {
4468 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4469
4470 let bytes_written = {
4471 let mut writable = &mut buf[..];
4472 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4473 };
4474
4475 let unit = test_parse_attribute_unit_default();
4476 let form = constants::DW_FORM_ref_udata;
4477 let value = AttributeValue::UnitRef(UnitOffset(4097));
4478 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4479 }
4480
4481 #[test]
test_parse_attribute_refaddr_32()4482 fn test_parse_attribute_refaddr_32() {
4483 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4484 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4485 let form = constants::DW_FORM_ref_addr;
4486 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4487 test_parse_attribute(&buf, 4, &unit, form, value);
4488 }
4489
4490 #[test]
4491 #[cfg(target_pointer_width = "64")]
test_parse_attribute_refaddr_64()4492 fn test_parse_attribute_refaddr_64() {
4493 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4494 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4495 let form = constants::DW_FORM_ref_addr;
4496 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4497 test_parse_attribute(&buf, 8, &unit, form, value);
4498 }
4499
4500 #[test]
test_parse_attribute_refaddr_version2()4501 fn test_parse_attribute_refaddr_version2() {
4502 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4503 let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4504 unit.encoding.version = 2;
4505 let form = constants::DW_FORM_ref_addr;
4506 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
4507 test_parse_attribute(&buf, 4, &unit, form, value);
4508 }
4509
4510 #[test]
4511 #[cfg(target_pointer_width = "64")]
test_parse_attribute_refaddr8_version2()4512 fn test_parse_attribute_refaddr8_version2() {
4513 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4514 let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
4515 unit.encoding.version = 2;
4516 let form = constants::DW_FORM_ref_addr;
4517 let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
4518 test_parse_attribute(&buf, 8, &unit, form, value);
4519 }
4520
4521 #[test]
test_parse_attribute_gnu_ref_alt_32()4522 fn test_parse_attribute_gnu_ref_alt_32() {
4523 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4524 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4525 let form = constants::DW_FORM_GNU_ref_alt;
4526 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
4527 test_parse_attribute(&buf, 4, &unit, form, value);
4528 }
4529
4530 #[test]
4531 #[cfg(target_pointer_width = "64")]
test_parse_attribute_gnu_ref_alt_64()4532 fn test_parse_attribute_gnu_ref_alt_64() {
4533 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4534 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4535 let form = constants::DW_FORM_GNU_ref_alt;
4536 let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
4537 test_parse_attribute(&buf, 8, &unit, form, value);
4538 }
4539
4540 #[test]
test_parse_attribute_refsig8()4541 fn test_parse_attribute_refsig8() {
4542 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4543 let unit = test_parse_attribute_unit_default();
4544 let form = constants::DW_FORM_ref_sig8;
4545 let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
4546 test_parse_attribute(&buf, 8, &unit, form, value);
4547 }
4548
4549 #[test]
test_parse_attribute_string()4550 fn test_parse_attribute_string() {
4551 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
4552 let unit = test_parse_attribute_unit_default();
4553 let form = constants::DW_FORM_string;
4554 let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
4555 test_parse_attribute(&buf, 6, &unit, form, value);
4556 }
4557
4558 #[test]
test_parse_attribute_strp_32()4559 fn test_parse_attribute_strp_32() {
4560 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4561 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4562 let form = constants::DW_FORM_strp;
4563 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
4564 test_parse_attribute(&buf, 4, &unit, form, value);
4565 }
4566
4567 #[test]
4568 #[cfg(target_pointer_width = "64")]
test_parse_attribute_strp_64()4569 fn test_parse_attribute_strp_64() {
4570 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4571 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4572 let form = constants::DW_FORM_strp;
4573 let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
4574 test_parse_attribute(&buf, 8, &unit, form, value);
4575 }
4576
4577 #[test]
test_parse_attribute_strp_sup_32()4578 fn test_parse_attribute_strp_sup_32() {
4579 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4580 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4581 let form = constants::DW_FORM_strp_sup;
4582 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4583 test_parse_attribute(&buf, 4, &unit, form, value);
4584 }
4585
4586 #[test]
4587 #[cfg(target_pointer_width = "64")]
test_parse_attribute_strp_sup_64()4588 fn test_parse_attribute_strp_sup_64() {
4589 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4590 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4591 let form = constants::DW_FORM_strp_sup;
4592 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4593 test_parse_attribute(&buf, 8, &unit, form, value);
4594 }
4595
4596 #[test]
test_parse_attribute_gnu_strp_alt_32()4597 fn test_parse_attribute_gnu_strp_alt_32() {
4598 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4599 let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
4600 let form = constants::DW_FORM_GNU_strp_alt;
4601 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
4602 test_parse_attribute(&buf, 4, &unit, form, value);
4603 }
4604
4605 #[test]
4606 #[cfg(target_pointer_width = "64")]
test_parse_attribute_gnu_strp_alt_64()4607 fn test_parse_attribute_gnu_strp_alt_64() {
4608 let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
4609 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4610 let form = constants::DW_FORM_GNU_strp_alt;
4611 let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
4612 test_parse_attribute(&buf, 8, &unit, form, value);
4613 }
4614
4615 #[test]
test_parse_attribute_strx()4616 fn test_parse_attribute_strx() {
4617 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4618
4619 let bytes_written = {
4620 let mut writable = &mut buf[..];
4621 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4622 };
4623
4624 let unit = test_parse_attribute_unit_default();
4625 let form = constants::DW_FORM_strx;
4626 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
4627 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4628 }
4629
4630 #[test]
test_parse_attribute_strx1()4631 fn test_parse_attribute_strx1() {
4632 let buf = [0x01, 0x99, 0x99];
4633 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4634 let form = constants::DW_FORM_strx1;
4635 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
4636 test_parse_attribute(&buf, 1, &unit, form, value);
4637 }
4638
4639 #[test]
test_parse_attribute_strx2()4640 fn test_parse_attribute_strx2() {
4641 let buf = [0x01, 0x02, 0x99, 0x99];
4642 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4643 let form = constants::DW_FORM_strx2;
4644 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
4645 test_parse_attribute(&buf, 2, &unit, form, value);
4646 }
4647
4648 #[test]
test_parse_attribute_strx3()4649 fn test_parse_attribute_strx3() {
4650 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4651 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4652 let form = constants::DW_FORM_strx3;
4653 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
4654 test_parse_attribute(&buf, 3, &unit, form, value);
4655 }
4656
4657 #[test]
test_parse_attribute_strx4()4658 fn test_parse_attribute_strx4() {
4659 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4660 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4661 let form = constants::DW_FORM_strx4;
4662 let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
4663 test_parse_attribute(&buf, 4, &unit, form, value);
4664 }
4665
4666 #[test]
test_parse_attribute_addrx()4667 fn test_parse_attribute_addrx() {
4668 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4669
4670 let bytes_written = {
4671 let mut writable = &mut buf[..];
4672 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4673 };
4674
4675 let unit = test_parse_attribute_unit_default();
4676 let form = constants::DW_FORM_addrx;
4677 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
4678 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4679 }
4680
4681 #[test]
test_parse_attribute_addrx1()4682 fn test_parse_attribute_addrx1() {
4683 let buf = [0x01, 0x99, 0x99];
4684 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4685 let form = constants::DW_FORM_addrx1;
4686 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
4687 test_parse_attribute(&buf, 1, &unit, form, value);
4688 }
4689
4690 #[test]
test_parse_attribute_addrx2()4691 fn test_parse_attribute_addrx2() {
4692 let buf = [0x01, 0x02, 0x99, 0x99];
4693 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4694 let form = constants::DW_FORM_addrx2;
4695 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
4696 test_parse_attribute(&buf, 2, &unit, form, value);
4697 }
4698
4699 #[test]
test_parse_attribute_addrx3()4700 fn test_parse_attribute_addrx3() {
4701 let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
4702 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4703 let form = constants::DW_FORM_addrx3;
4704 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
4705 test_parse_attribute(&buf, 3, &unit, form, value);
4706 }
4707
4708 #[test]
test_parse_attribute_addrx4()4709 fn test_parse_attribute_addrx4() {
4710 let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
4711 let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
4712 let form = constants::DW_FORM_addrx4;
4713 let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
4714 test_parse_attribute(&buf, 4, &unit, form, value);
4715 }
4716
4717 #[test]
test_parse_attribute_loclistx()4718 fn test_parse_attribute_loclistx() {
4719 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4720
4721 let bytes_written = {
4722 let mut writable = &mut buf[..];
4723 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4724 };
4725
4726 let unit = test_parse_attribute_unit_default();
4727 let form = constants::DW_FORM_loclistx;
4728 let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
4729 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4730 }
4731
4732 #[test]
test_parse_attribute_rnglistx()4733 fn test_parse_attribute_rnglistx() {
4734 let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4735
4736 let bytes_written = {
4737 let mut writable = &mut buf[..];
4738 leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
4739 };
4740
4741 let unit = test_parse_attribute_unit_default();
4742 let form = constants::DW_FORM_rnglistx;
4743 let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
4744 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4745 }
4746
4747 #[test]
test_parse_attribute_indirect()4748 fn test_parse_attribute_indirect() {
4749 let mut buf = [0; 100];
4750
4751 let bytes_written = {
4752 let mut writable = &mut buf[..];
4753 leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into())
4754 .expect("should write udata")
4755 + leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value")
4756 };
4757
4758 let unit = test_parse_attribute_unit_default();
4759 let form = constants::DW_FORM_indirect;
4760 let value = AttributeValue::Udata(9_999_999);
4761 test_parse_attribute(&buf, bytes_written, &unit, form, value);
4762 }
4763
4764 #[test]
test_parse_attribute_indirect_implicit_const()4765 fn test_parse_attribute_indirect_implicit_const() {
4766 let encoding = Encoding {
4767 format: Format::Dwarf32,
4768 version: 4,
4769 address_size: 4,
4770 };
4771 let mut buf = [0; 100];
4772 let mut writable = &mut buf[..];
4773 leb128::write::unsigned(&mut writable, constants::DW_FORM_implicit_const.0.into())
4774 .expect("should write implicit_const");
4775
4776 let input = &mut EndianSlice::new(&buf, LittleEndian);
4777 let spec =
4778 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
4779 assert_eq!(
4780 parse_attribute(input, encoding, spec),
4781 Err(Error::InvalidImplicitConst)
4782 );
4783 }
4784
4785 #[test]
test_attrs_iter()4786 fn test_attrs_iter() {
4787 let encoding = Encoding {
4788 format: Format::Dwarf32,
4789 version: 4,
4790 address_size: 4,
4791 };
4792 let unit = UnitHeader::new(
4793 encoding,
4794 7,
4795 DebugAbbrevOffset(0x0807_0605),
4796 EndianSlice::new(&[], LittleEndian),
4797 );
4798
4799 let abbrev = Abbreviation::new(
4800 42,
4801 constants::DW_TAG_subprogram,
4802 constants::DW_CHILDREN_yes,
4803 vec![
4804 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4805 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4806 AttributeSpecification::new(
4807 constants::DW_AT_high_pc,
4808 constants::DW_FORM_addr,
4809 None,
4810 ),
4811 ]
4812 .into(),
4813 );
4814
4815 // "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be
4816 let buf = [
4817 0x66, 0x6f, 0x6f, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x05, 0x00, 0x00, 0xaa, 0xaa,
4818 0xaa, 0xaa,
4819 ];
4820
4821 let entry = DebuggingInformationEntry {
4822 offset: UnitOffset(0),
4823 attrs_slice: EndianSlice::new(&buf, LittleEndian),
4824 attrs_len: Cell::new(None),
4825 abbrev: &abbrev,
4826 unit: &unit,
4827 };
4828
4829 let mut attrs = AttrsIter {
4830 input: EndianSlice::new(&buf, LittleEndian),
4831 attributes: abbrev.attributes(),
4832 entry: &entry,
4833 };
4834
4835 match attrs.next() {
4836 Ok(Some(attr)) => {
4837 assert_eq!(
4838 attr,
4839 Attribute {
4840 name: constants::DW_AT_name,
4841 value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
4842 }
4843 );
4844 }
4845 otherwise => {
4846 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4847 }
4848 }
4849
4850 assert!(entry.attrs_len.get().is_none());
4851
4852 match attrs.next() {
4853 Ok(Some(attr)) => {
4854 assert_eq!(
4855 attr,
4856 Attribute {
4857 name: constants::DW_AT_low_pc,
4858 value: AttributeValue::Addr(0x2a),
4859 }
4860 );
4861 }
4862 otherwise => {
4863 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4864 }
4865 }
4866
4867 assert!(entry.attrs_len.get().is_none());
4868
4869 match attrs.next() {
4870 Ok(Some(attr)) => {
4871 assert_eq!(
4872 attr,
4873 Attribute {
4874 name: constants::DW_AT_high_pc,
4875 value: AttributeValue::Addr(0x539),
4876 }
4877 );
4878 }
4879 otherwise => {
4880 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4881 }
4882 }
4883
4884 assert!(entry.attrs_len.get().is_none());
4885
4886 assert!(attrs.next().expect("should parse next").is_none());
4887 assert!(entry.attrs_len.get().is_some());
4888 assert_eq!(
4889 entry.attrs_len.get().expect("should have entry.attrs_len"),
4890 buf.len() - 4
4891 )
4892 }
4893
4894 #[test]
test_attrs_iter_incomplete()4895 fn test_attrs_iter_incomplete() {
4896 let encoding = Encoding {
4897 format: Format::Dwarf32,
4898 version: 4,
4899 address_size: 4,
4900 };
4901 let unit = UnitHeader::new(
4902 encoding,
4903 7,
4904 DebugAbbrevOffset(0x0807_0605),
4905 EndianSlice::new(&[], LittleEndian),
4906 );
4907
4908 let abbrev = Abbreviation::new(
4909 42,
4910 constants::DW_TAG_subprogram,
4911 constants::DW_CHILDREN_yes,
4912 vec![
4913 AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
4914 AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
4915 AttributeSpecification::new(
4916 constants::DW_AT_high_pc,
4917 constants::DW_FORM_addr,
4918 None,
4919 ),
4920 ]
4921 .into(),
4922 );
4923
4924 // "foo"
4925 let buf = [0x66, 0x6f, 0x6f, 0x00];
4926
4927 let entry = DebuggingInformationEntry {
4928 offset: UnitOffset(0),
4929 attrs_slice: EndianSlice::new(&buf, LittleEndian),
4930 attrs_len: Cell::new(None),
4931 abbrev: &abbrev,
4932 unit: &unit,
4933 };
4934
4935 let mut attrs = AttrsIter {
4936 input: EndianSlice::new(&buf, LittleEndian),
4937 attributes: abbrev.attributes(),
4938 entry: &entry,
4939 };
4940
4941 match attrs.next() {
4942 Ok(Some(attr)) => {
4943 assert_eq!(
4944 attr,
4945 Attribute {
4946 name: constants::DW_AT_name,
4947 value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
4948 }
4949 );
4950 }
4951 otherwise => {
4952 assert!(false, "Unexpected parse result = {:#?}", otherwise);
4953 }
4954 }
4955
4956 assert!(entry.attrs_len.get().is_none());
4957
4958 // Return error for incomplete attribute.
4959 assert!(attrs.next().is_err());
4960 assert!(entry.attrs_len.get().is_none());
4961
4962 // Return error for all subsequent calls.
4963 assert!(attrs.next().is_err());
4964 assert!(attrs.next().is_err());
4965 assert!(attrs.next().is_err());
4966 assert!(attrs.next().is_err());
4967 assert!(entry.attrs_len.get().is_none());
4968 }
4969
assert_entry_name<Endian>(entry: &DebuggingInformationEntry<EndianSlice<Endian>>, name: &str) where Endian: Endianity,4970 fn assert_entry_name<Endian>(entry: &DebuggingInformationEntry<EndianSlice<Endian>>, name: &str)
4971 where
4972 Endian: Endianity,
4973 {
4974 let value = entry
4975 .attr_value(constants::DW_AT_name)
4976 .expect("Should have parsed the name attribute")
4977 .expect("Should have found the name attribute");
4978
4979 assert_eq!(
4980 value,
4981 AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
4982 );
4983 }
4984
assert_current_name<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,4985 fn assert_current_name<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>, name: &str)
4986 where
4987 Endian: Endianity,
4988 {
4989 let entry = cursor.current().expect("Should have an entry result");
4990 assert_entry_name(entry, name);
4991 }
4992
assert_next_entry<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,4993 fn assert_next_entry<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
4994 where
4995 Endian: Endianity,
4996 {
4997 cursor
4998 .next_entry()
4999 .expect("Should parse next entry")
5000 .expect("Should have an entry");
5001 assert_current_name(cursor, name);
5002 }
5003
assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>) where Endian: Endianity,5004 fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>)
5005 where
5006 Endian: Endianity,
5007 {
5008 cursor
5009 .next_entry()
5010 .expect("Should parse next entry")
5011 .expect("Should have an entry");
5012 assert!(cursor.current().is_none());
5013 }
5014
assert_next_dfs<Endian>( cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str, depth: isize, ) where Endian: Endianity,5015 fn assert_next_dfs<Endian>(
5016 cursor: &mut EntriesCursor<EndianSlice<Endian>>,
5017 name: &str,
5018 depth: isize,
5019 ) where
5020 Endian: Endianity,
5021 {
5022 {
5023 let (val, entry) = cursor
5024 .next_dfs()
5025 .expect("Should parse next dfs")
5026 .expect("Should not be done with traversal");
5027 assert_eq!(val, depth);
5028 assert_entry_name(entry, name);
5029 }
5030 assert_current_name(cursor, name);
5031 }
5032
assert_next_sibling<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str) where Endian: Endianity,5033 fn assert_next_sibling<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
5034 where
5035 Endian: Endianity,
5036 {
5037 {
5038 let entry = cursor
5039 .next_sibling()
5040 .expect("Should parse next sibling")
5041 .expect("Should not be done with traversal");
5042 assert_entry_name(entry, name);
5043 }
5044 assert_current_name(cursor, name);
5045 }
5046
assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>) where Endian: Endianity,5047 fn assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>)
5048 where
5049 Endian: Endianity,
5050 {
5051 let sibling_ptr = cursor
5052 .current()
5053 .expect("Should have current entry")
5054 .attr_value(constants::DW_AT_sibling);
5055 match sibling_ptr {
5056 Ok(Some(AttributeValue::UnitRef(offset))) => {
5057 cursor
5058 .unit
5059 .range_from(offset..)
5060 .expect("Sibling offset should be valid");
5061 }
5062 _ => panic!("Invalid sibling pointer {:?}", sibling_ptr),
5063 }
5064 }
5065
entries_cursor_tests_abbrev_buf() -> Vec<u8>5066 fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
5067 #[rustfmt::skip]
5068 let section = Section::with_endian(Endian::Little)
5069 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5070 .abbrev_attr(DW_AT_name, DW_FORM_string)
5071 .abbrev_attr_null()
5072 .abbrev_null();
5073 section.get_contents().unwrap()
5074 }
5075
entries_cursor_tests_debug_info_buf() -> Vec<u8>5076 fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
5077 #[rustfmt::skip]
5078 let section = Section::with_endian(Endian::Little)
5079 .die(1, |s| s.attr_string("001"))
5080 .die(1, |s| s.attr_string("002"))
5081 .die(1, |s| s.attr_string("003"))
5082 .die_null()
5083 .die_null()
5084 .die(1, |s| s.attr_string("004"))
5085 .die(1, |s| s.attr_string("005"))
5086 .die_null()
5087 .die(1, |s| s.attr_string("006"))
5088 .die_null()
5089 .die_null()
5090 .die(1, |s| s.attr_string("007"))
5091 .die(1, |s| s.attr_string("008"))
5092 .die(1, |s| s.attr_string("009"))
5093 .die_null()
5094 .die_null()
5095 .die_null()
5096 .die(1, |s| s.attr_string("010"))
5097 .die_null()
5098 .die_null();
5099 let entries_buf = section.get_contents().unwrap();
5100
5101 let encoding = Encoding {
5102 format: Format::Dwarf32,
5103 version: 4,
5104 address_size: 4,
5105 };
5106 let mut unit = CompilationUnitHeader {
5107 header: UnitHeader {
5108 encoding,
5109 unit_length: 0,
5110 debug_abbrev_offset: DebugAbbrevOffset(0),
5111 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5112 },
5113 offset: DebugInfoOffset(0),
5114 };
5115 let section = Section::with_endian(Endian::Little).comp_unit(&mut unit);
5116 section.get_contents().unwrap()
5117 }
5118
5119 #[test]
test_cursor_next_entry_incomplete()5120 fn test_cursor_next_entry_incomplete() {
5121 #[rustfmt::skip]
5122 let section = Section::with_endian(Endian::Little)
5123 .die(1, |s| s.attr_string("001"))
5124 .die(1, |s| s.attr_string("002"))
5125 .die(1, |s| s);
5126 let entries_buf = section.get_contents().unwrap();
5127
5128 let encoding = Encoding {
5129 format: Format::Dwarf32,
5130 version: 4,
5131 address_size: 4,
5132 };
5133 let mut unit = CompilationUnitHeader {
5134 header: UnitHeader {
5135 encoding,
5136 unit_length: 0,
5137 debug_abbrev_offset: DebugAbbrevOffset(0),
5138 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5139 },
5140 offset: DebugInfoOffset(0),
5141 };
5142 let section = Section::with_endian(Endian::Little).comp_unit(&mut unit);
5143 let info_buf = §ion.get_contents().unwrap();
5144 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5145
5146 let unit = debug_info
5147 .units()
5148 .next()
5149 .expect("should have a unit result")
5150 .expect("and it should be ok");
5151
5152 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5153 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5154
5155 let abbrevs = unit
5156 .abbreviations(&debug_abbrev)
5157 .expect("Should parse abbreviations");
5158
5159 let mut cursor = unit.entries(&abbrevs);
5160
5161 assert_next_entry(&mut cursor, "001");
5162 assert_next_entry(&mut cursor, "002");
5163
5164 {
5165 // Entry code is present, but none of the attributes.
5166 cursor
5167 .next_entry()
5168 .expect("Should parse next entry")
5169 .expect("Should have an entry");
5170 let entry = cursor.current().expect("Should have an entry result");
5171 assert!(entry.attrs().next().is_err());
5172 }
5173
5174 assert!(cursor.next_entry().is_err());
5175 assert!(cursor.next_entry().is_err());
5176 }
5177
5178 #[test]
test_cursor_next_entry()5179 fn test_cursor_next_entry() {
5180 let info_buf = &entries_cursor_tests_debug_info_buf();
5181 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5182
5183 let unit = debug_info
5184 .units()
5185 .next()
5186 .expect("should have a unit result")
5187 .expect("and it should be ok");
5188
5189 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5190 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5191
5192 let abbrevs = unit
5193 .abbreviations(&debug_abbrev)
5194 .expect("Should parse abbreviations");
5195
5196 let mut cursor = unit.entries(&abbrevs);
5197
5198 assert_next_entry(&mut cursor, "001");
5199 assert_next_entry(&mut cursor, "002");
5200 assert_next_entry(&mut cursor, "003");
5201 assert_next_entry_null(&mut cursor);
5202 assert_next_entry_null(&mut cursor);
5203 assert_next_entry(&mut cursor, "004");
5204 assert_next_entry(&mut cursor, "005");
5205 assert_next_entry_null(&mut cursor);
5206 assert_next_entry(&mut cursor, "006");
5207 assert_next_entry_null(&mut cursor);
5208 assert_next_entry_null(&mut cursor);
5209 assert_next_entry(&mut cursor, "007");
5210 assert_next_entry(&mut cursor, "008");
5211 assert_next_entry(&mut cursor, "009");
5212 assert_next_entry_null(&mut cursor);
5213 assert_next_entry_null(&mut cursor);
5214 assert_next_entry_null(&mut cursor);
5215 assert_next_entry(&mut cursor, "010");
5216 assert_next_entry_null(&mut cursor);
5217 assert_next_entry_null(&mut cursor);
5218
5219 assert!(cursor
5220 .next_entry()
5221 .expect("Should parse next entry")
5222 .is_none());
5223 assert!(cursor.current().is_none());
5224 }
5225
5226 #[test]
test_cursor_next_dfs()5227 fn test_cursor_next_dfs() {
5228 let info_buf = &entries_cursor_tests_debug_info_buf();
5229 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5230
5231 let unit = debug_info
5232 .units()
5233 .next()
5234 .expect("should have a unit result")
5235 .expect("and it should be ok");
5236
5237 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5238 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5239
5240 let abbrevs = unit
5241 .abbreviations(&debug_abbrev)
5242 .expect("Should parse abbreviations");
5243
5244 let mut cursor = unit.entries(&abbrevs);
5245
5246 assert_next_dfs(&mut cursor, "001", 0);
5247 assert_next_dfs(&mut cursor, "002", 1);
5248 assert_next_dfs(&mut cursor, "003", 1);
5249 assert_next_dfs(&mut cursor, "004", -1);
5250 assert_next_dfs(&mut cursor, "005", 1);
5251 assert_next_dfs(&mut cursor, "006", 0);
5252 assert_next_dfs(&mut cursor, "007", -1);
5253 assert_next_dfs(&mut cursor, "008", 1);
5254 assert_next_dfs(&mut cursor, "009", 1);
5255 assert_next_dfs(&mut cursor, "010", -2);
5256
5257 assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
5258 assert!(cursor.current().is_none());
5259 }
5260
5261 #[test]
test_cursor_next_sibling_no_sibling_ptr()5262 fn test_cursor_next_sibling_no_sibling_ptr() {
5263 let info_buf = &entries_cursor_tests_debug_info_buf();
5264 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5265
5266 let unit = debug_info
5267 .units()
5268 .next()
5269 .expect("should have a unit result")
5270 .expect("and it should be ok");
5271
5272 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5273 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5274
5275 let abbrevs = unit
5276 .abbreviations(&debug_abbrev)
5277 .expect("Should parse abbreviations");
5278
5279 let mut cursor = unit.entries(&abbrevs);
5280
5281 assert_next_dfs(&mut cursor, "001", 0);
5282
5283 // Down to the first child of the root entry.
5284
5285 assert_next_dfs(&mut cursor, "002", 1);
5286
5287 // Now iterate all children of the root via `next_sibling`.
5288
5289 assert_next_sibling(&mut cursor, "004");
5290 assert_next_sibling(&mut cursor, "007");
5291 assert_next_sibling(&mut cursor, "010");
5292
5293 // There should be no more siblings.
5294
5295 assert!(cursor
5296 .next_sibling()
5297 .expect("Should parse next sibling")
5298 .is_none());
5299 assert!(cursor.current().is_none());
5300 }
5301
5302 #[test]
test_cursor_next_sibling_continuation()5303 fn test_cursor_next_sibling_continuation() {
5304 let info_buf = &entries_cursor_tests_debug_info_buf();
5305 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5306
5307 let unit = debug_info
5308 .units()
5309 .next()
5310 .expect("should have a unit result")
5311 .expect("and it should be ok");
5312
5313 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5314 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5315
5316 let abbrevs = unit
5317 .abbreviations(&debug_abbrev)
5318 .expect("Should parse abbreviations");
5319
5320 let mut cursor = unit.entries(&abbrevs);
5321
5322 assert_next_dfs(&mut cursor, "001", 0);
5323
5324 // Down to the first child of the root entry.
5325
5326 assert_next_dfs(&mut cursor, "002", 1);
5327
5328 // Get the next sibling, then iterate its children
5329
5330 assert_next_sibling(&mut cursor, "004");
5331 assert_next_dfs(&mut cursor, "005", 1);
5332 assert_next_sibling(&mut cursor, "006");
5333 assert!(cursor
5334 .next_sibling()
5335 .expect("Should parse next sibling")
5336 .is_none());
5337 assert!(cursor
5338 .next_sibling()
5339 .expect("Should parse next sibling")
5340 .is_none());
5341 assert!(cursor
5342 .next_sibling()
5343 .expect("Should parse next sibling")
5344 .is_none());
5345 assert!(cursor
5346 .next_sibling()
5347 .expect("Should parse next sibling")
5348 .is_none());
5349
5350 // And we should be able to continue with the children of the root entry.
5351
5352 assert_next_dfs(&mut cursor, "007", -1);
5353 assert_next_sibling(&mut cursor, "010");
5354
5355 // There should be no more siblings.
5356
5357 assert!(cursor
5358 .next_sibling()
5359 .expect("Should parse next sibling")
5360 .is_none());
5361 assert!(cursor.current().is_none());
5362 }
5363
entries_cursor_sibling_abbrev_buf() -> Vec<u8>5364 fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
5365 #[rustfmt::skip]
5366 let section = Section::with_endian(Endian::Little)
5367 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5368 .abbrev_attr(DW_AT_name, DW_FORM_string)
5369 .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
5370 .abbrev_attr_null()
5371 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
5372 .abbrev_attr(DW_AT_name, DW_FORM_string)
5373 .abbrev_attr_null()
5374 .abbrev_null();
5375 section.get_contents().unwrap()
5376 }
5377
entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8>5378 fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
5379 let start = Label::new();
5380 let sibling004_ref = Label::new();
5381 let sibling004 = Label::new();
5382 let sibling009_ref = Label::new();
5383 let sibling009 = Label::new();
5384
5385 #[rustfmt::skip]
5386 let section = Section::with_endian(Endian::Little)
5387 .mark(&start)
5388 .die(2, |s| s.attr_string("001"))
5389 // Valid sibling attribute.
5390 .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
5391 // Invalid code to ensure the sibling attribute was used.
5392 .die(10, |s| s.attr_string("003"))
5393 .die_null()
5394 .die_null()
5395 .mark(&sibling004)
5396 // Invalid sibling attribute.
5397 .die(1, |s| s.attr_string("004").attr_ref1(255))
5398 .die(2, |s| s.attr_string("005"))
5399 .die_null()
5400 .die_null()
5401 // Sibling attribute in child only.
5402 .die(2, |s| s.attr_string("006"))
5403 // Valid sibling attribute.
5404 .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
5405 // Invalid code to ensure the sibling attribute was used.
5406 .die(10, |s| s.attr_string("008"))
5407 .die_null()
5408 .die_null()
5409 .mark(&sibling009)
5410 .die(2, |s| s.attr_string("009"))
5411 .die_null()
5412 .die_null()
5413 // No sibling attribute.
5414 .die(2, |s| s.attr_string("010"))
5415 .die(2, |s| s.attr_string("011"))
5416 .die_null()
5417 .die_null()
5418 .die_null();
5419
5420 let offset = header_size as u64 + (&sibling004 - &start) as u64;
5421 sibling004_ref.set_const(offset);
5422
5423 let offset = header_size as u64 + (&sibling009 - &start) as u64;
5424 sibling009_ref.set_const(offset);
5425
5426 section.get_contents().unwrap()
5427 }
5428
test_cursor_next_sibling_with_ptr(cursor: &mut EntriesCursor<EndianSlice<LittleEndian>>)5429 fn test_cursor_next_sibling_with_ptr(cursor: &mut EntriesCursor<EndianSlice<LittleEndian>>) {
5430 assert_next_dfs(cursor, "001", 0);
5431
5432 // Down to the first child of the root.
5433
5434 assert_next_dfs(cursor, "002", 1);
5435
5436 // Now iterate all children of the root via `next_sibling`.
5437
5438 assert_valid_sibling_ptr(&cursor);
5439 assert_next_sibling(cursor, "004");
5440 assert_next_sibling(cursor, "006");
5441 assert_next_sibling(cursor, "010");
5442
5443 // There should be no more siblings.
5444
5445 assert!(cursor
5446 .next_sibling()
5447 .expect("Should parse next sibling")
5448 .is_none());
5449 assert!(cursor.current().is_none());
5450 }
5451
5452 #[test]
test_debug_info_next_sibling_with_ptr()5453 fn test_debug_info_next_sibling_with_ptr() {
5454 let encoding = Encoding {
5455 format: Format::Dwarf32,
5456 version: 4,
5457 address_size: 4,
5458 };
5459 let header_size =
5460 CompilationUnitHeader::<EndianSlice<LittleEndian>, _>::size_of_header(encoding);
5461 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5462
5463 let mut unit = CompilationUnitHeader {
5464 header: UnitHeader {
5465 encoding,
5466 unit_length: 0,
5467 debug_abbrev_offset: DebugAbbrevOffset(0),
5468 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5469 },
5470 offset: DebugInfoOffset(0),
5471 };
5472 let section = Section::with_endian(Endian::Little).comp_unit(&mut unit);
5473 let info_buf = section.get_contents().unwrap();
5474 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5475
5476 let unit = debug_info
5477 .units()
5478 .next()
5479 .expect("should have a unit result")
5480 .expect("and it should be ok");
5481
5482 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5483 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5484
5485 let abbrevs = unit
5486 .abbreviations(&debug_abbrev)
5487 .expect("Should parse abbreviations");
5488
5489 let mut cursor = unit.entries(&abbrevs);
5490 test_cursor_next_sibling_with_ptr(&mut cursor);
5491 }
5492
5493 #[test]
test_debug_types_next_sibling_with_ptr()5494 fn test_debug_types_next_sibling_with_ptr() {
5495 let encoding = Encoding {
5496 format: Format::Dwarf32,
5497 version: 4,
5498 address_size: 4,
5499 };
5500 let header_size = TypeUnitHeader::<EndianSlice<LittleEndian>, _>::size_of_header(encoding);
5501 let entries_buf = entries_cursor_sibling_entries_buf(header_size);
5502
5503 let mut unit = TypeUnitHeader {
5504 header: UnitHeader {
5505 encoding,
5506 unit_length: 0,
5507 debug_abbrev_offset: DebugAbbrevOffset(0),
5508 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5509 },
5510 type_signature: DebugTypeSignature(0),
5511 type_offset: UnitOffset(0),
5512 offset: DebugTypesOffset(0),
5513 };
5514 let section = Section::with_endian(Endian::Little).type_unit(&mut unit);
5515 let info_buf = section.get_contents().unwrap();
5516 let debug_types = DebugTypes::new(&info_buf, LittleEndian);
5517
5518 let unit = debug_types
5519 .units()
5520 .next()
5521 .expect("should have a unit result")
5522 .expect("and it should be ok");
5523
5524 let abbrev_buf = entries_cursor_sibling_abbrev_buf();
5525 let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
5526
5527 let abbrevs = unit
5528 .abbreviations(&debug_abbrev)
5529 .expect("Should parse abbreviations");
5530
5531 let mut cursor = unit.entries(&abbrevs);
5532 test_cursor_next_sibling_with_ptr(&mut cursor);
5533 }
5534
5535 #[test]
test_entries_at_offset()5536 fn test_entries_at_offset() {
5537 let info_buf = &entries_cursor_tests_debug_info_buf();
5538 let debug_info = DebugInfo::new(info_buf, LittleEndian);
5539
5540 let unit = debug_info
5541 .units()
5542 .next()
5543 .expect("should have a unit result")
5544 .expect("and it should be ok");
5545
5546 let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
5547 let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
5548
5549 let abbrevs = unit
5550 .abbreviations(&debug_abbrev)
5551 .expect("Should parse abbreviations");
5552
5553 let mut cursor = unit
5554 .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
5555 .unwrap();
5556 assert_next_entry(&mut cursor, "001");
5557
5558 let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
5559 match cursor {
5560 Err(Error::OffsetOutOfBounds) => {}
5561 otherwise => {
5562 assert!(false, "Unexpected parse result = {:#?}", otherwise);
5563 }
5564 }
5565 }
5566
entries_tree_tests_debug_abbrevs_buf() -> Vec<u8>5567 fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
5568 #[rustfmt::skip]
5569 let section = Section::with_endian(Endian::Little)
5570 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5571 .abbrev_attr(DW_AT_name, DW_FORM_string)
5572 .abbrev_attr_null()
5573 .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
5574 .abbrev_attr(DW_AT_name, DW_FORM_string)
5575 .abbrev_attr_null()
5576 .abbrev_null()
5577 .get_contents()
5578 .unwrap();
5579 section
5580 }
5581
entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset)5582 fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
5583 let start = Label::new();
5584 let entry2 = Label::new();
5585 #[rustfmt::skip]
5586 let section = Section::with_endian(Endian::Little)
5587 .mark(&start)
5588 .die(1, |s| s.attr_string("root"))
5589 .die(1, |s| s.attr_string("1"))
5590 .die(1, |s| s.attr_string("1a"))
5591 .die_null()
5592 .die(2, |s| s.attr_string("1b"))
5593 .die_null()
5594 .mark(&entry2)
5595 .die(1, |s| s.attr_string("2"))
5596 .die(1, |s| s.attr_string("2a"))
5597 .die(1, |s| s.attr_string("2a1"))
5598 .die_null()
5599 .die_null()
5600 .die(1, |s| s.attr_string("2b"))
5601 .die(2, |s| s.attr_string("2b1"))
5602 .die_null()
5603 .die_null()
5604 .die(1, |s| s.attr_string("3"))
5605 .die(1, |s| s.attr_string("3a"))
5606 .die(2, |s| s.attr_string("3a1"))
5607 .die(2, |s| s.attr_string("3a2"))
5608 .die_null()
5609 .die(2, |s| s.attr_string("3b"))
5610 .die_null()
5611 .die(2, |s| s.attr_string("final"))
5612 .die_null()
5613 .get_contents()
5614 .unwrap();
5615 let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
5616 (section, entry2)
5617 }
5618
5619 #[test]
test_entries_tree()5620 fn test_entries_tree() {
5621 fn assert_entry<'input, 'abbrev, 'unit, 'tree, Endian>(
5622 node: Result<
5623 Option<EntriesTreeNode<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>>,
5624 >,
5625 name: &str,
5626 ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>
5627 where
5628 Endian: Endianity,
5629 {
5630 let node = node
5631 .expect("Should parse entry")
5632 .expect("Should have entry");
5633 assert_entry_name(node.entry(), name);
5634 node.children()
5635 }
5636
5637 fn assert_null<E: Endianity>(node: Result<Option<EntriesTreeNode<EndianSlice<E>>>>) {
5638 match node {
5639 Ok(None) => {}
5640 otherwise => {
5641 assert!(false, "Unexpected parse result = {:#?}", otherwise);
5642 }
5643 }
5644 }
5645
5646 let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
5647 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5648
5649 let encoding = Encoding {
5650 format: Format::Dwarf32,
5651 version: 4,
5652 address_size: 4,
5653 };
5654 let header_size =
5655 CompilationUnitHeader::<EndianSlice<LittleEndian>, _>::size_of_header(encoding);
5656 let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
5657 let mut unit = CompilationUnitHeader {
5658 header: UnitHeader {
5659 encoding,
5660 unit_length: 0,
5661 debug_abbrev_offset: DebugAbbrevOffset(0),
5662 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5663 },
5664 offset: DebugInfoOffset(0),
5665 };
5666 let info_buf = Section::with_endian(Endian::Little)
5667 .comp_unit(&mut unit)
5668 .get_contents()
5669 .unwrap();
5670 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5671
5672 let unit = debug_info
5673 .units()
5674 .next()
5675 .expect("Should parse unit")
5676 .expect("and it should be some");
5677 let abbrevs = unit
5678 .abbreviations(&debug_abbrev)
5679 .expect("Should parse abbreviations");
5680 let mut tree = unit
5681 .entries_tree(&abbrevs, None)
5682 .expect("Should have entries tree");
5683
5684 // Test we can restart iteration of the tree.
5685 {
5686 let mut iter = assert_entry(tree.root().map(Some), "root");
5687 assert_entry(iter.next(), "1");
5688 }
5689 {
5690 let mut iter = assert_entry(tree.root().map(Some), "root");
5691 assert_entry(iter.next(), "1");
5692 }
5693
5694 let mut iter = assert_entry(tree.root().map(Some), "root");
5695 {
5696 // Test iteration with children.
5697 let mut iter = assert_entry(iter.next(), "1");
5698 {
5699 // Test iteration with children flag, but no children.
5700 let mut iter = assert_entry(iter.next(), "1a");
5701 assert_null(iter.next());
5702 assert_null(iter.next());
5703 }
5704 {
5705 // Test iteration without children flag.
5706 let mut iter = assert_entry(iter.next(), "1b");
5707 assert_null(iter.next());
5708 assert_null(iter.next());
5709 }
5710 assert_null(iter.next());
5711 assert_null(iter.next());
5712 }
5713 {
5714 // Test skipping over children.
5715 let mut iter = assert_entry(iter.next(), "2");
5716 assert_entry(iter.next(), "2a");
5717 assert_entry(iter.next(), "2b");
5718 assert_null(iter.next());
5719 }
5720 {
5721 // Test skipping after partial iteration.
5722 let mut iter = assert_entry(iter.next(), "3");
5723 {
5724 let mut iter = assert_entry(iter.next(), "3a");
5725 assert_entry(iter.next(), "3a1");
5726 // Parent iter should be able to skip over "3a2".
5727 }
5728 assert_entry(iter.next(), "3b");
5729 assert_null(iter.next());
5730 }
5731 assert_entry(iter.next(), "final");
5732 assert_null(iter.next());
5733
5734 // Test starting at an offset.
5735 let mut tree = unit
5736 .entries_tree(&abbrevs, Some(entry2))
5737 .expect("Should have entries tree");
5738 let mut iter = assert_entry(tree.root().map(Some), "2");
5739 assert_entry(iter.next(), "2a");
5740 assert_entry(iter.next(), "2b");
5741 assert_null(iter.next());
5742 }
5743
5744 #[test]
test_entries_raw()5745 fn test_entries_raw() {
5746 fn assert_abbrev<'input, 'abbrev, 'unit, Endian>(
5747 entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5748 tag: DwTag,
5749 ) -> &'abbrev Abbreviation
5750 where
5751 Endian: Endianity,
5752 {
5753 let abbrev = entries
5754 .read_abbreviation()
5755 .expect("Should parse abbrev")
5756 .expect("Should have abbrev");
5757 assert_eq!(abbrev.tag(), tag);
5758 abbrev
5759 }
5760
5761 fn assert_null<'input, 'abbrev, 'unit, Endian>(
5762 entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5763 ) where
5764 Endian: Endianity,
5765 {
5766 match entries.read_abbreviation() {
5767 Ok(None) => {}
5768 otherwise => {
5769 assert!(false, "Unexpected parse result = {:#?}", otherwise);
5770 }
5771 }
5772 }
5773
5774 fn assert_attr<'input, 'abbrev, 'unit, Endian>(
5775 entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
5776 spec: Option<AttributeSpecification>,
5777 name: DwAt,
5778 value: &str,
5779 ) where
5780 Endian: Endianity,
5781 {
5782 let spec = spec.expect("Should have attribute specification");
5783 let attr = entries
5784 .read_attribute(spec)
5785 .expect("Should parse attribute");
5786 assert_eq!(attr.name(), name);
5787 assert_eq!(
5788 attr.value(),
5789 AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
5790 );
5791 }
5792
5793 #[rustfmt::skip]
5794 let section = Section::with_endian(Endian::Little)
5795 .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
5796 .abbrev_attr(DW_AT_name, DW_FORM_string)
5797 .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
5798 .abbrev_attr_null()
5799 .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
5800 .abbrev_attr(DW_AT_name, DW_FORM_string)
5801 .abbrev_attr_null()
5802 .abbrev_null();
5803 let abbrevs_buf = section.get_contents().unwrap();
5804 let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
5805
5806 #[rustfmt::skip]
5807 let section = Section::with_endian(Endian::Little)
5808 .die(1, |s| s.attr_string("f1").attr_string("l1"))
5809 .die(2, |s| s.attr_string("v1"))
5810 .die(2, |s| s.attr_string("v2"))
5811 .die(1, |s| s.attr_string("f2").attr_string("l2"))
5812 .die_null()
5813 .die_null();
5814 let entries_buf = section.get_contents().unwrap();
5815
5816 let encoding = Encoding {
5817 format: Format::Dwarf32,
5818 version: 4,
5819 address_size: 4,
5820 };
5821 let mut unit = CompilationUnitHeader {
5822 header: UnitHeader {
5823 encoding,
5824 unit_length: 0,
5825 debug_abbrev_offset: DebugAbbrevOffset(0),
5826 entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
5827 },
5828 offset: DebugInfoOffset(0),
5829 };
5830 let section = Section::with_endian(Endian::Little).comp_unit(&mut unit);
5831 let info_buf = section.get_contents().unwrap();
5832 let debug_info = DebugInfo::new(&info_buf, LittleEndian);
5833
5834 let unit = debug_info
5835 .units()
5836 .next()
5837 .expect("should have a unit result")
5838 .expect("and it should be ok");
5839
5840 let abbrevs = unit
5841 .abbreviations(&debug_abbrev)
5842 .expect("Should parse abbreviations");
5843
5844 let mut entries = unit
5845 .entries_raw(&abbrevs, None)
5846 .expect("Should have entries");
5847
5848 assert_eq!(entries.next_depth(), 0);
5849 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5850 let mut attrs = abbrev.attributes().iter().copied();
5851 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
5852 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
5853 assert!(attrs.next().is_none());
5854
5855 assert_eq!(entries.next_depth(), 1);
5856 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5857 let mut attrs = abbrev.attributes().iter().copied();
5858 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
5859 assert!(attrs.next().is_none());
5860
5861 assert_eq!(entries.next_depth(), 1);
5862 let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
5863 let mut attrs = abbrev.attributes().iter().copied();
5864 assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
5865 assert!(attrs.next().is_none());
5866
5867 assert_eq!(entries.next_depth(), 1);
5868 let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
5869 let mut attrs = abbrev.attributes().iter().copied();
5870 assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
5871 assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
5872 assert!(attrs.next().is_none());
5873
5874 assert_eq!(entries.next_depth(), 2);
5875 assert_null(&mut entries);
5876
5877 assert_eq!(entries.next_depth(), 1);
5878 assert_null(&mut entries);
5879
5880 assert_eq!(entries.next_depth(), 0);
5881 assert!(entries.is_empty());
5882 }
5883
5884 #[test]
test_debug_info_offset()5885 fn test_debug_info_offset() {
5886 let padding = &[0; 10];
5887 let entries = &[0; 20];
5888 let encoding = Encoding {
5889 format: Format::Dwarf32,
5890 version: 4,
5891 address_size: 4,
5892 };
5893 let mut unit = CompilationUnitHeader {
5894 header: UnitHeader {
5895 encoding,
5896 unit_length: 0,
5897 debug_abbrev_offset: DebugAbbrevOffset(0),
5898 entries_buf: EndianSlice::new(entries, LittleEndian),
5899 },
5900 offset: DebugInfoOffset(0),
5901 };
5902 Section::with_endian(Endian::Little)
5903 .append_bytes(padding)
5904 .comp_unit(&mut unit);
5905 let offset = padding.len();
5906 let header_length =
5907 CompilationUnitHeader::<EndianSlice<LittleEndian>, _>::size_of_header(encoding);
5908 let length = unit.length_including_self();
5909 assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
5910 assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
5911 assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
5912 assert_eq!(
5913 DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
5914 None
5915 );
5916 assert_eq!(
5917 DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
5918 Some(UnitOffset(header_length))
5919 );
5920 assert_eq!(
5921 DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
5922 Some(UnitOffset(length - 1))
5923 );
5924 assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
5925 assert_eq!(
5926 UnitOffset(header_length).to_debug_info_offset(&unit),
5927 DebugInfoOffset(offset + header_length)
5928 );
5929 assert_eq!(
5930 UnitOffset(length - 1).to_debug_info_offset(&unit),
5931 DebugInfoOffset(offset + length - 1)
5932 );
5933 }
5934
5935 #[test]
test_debug_types_offset()5936 fn test_debug_types_offset() {
5937 let padding = &[0; 10];
5938 let entries = &[0; 20];
5939 let encoding = Encoding {
5940 format: Format::Dwarf32,
5941 version: 4,
5942 address_size: 4,
5943 };
5944 let mut unit = TypeUnitHeader {
5945 header: UnitHeader {
5946 encoding,
5947 unit_length: 0,
5948 debug_abbrev_offset: DebugAbbrevOffset(0),
5949 entries_buf: EndianSlice::new(entries, LittleEndian),
5950 },
5951 type_signature: DebugTypeSignature(0),
5952 type_offset: UnitOffset(0),
5953 offset: DebugTypesOffset(0),
5954 };
5955 Section::with_endian(Endian::Little)
5956 .append_bytes(padding)
5957 .type_unit(&mut unit);
5958 let offset = padding.len();
5959 let header_length =
5960 TypeUnitHeader::<EndianSlice<LittleEndian>, _>::size_of_header(encoding);
5961 let length = unit.length_including_self();
5962 assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
5963 assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
5964 assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
5965 assert_eq!(
5966 DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
5967 None
5968 );
5969 assert_eq!(
5970 DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
5971 Some(UnitOffset(header_length))
5972 );
5973 assert_eq!(
5974 DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
5975 Some(UnitOffset(length - 1))
5976 );
5977 assert_eq!(
5978 DebugTypesOffset(offset + length).to_unit_offset(&unit),
5979 None
5980 );
5981 assert_eq!(
5982 UnitOffset(header_length).to_debug_types_offset(&unit),
5983 DebugTypesOffset(offset + header_length)
5984 );
5985 assert_eq!(
5986 UnitOffset(length - 1).to_debug_types_offset(&unit),
5987 DebugTypesOffset(offset + length - 1)
5988 );
5989 }
5990
5991 #[test]
test_length_including_self()5992 fn test_length_including_self() {
5993 let encoding = Encoding {
5994 format: Format::Dwarf32,
5995 version: 4,
5996 address_size: 4,
5997 };
5998 let mut unit = UnitHeader {
5999 encoding,
6000 unit_length: 0,
6001 debug_abbrev_offset: DebugAbbrevOffset(0),
6002 entries_buf: EndianSlice::new(&[], LittleEndian),
6003 };
6004 unit.encoding.format = Format::Dwarf32;
6005 assert_eq!(unit.length_including_self(), 4);
6006 unit.encoding.format = Format::Dwarf64;
6007 assert_eq!(unit.length_including_self(), 12);
6008 unit.unit_length = 10;
6009 assert_eq!(unit.length_including_self(), 22);
6010 }
6011 }
6012