1use crate::common::{DebugMacinfoOffset, SectionId};
2use crate::endianity::Endianity;
3use crate::read::{EndianSlice, Reader, ReaderOffset, Section, UnitRef};
4use crate::{
5 constants, DebugLineOffset, DebugMacroOffset, DebugStrOffset, DebugStrOffsetsIndex, DwMacinfo,
6 DwMacro, Error, Format, Result,
7};
8
9#[derive(Debug, Default, Clone, Copy)]
11pub struct DebugMacinfo<R> {
12 pub(crate) section: R,
13}
14
15impl<'input, Endian> DebugMacinfo<EndianSlice<'input, Endian>>
16where
17 Endian: Endianity,
18{
19 pub fn new(macinfo_section: &'input [u8], endian: Endian) -> Self {
34 Self::from(EndianSlice::new(macinfo_section, endian))
35 }
36}
37
38impl<R: Reader> DebugMacinfo<R> {
39 pub fn get_macinfo(&self, offset: DebugMacinfoOffset<R::Offset>) -> Result<MacroIter<R>> {
60 let mut input = self.section.clone();
61 input.skip(offset.0)?;
62 Ok(MacroIter {
63 input,
64 format: Format::Dwarf32,
65 is_macro: false,
66 })
67 }
68}
69
70impl<T> DebugMacinfo<T> {
71 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugMacinfo<R>
77 where
78 F: FnMut(&'a T) -> R,
79 {
80 borrow(&self.section).into()
81 }
82}
83
84impl<R> Section<R> for DebugMacinfo<R> {
85 fn id() -> SectionId {
86 SectionId::DebugMacinfo
87 }
88
89 fn reader(&self) -> &R {
90 &self.section
91 }
92}
93
94impl<R> From<R> for DebugMacinfo<R> {
95 fn from(macinfo_section: R) -> Self {
96 DebugMacinfo {
97 section: macinfo_section,
98 }
99 }
100}
101
102#[derive(Debug, Default, Clone, Copy)]
104pub struct DebugMacro<R> {
105 pub(crate) section: R,
106}
107
108impl<'input, Endian> DebugMacro<EndianSlice<'input, Endian>>
109where
110 Endian: Endianity,
111{
112 pub fn new(macro_section: &'input [u8], endian: Endian) -> Self {
127 Self::from(EndianSlice::new(macro_section, endian))
128 }
129}
130
131impl<R: Reader> DebugMacro<R> {
132 pub fn get_macros(&self, offset: DebugMacroOffset<R::Offset>) -> Result<MacroIter<R>> {
153 let mut input = self.section.clone();
154 input.skip(offset.0)?;
155 let header = MacroUnitHeader::parse(&mut input)?;
156 Ok(MacroIter {
157 input,
158 format: header.format(),
159 is_macro: true,
160 })
161 }
162}
163
164impl<T> DebugMacro<T> {
165 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugMacro<R>
171 where
172 F: FnMut(&'a T) -> R,
173 {
174 borrow(&self.section).into()
175 }
176}
177
178impl<R> Section<R> for DebugMacro<R> {
179 fn id() -> SectionId {
180 SectionId::DebugMacro
181 }
182
183 fn reader(&self) -> &R {
184 &self.section
185 }
186}
187
188impl<R> From<R> for DebugMacro<R> {
189 fn from(macro_section: R) -> Self {
190 DebugMacro {
191 section: macro_section,
192 }
193 }
194}
195
196#[derive(Debug, Clone)]
197struct MacroUnitHeader<R: Reader> {
198 _version: u16,
200 flags: u8,
201 _debug_line_offset: DebugLineOffset<R::Offset>,
202}
203
204impl<R: Reader> MacroUnitHeader<R> {
205 const OFFSET_SIZE_FLAG: u8 = 0b0000_0001;
206 const DEBUG_LINE_OFFSET_FLAG: u8 = 0b0000_0010;
207 const OPCODE_OPERANDS_TABLE_FLAG: u8 = 0b0000_0100;
208
209 fn parse(input: &mut R) -> Result<Self> {
210 let version = input.read_u16()?;
211 let flags = input.read_u8()?;
212 let format = if flags & Self::OFFSET_SIZE_FLAG == 0 {
213 Format::Dwarf32
214 } else {
215 Format::Dwarf64
216 };
217 let _debug_line_offset = if flags & Self::DEBUG_LINE_OFFSET_FLAG != 0 {
218 DebugLineOffset(input.read_offset(format)?)
219 } else {
220 DebugLineOffset(R::Offset::from_u64(0)?)
221 };
222 if flags & Self::OPCODE_OPERANDS_TABLE_FLAG != 0 {
224 return Err(Error::UnsupportedOpcodeOperandsTable);
225 }
226 Ok(MacroUnitHeader {
227 _version: version,
228 flags,
229 _debug_line_offset,
230 })
231 }
232
233 fn format(&self) -> Format {
234 if self.flags & Self::OFFSET_SIZE_FLAG == 0 {
235 Format::Dwarf32
236 } else {
237 Format::Dwarf64
238 }
239 }
240}
241
242#[derive(Debug, Clone, PartialEq, Eq)]
244pub enum MacroString<R, Offset = <R as Reader>::Offset>
245where
246 R: Reader<Offset = Offset>,
247 Offset: ReaderOffset,
248{
249 Direct(R),
251 StringPointer(DebugStrOffset<Offset>),
253 IndirectStringPointer(DebugStrOffsetsIndex<Offset>),
256 Supplementary(DebugStrOffset<Offset>),
258}
259
260impl<R: Reader> MacroString<R> {
261 pub fn string(&self, unit: UnitRef<'_, R>) -> Result<R> {
263 match self {
264 MacroString::Direct(s) => Ok(s.clone()),
265 MacroString::StringPointer(offset) => unit.string(*offset),
266 MacroString::IndirectStringPointer(index) => {
267 let str_offset = unit.string_offset(*index)?;
268 unit.string(str_offset)
269 }
270 MacroString::Supplementary(offset) => unit.sup_string(*offset),
271 }
272 }
273}
274
275#[derive(Debug, Clone, PartialEq, Eq)]
277pub enum MacroEntry<R, Offset = <R as Reader>::Offset>
278where
279 R: Reader<Offset = Offset>,
280 Offset: ReaderOffset,
281{
282 Define {
284 line: u64,
286 text: MacroString<R>,
289 },
290 Undef {
292 line: u64,
294 name: MacroString<R>,
296 },
297 StartFile {
299 line: u64,
301 file: u64,
303 },
304 EndFile,
306 Import {
308 offset: DebugMacroOffset<Offset>,
310 },
311 ImportSup {
313 offset: DebugMacroOffset<Offset>,
315 },
316 VendorExt {
318 numeric: u64,
320 string: R,
322 },
323}
324
325#[derive(Clone, Debug)]
327pub struct MacroIter<R: Reader> {
328 input: R,
329 format: Format,
330 is_macro: bool,
331}
332
333impl<R: Reader> MacroIter<R> {
334 pub fn next(&mut self) -> Result<Option<MacroEntry<R>>> {
336 let macro_type = DwMacro(self.input.read_u8()?);
338 match macro_type {
339 DwMacro(0) => {
340 self.input.empty();
341 Ok(None)
342 }
343 constants::DW_MACRO_define => {
344 let line = self.input.read_uleb128()?;
345 let text = self.input.read_null_terminated_slice()?;
346 Ok(Some(MacroEntry::Define {
347 line,
348 text: MacroString::Direct(text),
349 }))
350 }
351 constants::DW_MACRO_undef => {
352 let line = self.input.read_uleb128()?;
353 let name = self.input.read_null_terminated_slice()?;
354 Ok(Some(MacroEntry::Undef {
355 line,
356 name: MacroString::Direct(name),
357 }))
358 }
359 constants::DW_MACRO_start_file => {
360 let line = self.input.read_uleb128()?;
361 let file = self.input.read_uleb128()?;
362 Ok(Some(MacroEntry::StartFile { line, file }))
363 }
364 constants::DW_MACRO_end_file => Ok(Some(MacroEntry::EndFile)),
365 constants::DW_MACRO_define_strp if self.is_macro => {
366 let line = self.input.read_uleb128()?;
367 let text_offset = DebugStrOffset(self.input.read_offset(self.format)?);
368 Ok(Some(MacroEntry::Define {
369 line,
370 text: MacroString::StringPointer(text_offset),
371 }))
372 }
373 constants::DW_MACRO_undef_strp if self.is_macro => {
374 let line = self.input.read_uleb128()?;
375 let name_offset = DebugStrOffset(self.input.read_offset(self.format)?);
376 Ok(Some(MacroEntry::Undef {
377 line,
378 name: MacroString::StringPointer(name_offset),
379 }))
380 }
381 constants::DW_MACRO_import if self.is_macro => {
382 let offset = DebugMacroOffset(self.input.read_offset(self.format)?);
383 Ok(Some(MacroEntry::Import { offset }))
384 }
385 constants::DW_MACRO_define_sup if self.is_macro => {
386 let line = self.input.read_uleb128()?;
387 let text_offset = DebugStrOffset(self.input.read_offset(self.format)?);
388 Ok(Some(MacroEntry::Define {
389 line,
390 text: MacroString::Supplementary(text_offset),
391 }))
392 }
393 constants::DW_MACRO_undef_sup if self.is_macro => {
394 let line = self.input.read_uleb128()?;
395 let name_offset = DebugStrOffset(self.input.read_offset(self.format)?);
396 Ok(Some(MacroEntry::Undef {
397 line,
398 name: MacroString::Supplementary(name_offset),
399 }))
400 }
401 constants::DW_MACRO_import_sup if self.is_macro => {
402 let offset = DebugMacroOffset(self.input.read_offset(self.format)?);
403 Ok(Some(MacroEntry::ImportSup { offset }))
404 }
405 constants::DW_MACRO_define_strx if self.is_macro => {
406 let line = self.input.read_uleb128()?;
407 let index = self.input.read_uleb128().and_then(R::Offset::from_u64)?;
408 let text_index = DebugStrOffsetsIndex(index);
409 Ok(Some(MacroEntry::Define {
410 line,
411 text: MacroString::IndirectStringPointer(text_index),
412 }))
413 }
414 constants::DW_MACRO_undef_strx if self.is_macro => {
415 let line = self.input.read_uleb128()?;
416 let index = self.input.read_uleb128().and_then(R::Offset::from_u64)?;
417 let name_index = DebugStrOffsetsIndex(index);
418 Ok(Some(MacroEntry::Undef {
419 line,
420 name: MacroString::IndirectStringPointer(name_index),
421 }))
422 }
423 _ => {
424 if self.is_macro {
425 self.input.empty();
426 Err(Error::InvalidMacroType(macro_type))
427 } else if macro_type.0 == constants::DW_MACINFO_vendor_ext.0 {
428 let numeric = self.input.read_uleb128()?;
429 let string = self.input.read_null_terminated_slice()?;
430 Ok(Some(MacroEntry::VendorExt { numeric, string }))
431 } else {
432 self.input.empty();
433 Err(Error::InvalidMacinfoType(DwMacinfo(macro_type.0)))
434 }
435 }
436 }
437 }
438}
439
440#[cfg(feature = "fallible-iterator")]
441impl<R: Reader> fallible_iterator::FallibleIterator for MacroIter<R> {
442 type Item = MacroEntry<R>;
443 type Error = Error;
444
445 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Error> {
446 MacroIter::next(self)
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453 use crate::{test_util::GimliSectionMethods, DebugStr, LittleEndian};
454 use test_assembler::{Endian, Label, LabelMaker, Section};
455
456 #[test]
457 fn test_get_macinfo() {
458 let position = Label::new();
459
460 let section = Section::with_endian(Endian::Little)
462 .set_start_const(0)
463 .mark(&position)
464 .D8(crate::DW_MACINFO_define.0)
465 .uleb(0) .append_bytes(b"__STDC__ 1\0")
467 .D8(crate::DW_MACINFO_define.0)
468 .uleb(1) .append_bytes(b"__GNUC__ 1\0")
470 .D8(crate::DW_MACINFO_undef.0)
471 .uleb(2) .append_bytes(b"__GNUC__\0")
473 .D8(crate::DW_MACINFO_start_file.0)
474 .uleb(3) .uleb(4) .D8(crate::DW_MACINFO_end_file.0) .D8(crate::DW_MACINFO_vendor_ext.0)
478 .uleb(5) .append_bytes(b"foo\0")
480 .D8(0); let section = section.get_contents().unwrap();
484 let debug_macinfo = DebugMacinfo::from(EndianSlice::new(§ion, LittleEndian));
485
486 let offset = position.value().unwrap() as usize;
487
488 let mut iter = debug_macinfo
489 .get_macinfo(DebugMacinfoOffset(offset))
490 .unwrap();
491
492 let entry = iter.next().unwrap().unwrap();
494 assert!(
495 matches!(entry, MacroEntry::Define { line: 0, text: MacroString::Direct(text) } if text.slice() == b"__STDC__ 1")
496 );
497
498 let entry = iter.next().unwrap().unwrap();
499 assert!(
500 matches!(entry, MacroEntry::Define { line: 1, text: MacroString::Direct(text) } if text.slice() == b"__GNUC__ 1")
501 );
502
503 let entry = iter.next().unwrap().unwrap();
504 assert!(
505 matches!(entry, MacroEntry::Undef { line: 2, name: MacroString::Direct(name) } if name.slice() == b"__GNUC__")
506 );
507
508 let entry = iter.next().unwrap().unwrap();
509 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 4 }));
510
511 let entry = iter.next().unwrap().unwrap();
512 assert!(matches!(entry, MacroEntry::EndFile));
513
514 let entry = iter.next().unwrap().unwrap();
515 assert!(
516 matches!(entry, MacroEntry::VendorExt { numeric: 5, string } if string.slice() == b"foo")
517 );
518
519 assert_eq!(iter.next(), Ok(None));
520 }
521
522 #[test]
523 fn get_macros_1() {
524 let position = Label::new();
525
526 let section = Section::with_endian(Endian::Little)
529 .set_start_const(0)
530 .mark(&position)
531 .D16(5) .D8(0b0000_0010) .D32(0) .D8(crate::DW_MACRO_start_file.0) .uleb(0) .uleb(0) .D8(crate::DW_MACRO_start_file.0) .uleb(1) .uleb(1) .D8(crate::DW_MACRO_define.0) .uleb(1) .append_bytes(b"LONGER_MACRO 1\0") .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"B 2\0") .D8(crate::DW_MACRO_start_file.0) .uleb(3) .uleb(2) .D8(crate::DW_MACRO_undef.0) .uleb(1) .append_bytes(b"B\0") .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"D 3\0") .D8(crate::DW_MACRO_define.0) .uleb(3) .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_define.0) .uleb(4) .append_bytes(b"B 3\0") .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") .D8(crate::DW_MACRO_start_file.0) .uleb(3) .uleb(2) .D8(crate::DW_MACRO_undef.0) .uleb(1) .append_bytes(b"B\0") .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"D 3\0") .D8(crate::DW_MACRO_define.0) .uleb(3) .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_end_file.0) .D8(0); let section = section.get_contents().unwrap();
584 let debug_macro = DebugMacro::from(EndianSlice::new(§ion, LittleEndian));
585
586 let offset = position.value().unwrap() as usize;
587
588 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
589 let entry = iter.next().unwrap().unwrap();
590 assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 }));
591 let entry = iter.next().unwrap().unwrap();
592 assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 }));
593 let entry = iter.next().unwrap().unwrap();
594 assert!(matches!(
595 entry,
596 MacroEntry::Define {
597 line: 1, text: MacroString::Direct(text)
598 } if text.slice() == b"LONGER_MACRO 1"
599 ));
600 let entry = iter.next().unwrap().unwrap();
601 assert!(matches!(
602 entry,
603 MacroEntry::Define {
604 line: 2, text: MacroString::Direct(text)
605 } if text.slice() == b"B 2"
606 ));
607 let entry = iter.next().unwrap().unwrap();
608 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
609 let entry = iter.next().unwrap().unwrap();
610 assert!(matches!(
611 entry,
612 MacroEntry::Undef {
613 line: 1, name: MacroString::Direct(name)
614 } if name.slice() == b"B"
615 ));
616 let entry = iter.next().unwrap().unwrap();
617 assert!(matches!(
618 entry,
619 MacroEntry::Define {
620 line: 2, text: MacroString::Direct(text)
621 } if text.slice() == b"D 3"
622 ));
623 let entry = iter.next().unwrap().unwrap();
624 assert!(matches!(
625 entry,
626 MacroEntry::Define {
627 line: 3, text: MacroString::Direct(text)
628 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
629 ));
630 let entry = iter.next().unwrap().unwrap();
631 assert!(matches!(entry, MacroEntry::EndFile));
632 let entry = iter.next().unwrap().unwrap();
633 assert!(matches!(
634 entry,
635 MacroEntry::Define {
636 line: 4, text: MacroString::Direct(text)
637 } if text.slice() == b"B 3"
638 ));
639 let entry = iter.next().unwrap().unwrap();
640 assert!(matches!(entry, MacroEntry::EndFile));
641 let entry = iter.next().unwrap().unwrap();
642 assert!(matches!(
643 entry,
644 MacroEntry::Define {
645 line: 2, text: MacroString::Direct(text)
646 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
647 ));
648 let entry = iter.next().unwrap().unwrap();
649 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
650 let entry = iter.next().unwrap().unwrap();
651 assert!(matches!(
652 entry,
653 MacroEntry::Undef {
654 line: 1, name: MacroString::Direct(name)
655 } if name.slice() == b"B"
656 ));
657 let entry = iter.next().unwrap().unwrap();
658 assert!(matches!(
659 entry,
660 MacroEntry::Define {
661 line: 2, text: MacroString::Direct(text)
662 } if text.slice() == b"D 3"
663 ));
664 let entry = iter.next().unwrap().unwrap();
665 assert!(matches!(
666 entry,
667 MacroEntry::Define {
668 line: 3, text: MacroString::Direct(text)
669 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
670 ));
671 let entry = iter.next().unwrap().unwrap();
672 assert!(matches!(entry, MacroEntry::EndFile));
673 let entry = iter.next().unwrap().unwrap();
674 assert!(matches!(entry, MacroEntry::EndFile));
675 assert_eq!(iter.next(), Ok(None));
676 }
677
678 #[test]
679 fn get_macros_2() {
680 let str_0 = Label::new();
681 let str_1 = Label::new();
682 let macro_unit_0 = Label::new();
683 let macro_unit_1 = Label::new();
684 let macro_unit_2 = Label::new();
685
686 let str_section = Section::with_endian(Endian::Little)
689 .set_start_const(0)
690 .mark(&str_0)
691 .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") .mark(&str_1)
693 .append_bytes(b"LONGER_MACRO 1\0"); let macro_section = Section::with_endian(Endian::Little)
696 .set_start_const(0)
697 .mark(¯o_unit_0) .D16(5) .D8(0b0000_0010) .D32(0) .D8(crate::DW_MACRO_start_file.0) .uleb(0) .uleb(0) .D8(crate::DW_MACRO_start_file.0) .uleb(1) .uleb(1) .D8(crate::DW_MACRO_import.0) .L32(macro_unit_1.clone()) .D8(crate::DW_MACRO_start_file.0) .uleb(3) .uleb(2) .D8(crate::DW_MACRO_import.0) .L32(macro_unit_2.clone()) .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_define.0) .uleb(4) .append_bytes(b"B 3\0") .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_define_strp.0) .uleb(2) .D32(0) .D8(crate::DW_MACRO_start_file.0) .uleb(3) .uleb(2) .D8(crate::DW_MACRO_import.0) .L32(¯o_unit_2) .D8(crate::DW_MACRO_end_file.0) .D8(crate::DW_MACRO_end_file.0) .D8(0)
731 .mark(¯o_unit_1) .D16(5) .D8(0b0000_0000) .D8(crate::DW_MACRO_define_strp.0) .uleb(1) .L32(str_0.clone()) .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"B 2\0") .D8(0) .mark(¯o_unit_2) .D16(5) .D8(0b0000_0000) .D8(crate::DW_MACRO_undef.0) .uleb(1) .append_bytes(b"B\0") .D8(crate::DW_MACRO_define.0) .uleb(2) .append_bytes(b"D 3\0") .D8(crate::DW_MACRO_define_strp.0) .uleb(2) .L32(str_1.clone()) .D8(0); let str_section = str_section.get_contents().unwrap();
759 let debug_str = DebugStr::from(EndianSlice::new(&str_section, LittleEndian));
760
761 let macro_section = macro_section.get_contents().unwrap();
763 let debug_macro = DebugMacro::from(EndianSlice::new(¯o_section, LittleEndian));
764
765 let offset = macro_unit_0.value().unwrap() as usize;
767 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
768 let entry = iter.next().unwrap().unwrap();
769 assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 }));
770 let entry = iter.next().unwrap().unwrap();
771 assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 }));
772 let entry = iter.next().unwrap().unwrap();
773 assert!(matches!(
774 entry,
775 MacroEntry::Import { offset } if offset.0 == macro_unit_1.value().unwrap() as usize
776 ));
777 let entry = iter.next().unwrap().unwrap();
778 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
779 let entry = iter.next().unwrap().unwrap();
780 assert!(matches!(
781 entry,
782 MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize
783 ));
784 let entry = iter.next().unwrap().unwrap();
785 assert!(matches!(entry, MacroEntry::EndFile));
786 let entry = iter.next().unwrap().unwrap();
787 assert!(matches!(
788 entry,
789 MacroEntry::Define {
790 line: 4, text: MacroString::Direct(text)
791 } if text.slice() == b"B 3"
792 ));
793 let entry = iter.next().unwrap().unwrap();
794 assert!(matches!(entry, MacroEntry::EndFile));
795 let entry = iter.next().unwrap().unwrap();
796 assert!(matches!(
797 entry,
798 MacroEntry::Define {
799 line: 2, text: MacroString::StringPointer(text_offset)
800 } if text_offset.0 == str_0.value().unwrap() as usize
801 ));
802 let entry = iter.next().unwrap().unwrap();
803 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
804 let entry = iter.next().unwrap().unwrap();
805 assert!(matches!(
806 entry,
807 MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize
808 ));
809 let entry = iter.next().unwrap().unwrap();
810 assert!(matches!(entry, MacroEntry::EndFile));
811 let entry = iter.next().unwrap().unwrap();
812 assert!(matches!(entry, MacroEntry::EndFile));
813 assert_eq!(iter.next(), Ok(None));
814
815 let offset = macro_unit_1.value().unwrap() as usize;
817 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
818 let entry = iter.next().unwrap().unwrap();
819 assert!(matches!(
820 entry,
821 MacroEntry::Define {
822 line: 1, text: MacroString::StringPointer(text_offset)
823 } if text_offset.0 == str_0.value().unwrap() as usize
824 ));
825 let entry = iter.next().unwrap().unwrap();
826 assert!(matches!(
827 entry,
828 MacroEntry::Define {
829 line: 2, text: MacroString::Direct(text)
830 } if text.slice() == b"B 2"
831 ));
832 assert_eq!(iter.next(), Ok(None));
833
834 let offset = macro_unit_2.value().unwrap() as usize;
836 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
837 let entry = iter.next().unwrap().unwrap();
838 assert!(matches!(
839 entry,
840 MacroEntry::Undef {
841 line: 1, name: MacroString::Direct(name)
842 } if name.slice() == b"B"
843 ));
844 let entry = iter.next().unwrap().unwrap();
845 assert!(matches!(
846 entry,
847 MacroEntry::Define {
848 line: 2, text: MacroString::Direct(text)
849 } if text.slice() == b"D 3"
850 ));
851 let entry = iter.next().unwrap().unwrap();
852 assert!(matches!(
853 entry,
854 MacroEntry::Define {
855 line: 2, text: MacroString::StringPointer(text_offset)
856 } if text_offset.0 == str_1.value().unwrap() as usize
857 ));
858 assert_eq!(iter.next(), Ok(None));
859
860 let text_offset = DebugStrOffset(str_0.value().unwrap() as usize);
862 assert_eq!(
863 debug_str.get_str(text_offset).unwrap().slice(),
864 b"FUNCTION_LIKE_MACRO(x) 4+x"
865 );
866 let text_offset = DebugStrOffset(str_1.value().unwrap() as usize);
867 assert_eq!(
868 debug_str.get_str(text_offset).unwrap().slice(),
869 b"LONGER_MACRO 1"
870 );
871 }
872}