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