1use crate::common::{DebugMacinfoOffset, SectionId};
2use crate::endianity::Endianity;
3use crate::read::{EndianSlice, Reader, ReaderOffset, Section, UnitRef};
4use crate::{
5 DebugLineOffset, DebugMacroOffset, DebugStrOffset, DebugStrOffsetsIndex, DwMacinfo, DwMacro,
6 Error, Format, Result, constants,
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
450impl<R: Reader> Iterator for MacroIter<R> {
451 type Item = Result<MacroEntry<R>>;
452
453 fn next(&mut self) -> Option<Self::Item> {
454 MacroIter::next(self).transpose()
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461 use crate::{DebugStr, LittleEndian, test_util::GimliSectionMethods};
462 use test_assembler::{Endian, Label, LabelMaker, Section};
463
464 #[test]
465 fn test_get_macinfo() {
466 let position = Label::new();
467
468 let section = Section::with_endian(Endian::Little)
470 .set_start_const(0)
471 .mark(&position)
472 .D8(crate::DW_MACINFO_define.0)
473 .uleb(0) .append_bytes(b"__STDC__ 1\0")
475 .D8(crate::DW_MACINFO_define.0)
476 .uleb(1) .append_bytes(b"__GNUC__ 1\0")
478 .D8(crate::DW_MACINFO_undef.0)
479 .uleb(2) .append_bytes(b"__GNUC__\0")
481 .D8(crate::DW_MACINFO_start_file.0)
482 .uleb(3) .uleb(4) .D8(crate::DW_MACINFO_end_file.0) .D8(crate::DW_MACINFO_vendor_ext.0)
486 .uleb(5) .append_bytes(b"foo\0")
488 .D8(0); let section = section.get_contents().unwrap();
492 let debug_macinfo = DebugMacinfo::from(EndianSlice::new(§ion, LittleEndian));
493
494 let offset = position.value().unwrap() as usize;
495
496 let mut iter = debug_macinfo
497 .get_macinfo(DebugMacinfoOffset(offset))
498 .unwrap();
499
500 let entry = iter.next().unwrap().unwrap();
502 assert!(
503 matches!(entry, MacroEntry::Define { line: 0, text: MacroString::Direct(text) } if text.slice() == b"__STDC__ 1")
504 );
505
506 let entry = iter.next().unwrap().unwrap();
507 assert!(
508 matches!(entry, MacroEntry::Define { line: 1, text: MacroString::Direct(text) } if text.slice() == b"__GNUC__ 1")
509 );
510
511 let entry = iter.next().unwrap().unwrap();
512 assert!(
513 matches!(entry, MacroEntry::Undef { line: 2, name: MacroString::Direct(name) } if name.slice() == b"__GNUC__")
514 );
515
516 let entry = iter.next().unwrap().unwrap();
517 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 4 }));
518
519 let entry = iter.next().unwrap().unwrap();
520 assert!(matches!(entry, MacroEntry::EndFile));
521
522 let entry = iter.next().unwrap().unwrap();
523 assert!(
524 matches!(entry, MacroEntry::VendorExt { numeric: 5, string } if string.slice() == b"foo")
525 );
526
527 assert_eq!(iter.next(), Ok(None));
528 }
529
530 #[test]
531 fn get_macros_1() {
532 let position = Label::new();
533
534 let section = Section::with_endian(Endian::Little)
537 .set_start_const(0)
538 .mark(&position)
539 .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();
592 let debug_macro = DebugMacro::from(EndianSlice::new(§ion, LittleEndian));
593
594 let offset = position.value().unwrap() as usize;
595
596 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
597 let entry = iter.next().unwrap().unwrap();
598 assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 }));
599 let entry = iter.next().unwrap().unwrap();
600 assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 }));
601 let entry = iter.next().unwrap().unwrap();
602 assert!(matches!(
603 entry,
604 MacroEntry::Define {
605 line: 1, text: MacroString::Direct(text)
606 } if text.slice() == b"LONGER_MACRO 1"
607 ));
608 let entry = iter.next().unwrap().unwrap();
609 assert!(matches!(
610 entry,
611 MacroEntry::Define {
612 line: 2, text: MacroString::Direct(text)
613 } if text.slice() == b"B 2"
614 ));
615 let entry = iter.next().unwrap().unwrap();
616 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
617 let entry = iter.next().unwrap().unwrap();
618 assert!(matches!(
619 entry,
620 MacroEntry::Undef {
621 line: 1, name: MacroString::Direct(name)
622 } if name.slice() == b"B"
623 ));
624 let entry = iter.next().unwrap().unwrap();
625 assert!(matches!(
626 entry,
627 MacroEntry::Define {
628 line: 2, text: MacroString::Direct(text)
629 } if text.slice() == b"D 3"
630 ));
631 let entry = iter.next().unwrap().unwrap();
632 assert!(matches!(
633 entry,
634 MacroEntry::Define {
635 line: 3, text: MacroString::Direct(text)
636 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
637 ));
638 let entry = iter.next().unwrap().unwrap();
639 assert!(matches!(entry, MacroEntry::EndFile));
640 let entry = iter.next().unwrap().unwrap();
641 assert!(matches!(
642 entry,
643 MacroEntry::Define {
644 line: 4, text: MacroString::Direct(text)
645 } if text.slice() == b"B 3"
646 ));
647 let entry = iter.next().unwrap().unwrap();
648 assert!(matches!(entry, MacroEntry::EndFile));
649 let entry = iter.next().unwrap().unwrap();
650 assert!(matches!(
651 entry,
652 MacroEntry::Define {
653 line: 2, text: MacroString::Direct(text)
654 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
655 ));
656 let entry = iter.next().unwrap().unwrap();
657 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
658 let entry = iter.next().unwrap().unwrap();
659 assert!(matches!(
660 entry,
661 MacroEntry::Undef {
662 line: 1, name: MacroString::Direct(name)
663 } if name.slice() == b"B"
664 ));
665 let entry = iter.next().unwrap().unwrap();
666 assert!(matches!(
667 entry,
668 MacroEntry::Define {
669 line: 2, text: MacroString::Direct(text)
670 } if text.slice() == b"D 3"
671 ));
672 let entry = iter.next().unwrap().unwrap();
673 assert!(matches!(
674 entry,
675 MacroEntry::Define {
676 line: 3, text: MacroString::Direct(text)
677 } if text.slice() == b"FUNCTION_LIKE_MACRO(x) 4+x"
678 ));
679 let entry = iter.next().unwrap().unwrap();
680 assert!(matches!(entry, MacroEntry::EndFile));
681 let entry = iter.next().unwrap().unwrap();
682 assert!(matches!(entry, MacroEntry::EndFile));
683 assert_eq!(iter.next(), Ok(None));
684 }
685
686 #[test]
687 fn get_macros_2() {
688 let str_0 = Label::new();
689 let str_1 = Label::new();
690 let macro_unit_0 = Label::new();
691 let macro_unit_1 = Label::new();
692 let macro_unit_2 = Label::new();
693
694 let str_section = Section::with_endian(Endian::Little)
697 .set_start_const(0)
698 .mark(&str_0)
699 .append_bytes(b"FUNCTION_LIKE_MACRO(x) 4+x\0") .mark(&str_1)
701 .append_bytes(b"LONGER_MACRO 1\0"); let macro_section = Section::with_endian(Endian::Little)
704 .set_start_const(0)
705 .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)
739 .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();
767 let debug_str = DebugStr::from(EndianSlice::new(&str_section, LittleEndian));
768
769 let macro_section = macro_section.get_contents().unwrap();
771 let debug_macro = DebugMacro::from(EndianSlice::new(¯o_section, LittleEndian));
772
773 let offset = macro_unit_0.value().unwrap() as usize;
775 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
776 let entry = iter.next().unwrap().unwrap();
777 assert!(matches!(entry, MacroEntry::StartFile { line: 0, file: 0 }));
778 let entry = iter.next().unwrap().unwrap();
779 assert!(matches!(entry, MacroEntry::StartFile { line: 1, file: 1 }));
780 let entry = iter.next().unwrap().unwrap();
781 assert!(matches!(
782 entry,
783 MacroEntry::Import { offset } if offset.0 == macro_unit_1.value().unwrap() as usize
784 ));
785 let entry = iter.next().unwrap().unwrap();
786 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
787 let entry = iter.next().unwrap().unwrap();
788 assert!(matches!(
789 entry,
790 MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize
791 ));
792 let entry = iter.next().unwrap().unwrap();
793 assert!(matches!(entry, MacroEntry::EndFile));
794 let entry = iter.next().unwrap().unwrap();
795 assert!(matches!(
796 entry,
797 MacroEntry::Define {
798 line: 4, text: MacroString::Direct(text)
799 } if text.slice() == b"B 3"
800 ));
801 let entry = iter.next().unwrap().unwrap();
802 assert!(matches!(entry, MacroEntry::EndFile));
803 let entry = iter.next().unwrap().unwrap();
804 assert!(matches!(
805 entry,
806 MacroEntry::Define {
807 line: 2, text: MacroString::StringPointer(text_offset)
808 } if text_offset.0 == str_0.value().unwrap() as usize
809 ));
810 let entry = iter.next().unwrap().unwrap();
811 assert!(matches!(entry, MacroEntry::StartFile { line: 3, file: 2 }));
812 let entry = iter.next().unwrap().unwrap();
813 assert!(matches!(
814 entry,
815 MacroEntry::Import { offset } if offset.0 == macro_unit_2.value().unwrap() as usize
816 ));
817 let entry = iter.next().unwrap().unwrap();
818 assert!(matches!(entry, MacroEntry::EndFile));
819 let entry = iter.next().unwrap().unwrap();
820 assert!(matches!(entry, MacroEntry::EndFile));
821 assert_eq!(iter.next(), Ok(None));
822
823 let offset = macro_unit_1.value().unwrap() as usize;
825 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
826 let entry = iter.next().unwrap().unwrap();
827 assert!(matches!(
828 entry,
829 MacroEntry::Define {
830 line: 1, text: MacroString::StringPointer(text_offset)
831 } if text_offset.0 == str_0.value().unwrap() as usize
832 ));
833 let entry = iter.next().unwrap().unwrap();
834 assert!(matches!(
835 entry,
836 MacroEntry::Define {
837 line: 2, text: MacroString::Direct(text)
838 } if text.slice() == b"B 2"
839 ));
840 assert_eq!(iter.next(), Ok(None));
841
842 let offset = macro_unit_2.value().unwrap() as usize;
844 let mut iter = debug_macro.get_macros(DebugMacroOffset(offset)).unwrap();
845 let entry = iter.next().unwrap().unwrap();
846 assert!(matches!(
847 entry,
848 MacroEntry::Undef {
849 line: 1, name: MacroString::Direct(name)
850 } if name.slice() == b"B"
851 ));
852 let entry = iter.next().unwrap().unwrap();
853 assert!(matches!(
854 entry,
855 MacroEntry::Define {
856 line: 2, text: MacroString::Direct(text)
857 } if text.slice() == b"D 3"
858 ));
859 let entry = iter.next().unwrap().unwrap();
860 assert!(matches!(
861 entry,
862 MacroEntry::Define {
863 line: 2, text: MacroString::StringPointer(text_offset)
864 } if text_offset.0 == str_1.value().unwrap() as usize
865 ));
866 assert_eq!(iter.next(), Ok(None));
867
868 let text_offset = DebugStrOffset(str_0.value().unwrap() as usize);
870 assert_eq!(
871 debug_str.get_str(text_offset).unwrap().slice(),
872 b"FUNCTION_LIKE_MACRO(x) 4+x"
873 );
874 let text_offset = DebugStrOffset(str_1.value().unwrap() as usize);
875 assert_eq!(
876 debug_str.get_str(text_offset).unwrap().slice(),
877 b"LONGER_MACRO 1"
878 );
879 }
880}