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)]
730#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
731#[allow(missing_docs)]
732pub struct DefRangeSymFramePointerRelFixed {
733 pub offset_to_frame_pointer: U32<LE>,
734
735 pub range: LVarAddrRange,
737}
738
739#[allow(missing_docs)]
741#[derive(Clone, Debug)]
742pub struct DefRangeSymFramePointerRel<'a> {
743 pub fixed: &'a DefRangeSymFramePointerRelFixed,
744 pub gaps: &'a [LVarAddrGap],
746}
747
748impl<'a> Parse<'a> for DefRangeSymFramePointerRel<'a> {
749 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
750 let fixed = p.get()?;
751 let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
752 Ok(Self { fixed, gaps })
753 }
754}
755
756#[repr(C)]
760#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
761#[allow(missing_docs)]
762pub struct RangeAttrLe {
763 pub value: U16<LE>,
766}
767
768#[repr(C)]
772#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
773#[allow(missing_docs)]
774pub struct DefRangeRegisterFixed {
775 pub reg: U16<LE>,
777 pub attr: RangeAttrLe,
779}
780
781#[derive(Clone, Debug)]
785#[allow(missing_docs)]
786pub struct DefRangeRegister<'a> {
787 pub fixed: &'a DefRangeRegisterFixed,
788 pub gaps: &'a [u8],
789}
790
791impl<'a> Parse<'a> for DefRangeRegister<'a> {
792 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
793 Ok(Self {
794 fixed: p.get()?,
795 gaps: p.take_rest(),
796 })
797 }
798}
799
800#[allow(missing_docs)]
802#[derive(Debug, Clone)]
803pub struct DefRangeRegisterRel<'a> {
804 pub fixed: &'a DefRangeRegisterRelFixed,
805
806 pub gaps: &'a [u8],
808}
809
810#[repr(C)]
812#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
813pub struct DefRangeRegisterRelFixed {
814 pub base_reg: U16<LE>,
816
817 pub flags: U16<LE>,
823
824 pub base_pointer_offset: I32<LE>,
826
827 pub range: LVarAddrRange,
829}
830
831impl<'a> Parse<'a> for DefRangeRegisterRel<'a> {
832 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
833 Ok(Self {
834 fixed: p.get()?,
835 gaps: p.take_rest(),
836 })
837 }
838}
839
840#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
844#[repr(C)]
845pub struct DefRangeFramePointerRelFullScope {
846 pub frame_pointer_offset: I32<LE>,
848}
849
850#[derive(Clone, Debug)]
854#[allow(missing_docs)]
855pub struct DefRangeSubFieldRegister<'a> {
856 pub fixed: &'a DefRangeSubFieldRegisterFixed,
857 pub gaps: &'a [u8],
858}
859
860#[repr(C)]
861#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
862#[allow(missing_docs)]
863pub struct DefRangeSubFieldRegisterFixed {
864 pub reg: U16<LE>,
865 pub attr: RangeAttrLe,
866 pub flags: U32<LE>,
867 pub range: LVarAddrRange,
868}
869
870impl<'a> Parse<'a> for DefRangeSubFieldRegister<'a> {
871 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
872 Ok(Self {
873 fixed: p.get()?,
874 gaps: p.take_rest(),
875 })
876 }
877}
878
879pub struct ManProcSym<'a> {
883 #[allow(missing_docs)]
884 pub fixed: &'a ManProcSymFixed,
885 #[allow(missing_docs)]
886 pub name: &'a BStr,
887}
888
889pub type TokenIdLe = U32<LE>;
891
892#[repr(C)]
893#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
894#[allow(missing_docs)]
895pub struct ManProcSymFixed {
896 pub block: BlockHeader,
897 pub pnext: U32<LE>,
899 pub len: U32<LE>,
901 pub dbg_start: U32<LE>,
903 pub dbg_end: U32<LE>,
905 pub token: TokenIdLe,
907 pub off: U32<LE>,
908 pub seg: U16<LE>,
909 pub flags: u8, pub padding: u8,
911 pub ret_reg: U16<LE>,
913 }
915
916impl<'a> Parse<'a> for ManProcSym<'a> {
917 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
918 Ok(Self {
919 fixed: p.get()?,
920 name: p.strz()?,
921 })
922 }
923}
924
925#[derive(Clone, Debug)]
927pub struct Trampoline<'a> {
928 pub fixed: &'a TrampolineFixed,
930
931 pub rest: &'a [u8],
933}
934
935#[repr(C)]
937#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
938pub struct TrampolineFixed {
939 pub tramp_type: U16<LE>,
941 pub cb_thunk: U16<LE>,
943 pub off_thunk: U32<LE>,
945 pub off_target: U32<LE>,
947 pub sect_thunk: U16<LE>,
949 pub sect_target: U16<LE>,
951}
952
953impl<'a> Parse<'a> for Trampoline<'a> {
954 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
955 Ok(Self {
956 fixed: p.get()?,
957 rest: p.take_rest(),
958 })
959 }
960}
961
962#[derive(Clone, Debug)]
966pub struct BuildInfo {
967 pub item: ItemId,
969}
970
971impl<'a> Parse<'a> for BuildInfo {
972 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
973 Ok(Self { item: p.u32()? })
974 }
975}
976
977#[derive(Clone, Debug)]
979pub struct UsingNamespace<'a> {
980 pub namespace: &'a BStr,
982}
983
984impl<'a> Parse<'a> for UsingNamespace<'a> {
985 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
986 Ok(Self {
987 namespace: p.strz()?,
988 })
989 }
990}
991
992#[derive(Clone, Debug)]
994#[allow(missing_docs)]
995pub struct Label<'a> {
996 pub fixed: &'a LabelFixed,
997 pub name: &'a BStr,
998}
999
1000#[repr(C)]
1002#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1003#[allow(missing_docs)]
1004pub struct LabelFixed {
1005 pub offset_segment: OffsetSegment,
1006 pub flags: u8,
1007}
1008
1009impl<'a> Parse<'a> for Label<'a> {
1010 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1011 Ok(Self {
1012 fixed: p.get()?,
1013 name: p.strz()?,
1014 })
1015 }
1016}
1017
1018#[derive(Clone, Debug)]
1020pub struct FunctionList<'a> {
1021 pub funcs: &'a [ItemIdLe],
1023
1024 pub counts: &'a [U32<LE>],
1031}
1032
1033impl<'a> Parse<'a> for FunctionList<'a> {
1034 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1035 let num_funcs = p.u32()? as usize;
1036 let funcs: &[ItemIdLe] = p.slice(num_funcs)?;
1037 let num_counts = num_funcs.min(p.len() / size_of::<U32<LE>>());
1038 let counts = p.slice(num_counts)?;
1039 Ok(Self { funcs, counts })
1040 }
1041}
1042
1043#[allow(missing_docs)]
1045#[derive(Clone, Debug)]
1046pub struct InlineSite<'a> {
1047 pub fixed: &'a InlineSiteFixed,
1048 pub binary_annotations: &'a [u8],
1050}
1051
1052#[repr(C)]
1054#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1055#[allow(missing_docs)]
1056pub struct InlineSiteFixed {
1057 pub block: BlockHeader,
1058 pub inlinee: ItemIdLe,
1059}
1060
1061impl<'a> Parse<'a> for InlineSite<'a> {
1062 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1063 Ok(Self {
1064 fixed: p.get()?,
1065 binary_annotations: p.take_rest(),
1066 })
1067 }
1068}
1069
1070#[allow(missing_docs)]
1072#[derive(Clone, Debug)]
1073pub struct InlineSite2<'a> {
1074 pub fixed: &'a InlineSite2Fixed,
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 InlineSite2Fixed {
1084 pub block: BlockHeader,
1085 pub inlinee: ItemIdLe,
1086 pub invocations: U32<LE>,
1087}
1088
1089impl<'a> Parse<'a> for InlineSite2<'a> {
1090 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1091 Ok(Self {
1092 fixed: p.get()?,
1093 binary_annotations: p.take_rest(),
1094 })
1095 }
1096}
1097
1098#[repr(C)]
1101#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1102#[allow(missing_docs)]
1103pub struct FrameCookie {
1104 pub offset: I32<LE>,
1106 pub reg: U16<LE>,
1107 pub cookie_type: u8,
1108 pub flags: u8,
1109}
1110
1111#[repr(C)]
1133#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1134#[allow(missing_docs)]
1135pub struct CallSiteInfo {
1136 pub offset: OffsetSegment,
1137 pub padding: U16<LE>,
1138 pub func_type: TypeIndexLe,
1139}
1140
1141#[repr(C)]
1143#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1144#[allow(missing_docs)]
1145pub struct HeapAllocSite {
1146 pub offset: OffsetSegment,
1147 pub instruction_size: U16<LE>,
1149 pub func_type: TypeIndexLe,
1150}
1151
1152#[allow(missing_docs)]
1154#[derive(Clone, Debug)]
1155pub struct Annotation<'a> {
1156 pub fixed: &'a AnnotationFixed,
1157 pub strings: &'a [u8],
1158}
1159
1160#[repr(C)]
1161#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1162#[allow(missing_docs)]
1163pub struct AnnotationFixed {
1164 pub offset: OffsetSegment,
1165 pub num_strings: U16<LE>,
1166}
1167
1168impl<'a> Parse<'a> for Annotation<'a> {
1169 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1170 Ok(Self {
1171 fixed: p.get()?,
1172 strings: p.take_rest(),
1173 })
1174 }
1175}
1176
1177impl<'a> Annotation<'a> {
1178 pub fn iter_strings(&self) -> AnnotationIterStrings<'a> {
1180 AnnotationIterStrings {
1181 num_strings: self.fixed.num_strings.get(),
1182 bytes: self.strings,
1183 }
1184 }
1185}
1186
1187#[allow(missing_docs)]
1189pub struct AnnotationIterStrings<'a> {
1190 pub num_strings: u16,
1191 pub bytes: &'a [u8],
1192}
1193
1194impl<'a> Iterator for AnnotationIterStrings<'a> {
1195 type Item = &'a BStr;
1196
1197 fn next(&mut self) -> Option<Self::Item> {
1198 if self.num_strings == 0 {
1199 return None;
1200 }
1201
1202 self.num_strings -= 1;
1203 let mut p = Parser::new(self.bytes);
1204 let s = p.strz().ok()?;
1205 self.bytes = p.into_rest();
1206 Some(s)
1207 }
1208}
1209
1210#[derive(Clone, Debug)]
1212pub struct HotPatchFunc<'a> {
1213 pub func: ItemId,
1215
1216 pub name: &'a BStr,
1218}
1219
1220impl<'a> Parse<'a> for HotPatchFunc<'a> {
1221 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1222 Ok(Self {
1223 func: p.u32()?,
1224 name: p.strz()?,
1225 })
1226 }
1227}
1228
1229#[repr(C)]
1236#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone)]
1237pub struct ArmSwitchTable {
1238 pub offset_base: U32<LE>,
1240 pub sect_base: U16<LE>,
1242 pub switch_type: U16<LE>,
1244 pub offset_branch: U32<LE>,
1246 pub offset_table: U32<LE>,
1248 pub sect_branch: U16<LE>,
1250 pub sect_table: U16<LE>,
1252 pub num_entries: U32<LE>,
1254}
1255
1256impl ArmSwitchTable {
1257 pub fn base(&self) -> OffsetSegment {
1265 OffsetSegment {
1266 offset: self.offset_base,
1267 segment: self.sect_base,
1268 }
1269 }
1270
1271 pub fn branch(&self) -> OffsetSegment {
1273 OffsetSegment {
1274 offset: self.offset_branch,
1275 segment: self.sect_branch,
1276 }
1277 }
1278
1279 pub fn table(&self) -> OffsetSegment {
1281 OffsetSegment {
1282 offset: self.offset_table,
1283 segment: self.sect_table,
1284 }
1285 }
1286
1287 pub fn switch_type(&self) -> ArmSwitchType {
1289 ArmSwitchType(self.switch_type.get())
1290 }
1291
1292 pub fn num_entries(&self) -> u32 {
1294 self.num_entries.get()
1295 }
1296}
1297
1298impl core::fmt::Debug for ArmSwitchTable {
1299 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1300 f.debug_struct("ArmSwitchTable")
1301 .field("base", &self.base())
1302 .field("branch", &self.branch())
1303 .field("table", &self.table())
1304 .field("switch_type", &self.switch_type())
1305 .field("num_entries", &self.num_entries())
1306 .finish()
1307 }
1308}
1309
1310#[derive(Copy, Clone, Eq, PartialEq)]
1312pub struct ArmSwitchType(pub u16);
1313
1314impl ArmSwitchType {
1315 pub const INT1: ArmSwitchType = ArmSwitchType(0);
1317 pub const UINT1: ArmSwitchType = ArmSwitchType(1);
1319 pub const INT2: ArmSwitchType = ArmSwitchType(2);
1321 pub const UINT2: ArmSwitchType = ArmSwitchType(3);
1323 pub const INT4: ArmSwitchType = ArmSwitchType(4);
1325 pub const UINT4: ArmSwitchType = ArmSwitchType(5);
1327 pub const POINTER: ArmSwitchType = ArmSwitchType(6);
1329 pub const UINT1SHL1: ArmSwitchType = ArmSwitchType(7);
1331 pub const UINT2SHL1: ArmSwitchType = ArmSwitchType(8);
1333 pub const INT1SHL1: ArmSwitchType = ArmSwitchType(9);
1335 pub const INT2SHL1: ArmSwitchType = ArmSwitchType(10);
1337 }
1340
1341impl core::fmt::Debug for ArmSwitchType {
1342 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1343 static NAMES: [&str; 11] = [
1344 "INT1",
1345 "UINT1",
1346 "INT2",
1347 "UINT2",
1348 "INT4",
1349 "UINT4",
1350 "POINTER",
1351 "UINT1SHL1",
1352 "UINT2SHL1",
1353 "INT1SHL1",
1354 "INT2SHL1",
1355 ];
1356
1357 if let Some(&s) = NAMES.get(self.0 as usize) {
1358 f.write_str(s)
1359 } else {
1360 write!(f, "??{}", self.0)
1361 }
1362 }
1363}
1364
1365pub const TRAMPOLINE_KIND_INCREMENTAL: u16 = 0;
1369pub const TRAMPOLINE_KIND_BRANCH_ISLAND: u16 = 1;
1371
1372#[repr(C)]
1374#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1375pub struct CoffGroupFixed {
1376 pub cb: U32<LE>,
1378 pub characteristics: U32<LE>,
1382 pub off_seg: OffsetSegment,
1384}
1385
1386#[derive(Clone, Debug)]
1392pub struct CoffGroup<'a> {
1393 pub fixed: &'a CoffGroupFixed,
1395 pub name: &'a BStr,
1397}
1398
1399impl<'a> Parse<'a> for CoffGroup<'a> {
1400 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1401 Ok(Self {
1402 fixed: p.get()?,
1403 name: p.strz()?,
1404 })
1405 }
1406}
1407
1408#[derive(Clone, Debug)]
1410pub struct Section<'a> {
1411 pub fixed: &'a SectionFixed,
1413 pub name: &'a BStr,
1415}
1416
1417#[repr(C)]
1419#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1420pub struct SectionFixed {
1421 pub section: U16<LE>,
1423 pub align: u8,
1425 pub reserved: u8,
1427 pub rva: U32<LE>,
1429 pub cb: U32<LE>,
1431 pub characteristics: U32<LE>,
1433}
1434
1435impl<'a> Parse<'a> for Section<'a> {
1436 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1437 Ok(Self {
1438 fixed: p.get()?,
1439 name: p.strz()?,
1440 })
1441 }
1442}
1443
1444#[derive(Clone, Debug)]
1446#[allow(missing_docs)]
1447pub enum SymData<'a> {
1448 Unknown,
1449 ObjName(ObjectName<'a>),
1450 Compile3(Compile3<'a>),
1451 Proc(Proc<'a>),
1452 Udt(Udt<'a>),
1453 Constant(Constant<'a>),
1454 ManagedConstant(ManagedConstant<'a>),
1455 RefSym2(RefSym2<'a>),
1456 Data(Data<'a>),
1457 ThreadData(ThreadStorageData<'a>),
1458 Pub(Pub<'a>),
1459 End,
1460 FrameProc(&'a FrameProc),
1461 RegRel(RegRel<'a>),
1462 Block(Block<'a>),
1463 Local(Local<'a>),
1464 DefRangeFramePointerRel(DefRangeSymFramePointerRel<'a>),
1465 DefRangeRegister(DefRangeRegister<'a>),
1466 DefRangeRegisterRel(DefRangeRegisterRel<'a>),
1467 DefRangeFramePointerRelFullScope(&'a DefRangeFramePointerRelFullScope),
1468 DefRangeSubFieldRegister(DefRangeSubFieldRegister<'a>),
1469 Trampoline(Trampoline<'a>),
1470 BuildInfo(BuildInfo),
1471 UsingNamespace(UsingNamespace<'a>),
1472 InlineSiteEnd,
1473 Label(Label<'a>),
1474 FunctionList(FunctionList<'a>),
1475 InlineSite(InlineSite<'a>),
1476 InlineSite2(InlineSite2<'a>),
1477 FrameCookie(&'a FrameCookie),
1478 CallSiteInfo(&'a CallSiteInfo),
1479 HeapAllocSite(&'a HeapAllocSite),
1480 ManagedProc(ManagedProc<'a>),
1481 Annotation(Annotation<'a>),
1482 HotPatchFunc(HotPatchFunc<'a>),
1483 CoffGroup(CoffGroup<'a>),
1484 ArmSwitchTable(&'a ArmSwitchTable),
1485 Section(Section<'a>),
1486}
1487
1488impl<'a> SymData<'a> {
1489 pub fn parse(kind: SymKind, data: &'a [u8]) -> Result<Self, ParserError> {
1492 let mut p = Parser::new(data);
1493 Self::from_parser(kind, &mut p)
1494 }
1495
1496 pub fn from_parser(kind: SymKind, p: &mut Parser<'a>) -> Result<Self, ParserError> {
1502 Ok(match kind {
1503 SymKind::S_OBJNAME => Self::ObjName(p.parse()?),
1504 SymKind::S_GPROC32 | SymKind::S_LPROC32 => Self::Proc(p.parse()?),
1505 SymKind::S_COMPILE3 => Self::Compile3(p.parse()?),
1506 SymKind::S_UDT => Self::Udt(p.parse()?),
1507 SymKind::S_CONSTANT => Self::Constant(p.parse()?),
1508 SymKind::S_MANCONSTANT => Self::Constant(p.parse()?),
1509 SymKind::S_PUB32 => Self::Pub(p.parse()?),
1510 SymKind::S_PUB32_ST => Self::Pub(Pub::parse_st(p)?),
1511
1512 SymKind::S_PROCREF
1513 | SymKind::S_LPROCREF
1514 | SymKind::S_DATAREF
1515 | SymKind::S_ANNOTATIONREF => Self::RefSym2(p.parse()?),
1516
1517 SymKind::S_LDATA32 | SymKind::S_GDATA32 | SymKind::S_LMANDATA | SymKind::S_GMANDATA => {
1518 Self::Data(p.parse()?)
1519 }
1520
1521 SymKind::S_LTHREAD32 | SymKind::S_GTHREAD32 => Self::ThreadData(p.parse()?),
1522 SymKind::S_END => Self::End,
1523 SymKind::S_FRAMEPROC => Self::FrameProc(p.get()?),
1524 SymKind::S_REGREL32 => Self::RegRel(p.parse()?),
1525 SymKind::S_BLOCK32 => Self::Block(p.parse()?),
1526 SymKind::S_LOCAL => Self::Local(p.parse()?),
1527 SymKind::S_DEFRANGE_FRAMEPOINTER_REL => Self::DefRangeFramePointerRel(p.parse()?),
1528 SymKind::S_DEFRANGE_REGISTER => Self::DefRangeRegister(p.parse()?),
1529 SymKind::S_DEFRANGE_REGISTER_REL => Self::DefRangeRegisterRel(p.parse()?),
1530 SymKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE => {
1531 Self::DefRangeFramePointerRelFullScope(p.get()?)
1532 }
1533 SymKind::S_DEFRANGE_SUBFIELD_REGISTER => Self::DefRangeSubFieldRegister(p.parse()?),
1534 SymKind::S_TRAMPOLINE => Self::Trampoline(p.parse()?),
1535 SymKind::S_BUILDINFO => Self::BuildInfo(p.parse()?),
1536 SymKind::S_UNAMESPACE => Self::UsingNamespace(p.parse()?),
1537 SymKind::S_INLINESITE_END => Self::InlineSiteEnd,
1538 SymKind::S_LABEL32 => Self::Label(p.parse()?),
1539 SymKind::S_CALLEES | SymKind::S_CALLERS => Self::FunctionList(p.parse()?),
1540 SymKind::S_INLINESITE => Self::InlineSite(p.parse()?),
1541 SymKind::S_INLINESITE2 => Self::InlineSite2(p.parse()?),
1542 SymKind::S_INLINEES => Self::FunctionList(p.parse()?),
1543 SymKind::S_FRAMECOOKIE => Self::FrameCookie(p.get()?),
1544 SymKind::S_CALLSITEINFO => Self::CallSiteInfo(p.get()?),
1545 SymKind::S_HEAPALLOCSITE => Self::HeapAllocSite(p.get()?),
1546 SymKind::S_GMANPROC | SymKind::S_LMANPROC => Self::ManagedProc(p.parse()?),
1547 SymKind::S_ANNOTATION => Self::Annotation(p.parse()?),
1548 SymKind::S_HOTPATCHFUNC => Self::HotPatchFunc(p.parse()?),
1549 SymKind::S_ARMSWITCHTABLE => Self::ArmSwitchTable(p.get()?),
1550 SymKind::S_COFFGROUP => Self::CoffGroup(p.parse()?),
1551 SymKind::S_SECTION => Self::Section(p.parse()?),
1552
1553 _ => Self::Unknown,
1554 })
1555 }
1556
1557 pub fn name(&self) -> Option<&'a BStr> {
1559 match self {
1560 Self::Proc(proc) => Some(proc.name),
1561 Self::Data(data) => Some(data.name),
1562 Self::ThreadData(thread_data) => Some(thread_data.name),
1563 Self::Udt(udt) => Some(udt.name),
1564 Self::Local(local) => Some(local.name),
1565 Self::RefSym2(refsym) => Some(refsym.name),
1566 Self::Constant(c) => Some(c.name),
1567 Self::ManagedConstant(c) => Some(c.name),
1568 _ => None,
1569 }
1570 }
1571}