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