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, Immutable, IntoBytes, KnownLayout, Unaligned, I32, LE, U16, U32};
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
286impl<'a> Debug for Sym<'a> {
287 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
288 write!(fmt, "{:?}", self.kind)
289 }
290}
291
292pub struct SymMut<'a> {
295 pub kind: SymKind,
297 pub data: &'a mut [u8],
299}
300
301#[allow(missing_docs)]
314#[derive(Clone, Debug)]
315pub struct Pub<'a> {
316 pub fixed: &'a PubFixed,
317 pub name: &'a BStr,
318}
319
320impl<'a> Pub<'a> {
321 pub fn offset_segment(&self) -> OffsetSegment {
323 self.fixed.offset_segment
324 }
325}
326
327#[allow(missing_docs)]
328#[repr(C)]
329#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
330pub struct PubFixed {
331 pub flags: U32<LE>,
332 pub offset_segment: OffsetSegment,
333 }
335
336#[allow(missing_docs)]
337impl<'a> Parse<'a> for Pub<'a> {
338 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
339 Ok(Self {
340 fixed: p.get()?,
341 name: p.strz()?,
342 })
343 }
344}
345
346impl<'a> Pub<'a> {
347 pub fn parse_st(p: &mut Parser<'a>) -> Result<Self, ParserError> {
349 Ok(Self {
350 fixed: p.get()?,
351 name: p.strt_raw()?,
352 })
353 }
354}
355
356#[allow(missing_docs)]
358#[derive(Clone, Debug)]
359pub struct Constant<'a> {
360 pub type_: TypeIndex,
361 pub value: Number<'a>,
362 pub name: &'a BStr,
363}
364
365impl<'a> Parse<'a> for Constant<'a> {
366 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
367 Ok(Self {
368 type_: p.type_index()?,
369 value: p.number()?,
370 name: p.strz()?,
371 })
372 }
373}
374
375#[allow(missing_docs)]
377#[derive(Clone, Debug)]
378pub struct ManagedConstant<'a> {
379 pub token: u32,
380 pub value: Number<'a>,
381 pub name: &'a BStr,
382}
383
384impl<'a> Parse<'a> for ManagedConstant<'a> {
385 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
386 Ok(Self {
387 token: p.u32()?,
388 value: p.number()?,
389 name: p.strz()?,
390 })
391 }
392}
393
394#[allow(missing_docs)]
402#[derive(Clone, Debug)]
403pub struct RefSym2<'a> {
404 pub header: &'a RefSym2Fixed,
405 pub name: &'a BStr,
406}
407
408#[allow(missing_docs)]
409#[repr(C)]
410#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
411pub struct RefSym2Fixed {
412 pub name_checksum: U32<LE>,
416
417 pub symbol_offset: U32<LE>,
422
423 pub module_index: U16<LE>,
427 }
429
430impl<'a> Parse<'a> for RefSym2<'a> {
431 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
432 Ok(Self {
433 header: p.get()?,
434 name: p.strz()?,
435 })
436 }
437}
438
439#[allow(missing_docs)]
440#[repr(C)]
441#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
442pub struct ThreadStorageFixed {
443 pub type_: TypeIndexLe,
444 pub offset_segment: OffsetSegment,
445}
446
447#[derive(Clone, Debug)]
451pub struct ThreadStorageData<'a> {
452 #[allow(missing_docs)]
453 pub header: &'a ThreadStorageFixed,
454 #[allow(missing_docs)]
455 pub name: &'a BStr,
456}
457
458impl<'a> Parse<'a> for ThreadStorageData<'a> {
459 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
460 Ok(Self {
461 header: p.get()?,
462 name: p.strz()?,
463 })
464 }
465}
466
467#[allow(missing_docs)]
468#[repr(C)]
469#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
470pub struct DataFixed {
471 pub type_: TypeIndexLe,
472 pub offset_segment: OffsetSegment,
473}
474
475#[allow(missing_docs)]
477#[derive(Clone)]
478pub struct Data<'a> {
479 pub header: &'a DataFixed,
480 pub name: &'a BStr,
481}
482
483impl<'a> Parse<'a> for Data<'a> {
484 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
485 Ok(Self {
486 header: p.get()?,
487 name: p.strz()?,
488 })
489 }
490}
491
492impl<'a> Debug for Data<'a> {
493 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
494 write!(
495 f,
496 "Data: {} {:?} {}",
497 self.header.offset_segment,
498 self.header.type_.get(),
499 self.name
500 )
501 }
502}
503
504#[derive(Clone, Debug)]
506pub struct Udt<'a> {
507 pub type_: TypeIndex,
509 pub name: &'a BStr,
511}
512
513impl<'a> Parse<'a> for Udt<'a> {
514 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
515 Ok(Self {
516 type_: p.type_index()?,
517 name: p.strz()?,
518 })
519 }
520}
521
522#[derive(Clone, Debug)]
524pub struct ObjectName<'a> {
525 pub signature: u32,
528 pub name: &'a BStr,
530}
531
532impl<'a> Parse<'a> for ObjectName<'a> {
533 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
534 Ok(Self {
535 signature: p.u32()?,
536 name: p.strz()?,
537 })
538 }
539}
540
541#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
543#[repr(C)]
544#[allow(missing_docs)]
545pub struct Compile3Fixed {
546 pub flags: U32<LE>,
547 pub machine: U16<LE>,
548 pub frontend_major: U16<LE>,
549 pub frontend_minor: U16<LE>,
550 pub frontend_build: U16<LE>,
551 pub frontend_qfe: U16<LE>,
552 pub ver_major: U16<LE>,
553 pub ver_minor: U16<LE>,
554 pub ver_build: U16<LE>,
555 pub ver_qfe: U16<LE>,
556 }
558
559#[allow(missing_docs)]
561#[derive(Clone, Debug)]
562pub struct Compile3<'a> {
563 pub fixed: &'a Compile3Fixed,
564 pub name: &'a BStr,
565}
566
567impl<'a> Parse<'a> for Compile3<'a> {
568 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
569 Ok(Self {
570 fixed: p.get()?,
571 name: p.strz()?,
572 })
573 }
574}
575
576#[repr(C)]
580#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
581#[allow(missing_docs)]
582pub struct FrameProc {
583 frame_size: U32<LE>,
585 pad_size: U32<LE>,
587 pad_offset: U32<LE>,
589 save_regs_size: U32<LE>,
591 offset_exception_handler: U32<LE>,
592 exception_handler_section: U16<LE>,
593 padding: U16<LE>,
594 flags: U32<LE>,
595}
596
597#[repr(C)]
598#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
599#[allow(missing_docs)]
600pub struct RegRelFixed {
601 pub offset: U32<LE>,
602 pub ty: TypeIndexLe,
603 pub register: U16<LE>,
604 }
606
607#[derive(Clone, Debug)]
610#[allow(missing_docs)]
611pub struct RegRel<'a> {
612 pub fixed: &'a RegRelFixed,
613 pub name: &'a BStr,
614}
615
616impl<'a> Parse<'a> for RegRel<'a> {
617 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
618 Ok(Self {
619 fixed: p.get()?,
620 name: p.strz()?,
621 })
622 }
623}
624
625#[derive(Clone, Debug)]
633#[allow(missing_docs)]
634pub struct Block<'a> {
635 pub fixed: &'a BlockFixed,
636 pub name: &'a BStr,
637}
638
639#[repr(C)]
640#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
641#[allow(missing_docs)]
642pub struct BlockFixed {
643 pub header: BlockHeader,
645
646 pub length: U32<LE>,
648
649 pub offset_segment: OffsetSegment,
650}
651
652impl<'a> Parse<'a> for Block<'a> {
653 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
654 Ok(Self {
655 fixed: p.get()?,
656 name: p.strz()?,
657 })
658 }
659}
660
661#[derive(Clone, Debug)]
666#[allow(missing_docs)]
667pub struct Local<'a> {
668 pub fixed: &'a LocalFixed,
669 pub name: &'a BStr,
670}
671
672#[repr(C)]
673#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
674#[allow(missing_docs)]
675pub struct LocalFixed {
676 pub ty: TypeIndexLe,
677 pub flags: U16<LE>,
679 }
681
682impl<'a> Parse<'a> for Local<'a> {
683 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
684 Ok(Self {
685 fixed: p.get()?,
686 name: p.strz()?,
687 })
688 }
689}
690
691#[repr(C)]
695#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
696pub struct LVarAddrRange {
697 pub start: OffsetSegment,
699 pub range_size: U16<LE>,
701}
702
703#[repr(C)]
708#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
709pub struct LVarAddrGap {
710 pub gap_start_offset: U16<LE>,
712 pub range_size: U16<LE>,
714}
715
716#[repr(C)]
718#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
719#[allow(missing_docs)]
720pub struct DefRangeSymFramePointerRelFixed {
721 pub offset_to_frame_pointer: U32<LE>,
722
723 pub range: LVarAddrRange,
725}
726
727#[allow(missing_docs)]
729#[derive(Clone, Debug)]
730pub struct DefRangeSymFramePointerRel<'a> {
731 pub fixed: &'a DefRangeSymFramePointerRelFixed,
732 pub gaps: &'a [LVarAddrGap],
734}
735
736impl<'a> Parse<'a> for DefRangeSymFramePointerRel<'a> {
737 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
738 let fixed = p.get()?;
739 let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
740 Ok(Self { fixed, gaps })
741 }
742}
743
744#[repr(C)]
748#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
749#[allow(missing_docs)]
750pub struct RangeAttrLe {
751 pub value: U16<LE>,
754}
755
756#[repr(C)]
760#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
761#[allow(missing_docs)]
762pub struct DefRangeRegisterFixed {
763 pub reg: U16<LE>,
765 pub attr: RangeAttrLe,
767}
768
769#[derive(Clone, Debug)]
773#[allow(missing_docs)]
774pub struct DefRangeRegister<'a> {
775 pub fixed: &'a DefRangeRegisterFixed,
776 pub gaps: &'a [u8],
777}
778
779impl<'a> Parse<'a> for DefRangeRegister<'a> {
780 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
781 Ok(Self {
782 fixed: p.get()?,
783 gaps: p.take_rest(),
784 })
785 }
786}
787
788#[allow(missing_docs)]
790#[derive(Debug, Clone)]
791pub struct DefRangeRegisterRel<'a> {
792 pub fixed: &'a DefRangeRegisterRelFixed,
793
794 pub gaps: &'a [u8],
796}
797
798#[repr(C)]
800#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
801pub struct DefRangeRegisterRelFixed {
802 pub base_reg: U16<LE>,
804
805 pub flags: U16<LE>,
811
812 pub base_pointer_offset: I32<LE>,
814
815 pub range: LVarAddrRange,
817}
818
819impl<'a> Parse<'a> for DefRangeRegisterRel<'a> {
820 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
821 Ok(Self {
822 fixed: p.get()?,
823 gaps: p.take_rest(),
824 })
825 }
826}
827
828#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
832#[repr(C)]
833pub struct DefRangeFramePointerRelFullScope {
834 pub frame_pointer_offset: I32<LE>,
836}
837
838#[derive(Clone, Debug)]
842#[allow(missing_docs)]
843pub struct DefRangeSubFieldRegister<'a> {
844 pub fixed: &'a DefRangeSubFieldRegisterFixed,
845 pub gaps: &'a [u8],
846}
847
848#[repr(C)]
849#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
850#[allow(missing_docs)]
851pub struct DefRangeSubFieldRegisterFixed {
852 pub reg: U16<LE>,
853 pub attr: RangeAttrLe,
854 pub flags: U32<LE>,
855 pub range: LVarAddrRange,
856}
857
858impl<'a> Parse<'a> for DefRangeSubFieldRegister<'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
867pub struct ManProcSym<'a> {
871 #[allow(missing_docs)]
872 pub fixed: &'a ManProcSymFixed,
873 #[allow(missing_docs)]
874 pub name: &'a BStr,
875}
876
877pub type TokenIdLe = U32<LE>;
879
880#[repr(C)]
881#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
882#[allow(missing_docs)]
883pub struct ManProcSymFixed {
884 pub block: BlockHeader,
885 pub pnext: U32<LE>,
887 pub len: U32<LE>,
889 pub dbg_start: U32<LE>,
891 pub dbg_end: U32<LE>,
893 pub token: TokenIdLe,
895 pub off: U32<LE>,
896 pub seg: U16<LE>,
897 pub flags: u8, pub padding: u8,
899 pub ret_reg: U16<LE>,
901 }
903
904impl<'a> Parse<'a> for ManProcSym<'a> {
905 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
906 Ok(Self {
907 fixed: p.get()?,
908 name: p.strz()?,
909 })
910 }
911}
912
913#[derive(Clone, Debug)]
915pub struct Trampoline<'a> {
916 pub fixed: &'a TrampolineFixed,
918
919 pub rest: &'a [u8],
921}
922
923#[repr(C)]
925#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
926pub struct TrampolineFixed {
927 pub tramp_type: U16<LE>,
929 pub cb_thunk: U16<LE>,
931 pub off_thunk: U32<LE>,
933 pub off_target: U32<LE>,
935 pub sect_thunk: U16<LE>,
937 pub sect_target: U16<LE>,
939}
940
941impl<'a> Parse<'a> for Trampoline<'a> {
942 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
943 Ok(Self {
944 fixed: p.get()?,
945 rest: p.take_rest(),
946 })
947 }
948}
949
950#[derive(Clone, Debug)]
954pub struct BuildInfo {
955 pub item: ItemId,
957}
958
959impl<'a> Parse<'a> for BuildInfo {
960 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
961 Ok(Self { item: p.u32()? })
962 }
963}
964
965#[derive(Clone, Debug)]
967pub struct UsingNamespace<'a> {
968 pub namespace: &'a BStr,
970}
971
972impl<'a> Parse<'a> for UsingNamespace<'a> {
973 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
974 Ok(Self {
975 namespace: p.strz()?,
976 })
977 }
978}
979
980#[derive(Clone, Debug)]
982#[allow(missing_docs)]
983pub struct Label<'a> {
984 pub fixed: &'a LabelFixed,
985 pub name: &'a BStr,
986}
987
988#[repr(C)]
990#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
991#[allow(missing_docs)]
992pub struct LabelFixed {
993 pub offset_segment: OffsetSegment,
994 pub flags: u8,
995}
996
997impl<'a> Parse<'a> for Label<'a> {
998 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
999 Ok(Self {
1000 fixed: p.get()?,
1001 name: p.strz()?,
1002 })
1003 }
1004}
1005
1006#[derive(Clone, Debug)]
1008pub struct FunctionList<'a> {
1009 pub funcs: &'a [ItemIdLe],
1011
1012 pub counts: &'a [U32<LE>],
1019}
1020
1021impl<'a> Parse<'a> for FunctionList<'a> {
1022 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1023 let num_funcs = p.u32()? as usize;
1024 let funcs: &[ItemIdLe] = p.slice(num_funcs)?;
1025 let num_counts = num_funcs.min(p.len() / size_of::<U32<LE>>());
1026 let counts = p.slice(num_counts)?;
1027 Ok(Self { funcs, counts })
1028 }
1029}
1030
1031#[allow(missing_docs)]
1033#[derive(Clone, Debug)]
1034pub struct InlineSite<'a> {
1035 pub fixed: &'a InlineSiteFixed,
1036 pub binary_annotations: &'a [u8],
1038}
1039
1040#[repr(C)]
1042#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1043#[allow(missing_docs)]
1044pub struct InlineSiteFixed {
1045 pub block: BlockHeader,
1046 pub inlinee: ItemIdLe,
1047}
1048
1049impl<'a> Parse<'a> for InlineSite<'a> {
1050 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1051 Ok(Self {
1052 fixed: p.get()?,
1053 binary_annotations: p.take_rest(),
1054 })
1055 }
1056}
1057
1058#[allow(missing_docs)]
1060#[derive(Clone, Debug)]
1061pub struct InlineSite2<'a> {
1062 pub fixed: &'a InlineSite2Fixed,
1063 pub binary_annotations: &'a [u8],
1065}
1066
1067#[repr(C)]
1069#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1070#[allow(missing_docs)]
1071pub struct InlineSite2Fixed {
1072 pub block: BlockHeader,
1073 pub inlinee: ItemIdLe,
1074 pub invocations: U32<LE>,
1075}
1076
1077impl<'a> Parse<'a> for InlineSite2<'a> {
1078 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1079 Ok(Self {
1080 fixed: p.get()?,
1081 binary_annotations: p.take_rest(),
1082 })
1083 }
1084}
1085
1086#[repr(C)]
1089#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1090#[allow(missing_docs)]
1091pub struct FrameCookie {
1092 pub offset: I32<LE>,
1094 pub reg: U16<LE>,
1095 pub cookie_type: u8,
1096 pub flags: u8,
1097}
1098
1099#[repr(C)]
1121#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1122#[allow(missing_docs)]
1123pub struct CallSiteInfo {
1124 pub offset: OffsetSegment,
1125 pub padding: U16<LE>,
1126 pub func_type: TypeIndexLe,
1127}
1128
1129#[repr(C)]
1131#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1132#[allow(missing_docs)]
1133pub struct HeapAllocSite {
1134 pub offset: OffsetSegment,
1135 pub instruction_size: U16<LE>,
1137 pub func_type: TypeIndexLe,
1138}
1139
1140#[allow(missing_docs)]
1142#[derive(Clone, Debug)]
1143pub struct Annotation<'a> {
1144 pub fixed: &'a AnnotationFixed,
1145 pub strings: &'a [u8],
1146}
1147
1148#[repr(C)]
1149#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1150#[allow(missing_docs)]
1151pub struct AnnotationFixed {
1152 pub offset: OffsetSegment,
1153 pub num_strings: U16<LE>,
1154}
1155
1156impl<'a> Parse<'a> for Annotation<'a> {
1157 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1158 Ok(Self {
1159 fixed: p.get()?,
1160 strings: p.take_rest(),
1161 })
1162 }
1163}
1164
1165impl<'a> Annotation<'a> {
1166 pub fn iter_strings(&self) -> AnnotationIterStrings<'a> {
1168 AnnotationIterStrings {
1169 num_strings: self.fixed.num_strings.get(),
1170 bytes: self.strings,
1171 }
1172 }
1173}
1174
1175#[allow(missing_docs)]
1177pub struct AnnotationIterStrings<'a> {
1178 pub num_strings: u16,
1179 pub bytes: &'a [u8],
1180}
1181
1182impl<'a> Iterator for AnnotationIterStrings<'a> {
1183 type Item = &'a BStr;
1184
1185 fn next(&mut self) -> Option<Self::Item> {
1186 if self.num_strings == 0 {
1187 return None;
1188 }
1189
1190 self.num_strings -= 1;
1191 let mut p = Parser::new(self.bytes);
1192 let s = p.strz().ok()?;
1193 self.bytes = p.into_rest();
1194 Some(s)
1195 }
1196}
1197
1198#[derive(Clone, Debug)]
1200pub struct HotPatchFunc<'a> {
1201 pub func: ItemId,
1203
1204 pub name: &'a BStr,
1206}
1207
1208impl<'a> Parse<'a> for HotPatchFunc<'a> {
1209 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1210 Ok(Self {
1211 func: p.u32()?,
1212 name: p.strz()?,
1213 })
1214 }
1215}
1216
1217pub const TRAMPOLINE_KIND_INCREMENTAL: u16 = 0;
1221pub const TRAMPOLINE_KIND_BRANCH_ISLAND: u16 = 1;
1223
1224#[derive(Clone, Debug)]
1226#[allow(missing_docs)]
1227pub enum SymData<'a> {
1228 Unknown,
1229 ObjName(ObjectName<'a>),
1230 Compile3(Compile3<'a>),
1231 Proc(Proc<'a>),
1232 Udt(Udt<'a>),
1233 Constant(Constant<'a>),
1234 ManagedConstant(ManagedConstant<'a>),
1235 RefSym2(RefSym2<'a>),
1236 Data(Data<'a>),
1237 ThreadData(ThreadStorageData<'a>),
1238 Pub(Pub<'a>),
1239 End,
1240 FrameProc(&'a FrameProc),
1241 RegRel(RegRel<'a>),
1242 Block(Block<'a>),
1243 Local(Local<'a>),
1244 DefRangeFramePointerRel(DefRangeSymFramePointerRel<'a>),
1245 DefRangeRegister(DefRangeRegister<'a>),
1246 DefRangeRegisterRel(DefRangeRegisterRel<'a>),
1247 DefRangeFramePointerRelFullScope(&'a DefRangeFramePointerRelFullScope),
1248 DefRangeSubFieldRegister(DefRangeSubFieldRegister<'a>),
1249 Trampoline(Trampoline<'a>),
1250 BuildInfo(BuildInfo),
1251 UsingNamespace(UsingNamespace<'a>),
1252 InlineSiteEnd,
1253 Label(Label<'a>),
1254 FunctionList(FunctionList<'a>),
1255 InlineSite(InlineSite<'a>),
1256 InlineSite2(InlineSite2<'a>),
1257 FrameCookie(&'a FrameCookie),
1258 CallSiteInfo(&'a CallSiteInfo),
1259 HeapAllocSite(&'a HeapAllocSite),
1260 ManagedProc(ManagedProc<'a>),
1261 Annotation(Annotation<'a>),
1262 HotPatchFunc(HotPatchFunc<'a>),
1263}
1264
1265impl<'a> SymData<'a> {
1266 pub fn parse(kind: SymKind, data: &'a [u8]) -> Result<Self, ParserError> {
1269 let mut p = Parser::new(data);
1270 Self::from_parser(kind, &mut p)
1271 }
1272
1273 pub fn from_parser(kind: SymKind, p: &mut Parser<'a>) -> Result<Self, ParserError> {
1279 Ok(match kind {
1280 SymKind::S_OBJNAME => Self::ObjName(p.parse()?),
1281 SymKind::S_GPROC32 | SymKind::S_LPROC32 => Self::Proc(p.parse()?),
1282 SymKind::S_COMPILE3 => Self::Compile3(p.parse()?),
1283 SymKind::S_UDT => Self::Udt(p.parse()?),
1284 SymKind::S_CONSTANT => Self::Constant(p.parse()?),
1285 SymKind::S_MANCONSTANT => Self::Constant(p.parse()?),
1286 SymKind::S_PUB32 => Self::Pub(p.parse()?),
1287 SymKind::S_PUB32_ST => Self::Pub(Pub::parse_st(p)?),
1288
1289 SymKind::S_PROCREF
1290 | SymKind::S_LPROCREF
1291 | SymKind::S_DATAREF
1292 | SymKind::S_ANNOTATIONREF => Self::RefSym2(p.parse()?),
1293
1294 SymKind::S_LDATA32 | SymKind::S_GDATA32 | SymKind::S_LMANDATA | SymKind::S_GMANDATA => {
1295 Self::Data(p.parse()?)
1296 }
1297
1298 SymKind::S_LTHREAD32 | SymKind::S_GTHREAD32 => Self::ThreadData(p.parse()?),
1299 SymKind::S_END => Self::End,
1300 SymKind::S_FRAMEPROC => Self::FrameProc(p.get()?),
1301 SymKind::S_REGREL32 => Self::RegRel(p.parse()?),
1302 SymKind::S_BLOCK32 => Self::Block(p.parse()?),
1303 SymKind::S_LOCAL => Self::Local(p.parse()?),
1304 SymKind::S_DEFRANGE_FRAMEPOINTER_REL => Self::DefRangeFramePointerRel(p.parse()?),
1305 SymKind::S_DEFRANGE_REGISTER => Self::DefRangeRegister(p.parse()?),
1306 SymKind::S_DEFRANGE_REGISTER_REL => Self::DefRangeRegisterRel(p.parse()?),
1307 SymKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE => {
1308 Self::DefRangeFramePointerRelFullScope(p.get()?)
1309 }
1310 SymKind::S_DEFRANGE_SUBFIELD_REGISTER => Self::DefRangeSubFieldRegister(p.parse()?),
1311 SymKind::S_TRAMPOLINE => Self::Trampoline(p.parse()?),
1312 SymKind::S_BUILDINFO => Self::BuildInfo(p.parse()?),
1313 SymKind::S_UNAMESPACE => Self::UsingNamespace(p.parse()?),
1314 SymKind::S_INLINESITE_END => Self::InlineSiteEnd,
1315 SymKind::S_LABEL32 => Self::Label(p.parse()?),
1316 SymKind::S_CALLEES | SymKind::S_CALLERS => Self::FunctionList(p.parse()?),
1317 SymKind::S_INLINESITE => Self::InlineSite(p.parse()?),
1318 SymKind::S_INLINESITE2 => Self::InlineSite2(p.parse()?),
1319 SymKind::S_INLINEES => Self::FunctionList(p.parse()?),
1320 SymKind::S_FRAMECOOKIE => Self::FrameCookie(p.get()?),
1321 SymKind::S_CALLSITEINFO => Self::CallSiteInfo(p.get()?),
1322 SymKind::S_HEAPALLOCSITE => Self::HeapAllocSite(p.get()?),
1323 SymKind::S_GMANPROC | SymKind::S_LMANPROC => Self::ManagedProc(p.parse()?),
1324 SymKind::S_ANNOTATION => Self::Annotation(p.parse()?),
1325 SymKind::S_HOTPATCHFUNC => Self::HotPatchFunc(p.parse()?),
1326
1327 _ => Self::Unknown,
1328 })
1329 }
1330
1331 pub fn name(&self) -> Option<&'a BStr> {
1333 match self {
1334 Self::Proc(proc) => Some(proc.name),
1335 Self::Data(data) => Some(data.name),
1336 Self::ThreadData(thread_data) => Some(thread_data.name),
1337 Self::Udt(udt) => Some(udt.name),
1338 Self::Local(local) => Some(local.name),
1339 Self::RefSym2(refsym) => Some(refsym.name),
1340 Self::Constant(c) => Some(c.name),
1341 Self::ManagedConstant(c) => Some(c.name),
1342 _ => None,
1343 }
1344 }
1345}