1pub mod builder;
9mod iter;
10mod kind;
11mod offset_segment;
12
13#[doc(inline)]
14pub use self::{iter::*, kind::SymKind, offset_segment::*};
15
16use crate::parser::{Number, Parse, Parser, ParserError, ParserMut};
17use crate::types::{ItemId, ItemIdLe, TypeIndex, TypeIndexLe};
18use bitflags::bitflags;
19use bstr::BStr;
20use std::fmt::Debug;
21use std::mem::size_of;
22use zerocopy::{FromBytes, I32, Immutable, IntoBytes, KnownLayout, LE, U16, U32, Unaligned};
23
24#[derive(IntoBytes, FromBytes, Unaligned, Immutable, KnownLayout, Default, Clone, Debug)]
26#[repr(C)]
27#[allow(missing_docs)]
28pub struct BlockHeader {
29 pub p_parent: U32<LE>,
35
36 pub p_end: U32<LE>,
38}
39
40#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned, Debug)]
45#[repr(C)]
46#[allow(missing_docs)]
47pub struct ProcFixed {
48 pub p_parent: U32<LE>,
50
51 pub p_end: U32<LE>,
54
55 pub p_next: U32<LE>,
56
57 pub proc_len: U32<LE>,
59
60 pub debug_start: U32<LE>,
63
64 pub debug_end: U32<LE>,
68
69 pub proc_type: TypeIndexLe,
78
79 pub offset_segment: OffsetSegment,
80 pub flags: u8,
81}
82
83bitflags! {
84 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
88 pub struct ProcFlags: u8 {
89 const NOFPO = 1 << 0;
91
92 const INT = 1 << 1;
94
95 const FAR = 1 << 2;
97
98 const NEVER = 1 << 3;
100
101 const NOTREACHED = 1 << 4;
103
104 const CUST_CALL = 1 << 5;
106
107 const NOINLINE = 1 << 6;
109
110 const OPTDBGINFO = 1 << 7;
112 }
113}
114
115#[allow(missing_docs)]
127#[derive(Clone, Debug)]
128pub struct Proc<'a> {
129 pub fixed: &'a ProcFixed,
130 pub name: &'a BStr,
131}
132
133impl<'a> Proc<'a> {
134 pub fn flags(&self) -> ProcFlags {
136 ProcFlags::from_bits_retain(self.fixed.flags)
137 }
138}
139
140impl<'a> Parse<'a> for Proc<'a> {
141 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
142 Ok(Self {
143 fixed: p.get()?,
144 name: p.strz()?,
145 })
146 }
147}
148
149#[test]
151fn test_parse_proc() {
152 #[rustfmt::skip]
153 let data = &[
154 0x2e, 0, 0x10, 0x11, 0, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0xee, 0x10, 0, 0, 0xcc, 0x1, 0, 0, 1, 0, 0x50, b'm', b'e', b'm', b's', b'e', b't', 0, 0xf1, 0xf2, 2, 0, 6, 0 ];
169
170 let mut i = SymIter::new(data);
171
172 let s0 = i.next().unwrap();
173 assert_eq!(s0.kind, SymKind::S_GPROC32);
174 assert_eq!(s0.data.len(), 0x2c);
175
176 match s0.parse().unwrap() {
177 SymData::Proc(proc) => {
178 assert_eq!(proc.fixed.p_parent.get(), 0);
179 assert_eq!(proc.fixed.p_end.get(), 0x40);
180 assert_eq!(proc.name, "memset");
181 }
182 _ => panic!(),
183 }
184
185 let s1 = i.next().unwrap();
186 assert_eq!(s1.kind, SymKind::S_END);
187 assert!(s1.data.is_empty());
188}
189
190#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned, Debug)]
194#[repr(C)]
195#[allow(missing_docs)]
196pub struct ManagedProcFixed {
197 pub p_parent: U32<LE>,
198 pub p_end: U32<LE>,
199 pub p_next: U32<LE>,
200 pub proc_len: U32<LE>,
201 pub debug_start: U32<LE>,
202 pub debug_end: U32<LE>,
203 pub token: U32<LE>,
204 pub offset_segment: OffsetSegment,
205 pub flags: u8,
206 pub return_reg: U16<LE>,
207}
208
209#[allow(missing_docs)]
211#[derive(Clone, Debug)]
212pub struct ManagedProc<'a> {
213 pub fixed: &'a ManagedProcFixed,
214 pub name: &'a BStr,
215}
216
217impl<'a> Parse<'a> for ManagedProc<'a> {
218 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
219 Ok(Self {
220 fixed: p.get()?,
221 name: p.strz()?,
222 })
223 }
224}
225
226#[repr(C)]
227#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Default)]
228#[allow(missing_docs)]
229pub struct ThunkFixed {
230 pub block: BlockHeader,
231 pub p_next: U32<LE>,
232 pub offset_segment: OffsetSegment,
233 pub length: U16<LE>,
234 pub thunk_ordinal: u8,
235 }
238
239#[allow(missing_docs)]
240pub struct Thunk<'a> {
241 pub fixed: &'a ThunkFixed,
242 pub name: &'a BStr,
243 pub variant: &'a [u8],
244}
245
246impl<'a> Parse<'a> for Thunk<'a> {
247 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
248 Ok(Self {
249 fixed: p.get()?,
250 name: p.strz()?,
251 variant: p.take_rest(),
252 })
253 }
254}
255
256#[repr(C)]
258#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Default)]
259pub struct SymHeader {
260 pub len: U16<LE>,
265
266 pub kind: U16<LE>,
268}
269
270#[derive(Clone)]
272pub struct Sym<'a> {
273 pub kind: SymKind,
275 pub data: &'a [u8],
277}
278
279impl<'a> Sym<'a> {
280 pub fn parse(&self) -> Result<SymData<'a>, ParserError> {
282 SymData::parse(self.kind, self.data)
283 }
284
285 pub fn parse_as<T>(&self) -> Result<T, ParserError>
290 where
291 T: Parse<'a>,
292 {
293 let mut p = Parser::new(self.data);
294 p.parse::<T>()
295 }
296}
297
298impl<'a> Debug for Sym<'a> {
299 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
300 write!(fmt, "{:?}", self.kind)
301 }
302}
303
304pub struct SymMut<'a> {
307 pub kind: SymKind,
309 pub data: &'a mut [u8],
311}
312
313#[allow(missing_docs)]
326#[derive(Clone, Debug)]
327pub struct Pub<'a> {
328 pub fixed: &'a PubFixed,
329 pub name: &'a BStr,
330}
331
332impl<'a> Pub<'a> {
333 pub fn offset_segment(&self) -> OffsetSegment {
335 self.fixed.offset_segment
336 }
337}
338
339#[allow(missing_docs)]
340#[repr(C)]
341#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
342pub struct PubFixed {
343 pub flags: U32<LE>,
344 pub offset_segment: OffsetSegment,
345 }
347
348#[allow(missing_docs)]
349impl<'a> Parse<'a> for Pub<'a> {
350 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
351 Ok(Self {
352 fixed: p.get()?,
353 name: p.strz()?,
354 })
355 }
356}
357
358impl<'a> Pub<'a> {
359 pub fn parse_st(p: &mut Parser<'a>) -> Result<Self, ParserError> {
361 Ok(Self {
362 fixed: p.get()?,
363 name: p.strt_raw()?,
364 })
365 }
366}
367
368#[allow(missing_docs)]
370#[derive(Clone, Debug)]
371pub struct Constant<'a> {
372 pub type_: TypeIndex,
373 pub value: Number<'a>,
374 pub name: &'a BStr,
375}
376
377impl<'a> Parse<'a> for Constant<'a> {
378 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
379 Ok(Self {
380 type_: p.type_index()?,
381 value: p.number()?,
382 name: p.strz()?,
383 })
384 }
385}
386
387#[allow(missing_docs)]
389#[derive(Clone, Debug)]
390pub struct ManagedConstant<'a> {
391 pub token: u32,
392 pub value: Number<'a>,
393 pub name: &'a BStr,
394}
395
396impl<'a> Parse<'a> for ManagedConstant<'a> {
397 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
398 Ok(Self {
399 token: p.u32()?,
400 value: p.number()?,
401 name: p.strz()?,
402 })
403 }
404}
405
406#[allow(missing_docs)]
414#[derive(Clone, Debug)]
415pub struct RefSym2<'a> {
416 pub header: &'a RefSym2Fixed,
417 pub name: &'a BStr,
418}
419
420#[allow(missing_docs)]
421#[repr(C)]
422#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
423pub struct RefSym2Fixed {
424 pub name_checksum: U32<LE>,
428
429 pub symbol_offset: U32<LE>,
434
435 pub module_index: U16<LE>,
439 }
441
442impl<'a> Parse<'a> for RefSym2<'a> {
443 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
444 Ok(Self {
445 header: p.get()?,
446 name: p.strz()?,
447 })
448 }
449}
450
451#[allow(missing_docs)]
452#[repr(C)]
453#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
454pub struct ThreadStorageFixed {
455 pub type_: TypeIndexLe,
456 pub offset_segment: OffsetSegment,
457}
458
459#[derive(Clone, Debug)]
463pub struct ThreadStorageData<'a> {
464 #[allow(missing_docs)]
465 pub header: &'a ThreadStorageFixed,
466 #[allow(missing_docs)]
467 pub name: &'a BStr,
468}
469
470impl<'a> Parse<'a> for ThreadStorageData<'a> {
471 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
472 Ok(Self {
473 header: p.get()?,
474 name: p.strz()?,
475 })
476 }
477}
478
479#[allow(missing_docs)]
480#[repr(C)]
481#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
482pub struct DataFixed {
483 pub type_: TypeIndexLe,
484 pub offset_segment: OffsetSegment,
485}
486
487#[allow(missing_docs)]
489#[derive(Clone)]
490pub struct Data<'a> {
491 pub header: &'a DataFixed,
492 pub name: &'a BStr,
493}
494
495impl<'a> Parse<'a> for Data<'a> {
496 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
497 Ok(Self {
498 header: p.get()?,
499 name: p.strz()?,
500 })
501 }
502}
503
504impl<'a> Debug for Data<'a> {
505 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
506 write!(
507 f,
508 "Data: {} {:?} {}",
509 self.header.offset_segment,
510 self.header.type_.get(),
511 self.name
512 )
513 }
514}
515
516#[derive(Clone, Debug)]
518pub struct Udt<'a> {
519 pub type_: TypeIndex,
521 pub name: &'a BStr,
523}
524
525impl<'a> Parse<'a> for Udt<'a> {
526 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
527 Ok(Self {
528 type_: p.type_index()?,
529 name: p.strz()?,
530 })
531 }
532}
533
534#[derive(Clone, Debug)]
536pub struct ObjectName<'a> {
537 pub signature: u32,
540 pub name: &'a BStr,
542}
543
544impl<'a> Parse<'a> for ObjectName<'a> {
545 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
546 Ok(Self {
547 signature: p.u32()?,
548 name: p.strz()?,
549 })
550 }
551}
552
553#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
555#[repr(C)]
556#[allow(missing_docs)]
557pub struct Compile3Fixed {
558 pub flags: U32<LE>,
559 pub machine: U16<LE>,
560 pub frontend_major: U16<LE>,
561 pub frontend_minor: U16<LE>,
562 pub frontend_build: U16<LE>,
563 pub frontend_qfe: U16<LE>,
564 pub ver_major: U16<LE>,
565 pub ver_minor: U16<LE>,
566 pub ver_build: U16<LE>,
567 pub ver_qfe: U16<LE>,
568 }
570
571#[allow(missing_docs)]
573#[derive(Clone, Debug)]
574pub struct Compile3<'a> {
575 pub fixed: &'a Compile3Fixed,
576 pub name: &'a BStr,
577}
578
579impl<'a> Parse<'a> for Compile3<'a> {
580 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
581 Ok(Self {
582 fixed: p.get()?,
583 name: p.strz()?,
584 })
585 }
586}
587
588#[repr(C)]
592#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
593#[allow(missing_docs)]
594pub struct FrameProc {
595 frame_size: U32<LE>,
597 pad_size: U32<LE>,
599 pad_offset: U32<LE>,
601 save_regs_size: U32<LE>,
603 offset_exception_handler: U32<LE>,
604 exception_handler_section: U16<LE>,
605 padding: U16<LE>,
606 flags: U32<LE>,
607}
608
609#[repr(C)]
610#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
611#[allow(missing_docs)]
612pub struct RegRelFixed {
613 pub offset: U32<LE>,
614 pub ty: TypeIndexLe,
615 pub register: U16<LE>,
616 }
618
619#[derive(Clone, Debug)]
622#[allow(missing_docs)]
623pub struct RegRel<'a> {
624 pub fixed: &'a RegRelFixed,
625 pub name: &'a BStr,
626}
627
628impl<'a> Parse<'a> for RegRel<'a> {
629 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
630 Ok(Self {
631 fixed: p.get()?,
632 name: p.strz()?,
633 })
634 }
635}
636
637#[derive(Clone, Debug)]
645#[allow(missing_docs)]
646pub struct Block<'a> {
647 pub fixed: &'a BlockFixed,
648 pub name: &'a BStr,
649}
650
651#[repr(C)]
652#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
653#[allow(missing_docs)]
654pub struct BlockFixed {
655 pub header: BlockHeader,
657
658 pub length: U32<LE>,
660
661 pub offset_segment: OffsetSegment,
662}
663
664impl<'a> Parse<'a> for Block<'a> {
665 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
666 Ok(Self {
667 fixed: p.get()?,
668 name: p.strz()?,
669 })
670 }
671}
672
673#[derive(Clone, Debug)]
678#[allow(missing_docs)]
679pub struct Local<'a> {
680 pub fixed: &'a LocalFixed,
681 pub name: &'a BStr,
682}
683
684#[repr(C)]
685#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
686#[allow(missing_docs)]
687pub struct LocalFixed {
688 pub ty: TypeIndexLe,
689 pub flags: U16<LE>,
691 }
693
694impl<'a> Parse<'a> for Local<'a> {
695 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
696 Ok(Self {
697 fixed: p.get()?,
698 name: p.strz()?,
699 })
700 }
701}
702
703#[repr(C)]
707#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
708pub struct LVarAddrRange {
709 pub start: OffsetSegment,
711 pub range_size: U16<LE>,
713}
714
715#[repr(C)]
720#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
721pub struct LVarAddrGap {
722 pub gap_start_offset: U16<LE>,
724 pub range_size: U16<LE>,
726}
727
728#[repr(C)]
729#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
730#[allow(missing_docs)]
731pub struct DefRangeFixed {
732 pub program: U32<LE>,
734
735 pub range: LVarAddrRange,
736 }
738
739#[allow(missing_docs)]
741#[derive(Clone, Debug)]
742pub struct DefRange<'a> {
743 pub fixed: &'a DefRangeFixed,
744 pub gaps: &'a [LVarAddrGap],
745}
746
747impl<'a> Parse<'a> for DefRange<'a> {
748 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
749 let fixed = p.get()?;
750 let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
751 Ok(Self { fixed, gaps })
752 }
753}
754
755#[repr(C)]
757#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
758#[allow(missing_docs)]
759pub struct DefRangeSymFramePointerRelFixed {
760 pub offset_to_frame_pointer: U32<LE>,
761
762 pub range: LVarAddrRange,
764}
765
766#[allow(missing_docs)]
768#[derive(Clone, Debug)]
769pub struct DefRangeSymFramePointerRel<'a> {
770 pub fixed: &'a DefRangeSymFramePointerRelFixed,
771 pub gaps: &'a [LVarAddrGap],
773}
774
775impl<'a> Parse<'a> for DefRangeSymFramePointerRel<'a> {
776 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
777 let fixed = p.get()?;
778 let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
779 Ok(Self { fixed, gaps })
780 }
781}
782
783#[repr(C)]
787#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
788#[allow(missing_docs)]
789pub struct RangeAttrLe {
790 pub value: U16<LE>,
793}
794
795#[repr(C)]
799#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
800#[allow(missing_docs)]
801pub struct DefRangeRegisterFixed {
802 pub reg: U16<LE>,
804 pub attr: RangeAttrLe,
806}
807
808#[derive(Clone, Debug)]
812#[allow(missing_docs)]
813pub struct DefRangeRegister<'a> {
814 pub fixed: &'a DefRangeRegisterFixed,
815 pub gaps: &'a [u8],
816}
817
818impl<'a> Parse<'a> for DefRangeRegister<'a> {
819 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
820 Ok(Self {
821 fixed: p.get()?,
822 gaps: p.take_rest(),
823 })
824 }
825}
826
827#[allow(missing_docs)]
829#[derive(Debug, Clone)]
830pub struct DefRangeRegisterRel<'a> {
831 pub fixed: &'a DefRangeRegisterRelFixed,
832
833 pub gaps: &'a [u8],
835}
836
837#[repr(C)]
839#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
840pub struct DefRangeRegisterRelFixed {
841 pub base_reg: U16<LE>,
843
844 pub flags: U16<LE>,
850
851 pub base_pointer_offset: I32<LE>,
853
854 pub range: LVarAddrRange,
856}
857
858impl<'a> Parse<'a> for DefRangeRegisterRel<'a> {
859 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
860 Ok(Self {
861 fixed: p.get()?,
862 gaps: p.take_rest(),
863 })
864 }
865}
866
867#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
871#[repr(C)]
872pub struct DefRangeFramePointerRelFullScope {
873 pub frame_pointer_offset: I32<LE>,
875}
876
877#[derive(Clone, Debug)]
881#[allow(missing_docs)]
882pub struct DefRangeSubFieldRegister<'a> {
883 pub fixed: &'a DefRangeSubFieldRegisterFixed,
884 pub gaps: &'a [u8],
885}
886
887#[repr(C)]
888#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
889#[allow(missing_docs)]
890pub struct DefRangeSubFieldRegisterFixed {
891 pub reg: U16<LE>,
892 pub attr: RangeAttrLe,
893 pub flags: U32<LE>,
894 pub range: LVarAddrRange,
895}
896
897impl<'a> Parse<'a> for DefRangeSubFieldRegister<'a> {
898 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
899 Ok(Self {
900 fixed: p.get()?,
901 gaps: p.take_rest(),
902 })
903 }
904}
905
906pub struct ManProcSym<'a> {
910 #[allow(missing_docs)]
911 pub fixed: &'a ManProcSymFixed,
912 #[allow(missing_docs)]
913 pub name: &'a BStr,
914}
915
916pub type TokenIdLe = U32<LE>;
918
919#[repr(C)]
920#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
921#[allow(missing_docs)]
922pub struct ManProcSymFixed {
923 pub block: BlockHeader,
924 pub pnext: U32<LE>,
926 pub len: U32<LE>,
928 pub dbg_start: U32<LE>,
930 pub dbg_end: U32<LE>,
932 pub token: TokenIdLe,
934 pub off: U32<LE>,
935 pub seg: U16<LE>,
936 pub flags: u8, pub padding: u8,
938 pub ret_reg: U16<LE>,
940 }
942
943impl<'a> Parse<'a> for ManProcSym<'a> {
944 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
945 Ok(Self {
946 fixed: p.get()?,
947 name: p.strz()?,
948 })
949 }
950}
951
952#[derive(Clone, Debug)]
954pub struct Trampoline<'a> {
955 pub fixed: &'a TrampolineFixed,
957
958 pub rest: &'a [u8],
960}
961
962#[repr(C)]
964#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
965pub struct TrampolineFixed {
966 pub tramp_type: U16<LE>,
968 pub cb_thunk: U16<LE>,
970 pub off_thunk: U32<LE>,
972 pub off_target: U32<LE>,
974 pub sect_thunk: U16<LE>,
976 pub sect_target: U16<LE>,
978}
979
980impl<'a> Parse<'a> for Trampoline<'a> {
981 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
982 Ok(Self {
983 fixed: p.get()?,
984 rest: p.take_rest(),
985 })
986 }
987}
988
989#[derive(Clone, Debug)]
993pub struct BuildInfo {
994 pub item: ItemId,
996}
997
998impl<'a> Parse<'a> for BuildInfo {
999 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1000 Ok(Self { item: p.u32()? })
1001 }
1002}
1003
1004#[derive(Clone, Debug)]
1006pub struct UsingNamespace<'a> {
1007 pub namespace: &'a BStr,
1009}
1010
1011impl<'a> Parse<'a> for UsingNamespace<'a> {
1012 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1013 Ok(Self {
1014 namespace: p.strz()?,
1015 })
1016 }
1017}
1018
1019#[derive(Clone, Debug)]
1021#[allow(missing_docs)]
1022pub struct Label<'a> {
1023 pub fixed: &'a LabelFixed,
1024 pub name: &'a BStr,
1025}
1026
1027#[repr(C)]
1029#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1030#[allow(missing_docs)]
1031pub struct LabelFixed {
1032 pub offset_segment: OffsetSegment,
1033 pub flags: u8,
1034}
1035
1036impl<'a> Parse<'a> for Label<'a> {
1037 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1038 Ok(Self {
1039 fixed: p.get()?,
1040 name: p.strz()?,
1041 })
1042 }
1043}
1044
1045#[derive(Clone, Debug)]
1047pub struct FunctionList<'a> {
1048 pub funcs: &'a [ItemIdLe],
1050
1051 pub counts: &'a [U32<LE>],
1058}
1059
1060impl<'a> Parse<'a> for FunctionList<'a> {
1061 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1062 let num_funcs = p.u32()? as usize;
1063 let funcs: &[ItemIdLe] = p.slice(num_funcs)?;
1064 let num_counts = num_funcs.min(p.len() / size_of::<U32<LE>>());
1065 let counts = p.slice(num_counts)?;
1066 Ok(Self { funcs, counts })
1067 }
1068}
1069
1070#[allow(missing_docs)]
1072#[derive(Clone, Debug)]
1073pub struct InlineSite<'a> {
1074 pub fixed: &'a InlineSiteFixed,
1075 pub binary_annotations: &'a [u8],
1077}
1078
1079#[repr(C)]
1081#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1082#[allow(missing_docs)]
1083pub struct InlineSiteFixed {
1084 pub block: BlockHeader,
1085 pub inlinee: ItemIdLe,
1086}
1087
1088impl<'a> Parse<'a> for InlineSite<'a> {
1089 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1090 Ok(Self {
1091 fixed: p.get()?,
1092 binary_annotations: p.take_rest(),
1093 })
1094 }
1095}
1096
1097#[allow(missing_docs)]
1099#[derive(Clone, Debug)]
1100pub struct InlineSite2<'a> {
1101 pub fixed: &'a InlineSite2Fixed,
1102 pub binary_annotations: &'a [u8],
1104}
1105
1106#[repr(C)]
1108#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1109#[allow(missing_docs)]
1110pub struct InlineSite2Fixed {
1111 pub block: BlockHeader,
1112 pub inlinee: ItemIdLe,
1113 pub invocations: U32<LE>,
1114}
1115
1116impl<'a> Parse<'a> for InlineSite2<'a> {
1117 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1118 Ok(Self {
1119 fixed: p.get()?,
1120 binary_annotations: p.take_rest(),
1121 })
1122 }
1123}
1124
1125#[repr(C)]
1128#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1129#[allow(missing_docs)]
1130pub struct FrameCookie {
1131 pub offset: I32<LE>,
1133 pub reg: U16<LE>,
1134 pub cookie_type: u8,
1135 pub flags: u8,
1136}
1137
1138#[repr(C)]
1160#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1161#[allow(missing_docs)]
1162pub struct CallSiteInfo {
1163 pub offset: OffsetSegment,
1164 pub padding: U16<LE>,
1165 pub func_type: TypeIndexLe,
1166}
1167
1168#[repr(C)]
1170#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1171#[allow(missing_docs)]
1172pub struct HeapAllocSite {
1173 pub offset: OffsetSegment,
1174 pub instruction_size: U16<LE>,
1176 pub func_type: TypeIndexLe,
1177}
1178
1179#[allow(missing_docs)]
1181#[derive(Clone, Debug)]
1182pub struct Annotation<'a> {
1183 pub fixed: &'a AnnotationFixed,
1184 pub strings: &'a [u8],
1185}
1186
1187#[repr(C)]
1188#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1189#[allow(missing_docs)]
1190pub struct AnnotationFixed {
1191 pub offset: OffsetSegment,
1192 pub num_strings: U16<LE>,
1193}
1194
1195impl<'a> Parse<'a> for Annotation<'a> {
1196 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1197 Ok(Self {
1198 fixed: p.get()?,
1199 strings: p.take_rest(),
1200 })
1201 }
1202}
1203
1204impl<'a> Annotation<'a> {
1205 pub fn iter_strings(&self) -> AnnotationIterStrings<'a> {
1207 AnnotationIterStrings {
1208 num_strings: self.fixed.num_strings.get(),
1209 bytes: self.strings,
1210 }
1211 }
1212}
1213
1214#[allow(missing_docs)]
1216pub struct AnnotationIterStrings<'a> {
1217 pub num_strings: u16,
1218 pub bytes: &'a [u8],
1219}
1220
1221impl<'a> Iterator for AnnotationIterStrings<'a> {
1222 type Item = &'a BStr;
1223
1224 fn next(&mut self) -> Option<Self::Item> {
1225 if self.num_strings == 0 {
1226 return None;
1227 }
1228
1229 self.num_strings -= 1;
1230 let mut p = Parser::new(self.bytes);
1231 let s = p.strz().ok()?;
1232 self.bytes = p.into_rest();
1233 Some(s)
1234 }
1235}
1236
1237#[derive(Clone, Debug)]
1239pub struct HotPatchFunc<'a> {
1240 pub func: ItemId,
1242
1243 pub name: &'a BStr,
1245}
1246
1247impl<'a> Parse<'a> for HotPatchFunc<'a> {
1248 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1249 Ok(Self {
1250 func: p.u32()?,
1251 name: p.strz()?,
1252 })
1253 }
1254}
1255
1256#[repr(C)]
1263#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone)]
1264pub struct ArmSwitchTable {
1265 pub offset_base: U32<LE>,
1267 pub sect_base: U16<LE>,
1269 pub switch_type: U16<LE>,
1271 pub offset_branch: U32<LE>,
1273 pub offset_table: U32<LE>,
1275 pub sect_branch: U16<LE>,
1277 pub sect_table: U16<LE>,
1279 pub num_entries: U32<LE>,
1281}
1282
1283impl ArmSwitchTable {
1284 pub fn base(&self) -> OffsetSegment {
1292 OffsetSegment {
1293 offset: self.offset_base,
1294 segment: self.sect_base,
1295 }
1296 }
1297
1298 pub fn branch(&self) -> OffsetSegment {
1300 OffsetSegment {
1301 offset: self.offset_branch,
1302 segment: self.sect_branch,
1303 }
1304 }
1305
1306 pub fn table(&self) -> OffsetSegment {
1308 OffsetSegment {
1309 offset: self.offset_table,
1310 segment: self.sect_table,
1311 }
1312 }
1313
1314 pub fn switch_type(&self) -> ArmSwitchType {
1316 ArmSwitchType(self.switch_type.get())
1317 }
1318
1319 pub fn num_entries(&self) -> u32 {
1321 self.num_entries.get()
1322 }
1323}
1324
1325impl core::fmt::Debug for ArmSwitchTable {
1326 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1327 f.debug_struct("ArmSwitchTable")
1328 .field("base", &self.base())
1329 .field("branch", &self.branch())
1330 .field("table", &self.table())
1331 .field("switch_type", &self.switch_type())
1332 .field("num_entries", &self.num_entries())
1333 .finish()
1334 }
1335}
1336
1337#[derive(Copy, Clone, Eq, PartialEq)]
1339pub struct ArmSwitchType(pub u16);
1340
1341impl ArmSwitchType {
1342 pub const INT1: ArmSwitchType = ArmSwitchType(0);
1344 pub const UINT1: ArmSwitchType = ArmSwitchType(1);
1346 pub const INT2: ArmSwitchType = ArmSwitchType(2);
1348 pub const UINT2: ArmSwitchType = ArmSwitchType(3);
1350 pub const INT4: ArmSwitchType = ArmSwitchType(4);
1352 pub const UINT4: ArmSwitchType = ArmSwitchType(5);
1354 pub const POINTER: ArmSwitchType = ArmSwitchType(6);
1356 pub const UINT1SHL1: ArmSwitchType = ArmSwitchType(7);
1358 pub const UINT2SHL1: ArmSwitchType = ArmSwitchType(8);
1360 pub const INT1SHL1: ArmSwitchType = ArmSwitchType(9);
1362 pub const INT2SHL1: ArmSwitchType = ArmSwitchType(10);
1364 }
1367
1368impl core::fmt::Debug for ArmSwitchType {
1369 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1370 static NAMES: [&str; 11] = [
1371 "INT1",
1372 "UINT1",
1373 "INT2",
1374 "UINT2",
1375 "INT4",
1376 "UINT4",
1377 "POINTER",
1378 "UINT1SHL1",
1379 "UINT2SHL1",
1380 "INT1SHL1",
1381 "INT2SHL1",
1382 ];
1383
1384 if let Some(&s) = NAMES.get(self.0 as usize) {
1385 f.write_str(s)
1386 } else {
1387 write!(f, "??{}", self.0)
1388 }
1389 }
1390}
1391
1392pub const TRAMPOLINE_KIND_INCREMENTAL: u16 = 0;
1396pub const TRAMPOLINE_KIND_BRANCH_ISLAND: u16 = 1;
1398
1399#[repr(C)]
1401#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1402pub struct CoffGroupFixed {
1403 pub cb: U32<LE>,
1405 pub characteristics: U32<LE>,
1409 pub off_seg: OffsetSegment,
1411}
1412
1413#[derive(Clone, Debug)]
1419pub struct CoffGroup<'a> {
1420 pub fixed: &'a CoffGroupFixed,
1422 pub name: &'a BStr,
1424}
1425
1426impl<'a> Parse<'a> for CoffGroup<'a> {
1427 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1428 Ok(Self {
1429 fixed: p.get()?,
1430 name: p.strz()?,
1431 })
1432 }
1433}
1434
1435#[derive(Clone, Debug)]
1437pub struct Section<'a> {
1438 pub fixed: &'a SectionFixed,
1440 pub name: &'a BStr,
1442}
1443
1444#[repr(C)]
1446#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1447pub struct SectionFixed {
1448 pub section: U16<LE>,
1450 pub align: u8,
1452 pub reserved: u8,
1454 pub rva: U32<LE>,
1456 pub cb: U32<LE>,
1458 pub characteristics: U32<LE>,
1460}
1461
1462impl<'a> Parse<'a> for Section<'a> {
1463 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1464 Ok(Self {
1465 fixed: p.get()?,
1466 name: p.strz()?,
1467 })
1468 }
1469}
1470
1471#[derive(Clone, Debug)]
1473#[allow(missing_docs)]
1474pub enum SymData<'a> {
1475 Unknown,
1476 ObjName(ObjectName<'a>),
1477 Compile3(Compile3<'a>),
1478 Proc(Proc<'a>),
1479 Udt(Udt<'a>),
1480 Constant(Constant<'a>),
1481 ManagedConstant(ManagedConstant<'a>),
1482 RefSym2(RefSym2<'a>),
1483 Data(Data<'a>),
1484 ThreadData(ThreadStorageData<'a>),
1485 Pub(Pub<'a>),
1486 End,
1487 FrameProc(&'a FrameProc),
1488 RegRel(RegRel<'a>),
1489 Block(Block<'a>),
1490 Local(Local<'a>),
1491 DefRange(DefRange<'a>),
1492 DefRangeFramePointerRel(DefRangeSymFramePointerRel<'a>),
1493 DefRangeRegister(DefRangeRegister<'a>),
1494 DefRangeRegisterRel(DefRangeRegisterRel<'a>),
1495 DefRangeFramePointerRelFullScope(&'a DefRangeFramePointerRelFullScope),
1496 DefRangeSubFieldRegister(DefRangeSubFieldRegister<'a>),
1497 Trampoline(Trampoline<'a>),
1498 BuildInfo(BuildInfo),
1499 UsingNamespace(UsingNamespace<'a>),
1500 InlineSiteEnd,
1501 Label(Label<'a>),
1502 FunctionList(FunctionList<'a>),
1503 InlineSite(InlineSite<'a>),
1504 InlineSite2(InlineSite2<'a>),
1505 FrameCookie(&'a FrameCookie),
1506 CallSiteInfo(&'a CallSiteInfo),
1507 HeapAllocSite(&'a HeapAllocSite),
1508 ManagedProc(ManagedProc<'a>),
1509 Annotation(Annotation<'a>),
1510 HotPatchFunc(HotPatchFunc<'a>),
1511 CoffGroup(CoffGroup<'a>),
1512 ArmSwitchTable(&'a ArmSwitchTable),
1513 Section(Section<'a>),
1514}
1515
1516impl<'a> SymData<'a> {
1517 pub fn parse(kind: SymKind, data: &'a [u8]) -> Result<Self, ParserError> {
1520 let mut p = Parser::new(data);
1521 Self::from_parser(kind, &mut p)
1522 }
1523
1524 pub fn from_parser(kind: SymKind, p: &mut Parser<'a>) -> Result<Self, ParserError> {
1530 Ok(match kind {
1531 SymKind::S_OBJNAME => Self::ObjName(p.parse()?),
1532 SymKind::S_GPROC32 | SymKind::S_LPROC32 => Self::Proc(p.parse()?),
1533 SymKind::S_COMPILE3 => Self::Compile3(p.parse()?),
1534 SymKind::S_UDT => Self::Udt(p.parse()?),
1535 SymKind::S_CONSTANT => Self::Constant(p.parse()?),
1536 SymKind::S_MANCONSTANT => Self::Constant(p.parse()?),
1537 SymKind::S_PUB32 => Self::Pub(p.parse()?),
1538 SymKind::S_PUB32_ST => Self::Pub(Pub::parse_st(p)?),
1539
1540 SymKind::S_PROCREF
1541 | SymKind::S_LPROCREF
1542 | SymKind::S_DATAREF
1543 | SymKind::S_ANNOTATIONREF => Self::RefSym2(p.parse()?),
1544
1545 SymKind::S_LDATA32 | SymKind::S_GDATA32 | SymKind::S_LMANDATA | SymKind::S_GMANDATA => {
1546 Self::Data(p.parse()?)
1547 }
1548
1549 SymKind::S_LTHREAD32 | SymKind::S_GTHREAD32 => Self::ThreadData(p.parse()?),
1550 SymKind::S_END => Self::End,
1551 SymKind::S_FRAMEPROC => Self::FrameProc(p.get()?),
1552 SymKind::S_REGREL32 => Self::RegRel(p.parse()?),
1553 SymKind::S_BLOCK32 => Self::Block(p.parse()?),
1554 SymKind::S_LOCAL => Self::Local(p.parse()?),
1555 SymKind::S_DEFRANGE => Self::DefRange(p.parse()?),
1556 SymKind::S_DEFRANGE_FRAMEPOINTER_REL => Self::DefRangeFramePointerRel(p.parse()?),
1557 SymKind::S_DEFRANGE_REGISTER => Self::DefRangeRegister(p.parse()?),
1558 SymKind::S_DEFRANGE_REGISTER_REL => Self::DefRangeRegisterRel(p.parse()?),
1559 SymKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE => {
1560 Self::DefRangeFramePointerRelFullScope(p.get()?)
1561 }
1562 SymKind::S_DEFRANGE_SUBFIELD_REGISTER => Self::DefRangeSubFieldRegister(p.parse()?),
1563 SymKind::S_TRAMPOLINE => Self::Trampoline(p.parse()?),
1564 SymKind::S_BUILDINFO => Self::BuildInfo(p.parse()?),
1565 SymKind::S_UNAMESPACE => Self::UsingNamespace(p.parse()?),
1566 SymKind::S_INLINESITE_END => Self::InlineSiteEnd,
1567 SymKind::S_LABEL32 => Self::Label(p.parse()?),
1568 SymKind::S_CALLEES | SymKind::S_CALLERS => Self::FunctionList(p.parse()?),
1569 SymKind::S_INLINESITE => Self::InlineSite(p.parse()?),
1570 SymKind::S_INLINESITE2 => Self::InlineSite2(p.parse()?),
1571 SymKind::S_INLINEES => Self::FunctionList(p.parse()?),
1572 SymKind::S_FRAMECOOKIE => Self::FrameCookie(p.get()?),
1573 SymKind::S_CALLSITEINFO => Self::CallSiteInfo(p.get()?),
1574 SymKind::S_HEAPALLOCSITE => Self::HeapAllocSite(p.get()?),
1575 SymKind::S_GMANPROC | SymKind::S_LMANPROC => Self::ManagedProc(p.parse()?),
1576 SymKind::S_ANNOTATION => Self::Annotation(p.parse()?),
1577 SymKind::S_HOTPATCHFUNC => Self::HotPatchFunc(p.parse()?),
1578 SymKind::S_ARMSWITCHTABLE => Self::ArmSwitchTable(p.get()?),
1579 SymKind::S_COFFGROUP => Self::CoffGroup(p.parse()?),
1580 SymKind::S_SECTION => Self::Section(p.parse()?),
1581
1582 _ => Self::Unknown,
1583 })
1584 }
1585
1586 pub fn name(&self) -> Option<&'a BStr> {
1588 match self {
1589 Self::Proc(proc) => Some(proc.name),
1590 Self::Data(data) => Some(data.name),
1591 Self::ThreadData(thread_data) => Some(thread_data.name),
1592 Self::Udt(udt) => Some(udt.name),
1593 Self::Local(local) => Some(local.name),
1594 Self::RefSym2(refsym) => Some(refsym.name),
1595 Self::Constant(c) => Some(c.name),
1596 Self::ManagedConstant(c) => Some(c.name),
1597 _ => None,
1598 }
1599 }
1600}