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, Debug, 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#[derive(Clone, Debug)]
240#[allow(missing_docs)]
241pub struct Thunk<'a> {
242 pub fixed: &'a ThunkFixed,
243 pub name: &'a BStr,
244 pub variant: &'a [u8],
245}
246
247impl<'a> Parse<'a> for Thunk<'a> {
248 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
249 Ok(Self {
250 fixed: p.get()?,
251 name: p.strz()?,
252 variant: p.take_rest(),
253 })
254 }
255}
256
257#[repr(C)]
259#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Default)]
260pub struct SymHeader {
261 pub len: U16<LE>,
266
267 pub kind: U16<LE>,
269}
270
271#[derive(Clone)]
273pub struct Sym<'a> {
274 pub kind: SymKind,
276 pub data: &'a [u8],
278}
279
280impl<'a> Sym<'a> {
281 pub fn parse(&self) -> Result<SymData<'a>, ParserError> {
283 SymData::parse(self.kind, self.data)
284 }
285
286 pub fn parse_as<T>(&self) -> Result<T, ParserError>
291 where
292 T: Parse<'a>,
293 {
294 let mut p = Parser::new(self.data);
295 p.parse::<T>()
296 }
297}
298
299impl<'a> Debug for Sym<'a> {
300 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
301 write!(fmt, "{:?}", self.kind)
302 }
303}
304
305pub struct SymMut<'a> {
308 pub kind: SymKind,
310 pub data: &'a mut [u8],
312}
313
314#[allow(missing_docs)]
327#[derive(Clone, Debug)]
328pub struct Pub<'a> {
329 pub fixed: &'a PubFixed,
330 pub name: &'a BStr,
331}
332
333impl<'a> Pub<'a> {
334 pub fn offset_segment(&self) -> OffsetSegment {
336 self.fixed.offset_segment
337 }
338}
339
340#[allow(missing_docs)]
341#[repr(C)]
342#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
343pub struct PubFixed {
344 pub flags: U32<LE>,
345 pub offset_segment: OffsetSegment,
346 }
348
349#[allow(missing_docs)]
350impl<'a> Parse<'a> for Pub<'a> {
351 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
352 Ok(Self {
353 fixed: p.get()?,
354 name: p.strz()?,
355 })
356 }
357}
358
359impl<'a> Pub<'a> {
360 pub fn parse_st(p: &mut Parser<'a>) -> Result<Self, ParserError> {
362 Ok(Self {
363 fixed: p.get()?,
364 name: p.strt_raw()?,
365 })
366 }
367}
368
369#[allow(missing_docs)]
371#[derive(Clone, Debug)]
372pub struct Constant<'a> {
373 pub type_: TypeIndex,
374 pub value: Number<'a>,
375 pub name: &'a BStr,
376}
377
378impl<'a> Parse<'a> for Constant<'a> {
379 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
380 Ok(Self {
381 type_: p.type_index()?,
382 value: p.number()?,
383 name: p.strz()?,
384 })
385 }
386}
387
388#[allow(missing_docs)]
390#[derive(Clone, Debug)]
391pub struct ManagedConstant<'a> {
392 pub token: u32,
393 pub value: Number<'a>,
394 pub name: &'a BStr,
395}
396
397impl<'a> Parse<'a> for ManagedConstant<'a> {
398 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
399 Ok(Self {
400 token: p.u32()?,
401 value: p.number()?,
402 name: p.strz()?,
403 })
404 }
405}
406
407#[allow(missing_docs)]
415#[derive(Clone, Debug)]
416pub struct RefSym2<'a> {
417 pub header: &'a RefSym2Fixed,
418 pub name: &'a BStr,
419}
420
421#[allow(missing_docs)]
422#[repr(C)]
423#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
424pub struct RefSym2Fixed {
425 pub name_checksum: U32<LE>,
429
430 pub symbol_offset: U32<LE>,
435
436 pub module_index: U16<LE>,
440 }
442
443impl<'a> Parse<'a> for RefSym2<'a> {
444 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
445 Ok(Self {
446 header: p.get()?,
447 name: p.strz()?,
448 })
449 }
450}
451
452#[allow(missing_docs)]
453#[repr(C)]
454#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
455pub struct ThreadStorageFixed {
456 pub type_: TypeIndexLe,
457 pub offset_segment: OffsetSegment,
458}
459
460#[derive(Clone, Debug)]
464pub struct ThreadStorageData<'a> {
465 #[allow(missing_docs)]
466 pub header: &'a ThreadStorageFixed,
467 #[allow(missing_docs)]
468 pub name: &'a BStr,
469}
470
471impl<'a> Parse<'a> for ThreadStorageData<'a> {
472 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
473 Ok(Self {
474 header: p.get()?,
475 name: p.strz()?,
476 })
477 }
478}
479
480#[allow(missing_docs)]
481#[repr(C)]
482#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
483pub struct DataFixed {
484 pub type_: TypeIndexLe,
485 pub offset_segment: OffsetSegment,
486}
487
488#[allow(missing_docs)]
490#[derive(Clone)]
491pub struct Data<'a> {
492 pub header: &'a DataFixed,
493 pub name: &'a BStr,
494}
495
496impl<'a> Parse<'a> for Data<'a> {
497 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
498 Ok(Self {
499 header: p.get()?,
500 name: p.strz()?,
501 })
502 }
503}
504
505impl<'a> Debug for Data<'a> {
506 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
507 write!(
508 f,
509 "Data: {} {:?} {}",
510 self.header.offset_segment,
511 self.header.type_.get(),
512 self.name
513 )
514 }
515}
516
517#[derive(Clone, Debug)]
519pub struct Udt<'a> {
520 pub type_: TypeIndex,
522 pub name: &'a BStr,
524}
525
526impl<'a> Parse<'a> for Udt<'a> {
527 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
528 Ok(Self {
529 type_: p.type_index()?,
530 name: p.strz()?,
531 })
532 }
533}
534
535#[derive(Clone, Debug)]
537pub struct ObjectName<'a> {
538 pub signature: u32,
541 pub name: &'a BStr,
543}
544
545impl<'a> Parse<'a> for ObjectName<'a> {
546 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
547 Ok(Self {
548 signature: p.u32()?,
549 name: p.strz()?,
550 })
551 }
552}
553
554#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
556#[repr(C)]
557#[allow(missing_docs)]
558pub struct Compile3Fixed {
559 pub flags: U32<LE>,
560 pub machine: U16<LE>,
561 pub frontend_major: U16<LE>,
562 pub frontend_minor: U16<LE>,
563 pub frontend_build: U16<LE>,
564 pub frontend_qfe: U16<LE>,
565 pub ver_major: U16<LE>,
566 pub ver_minor: U16<LE>,
567 pub ver_build: U16<LE>,
568 pub ver_qfe: U16<LE>,
569 }
571
572#[allow(missing_docs)]
574#[derive(Clone, Debug)]
575pub struct Compile3<'a> {
576 pub fixed: &'a Compile3Fixed,
577 pub name: &'a BStr,
578}
579
580impl<'a> Parse<'a> for Compile3<'a> {
581 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
582 Ok(Self {
583 fixed: p.get()?,
584 name: p.strz()?,
585 })
586 }
587}
588
589#[repr(C)]
593#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
594#[allow(missing_docs)]
595pub struct FrameProc {
596 frame_size: U32<LE>,
598 pad_size: U32<LE>,
600 pad_offset: U32<LE>,
602 save_regs_size: U32<LE>,
604 offset_exception_handler: U32<LE>,
605 exception_handler_section: U16<LE>,
606 padding: U16<LE>,
607 flags: U32<LE>,
608}
609
610#[repr(C)]
611#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
612#[allow(missing_docs)]
613pub struct RegRelFixed {
614 pub offset: U32<LE>,
615 pub ty: TypeIndexLe,
616 pub register: U16<LE>,
617 }
619
620#[derive(Clone, Debug)]
623#[allow(missing_docs)]
624pub struct RegRel<'a> {
625 pub fixed: &'a RegRelFixed,
626 pub name: &'a BStr,
627}
628
629impl<'a> Parse<'a> for RegRel<'a> {
630 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
631 Ok(Self {
632 fixed: p.get()?,
633 name: p.strz()?,
634 })
635 }
636}
637
638#[derive(Clone, Debug)]
646#[allow(missing_docs)]
647pub struct Block<'a> {
648 pub fixed: &'a BlockFixed,
649 pub name: &'a BStr,
650}
651
652#[repr(C)]
653#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
654#[allow(missing_docs)]
655pub struct BlockFixed {
656 pub header: BlockHeader,
658
659 pub length: U32<LE>,
661
662 pub offset_segment: OffsetSegment,
663}
664
665impl<'a> Parse<'a> for Block<'a> {
666 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
667 Ok(Self {
668 fixed: p.get()?,
669 name: p.strz()?,
670 })
671 }
672}
673
674#[derive(Clone, Debug)]
679#[allow(missing_docs)]
680pub struct Local<'a> {
681 pub fixed: &'a LocalFixed,
682 pub name: &'a BStr,
683}
684
685#[repr(C)]
686#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
687#[allow(missing_docs)]
688pub struct LocalFixed {
689 pub ty: TypeIndexLe,
690 pub flags: U16<LE>,
692 }
694
695impl<'a> Parse<'a> for Local<'a> {
696 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
697 Ok(Self {
698 fixed: p.get()?,
699 name: p.strz()?,
700 })
701 }
702}
703
704#[repr(C)]
708#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
709pub struct LVarAddrRange {
710 pub start: OffsetSegment,
712 pub range_size: U16<LE>,
714}
715
716#[repr(C)]
721#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
722pub struct LVarAddrGap {
723 pub gap_start_offset: U16<LE>,
725 pub range_size: U16<LE>,
727}
728
729#[repr(C)]
730#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
731#[allow(missing_docs)]
732pub struct DefRangeFixed {
733 pub program: U32<LE>,
735
736 pub range: LVarAddrRange,
737 }
739
740#[allow(missing_docs)]
742#[derive(Clone, Debug)]
743pub struct DefRange<'a> {
744 pub fixed: &'a DefRangeFixed,
745 pub gaps: &'a [LVarAddrGap],
746}
747
748impl<'a> Parse<'a> for DefRange<'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)]
758#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
759#[allow(missing_docs)]
760pub struct DefRangeSymFramePointerRelFixed {
761 pub offset_to_frame_pointer: U32<LE>,
762
763 pub range: LVarAddrRange,
765}
766
767#[allow(missing_docs)]
769#[derive(Clone, Debug)]
770pub struct DefRangeSymFramePointerRel<'a> {
771 pub fixed: &'a DefRangeSymFramePointerRelFixed,
772 pub gaps: &'a [LVarAddrGap],
774}
775
776impl<'a> Parse<'a> for DefRangeSymFramePointerRel<'a> {
777 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
778 let fixed = p.get()?;
779 let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
780 Ok(Self { fixed, gaps })
781 }
782}
783
784#[repr(C)]
788#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
789#[allow(missing_docs)]
790pub struct RangeAttrLe {
791 pub value: U16<LE>,
794}
795
796#[repr(C)]
800#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
801#[allow(missing_docs)]
802pub struct DefRangeRegisterFixed {
803 pub reg: U16<LE>,
805 pub attr: RangeAttrLe,
807}
808
809#[derive(Clone, Debug)]
813#[allow(missing_docs)]
814pub struct DefRangeRegister<'a> {
815 pub fixed: &'a DefRangeRegisterFixed,
816 pub gaps: &'a [u8],
817}
818
819impl<'a> Parse<'a> for DefRangeRegister<'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#[allow(missing_docs)]
830#[derive(Debug, Clone)]
831pub struct DefRangeRegisterRel<'a> {
832 pub fixed: &'a DefRangeRegisterRelFixed,
833
834 pub gaps: &'a [u8],
836}
837
838#[repr(C)]
840#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
841pub struct DefRangeRegisterRelFixed {
842 pub base_reg: U16<LE>,
844
845 pub flags: U16<LE>,
851
852 pub base_pointer_offset: I32<LE>,
854
855 pub range: LVarAddrRange,
857}
858
859impl<'a> Parse<'a> for DefRangeRegisterRel<'a> {
860 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
861 Ok(Self {
862 fixed: p.get()?,
863 gaps: p.take_rest(),
864 })
865 }
866}
867
868#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
872#[repr(C)]
873pub struct DefRangeFramePointerRelFullScope {
874 pub frame_pointer_offset: I32<LE>,
876}
877
878#[derive(Clone, Debug)]
882#[allow(missing_docs)]
883pub struct DefRangeSubFieldRegister<'a> {
884 pub fixed: &'a DefRangeSubFieldRegisterFixed,
885 pub gaps: &'a [u8],
886}
887
888#[repr(C)]
889#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
890#[allow(missing_docs)]
891pub struct DefRangeSubFieldRegisterFixed {
892 pub reg: U16<LE>,
893 pub attr: RangeAttrLe,
894 pub flags: U32<LE>,
895 pub range: LVarAddrRange,
896}
897
898impl<'a> Parse<'a> for DefRangeSubFieldRegister<'a> {
899 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
900 Ok(Self {
901 fixed: p.get()?,
902 gaps: p.take_rest(),
903 })
904 }
905}
906
907pub struct ManProcSym<'a> {
911 #[allow(missing_docs)]
912 pub fixed: &'a ManProcSymFixed,
913 #[allow(missing_docs)]
914 pub name: &'a BStr,
915}
916
917pub type TokenIdLe = U32<LE>;
919
920#[repr(C)]
921#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
922#[allow(missing_docs)]
923pub struct ManProcSymFixed {
924 pub block: BlockHeader,
925 pub pnext: U32<LE>,
927 pub len: U32<LE>,
929 pub dbg_start: U32<LE>,
931 pub dbg_end: U32<LE>,
933 pub token: TokenIdLe,
935 pub off: U32<LE>,
936 pub seg: U16<LE>,
937 pub flags: u8, pub padding: u8,
939 pub ret_reg: U16<LE>,
941 }
943
944impl<'a> Parse<'a> for ManProcSym<'a> {
945 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
946 Ok(Self {
947 fixed: p.get()?,
948 name: p.strz()?,
949 })
950 }
951}
952
953#[derive(Clone, Debug)]
955pub struct Trampoline<'a> {
956 pub fixed: &'a TrampolineFixed,
958
959 pub rest: &'a [u8],
961}
962
963#[repr(C)]
965#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
966pub struct TrampolineFixed {
967 pub kind: U16<LE>,
969 pub thunk_len: U16<LE>,
971 pub thunk_offset: U32<LE>,
973 pub target_offset: U32<LE>,
975 pub thunk_segment: U16<LE>,
977 pub target_segment: U16<LE>,
979}
980
981impl TrampolineFixed {
982 pub fn thunk(&self) -> OffsetSegment {
984 OffsetSegment {
985 offset: self.thunk_offset,
986 segment: self.thunk_segment,
987 }
988 }
989
990 pub fn target(&self) -> OffsetSegment {
992 OffsetSegment {
993 offset: self.target_offset,
994 segment: self.target_segment,
995 }
996 }
997}
998
999impl<'a> Parse<'a> for Trampoline<'a> {
1000 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1001 Ok(Self {
1002 fixed: p.get()?,
1003 rest: p.take_rest(),
1004 })
1005 }
1006}
1007
1008#[test]
1009fn test_trampoline() {
1010 use hex_literal::hex;
1011
1012 let data = hex!(
1013 "0101" "0202" "03030303" "04040404" "0505" "0606" "cccccc" );
1019
1020 let sym = Trampoline::parse(&data).unwrap();
1021
1022 assert_eq!(sym.fixed.kind.get(), 0x0101);
1023 assert_eq!(sym.fixed.thunk_len.get(), 0x0202);
1024 assert_eq!(sym.fixed.thunk_offset.get(), 0x03030303);
1025 assert_eq!(sym.fixed.target_offset.get(), 0x04040404);
1026 assert_eq!(sym.fixed.thunk_segment.get(), 0x0505);
1027 assert_eq!(sym.fixed.target_segment.get(), 0x0606);
1028 assert_eq!(sym.rest, &hex!("cccccc"));
1029
1030 assert_eq!(sym.fixed.thunk().offset, sym.fixed.thunk_offset);
1031 assert_eq!(sym.fixed.thunk().segment, sym.fixed.thunk_segment);
1032 assert_eq!(sym.fixed.target().offset, sym.fixed.target_offset);
1033 assert_eq!(sym.fixed.target().segment, sym.fixed.target_segment);
1034}
1035
1036#[derive(Clone, Debug)]
1040pub struct BuildInfo {
1041 pub item: ItemId,
1043}
1044
1045impl<'a> Parse<'a> for BuildInfo {
1046 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1047 Ok(Self { item: p.u32()? })
1048 }
1049}
1050
1051#[derive(Clone, Debug)]
1053pub struct UsingNamespace<'a> {
1054 pub namespace: &'a BStr,
1056}
1057
1058impl<'a> Parse<'a> for UsingNamespace<'a> {
1059 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1060 Ok(Self {
1061 namespace: p.strz()?,
1062 })
1063 }
1064}
1065
1066#[derive(Clone, Debug)]
1068#[allow(missing_docs)]
1069pub struct Label<'a> {
1070 pub fixed: &'a LabelFixed,
1071 pub name: &'a BStr,
1072}
1073
1074#[repr(C)]
1076#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1077#[allow(missing_docs)]
1078pub struct LabelFixed {
1079 pub offset_segment: OffsetSegment,
1080 pub flags: u8,
1081}
1082
1083impl<'a> Parse<'a> for Label<'a> {
1084 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1085 Ok(Self {
1086 fixed: p.get()?,
1087 name: p.strz()?,
1088 })
1089 }
1090}
1091
1092#[derive(Clone, Debug)]
1094pub struct FunctionList<'a> {
1095 pub funcs: &'a [ItemIdLe],
1097
1098 pub counts: &'a [U32<LE>],
1105}
1106
1107impl<'a> Parse<'a> for FunctionList<'a> {
1108 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1109 let num_funcs = p.u32()? as usize;
1110 let funcs: &[ItemIdLe] = p.slice(num_funcs)?;
1111 let num_counts = num_funcs.min(p.len() / size_of::<U32<LE>>());
1112 let counts = p.slice(num_counts)?;
1113 Ok(Self { funcs, counts })
1114 }
1115}
1116
1117#[allow(missing_docs)]
1119#[derive(Clone, Debug)]
1120pub struct InlineSite<'a> {
1121 pub fixed: &'a InlineSiteFixed,
1122 pub binary_annotations: &'a [u8],
1124}
1125
1126#[repr(C)]
1128#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1129#[allow(missing_docs)]
1130pub struct InlineSiteFixed {
1131 pub block: BlockHeader,
1132 pub inlinee: ItemIdLe,
1133}
1134
1135impl<'a> Parse<'a> for InlineSite<'a> {
1136 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1137 Ok(Self {
1138 fixed: p.get()?,
1139 binary_annotations: p.take_rest(),
1140 })
1141 }
1142}
1143
1144#[allow(missing_docs)]
1146#[derive(Clone, Debug)]
1147pub struct InlineSite2<'a> {
1148 pub fixed: &'a InlineSite2Fixed,
1149 pub binary_annotations: &'a [u8],
1151}
1152
1153#[repr(C)]
1155#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1156#[allow(missing_docs)]
1157pub struct InlineSite2Fixed {
1158 pub block: BlockHeader,
1159 pub inlinee: ItemIdLe,
1160 pub invocations: U32<LE>,
1161}
1162
1163impl<'a> Parse<'a> for InlineSite2<'a> {
1164 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1165 Ok(Self {
1166 fixed: p.get()?,
1167 binary_annotations: p.take_rest(),
1168 })
1169 }
1170}
1171
1172#[repr(C)]
1175#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1176#[allow(missing_docs)]
1177pub struct FrameCookie {
1178 pub offset: I32<LE>,
1180 pub reg: U16<LE>,
1181 pub cookie_type: u8,
1182 pub flags: u8,
1183}
1184
1185#[repr(C)]
1207#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1208#[allow(missing_docs)]
1209pub struct CallSiteInfo {
1210 pub offset: OffsetSegment,
1211 pub padding: U16<LE>,
1212 pub func_type: TypeIndexLe,
1213}
1214
1215#[repr(C)]
1217#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1218#[allow(missing_docs)]
1219pub struct HeapAllocSite {
1220 pub offset: OffsetSegment,
1221 pub instruction_size: U16<LE>,
1223 pub func_type: TypeIndexLe,
1224}
1225
1226#[allow(missing_docs)]
1228#[derive(Clone, Debug)]
1229pub struct Annotation<'a> {
1230 pub fixed: &'a AnnotationFixed,
1231 pub strings: &'a [u8],
1232}
1233
1234#[repr(C)]
1235#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1236#[allow(missing_docs)]
1237pub struct AnnotationFixed {
1238 pub offset: OffsetSegment,
1239 pub num_strings: U16<LE>,
1240}
1241
1242impl<'a> Parse<'a> for Annotation<'a> {
1243 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1244 Ok(Self {
1245 fixed: p.get()?,
1246 strings: p.take_rest(),
1247 })
1248 }
1249}
1250
1251impl<'a> Annotation<'a> {
1252 pub fn iter_strings(&self) -> AnnotationIterStrings<'a> {
1254 AnnotationIterStrings {
1255 num_strings: self.fixed.num_strings.get(),
1256 bytes: self.strings,
1257 }
1258 }
1259}
1260
1261#[allow(missing_docs)]
1263pub struct AnnotationIterStrings<'a> {
1264 pub num_strings: u16,
1265 pub bytes: &'a [u8],
1266}
1267
1268impl<'a> Iterator for AnnotationIterStrings<'a> {
1269 type Item = &'a BStr;
1270
1271 fn next(&mut self) -> Option<Self::Item> {
1272 if self.num_strings == 0 {
1273 return None;
1274 }
1275
1276 self.num_strings -= 1;
1277 let mut p = Parser::new(self.bytes);
1278 let s = p.strz().ok()?;
1279 self.bytes = p.into_rest();
1280 Some(s)
1281 }
1282}
1283
1284#[derive(Clone, Debug)]
1286pub struct HotPatchFunc<'a> {
1287 pub func: ItemId,
1289
1290 pub name: &'a BStr,
1292}
1293
1294impl<'a> Parse<'a> for HotPatchFunc<'a> {
1295 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1296 Ok(Self {
1297 func: p.u32()?,
1298 name: p.strz()?,
1299 })
1300 }
1301}
1302
1303#[repr(C)]
1310#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone)]
1311pub struct ArmSwitchTable {
1312 pub offset_base: U32<LE>,
1314 pub sect_base: U16<LE>,
1316 pub switch_type: U16<LE>,
1318 pub offset_branch: U32<LE>,
1320 pub offset_table: U32<LE>,
1322 pub sect_branch: U16<LE>,
1324 pub sect_table: U16<LE>,
1326 pub num_entries: U32<LE>,
1328}
1329
1330impl ArmSwitchTable {
1331 pub fn base(&self) -> OffsetSegment {
1339 OffsetSegment {
1340 offset: self.offset_base,
1341 segment: self.sect_base,
1342 }
1343 }
1344
1345 pub fn branch(&self) -> OffsetSegment {
1347 OffsetSegment {
1348 offset: self.offset_branch,
1349 segment: self.sect_branch,
1350 }
1351 }
1352
1353 pub fn table(&self) -> OffsetSegment {
1355 OffsetSegment {
1356 offset: self.offset_table,
1357 segment: self.sect_table,
1358 }
1359 }
1360
1361 pub fn switch_type(&self) -> ArmSwitchType {
1363 ArmSwitchType(self.switch_type.get())
1364 }
1365
1366 pub fn num_entries(&self) -> u32 {
1368 self.num_entries.get()
1369 }
1370}
1371
1372impl core::fmt::Debug for ArmSwitchTable {
1373 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1374 f.debug_struct("ArmSwitchTable")
1375 .field("base", &self.base())
1376 .field("branch", &self.branch())
1377 .field("table", &self.table())
1378 .field("switch_type", &self.switch_type())
1379 .field("num_entries", &self.num_entries())
1380 .finish()
1381 }
1382}
1383
1384#[derive(Copy, Clone, Eq, PartialEq)]
1386pub struct ArmSwitchType(pub u16);
1387
1388impl ArmSwitchType {
1389 pub const INT1: ArmSwitchType = ArmSwitchType(0);
1391 pub const UINT1: ArmSwitchType = ArmSwitchType(1);
1393 pub const INT2: ArmSwitchType = ArmSwitchType(2);
1395 pub const UINT2: ArmSwitchType = ArmSwitchType(3);
1397 pub const INT4: ArmSwitchType = ArmSwitchType(4);
1399 pub const UINT4: ArmSwitchType = ArmSwitchType(5);
1401 pub const POINTER: ArmSwitchType = ArmSwitchType(6);
1403 pub const UINT1SHL1: ArmSwitchType = ArmSwitchType(7);
1405 pub const UINT2SHL1: ArmSwitchType = ArmSwitchType(8);
1407 pub const INT1SHL1: ArmSwitchType = ArmSwitchType(9);
1409 pub const INT2SHL1: ArmSwitchType = ArmSwitchType(10);
1411 }
1414
1415impl core::fmt::Debug for ArmSwitchType {
1416 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1417 static NAMES: [&str; 11] = [
1418 "INT1",
1419 "UINT1",
1420 "INT2",
1421 "UINT2",
1422 "INT4",
1423 "UINT4",
1424 "POINTER",
1425 "UINT1SHL1",
1426 "UINT2SHL1",
1427 "INT1SHL1",
1428 "INT2SHL1",
1429 ];
1430
1431 if let Some(&s) = NAMES.get(self.0 as usize) {
1432 f.write_str(s)
1433 } else {
1434 write!(f, "??{}", self.0)
1435 }
1436 }
1437}
1438
1439pub const TRAMPOLINE_KIND_INCREMENTAL: u16 = 0;
1443pub const TRAMPOLINE_KIND_BRANCH_ISLAND: u16 = 1;
1445
1446#[repr(C)]
1448#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1449pub struct CoffGroupFixed {
1450 pub cb: U32<LE>,
1452 pub characteristics: U32<LE>,
1456 pub off_seg: OffsetSegment,
1458}
1459
1460#[derive(Clone, Debug)]
1466pub struct CoffGroup<'a> {
1467 pub fixed: &'a CoffGroupFixed,
1469 pub name: &'a BStr,
1471}
1472
1473impl<'a> Parse<'a> for CoffGroup<'a> {
1474 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1475 Ok(Self {
1476 fixed: p.get()?,
1477 name: p.strz()?,
1478 })
1479 }
1480}
1481
1482#[derive(Clone, Debug)]
1484pub struct Section<'a> {
1485 pub fixed: &'a SectionFixed,
1487 pub name: &'a BStr,
1489}
1490
1491#[repr(C)]
1493#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
1494pub struct SectionFixed {
1495 pub section: U16<LE>,
1497 pub align: u8,
1499 pub reserved: u8,
1501 pub rva: U32<LE>,
1503 pub cb: U32<LE>,
1505 pub characteristics: U32<LE>,
1507}
1508
1509impl<'a> Parse<'a> for Section<'a> {
1510 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
1511 Ok(Self {
1512 fixed: p.get()?,
1513 name: p.strz()?,
1514 })
1515 }
1516}
1517
1518#[derive(Clone, Debug)]
1520#[allow(missing_docs)]
1521pub enum SymData<'a> {
1522 Unknown,
1523 ObjName(ObjectName<'a>),
1524 Compile3(Compile3<'a>),
1525 Proc(Proc<'a>),
1526 Thunk(Thunk<'a>),
1527 Udt(Udt<'a>),
1528 Constant(Constant<'a>),
1529 ManagedConstant(ManagedConstant<'a>),
1530 RefSym2(RefSym2<'a>),
1531 Data(Data<'a>),
1532 ThreadData(ThreadStorageData<'a>),
1533 Pub(Pub<'a>),
1534 End,
1535 FrameProc(&'a FrameProc),
1536 RegRel(RegRel<'a>),
1537 Block(Block<'a>),
1538 Local(Local<'a>),
1539 DefRange(DefRange<'a>),
1540 DefRangeFramePointerRel(DefRangeSymFramePointerRel<'a>),
1541 DefRangeRegister(DefRangeRegister<'a>),
1542 DefRangeRegisterRel(DefRangeRegisterRel<'a>),
1543 DefRangeFramePointerRelFullScope(&'a DefRangeFramePointerRelFullScope),
1544 DefRangeSubFieldRegister(DefRangeSubFieldRegister<'a>),
1545 Trampoline(Trampoline<'a>),
1546 BuildInfo(BuildInfo),
1547 UsingNamespace(UsingNamespace<'a>),
1548 InlineSiteEnd,
1549 Label(Label<'a>),
1550 FunctionList(FunctionList<'a>),
1551 InlineSite(InlineSite<'a>),
1552 InlineSite2(InlineSite2<'a>),
1553 FrameCookie(&'a FrameCookie),
1554 CallSiteInfo(&'a CallSiteInfo),
1555 HeapAllocSite(&'a HeapAllocSite),
1556 ManagedProc(ManagedProc<'a>),
1557 Annotation(Annotation<'a>),
1558 HotPatchFunc(HotPatchFunc<'a>),
1559 CoffGroup(CoffGroup<'a>),
1560 ArmSwitchTable(&'a ArmSwitchTable),
1561 Section(Section<'a>),
1562}
1563
1564impl<'a> SymData<'a> {
1565 pub fn parse(kind: SymKind, data: &'a [u8]) -> Result<Self, ParserError> {
1568 let mut p = Parser::new(data);
1569 Self::from_parser(kind, &mut p)
1570 }
1571
1572 pub fn from_parser(kind: SymKind, p: &mut Parser<'a>) -> Result<Self, ParserError> {
1578 Ok(match kind {
1579 SymKind::S_OBJNAME => Self::ObjName(p.parse()?),
1580 SymKind::S_GPROC32 | SymKind::S_LPROC32 => Self::Proc(p.parse()?),
1581 SymKind::S_THUNK32 => Self::Thunk(p.parse()?),
1582 SymKind::S_COMPILE3 => Self::Compile3(p.parse()?),
1583 SymKind::S_UDT => Self::Udt(p.parse()?),
1584 SymKind::S_CONSTANT => Self::Constant(p.parse()?),
1585 SymKind::S_MANCONSTANT => Self::Constant(p.parse()?),
1586 SymKind::S_PUB32 => Self::Pub(p.parse()?),
1587 SymKind::S_PUB32_ST => Self::Pub(Pub::parse_st(p)?),
1588
1589 SymKind::S_PROCREF
1590 | SymKind::S_LPROCREF
1591 | SymKind::S_DATAREF
1592 | SymKind::S_ANNOTATIONREF => Self::RefSym2(p.parse()?),
1593
1594 SymKind::S_LDATA32 | SymKind::S_GDATA32 | SymKind::S_LMANDATA | SymKind::S_GMANDATA => {
1595 Self::Data(p.parse()?)
1596 }
1597
1598 SymKind::S_LTHREAD32 | SymKind::S_GTHREAD32 => Self::ThreadData(p.parse()?),
1599 SymKind::S_END => Self::End,
1600 SymKind::S_FRAMEPROC => Self::FrameProc(p.get()?),
1601 SymKind::S_REGREL32 => Self::RegRel(p.parse()?),
1602 SymKind::S_BLOCK32 => Self::Block(p.parse()?),
1603 SymKind::S_LOCAL => Self::Local(p.parse()?),
1604 SymKind::S_DEFRANGE => Self::DefRange(p.parse()?),
1605 SymKind::S_DEFRANGE_FRAMEPOINTER_REL => Self::DefRangeFramePointerRel(p.parse()?),
1606 SymKind::S_DEFRANGE_REGISTER => Self::DefRangeRegister(p.parse()?),
1607 SymKind::S_DEFRANGE_REGISTER_REL => Self::DefRangeRegisterRel(p.parse()?),
1608 SymKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE => {
1609 Self::DefRangeFramePointerRelFullScope(p.get()?)
1610 }
1611 SymKind::S_DEFRANGE_SUBFIELD_REGISTER => Self::DefRangeSubFieldRegister(p.parse()?),
1612 SymKind::S_TRAMPOLINE => Self::Trampoline(p.parse()?),
1613 SymKind::S_BUILDINFO => Self::BuildInfo(p.parse()?),
1614 SymKind::S_UNAMESPACE => Self::UsingNamespace(p.parse()?),
1615 SymKind::S_INLINESITE_END => Self::InlineSiteEnd,
1616 SymKind::S_LABEL32 => Self::Label(p.parse()?),
1617 SymKind::S_CALLEES | SymKind::S_CALLERS => Self::FunctionList(p.parse()?),
1618 SymKind::S_INLINESITE => Self::InlineSite(p.parse()?),
1619 SymKind::S_INLINESITE2 => Self::InlineSite2(p.parse()?),
1620 SymKind::S_INLINEES => Self::FunctionList(p.parse()?),
1621 SymKind::S_FRAMECOOKIE => Self::FrameCookie(p.get()?),
1622 SymKind::S_CALLSITEINFO => Self::CallSiteInfo(p.get()?),
1623 SymKind::S_HEAPALLOCSITE => Self::HeapAllocSite(p.get()?),
1624 SymKind::S_GMANPROC | SymKind::S_LMANPROC => Self::ManagedProc(p.parse()?),
1625 SymKind::S_ANNOTATION => Self::Annotation(p.parse()?),
1626 SymKind::S_HOTPATCHFUNC => Self::HotPatchFunc(p.parse()?),
1627 SymKind::S_ARMSWITCHTABLE => Self::ArmSwitchTable(p.get()?),
1628 SymKind::S_COFFGROUP => Self::CoffGroup(p.parse()?),
1629 SymKind::S_SECTION => Self::Section(p.parse()?),
1630
1631 _ => Self::Unknown,
1632 })
1633 }
1634
1635 pub fn name(&self) -> Option<&'a BStr> {
1637 match self {
1638 Self::Proc(proc) => Some(proc.name),
1639 Self::Data(data) => Some(data.name),
1640 Self::ThreadData(thread_data) => Some(thread_data.name),
1641 Self::Udt(udt) => Some(udt.name),
1642 Self::Local(local) => Some(local.name),
1643 Self::RefSym2(refsym) => Some(refsym.name),
1644 Self::Constant(c) => Some(c.name),
1645 Self::ManagedConstant(c) => Some(c.name),
1646 _ => None,
1647 }
1648 }
1649}