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