1 | //! Functions for parsing DWARF debugging abbreviations. |
2 | |
3 | use alloc::collections::btree_map; |
4 | use alloc::sync::Arc; |
5 | use alloc::vec::Vec; |
6 | use core::convert::TryFrom; |
7 | use core::fmt::{self, Debug}; |
8 | use core::iter::FromIterator; |
9 | use core::ops::Deref; |
10 | |
11 | use crate::common::{DebugAbbrevOffset, Encoding, SectionId}; |
12 | use crate::constants; |
13 | use crate::endianity::Endianity; |
14 | use crate::read::{ |
15 | DebugInfoUnitHeadersIter, EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader, |
16 | }; |
17 | |
18 | /// The `DebugAbbrev` struct represents the abbreviations describing |
19 | /// `DebuggingInformationEntry`s' attribute names and forms found in the |
20 | /// `.debug_abbrev` section. |
21 | #[derive (Debug, Default, Clone, Copy)] |
22 | pub struct DebugAbbrev<R> { |
23 | debug_abbrev_section: R, |
24 | } |
25 | |
26 | impl<'input, Endian> DebugAbbrev<EndianSlice<'input, Endian>> |
27 | where |
28 | Endian: Endianity, |
29 | { |
30 | /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev` |
31 | /// section. |
32 | /// |
33 | /// It is the caller's responsibility to read the `.debug_abbrev` section and |
34 | /// present it as a `&[u8]` slice. That means using some ELF loader on |
35 | /// Linux, a Mach-O loader on macOS, etc. |
36 | /// |
37 | /// ``` |
38 | /// use gimli::{DebugAbbrev, LittleEndian}; |
39 | /// |
40 | /// # let buf = [0x00, 0x01, 0x02, 0x03]; |
41 | /// # let read_debug_abbrev_section_somehow = || &buf; |
42 | /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian); |
43 | /// ``` |
44 | pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self { |
45 | Self::from(EndianSlice::new(slice:debug_abbrev_section, endian)) |
46 | } |
47 | } |
48 | |
49 | impl<R: Reader> DebugAbbrev<R> { |
50 | /// Parse the abbreviations at the given `offset` within this |
51 | /// `.debug_abbrev` section. |
52 | /// |
53 | /// The `offset` should generally be retrieved from a unit header. |
54 | pub fn abbreviations( |
55 | &self, |
56 | debug_abbrev_offset: DebugAbbrevOffset<R::Offset>, |
57 | ) -> Result<Abbreviations> { |
58 | let input: &mut R = &mut self.debug_abbrev_section.clone(); |
59 | input.skip(len:debug_abbrev_offset.0)?; |
60 | Abbreviations::parse(input) |
61 | } |
62 | } |
63 | |
64 | impl<T> DebugAbbrev<T> { |
65 | /// Create a `DebugAbbrev` section that references the data in `self`. |
66 | /// |
67 | /// This is useful when `R` implements `Reader` but `T` does not. |
68 | /// |
69 | /// ## Example Usage |
70 | /// |
71 | /// ```rust,no_run |
72 | /// # let load_section = || unimplemented!(); |
73 | /// // Read the DWARF section into a `Vec` with whatever object loader you're using. |
74 | /// let owned_section: gimli::DebugAbbrev<Vec<u8>> = load_section(); |
75 | /// // Create a reference to the DWARF section. |
76 | /// let section = owned_section.borrow(|section| { |
77 | /// gimli::EndianSlice::new(§ion, gimli::LittleEndian) |
78 | /// }); |
79 | /// ``` |
80 | pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev<R> |
81 | where |
82 | F: FnMut(&'a T) -> R, |
83 | { |
84 | borrow(&self.debug_abbrev_section).into() |
85 | } |
86 | } |
87 | |
88 | impl<R> Section<R> for DebugAbbrev<R> { |
89 | fn id() -> SectionId { |
90 | SectionId::DebugAbbrev |
91 | } |
92 | |
93 | fn reader(&self) -> &R { |
94 | &self.debug_abbrev_section |
95 | } |
96 | } |
97 | |
98 | impl<R> From<R> for DebugAbbrev<R> { |
99 | fn from(debug_abbrev_section: R) -> Self { |
100 | DebugAbbrev { |
101 | debug_abbrev_section, |
102 | } |
103 | } |
104 | } |
105 | |
106 | /// The strategy to use for caching abbreviations. |
107 | #[derive (Clone, Copy, Debug, PartialEq, Eq)] |
108 | #[non_exhaustive ] |
109 | pub enum AbbreviationsCacheStrategy { |
110 | /// Cache abbreviations that are used more than once. |
111 | /// |
112 | /// This is useful if the units in the `.debug_info` section will be parsed only once. |
113 | Duplicates, |
114 | /// Cache all abbreviations. |
115 | /// |
116 | /// This is useful if the units in the `.debug_info` section will be parsed more than once. |
117 | All, |
118 | } |
119 | |
120 | /// A cache of previously parsed `Abbreviations`. |
121 | #[derive (Debug, Default)] |
122 | pub struct AbbreviationsCache { |
123 | abbreviations: btree_map::BTreeMap<u64, Result<Arc<Abbreviations>>>, |
124 | } |
125 | |
126 | impl AbbreviationsCache { |
127 | /// Create an empty abbreviations cache. |
128 | pub fn new() -> Self { |
129 | Self::default() |
130 | } |
131 | |
132 | /// Parse abbreviations and store them in the cache. |
133 | /// |
134 | /// This will iterate over the given units to determine the abbreviations |
135 | /// offsets. Any existing cache entries are discarded. |
136 | /// |
137 | /// Errors during parsing abbreviations are also stored in the cache. |
138 | /// Errors during iterating over the units are ignored. |
139 | pub fn populate<R: Reader>( |
140 | &mut self, |
141 | strategy: AbbreviationsCacheStrategy, |
142 | debug_abbrev: &DebugAbbrev<R>, |
143 | mut units: DebugInfoUnitHeadersIter<R>, |
144 | ) { |
145 | let mut offsets = Vec::new(); |
146 | match strategy { |
147 | AbbreviationsCacheStrategy::Duplicates => { |
148 | while let Ok(Some(unit)) = units.next() { |
149 | offsets.push(unit.debug_abbrev_offset()); |
150 | } |
151 | offsets.sort_unstable_by_key(|offset| offset.0); |
152 | let mut prev_offset = R::Offset::from_u8(0); |
153 | let mut count = 0; |
154 | offsets.retain(|offset| { |
155 | if count == 0 || prev_offset != offset.0 { |
156 | prev_offset = offset.0; |
157 | count = 1; |
158 | } else { |
159 | count += 1; |
160 | } |
161 | count == 2 |
162 | }); |
163 | } |
164 | AbbreviationsCacheStrategy::All => { |
165 | while let Ok(Some(unit)) = units.next() { |
166 | offsets.push(unit.debug_abbrev_offset()); |
167 | } |
168 | offsets.sort_unstable_by_key(|offset| offset.0); |
169 | offsets.dedup(); |
170 | } |
171 | } |
172 | self.abbreviations = offsets |
173 | .into_iter() |
174 | .map(|offset| { |
175 | ( |
176 | offset.0.into_u64(), |
177 | debug_abbrev.abbreviations(offset).map(Arc::new), |
178 | ) |
179 | }) |
180 | .collect(); |
181 | } |
182 | |
183 | /// Set an entry in the abbreviations cache. |
184 | /// |
185 | /// This is only required if you want to manually populate the cache. |
186 | pub fn set<R: Reader>( |
187 | &mut self, |
188 | offset: DebugAbbrevOffset<R::Offset>, |
189 | abbreviations: Arc<Abbreviations>, |
190 | ) { |
191 | self.abbreviations |
192 | .insert(offset.0.into_u64(), Ok(abbreviations)); |
193 | } |
194 | |
195 | /// Parse the abbreviations at the given offset. |
196 | /// |
197 | /// This uses the cache if possible, but does not update it. |
198 | pub fn get<R: Reader>( |
199 | &self, |
200 | debug_abbrev: &DebugAbbrev<R>, |
201 | offset: DebugAbbrevOffset<R::Offset>, |
202 | ) -> Result<Arc<Abbreviations>> { |
203 | match self.abbreviations.get(&offset.0.into_u64()) { |
204 | Some(entry) => entry.clone(), |
205 | None => debug_abbrev.abbreviations(offset).map(Arc::new), |
206 | } |
207 | } |
208 | } |
209 | |
210 | /// A set of type abbreviations. |
211 | /// |
212 | /// Construct an `Abbreviations` instance with the |
213 | /// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations) |
214 | /// method. |
215 | #[derive (Debug, Default, Clone)] |
216 | pub struct Abbreviations { |
217 | vec: Vec<Abbreviation>, |
218 | map: btree_map::BTreeMap<u64, Abbreviation>, |
219 | } |
220 | |
221 | impl Abbreviations { |
222 | /// Construct a new, empty set of abbreviations. |
223 | fn empty() -> Abbreviations { |
224 | Abbreviations { |
225 | vec: Vec::new(), |
226 | map: btree_map::BTreeMap::new(), |
227 | } |
228 | } |
229 | |
230 | /// Insert an abbreviation into the set. |
231 | /// |
232 | /// Returns `Ok` if it is the first abbreviation in the set with its code, |
233 | /// `Err` if the code is a duplicate and there already exists an |
234 | /// abbreviation in the set with the given abbreviation's code. |
235 | fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> { |
236 | let code_usize = abbrev.code as usize; |
237 | if code_usize as u64 == abbrev.code { |
238 | // Optimize for sequential abbreviation codes by storing them |
239 | // in a Vec, as long as the map doesn't already contain them. |
240 | // A potential further optimization would be to allow some |
241 | // holes in the Vec, but there's no need for that yet. |
242 | if code_usize - 1 < self.vec.len() { |
243 | return Err(()); |
244 | } else if code_usize - 1 == self.vec.len() { |
245 | if !self.map.is_empty() && self.map.contains_key(&abbrev.code) { |
246 | return Err(()); |
247 | } else { |
248 | self.vec.push(abbrev); |
249 | return Ok(()); |
250 | } |
251 | } |
252 | } |
253 | match self.map.entry(abbrev.code) { |
254 | btree_map::Entry::Occupied(_) => Err(()), |
255 | btree_map::Entry::Vacant(entry) => { |
256 | entry.insert(abbrev); |
257 | Ok(()) |
258 | } |
259 | } |
260 | } |
261 | |
262 | /// Get the abbreviation associated with the given code. |
263 | #[inline ] |
264 | pub fn get(&self, code: u64) -> Option<&Abbreviation> { |
265 | if let Ok(code) = usize::try_from(code) { |
266 | let index = code.checked_sub(1)?; |
267 | if index < self.vec.len() { |
268 | return Some(&self.vec[index]); |
269 | } |
270 | } |
271 | |
272 | self.map.get(&code) |
273 | } |
274 | |
275 | /// Parse a series of abbreviations, terminated by a null abbreviation. |
276 | fn parse<R: Reader>(input: &mut R) -> Result<Abbreviations> { |
277 | let mut abbrevs = Abbreviations::empty(); |
278 | |
279 | while let Some(abbrev) = Abbreviation::parse(input)? { |
280 | if abbrevs.insert(abbrev).is_err() { |
281 | return Err(Error::DuplicateAbbreviationCode); |
282 | } |
283 | } |
284 | |
285 | Ok(abbrevs) |
286 | } |
287 | } |
288 | |
289 | /// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type: |
290 | /// its code, tag type, whether it has children, and its set of attributes. |
291 | #[derive (Debug, Clone, PartialEq, Eq)] |
292 | pub struct Abbreviation { |
293 | code: u64, |
294 | tag: constants::DwTag, |
295 | has_children: constants::DwChildren, |
296 | attributes: Attributes, |
297 | } |
298 | |
299 | impl Abbreviation { |
300 | /// Construct a new `Abbreviation`. |
301 | /// |
302 | /// ### Panics |
303 | /// |
304 | /// Panics if `code` is `0`. |
305 | pub(crate) fn new( |
306 | code: u64, |
307 | tag: constants::DwTag, |
308 | has_children: constants::DwChildren, |
309 | attributes: Attributes, |
310 | ) -> Abbreviation { |
311 | assert_ne!(code, 0); |
312 | Abbreviation { |
313 | code, |
314 | tag, |
315 | has_children, |
316 | attributes, |
317 | } |
318 | } |
319 | |
320 | /// Get this abbreviation's code. |
321 | #[inline ] |
322 | pub fn code(&self) -> u64 { |
323 | self.code |
324 | } |
325 | |
326 | /// Get this abbreviation's tag. |
327 | #[inline ] |
328 | pub fn tag(&self) -> constants::DwTag { |
329 | self.tag |
330 | } |
331 | |
332 | /// Return true if this abbreviation's type has children, false otherwise. |
333 | #[inline ] |
334 | pub fn has_children(&self) -> bool { |
335 | self.has_children == constants::DW_CHILDREN_yes |
336 | } |
337 | |
338 | /// Get this abbreviation's attributes. |
339 | #[inline ] |
340 | pub fn attributes(&self) -> &[AttributeSpecification] { |
341 | &self.attributes[..] |
342 | } |
343 | |
344 | /// Parse an abbreviation's tag. |
345 | fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> { |
346 | let val = input.read_uleb128_u16()?; |
347 | if val == 0 { |
348 | Err(Error::AbbreviationTagZero) |
349 | } else { |
350 | Ok(constants::DwTag(val)) |
351 | } |
352 | } |
353 | |
354 | /// Parse an abbreviation's "does the type have children?" byte. |
355 | fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> { |
356 | let val = input.read_u8()?; |
357 | let val = constants::DwChildren(val); |
358 | if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes { |
359 | Ok(val) |
360 | } else { |
361 | Err(Error::BadHasChildren) |
362 | } |
363 | } |
364 | |
365 | /// Parse a series of attribute specifications, terminated by a null attribute |
366 | /// specification. |
367 | fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> { |
368 | let mut attrs = Attributes::new(); |
369 | |
370 | while let Some(attr) = AttributeSpecification::parse(input)? { |
371 | attrs.push(attr); |
372 | } |
373 | |
374 | Ok(attrs) |
375 | } |
376 | |
377 | /// Parse an abbreviation. Return `None` for the null abbreviation, `Some` |
378 | /// for an actual abbreviation. |
379 | fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> { |
380 | let code = input.read_uleb128()?; |
381 | if code == 0 { |
382 | return Ok(None); |
383 | } |
384 | |
385 | let tag = Self::parse_tag(input)?; |
386 | let has_children = Self::parse_has_children(input)?; |
387 | let attributes = Self::parse_attributes(input)?; |
388 | let abbrev = Abbreviation::new(code, tag, has_children, attributes); |
389 | Ok(Some(abbrev)) |
390 | } |
391 | } |
392 | |
393 | /// A list of attributes found in an `Abbreviation` |
394 | #[derive (Clone)] |
395 | pub(crate) enum Attributes { |
396 | Inline { |
397 | buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE], |
398 | len: usize, |
399 | }, |
400 | Heap(Vec<AttributeSpecification>), |
401 | } |
402 | |
403 | // Length of 5 based on benchmark results for both x86-64 and i686. |
404 | const MAX_ATTRIBUTES_INLINE: usize = 5; |
405 | |
406 | impl Attributes { |
407 | /// Returns a new empty list of attributes |
408 | fn new() -> Attributes { |
409 | let default = |
410 | AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None); |
411 | Attributes::Inline { |
412 | buf: [default; 5], |
413 | len: 0, |
414 | } |
415 | } |
416 | |
417 | /// Pushes a new value onto this list of attributes. |
418 | fn push(&mut self, attr: AttributeSpecification) { |
419 | match self { |
420 | Attributes::Heap(list) => list.push(attr), |
421 | Attributes::Inline { |
422 | buf, |
423 | len: MAX_ATTRIBUTES_INLINE, |
424 | } => { |
425 | let mut list = buf.to_vec(); |
426 | list.push(attr); |
427 | *self = Attributes::Heap(list); |
428 | } |
429 | Attributes::Inline { buf, len } => { |
430 | buf[*len] = attr; |
431 | *len += 1; |
432 | } |
433 | } |
434 | } |
435 | } |
436 | |
437 | impl Debug for Attributes { |
438 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
439 | (**self).fmt(f) |
440 | } |
441 | } |
442 | |
443 | impl PartialEq for Attributes { |
444 | fn eq(&self, other: &Attributes) -> bool { |
445 | **self == **other |
446 | } |
447 | } |
448 | |
449 | impl Eq for Attributes {} |
450 | |
451 | impl Deref for Attributes { |
452 | type Target = [AttributeSpecification]; |
453 | fn deref(&self) -> &[AttributeSpecification] { |
454 | match self { |
455 | Attributes::Inline { buf: &[AttributeSpecification; 5], len: &usize } => &buf[..*len], |
456 | Attributes::Heap(list: &Vec) => list, |
457 | } |
458 | } |
459 | } |
460 | |
461 | impl FromIterator<AttributeSpecification> for Attributes { |
462 | fn from_iter<I>(iter: I) -> Attributes |
463 | where |
464 | I: IntoIterator<Item = AttributeSpecification>, |
465 | { |
466 | let mut list: Attributes = Attributes::new(); |
467 | for item: AttributeSpecification in iter { |
468 | list.push(attr:item); |
469 | } |
470 | list |
471 | } |
472 | } |
473 | |
474 | impl From<Vec<AttributeSpecification>> for Attributes { |
475 | fn from(list: Vec<AttributeSpecification>) -> Attributes { |
476 | Attributes::Heap(list) |
477 | } |
478 | } |
479 | |
480 | /// The description of an attribute in an abbreviated type. It is a pair of name |
481 | /// and form. |
482 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
483 | pub struct AttributeSpecification { |
484 | name: constants::DwAt, |
485 | form: constants::DwForm, |
486 | implicit_const_value: i64, |
487 | } |
488 | |
489 | impl AttributeSpecification { |
490 | /// Construct a new `AttributeSpecification` from the given name and form |
491 | /// and implicit const value. |
492 | #[inline ] |
493 | pub fn new( |
494 | name: constants::DwAt, |
495 | form: constants::DwForm, |
496 | implicit_const_value: Option<i64>, |
497 | ) -> AttributeSpecification { |
498 | debug_assert!( |
499 | (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some()) |
500 | || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none()) |
501 | ); |
502 | AttributeSpecification { |
503 | name, |
504 | form, |
505 | implicit_const_value: implicit_const_value.unwrap_or(0), |
506 | } |
507 | } |
508 | |
509 | /// Get the attribute's name. |
510 | #[inline ] |
511 | pub fn name(&self) -> constants::DwAt { |
512 | self.name |
513 | } |
514 | |
515 | /// Get the attribute's form. |
516 | #[inline ] |
517 | pub fn form(&self) -> constants::DwForm { |
518 | self.form |
519 | } |
520 | |
521 | /// Get the attribute's implicit const value. |
522 | #[inline ] |
523 | pub fn implicit_const_value(&self) -> Option<i64> { |
524 | if self.form == constants::DW_FORM_implicit_const { |
525 | Some(self.implicit_const_value) |
526 | } else { |
527 | None |
528 | } |
529 | } |
530 | |
531 | /// Return the size of the attribute, in bytes. |
532 | /// |
533 | /// Note that because some attributes are variably sized, the size cannot |
534 | /// always be known without parsing, in which case we return `None`. |
535 | pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> { |
536 | get_attribute_size(self.form, header.encoding()).map(usize::from) |
537 | } |
538 | |
539 | /// Parse an attribute's form. |
540 | fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> { |
541 | let val = input.read_uleb128_u16()?; |
542 | if val == 0 { |
543 | Err(Error::AttributeFormZero) |
544 | } else { |
545 | Ok(constants::DwForm(val)) |
546 | } |
547 | } |
548 | |
549 | /// Parse an attribute specification. Returns `None` for the null attribute |
550 | /// specification, `Some` for an actual attribute specification. |
551 | fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> { |
552 | let name = input.read_uleb128_u16()?; |
553 | if name == 0 { |
554 | // Parse the null attribute specification. |
555 | let form = input.read_uleb128_u16()?; |
556 | return if form == 0 { |
557 | Ok(None) |
558 | } else { |
559 | Err(Error::ExpectedZero) |
560 | }; |
561 | } |
562 | |
563 | let name = constants::DwAt(name); |
564 | let form = Self::parse_form(input)?; |
565 | let implicit_const_value = if form == constants::DW_FORM_implicit_const { |
566 | Some(input.read_sleb128()?) |
567 | } else { |
568 | None |
569 | }; |
570 | let spec = AttributeSpecification::new(name, form, implicit_const_value); |
571 | Ok(Some(spec)) |
572 | } |
573 | } |
574 | |
575 | #[inline ] |
576 | pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> { |
577 | match form { |
578 | constants::DW_FORM_addr => Some(encoding.address_size), |
579 | |
580 | constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0), |
581 | |
582 | constants::DW_FORM_data1 |
583 | | constants::DW_FORM_flag |
584 | | constants::DW_FORM_strx1 |
585 | | constants::DW_FORM_ref1 |
586 | | constants::DW_FORM_addrx1 => Some(1), |
587 | |
588 | constants::DW_FORM_data2 |
589 | | constants::DW_FORM_ref2 |
590 | | constants::DW_FORM_addrx2 |
591 | | constants::DW_FORM_strx2 => Some(2), |
592 | |
593 | constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3), |
594 | |
595 | constants::DW_FORM_data4 |
596 | | constants::DW_FORM_ref_sup4 |
597 | | constants::DW_FORM_ref4 |
598 | | constants::DW_FORM_strx4 |
599 | | constants::DW_FORM_addrx4 => Some(4), |
600 | |
601 | constants::DW_FORM_data8 |
602 | | constants::DW_FORM_ref8 |
603 | | constants::DW_FORM_ref_sig8 |
604 | | constants::DW_FORM_ref_sup8 => Some(8), |
605 | |
606 | constants::DW_FORM_data16 => Some(16), |
607 | |
608 | constants::DW_FORM_sec_offset |
609 | | constants::DW_FORM_GNU_ref_alt |
610 | | constants::DW_FORM_strp |
611 | | constants::DW_FORM_strp_sup |
612 | | constants::DW_FORM_GNU_strp_alt |
613 | | constants::DW_FORM_line_strp => Some(encoding.format.word_size()), |
614 | |
615 | constants::DW_FORM_ref_addr => { |
616 | // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr |
617 | // has the same size as an address on the target system. This was changed |
618 | // in DWARF version 3. |
619 | Some(if encoding.version == 2 { |
620 | encoding.address_size |
621 | } else { |
622 | encoding.format.word_size() |
623 | }) |
624 | } |
625 | |
626 | // Variably sized forms. |
627 | constants::DW_FORM_block |
628 | | constants::DW_FORM_block1 |
629 | | constants::DW_FORM_block2 |
630 | | constants::DW_FORM_block4 |
631 | | constants::DW_FORM_exprloc |
632 | | constants::DW_FORM_ref_udata |
633 | | constants::DW_FORM_string |
634 | | constants::DW_FORM_sdata |
635 | | constants::DW_FORM_udata |
636 | | constants::DW_FORM_indirect => None, |
637 | |
638 | // We don't know the size of unknown forms. |
639 | _ => None, |
640 | } |
641 | } |
642 | |
643 | #[cfg (test)] |
644 | pub mod tests { |
645 | use super::*; |
646 | use crate::constants; |
647 | use crate::endianity::LittleEndian; |
648 | use crate::read::{EndianSlice, Error}; |
649 | use crate::test_util::GimliSectionMethods; |
650 | #[cfg (target_pointer_width = "32" )] |
651 | use core::u32; |
652 | use test_assembler::Section; |
653 | |
654 | pub trait AbbrevSectionMethods { |
655 | fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self; |
656 | fn abbrev_null(self) -> Self; |
657 | fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self; |
658 | fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self; |
659 | fn abbrev_attr_null(self) -> Self; |
660 | } |
661 | |
662 | impl AbbrevSectionMethods for Section { |
663 | fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self { |
664 | self.uleb(code).uleb(tag.0.into()).D8(children.0) |
665 | } |
666 | |
667 | fn abbrev_null(self) -> Self { |
668 | self.D8(0) |
669 | } |
670 | |
671 | fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self { |
672 | self.uleb(name.0.into()).uleb(form.0.into()) |
673 | } |
674 | |
675 | fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self { |
676 | self.uleb(name.0.into()) |
677 | .uleb(constants::DW_FORM_implicit_const.0.into()) |
678 | .sleb(value) |
679 | } |
680 | |
681 | fn abbrev_attr_null(self) -> Self { |
682 | self.D8(0).D8(0) |
683 | } |
684 | } |
685 | |
686 | #[test ] |
687 | fn test_debug_abbrev_ok() { |
688 | let extra_start = [1, 2, 3, 4]; |
689 | let expected_rest = [5, 6, 7, 8]; |
690 | #[rustfmt::skip] |
691 | let buf = Section::new() |
692 | .append_bytes(&extra_start) |
693 | .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
694 | .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) |
695 | .abbrev_attr_null() |
696 | .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) |
697 | .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) |
698 | .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) |
699 | .abbrev_attr_null() |
700 | .abbrev_null() |
701 | .append_bytes(&expected_rest) |
702 | .get_contents() |
703 | .unwrap(); |
704 | |
705 | let abbrev1 = Abbreviation::new( |
706 | 1, |
707 | constants::DW_TAG_compile_unit, |
708 | constants::DW_CHILDREN_yes, |
709 | vec![ |
710 | AttributeSpecification::new( |
711 | constants::DW_AT_producer, |
712 | constants::DW_FORM_strp, |
713 | None, |
714 | ), |
715 | AttributeSpecification::new( |
716 | constants::DW_AT_language, |
717 | constants::DW_FORM_data2, |
718 | None, |
719 | ), |
720 | ] |
721 | .into(), |
722 | ); |
723 | |
724 | let abbrev2 = Abbreviation::new( |
725 | 2, |
726 | constants::DW_TAG_subprogram, |
727 | constants::DW_CHILDREN_no, |
728 | vec![AttributeSpecification::new( |
729 | constants::DW_AT_name, |
730 | constants::DW_FORM_string, |
731 | None, |
732 | )] |
733 | .into(), |
734 | ); |
735 | |
736 | let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian); |
737 | let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len()); |
738 | let abbrevs = debug_abbrev |
739 | .abbreviations(debug_abbrev_offset) |
740 | .expect("Should parse abbreviations" ); |
741 | assert_eq!(abbrevs.get(1), Some(&abbrev1)); |
742 | assert_eq!(abbrevs.get(2), Some(&abbrev2)); |
743 | } |
744 | |
745 | #[test ] |
746 | fn test_abbreviations_insert() { |
747 | fn abbrev(code: u16) -> Abbreviation { |
748 | Abbreviation::new( |
749 | code.into(), |
750 | constants::DwTag(code), |
751 | constants::DW_CHILDREN_no, |
752 | vec![].into(), |
753 | ) |
754 | } |
755 | |
756 | fn assert_abbrev(abbrevs: &Abbreviations, code: u16) { |
757 | let abbrev = abbrevs.get(code.into()).unwrap(); |
758 | assert_eq!(abbrev.tag(), constants::DwTag(code)); |
759 | } |
760 | |
761 | // Sequential insert. |
762 | let mut abbrevs = Abbreviations::empty(); |
763 | abbrevs.insert(abbrev(1)).unwrap(); |
764 | abbrevs.insert(abbrev(2)).unwrap(); |
765 | assert_eq!(abbrevs.vec.len(), 2); |
766 | assert!(abbrevs.map.is_empty()); |
767 | assert_abbrev(&abbrevs, 1); |
768 | assert_abbrev(&abbrevs, 2); |
769 | |
770 | // Out of order insert. |
771 | let mut abbrevs = Abbreviations::empty(); |
772 | abbrevs.insert(abbrev(2)).unwrap(); |
773 | abbrevs.insert(abbrev(3)).unwrap(); |
774 | assert!(abbrevs.vec.is_empty()); |
775 | assert_abbrev(&abbrevs, 2); |
776 | assert_abbrev(&abbrevs, 3); |
777 | |
778 | // Mixed order insert. |
779 | let mut abbrevs = Abbreviations::empty(); |
780 | abbrevs.insert(abbrev(1)).unwrap(); |
781 | abbrevs.insert(abbrev(3)).unwrap(); |
782 | abbrevs.insert(abbrev(2)).unwrap(); |
783 | assert_eq!(abbrevs.vec.len(), 2); |
784 | assert_abbrev(&abbrevs, 1); |
785 | assert_abbrev(&abbrevs, 2); |
786 | assert_abbrev(&abbrevs, 3); |
787 | |
788 | // Duplicate code in vec. |
789 | let mut abbrevs = Abbreviations::empty(); |
790 | abbrevs.insert(abbrev(1)).unwrap(); |
791 | abbrevs.insert(abbrev(2)).unwrap(); |
792 | assert_eq!(abbrevs.insert(abbrev(1)), Err(())); |
793 | assert_eq!(abbrevs.insert(abbrev(2)), Err(())); |
794 | |
795 | // Duplicate code in map when adding to map. |
796 | let mut abbrevs = Abbreviations::empty(); |
797 | abbrevs.insert(abbrev(2)).unwrap(); |
798 | assert_eq!(abbrevs.insert(abbrev(2)), Err(())); |
799 | |
800 | // Duplicate code in map when adding to vec. |
801 | let mut abbrevs = Abbreviations::empty(); |
802 | abbrevs.insert(abbrev(2)).unwrap(); |
803 | abbrevs.insert(abbrev(1)).unwrap(); |
804 | assert_eq!(abbrevs.insert(abbrev(2)), Err(())); |
805 | |
806 | // 32-bit usize conversions. |
807 | let mut abbrevs = Abbreviations::empty(); |
808 | abbrevs.insert(abbrev(2)).unwrap(); |
809 | } |
810 | |
811 | #[test ] |
812 | #[cfg (target_pointer_width = "32" )] |
813 | fn test_abbreviations_insert_32() { |
814 | fn abbrev(code: u64) -> Abbreviation { |
815 | Abbreviation::new( |
816 | code, |
817 | constants::DwTag(code as u16), |
818 | constants::DW_CHILDREN_no, |
819 | vec![].into(), |
820 | ) |
821 | } |
822 | |
823 | fn assert_abbrev(abbrevs: &Abbreviations, code: u64) { |
824 | let abbrev = abbrevs.get(code).unwrap(); |
825 | assert_eq!(abbrev.tag(), constants::DwTag(code as u16)); |
826 | } |
827 | |
828 | let mut abbrevs = Abbreviations::empty(); |
829 | abbrevs.insert(abbrev(1)).unwrap(); |
830 | |
831 | let wrap_code = (u32::MAX as u64 + 1) + 1; |
832 | // `get` should not treat the wrapped code as `1`. |
833 | assert_eq!(abbrevs.get(wrap_code), None); |
834 | // `insert` should not treat the wrapped code as `1`. |
835 | abbrevs.insert(abbrev(wrap_code)).unwrap(); |
836 | assert_abbrev(&abbrevs, 1); |
837 | assert_abbrev(&abbrevs, wrap_code); |
838 | } |
839 | |
840 | #[test ] |
841 | fn test_parse_abbreviations_ok() { |
842 | let expected_rest = [1, 2, 3, 4]; |
843 | #[rustfmt::skip] |
844 | let buf = Section::new() |
845 | .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
846 | .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) |
847 | .abbrev_attr_null() |
848 | .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) |
849 | .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) |
850 | .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) |
851 | .abbrev_attr_null() |
852 | .abbrev_null() |
853 | .append_bytes(&expected_rest) |
854 | .get_contents() |
855 | .unwrap(); |
856 | let rest = &mut EndianSlice::new(&*buf, LittleEndian); |
857 | |
858 | let abbrev1 = Abbreviation::new( |
859 | 1, |
860 | constants::DW_TAG_compile_unit, |
861 | constants::DW_CHILDREN_yes, |
862 | vec![ |
863 | AttributeSpecification::new( |
864 | constants::DW_AT_producer, |
865 | constants::DW_FORM_strp, |
866 | None, |
867 | ), |
868 | AttributeSpecification::new( |
869 | constants::DW_AT_language, |
870 | constants::DW_FORM_data2, |
871 | None, |
872 | ), |
873 | ] |
874 | .into(), |
875 | ); |
876 | |
877 | let abbrev2 = Abbreviation::new( |
878 | 2, |
879 | constants::DW_TAG_subprogram, |
880 | constants::DW_CHILDREN_no, |
881 | vec![AttributeSpecification::new( |
882 | constants::DW_AT_name, |
883 | constants::DW_FORM_string, |
884 | None, |
885 | )] |
886 | .into(), |
887 | ); |
888 | |
889 | let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations" ); |
890 | assert_eq!(abbrevs.get(1), Some(&abbrev1)); |
891 | assert_eq!(abbrevs.get(2), Some(&abbrev2)); |
892 | assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); |
893 | } |
894 | |
895 | #[test ] |
896 | fn test_parse_abbreviations_duplicate() { |
897 | let expected_rest = [1, 2, 3, 4]; |
898 | #[rustfmt::skip] |
899 | let buf = Section::new() |
900 | .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
901 | .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) |
902 | .abbrev_attr_null() |
903 | .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes) |
904 | .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp) |
905 | .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2) |
906 | .abbrev_attr_null() |
907 | .abbrev_null() |
908 | .append_bytes(&expected_rest) |
909 | .get_contents() |
910 | .unwrap(); |
911 | let buf = &mut EndianSlice::new(&*buf, LittleEndian); |
912 | |
913 | match Abbreviations::parse(buf) { |
914 | Err(Error::DuplicateAbbreviationCode) => {} |
915 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
916 | }; |
917 | } |
918 | |
919 | #[test ] |
920 | fn test_parse_abbreviation_tag_ok() { |
921 | let buf = [0x01, 0x02]; |
922 | let rest = &mut EndianSlice::new(&buf, LittleEndian); |
923 | let tag = Abbreviation::parse_tag(rest).expect("Should parse tag" ); |
924 | assert_eq!(tag, constants::DW_TAG_array_type); |
925 | assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian)); |
926 | } |
927 | |
928 | #[test ] |
929 | fn test_parse_abbreviation_tag_zero() { |
930 | let buf = [0x00]; |
931 | let buf = &mut EndianSlice::new(&buf, LittleEndian); |
932 | match Abbreviation::parse_tag(buf) { |
933 | Err(Error::AbbreviationTagZero) => {} |
934 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
935 | }; |
936 | } |
937 | |
938 | #[test ] |
939 | fn test_parse_abbreviation_has_children() { |
940 | let buf = [0x00, 0x01, 0x02]; |
941 | let rest = &mut EndianSlice::new(&buf, LittleEndian); |
942 | let val = Abbreviation::parse_has_children(rest).expect("Should parse children" ); |
943 | assert_eq!(val, constants::DW_CHILDREN_no); |
944 | let val = Abbreviation::parse_has_children(rest).expect("Should parse children" ); |
945 | assert_eq!(val, constants::DW_CHILDREN_yes); |
946 | match Abbreviation::parse_has_children(rest) { |
947 | Err(Error::BadHasChildren) => {} |
948 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
949 | }; |
950 | } |
951 | |
952 | #[test ] |
953 | fn test_parse_abbreviation_ok() { |
954 | let expected_rest = [0x01, 0x02, 0x03, 0x04]; |
955 | let buf = Section::new() |
956 | .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
957 | .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string) |
958 | .abbrev_attr_null() |
959 | .append_bytes(&expected_rest) |
960 | .get_contents() |
961 | .unwrap(); |
962 | let rest = &mut EndianSlice::new(&*buf, LittleEndian); |
963 | |
964 | let expect = Some(Abbreviation::new( |
965 | 1, |
966 | constants::DW_TAG_subprogram, |
967 | constants::DW_CHILDREN_no, |
968 | vec![AttributeSpecification::new( |
969 | constants::DW_AT_name, |
970 | constants::DW_FORM_string, |
971 | None, |
972 | )] |
973 | .into(), |
974 | )); |
975 | |
976 | let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation" ); |
977 | assert_eq!(abbrev, expect); |
978 | assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); |
979 | } |
980 | |
981 | #[test ] |
982 | fn test_parse_abbreviation_implicit_const_ok() { |
983 | let expected_rest = [0x01, 0x02, 0x03, 0x04]; |
984 | let buf = Section::new() |
985 | .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
986 | .abbrev_attr_implicit_const(constants::DW_AT_name, -42) |
987 | .abbrev_attr_null() |
988 | .append_bytes(&expected_rest) |
989 | .get_contents() |
990 | .unwrap(); |
991 | let rest = &mut EndianSlice::new(&*buf, LittleEndian); |
992 | |
993 | let expect = Some(Abbreviation::new( |
994 | 1, |
995 | constants::DW_TAG_subprogram, |
996 | constants::DW_CHILDREN_no, |
997 | vec![AttributeSpecification::new( |
998 | constants::DW_AT_name, |
999 | constants::DW_FORM_implicit_const, |
1000 | Some(-42), |
1001 | )] |
1002 | .into(), |
1003 | )); |
1004 | |
1005 | let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation" ); |
1006 | assert_eq!(abbrev, expect); |
1007 | assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); |
1008 | } |
1009 | |
1010 | #[test ] |
1011 | fn test_parse_abbreviation_implicit_const_no_const() { |
1012 | let buf = Section::new() |
1013 | .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no) |
1014 | .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const) |
1015 | .get_contents() |
1016 | .unwrap(); |
1017 | let buf = &mut EndianSlice::new(&*buf, LittleEndian); |
1018 | |
1019 | match Abbreviation::parse(buf) { |
1020 | Err(Error::UnexpectedEof(_)) => {} |
1021 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
1022 | } |
1023 | } |
1024 | |
1025 | #[test ] |
1026 | fn test_parse_null_abbreviation_ok() { |
1027 | let expected_rest = [0x01, 0x02, 0x03, 0x04]; |
1028 | let buf = Section::new() |
1029 | .abbrev_null() |
1030 | .append_bytes(&expected_rest) |
1031 | .get_contents() |
1032 | .unwrap(); |
1033 | let rest = &mut EndianSlice::new(&*buf, LittleEndian); |
1034 | |
1035 | let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation" ); |
1036 | assert!(abbrev.is_none()); |
1037 | assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian)); |
1038 | } |
1039 | |
1040 | #[test ] |
1041 | fn test_parse_attribute_form_ok() { |
1042 | let buf = [0x01, 0x02]; |
1043 | let rest = &mut EndianSlice::new(&buf, LittleEndian); |
1044 | let tag = AttributeSpecification::parse_form(rest).expect("Should parse form" ); |
1045 | assert_eq!(tag, constants::DW_FORM_addr); |
1046 | assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian)); |
1047 | } |
1048 | |
1049 | #[test ] |
1050 | fn test_parse_attribute_form_zero() { |
1051 | let buf = [0x00]; |
1052 | let buf = &mut EndianSlice::new(&buf, LittleEndian); |
1053 | match AttributeSpecification::parse_form(buf) { |
1054 | Err(Error::AttributeFormZero) => {} |
1055 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
1056 | }; |
1057 | } |
1058 | |
1059 | #[test ] |
1060 | fn test_parse_null_attribute_specification_ok() { |
1061 | let buf = [0x00, 0x00, 0x01]; |
1062 | let rest = &mut EndianSlice::new(&buf, LittleEndian); |
1063 | let attr = |
1064 | AttributeSpecification::parse(rest).expect("Should parse null attribute specification" ); |
1065 | assert!(attr.is_none()); |
1066 | assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian)); |
1067 | } |
1068 | |
1069 | #[test ] |
1070 | fn test_parse_attribute_specifications_name_zero() { |
1071 | let buf = [0x00, 0x01, 0x00, 0x00]; |
1072 | let buf = &mut EndianSlice::new(&buf, LittleEndian); |
1073 | match AttributeSpecification::parse(buf) { |
1074 | Err(Error::ExpectedZero) => {} |
1075 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
1076 | }; |
1077 | } |
1078 | |
1079 | #[test ] |
1080 | fn test_parse_attribute_specifications_form_zero() { |
1081 | let buf = [0x01, 0x00, 0x00, 0x00]; |
1082 | let buf = &mut EndianSlice::new(&buf, LittleEndian); |
1083 | match AttributeSpecification::parse(buf) { |
1084 | Err(Error::AttributeFormZero) => {} |
1085 | otherwise => panic!("Unexpected result: {:?}" , otherwise), |
1086 | }; |
1087 | } |
1088 | |
1089 | #[test ] |
1090 | fn test_get_abbrev_zero() { |
1091 | let mut abbrevs = Abbreviations::empty(); |
1092 | abbrevs |
1093 | .insert(Abbreviation::new( |
1094 | 1, |
1095 | constants::DwTag(1), |
1096 | constants::DW_CHILDREN_no, |
1097 | vec![].into(), |
1098 | )) |
1099 | .unwrap(); |
1100 | assert!(abbrevs.get(0).is_none()); |
1101 | } |
1102 | } |
1103 | |