pub mod builder;
mod iter;
mod kind;
mod offset_segment;
#[doc(inline)]
pub use self::{iter::*, kind::SymKind, offset_segment::*};
use crate::parser::{Number, Parse, Parser, ParserError, ParserMut};
use crate::types::{ItemId, ItemIdLe, TypeIndex, TypeIndexLe};
use bstr::BStr;
use std::fmt::Debug;
use std::mem::size_of;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned, I32, LE, U16, U32};
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SymbolStreamKind {
Global,
Module,
}
impl SymbolStreamKind {
pub fn stream_offset(self) -> usize {
match self {
Self::Global => 0,
Self::Module => 4,
}
}
}
#[derive(IntoBytes, FromBytes, Unaligned, Immutable, KnownLayout, Default, Clone, Debug)]
#[repr(C)]
#[allow(missing_docs)]
pub struct BlockHeader {
pub p_parent: U32<LE>,
pub p_end: U32<LE>,
}
#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned, Debug)]
#[repr(C)]
#[allow(missing_docs)]
pub struct ProcFixed {
pub p_parent: U32<LE>,
pub p_end: U32<LE>,
pub p_next: U32<LE>,
pub proc_len: U32<LE>,
pub debug_start: U32<LE>,
pub debug_end: U32<LE>,
pub proc_type: TypeIndexLe,
pub offset_segment: OffsetSegment,
pub flags: u8,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct Proc<'a> {
pub fixed: &'a ProcFixed,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for Proc<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[test]
fn test_parse_proc() {
#[rustfmt::skip]
let data = &[
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 ];
let mut i = SymIter::new(data);
let s0 = i.next().unwrap();
assert_eq!(s0.kind, SymKind::S_GPROC32);
assert_eq!(s0.data.len(), 0x2c);
match s0.parse().unwrap() {
SymData::Proc(proc) => {
assert_eq!(proc.fixed.p_parent.get(), 0);
assert_eq!(proc.fixed.p_end.get(), 0x40);
assert_eq!(proc.name, "memset");
}
_ => panic!(),
}
let s1 = i.next().unwrap();
assert_eq!(s1.kind, SymKind::S_END);
assert!(s1.data.is_empty());
}
#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned, Debug)]
#[repr(C)]
#[allow(missing_docs)]
pub struct ManagedProcFixed {
pub p_parent: U32<LE>,
pub p_end: U32<LE>,
pub p_next: U32<LE>,
pub proc_len: U32<LE>,
pub debug_start: U32<LE>,
pub debug_end: U32<LE>,
pub token: U32<LE>,
pub offset_segment: OffsetSegment,
pub flags: u8,
pub return_reg: U16<LE>,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct ManagedProc<'a> {
pub fixed: &'a ManagedProcFixed,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for ManagedProc<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Default)]
#[allow(missing_docs)]
pub struct ThunkFixed {
pub block: BlockHeader,
pub p_next: U32<LE>,
pub offset_segment: OffsetSegment,
pub length: U16<LE>,
pub thunk_ordinal: u8,
}
#[allow(missing_docs)]
pub struct Thunk<'a> {
pub fixed: &'a ThunkFixed,
pub name: &'a BStr,
pub variant: &'a [u8],
}
impl<'a> Parse<'a> for Thunk<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
variant: p.take_rest(),
})
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Default)]
pub struct SymHeader {
pub len: U16<LE>,
pub kind: U16<LE>,
}
#[derive(Clone)]
pub struct Sym<'a> {
pub kind: SymKind,
pub data: &'a [u8],
}
impl<'a> Sym<'a> {
pub fn parse(&self) -> Result<SymData<'a>, ParserError> {
SymData::parse(self.kind, self.data)
}
}
impl<'a> Debug for Sym<'a> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "{:?}", self.kind)
}
}
pub struct SymMut<'a> {
pub kind: SymKind,
pub data: &'a mut [u8],
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct Pub<'a> {
pub fixed: &'a PubFixed,
pub name: &'a BStr,
}
impl<'a> Pub<'a> {
pub fn offset_segment(&self) -> OffsetSegment {
self.fixed.offset_segment.clone()
}
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct PubFixed {
pub flags: U32<LE>,
pub offset_segment: OffsetSegment,
}
#[allow(missing_docs)]
impl<'a> Parse<'a> for Pub<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
impl<'a> Pub<'a> {
pub fn parse_st(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strt_raw()?,
})
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct Constant<'a> {
pub type_: TypeIndex,
pub value: Number<'a>,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for Constant<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
type_: p.type_index()?,
value: p.number()?,
name: p.strz()?,
})
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct ManagedConstant<'a> {
pub token: u32,
pub value: Number<'a>,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for ManagedConstant<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
token: p.u32()?,
value: p.number()?,
name: p.strz()?,
})
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct RefSym2<'a> {
pub header: &'a RefSym2Fixed,
pub name: &'a BStr,
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct RefSym2Fixed {
pub name_checksum: U32<LE>,
pub symbol_offset: U32<LE>,
pub module_index: U16<LE>,
}
impl<'a> Parse<'a> for RefSym2<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
header: p.get()?,
name: p.strz()?,
})
}
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct ThreadStorageFixed {
pub type_: TypeIndexLe,
pub offset_segment: OffsetSegment,
}
#[derive(Clone, Debug)]
pub struct ThreadStorageData<'a> {
#[allow(missing_docs)]
pub header: &'a ThreadStorageFixed,
#[allow(missing_docs)]
pub name: &'a BStr,
}
impl<'a> Parse<'a> for ThreadStorageData<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
header: p.get()?,
name: p.strz()?,
})
}
}
#[allow(missing_docs)]
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct DataFixed {
pub type_: TypeIndexLe,
pub offset_segment: OffsetSegment,
}
#[allow(missing_docs)]
#[derive(Clone)]
pub struct Data<'a> {
pub header: &'a DataFixed,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for Data<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
header: p.get()?,
name: p.strz()?,
})
}
}
impl<'a> Debug for Data<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Data: {} {:?} {}",
self.header.offset_segment,
self.header.type_.get(),
self.name
)
}
}
#[derive(Clone, Debug)]
pub struct Udt<'a> {
pub type_: TypeIndex,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for Udt<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
type_: p.type_index()?,
name: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
pub struct ObjectName<'a> {
pub signature: u32,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for ObjectName<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
signature: p.u32()?,
name: p.strz()?,
})
}
}
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[repr(C)]
#[allow(missing_docs)]
pub struct Compile3Fixed {
pub flags: U32<LE>,
pub machine: U16<LE>,
pub frontend_major: U16<LE>,
pub frontend_minor: U16<LE>,
pub frontend_build: U16<LE>,
pub frontend_qfe: U16<LE>,
pub ver_major: U16<LE>,
pub ver_minor: U16<LE>,
pub ver_build: U16<LE>,
pub ver_qfe: U16<LE>,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct Compile3<'a> {
pub fixed: &'a Compile3Fixed,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for Compile3<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct FrameProc {
frame_size: U32<LE>,
pad_size: U32<LE>,
pad_offset: U32<LE>,
save_regs_size: U32<LE>,
offset_exception_handler: U32<LE>,
exception_handler_section: U16<LE>,
padding: U16<LE>,
flags: U32<LE>,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct RegRelFixed {
pub offset: U32<LE>,
pub ty: TypeIndexLe,
pub register: U16<LE>,
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct RegRel<'a> {
pub fixed: &'a RegRelFixed,
pub name: &'a BStr,
}
impl<'a> Parse<'a> for RegRel<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Block<'a> {
pub fixed: &'a BlockFixed,
pub name: &'a BStr,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct BlockFixed {
pub header: BlockHeader,
pub length: U32<LE>,
pub offset_segment: OffsetSegment,
}
impl<'a> Parse<'a> for Block<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Local<'a> {
pub fixed: &'a LocalFixed,
pub name: &'a BStr,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct LocalFixed {
pub ty: TypeIndexLe,
pub flags: U16<LE>,
}
impl<'a> Parse<'a> for Local<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct LVarAddrRange {
pub start: OffsetSegment,
pub range_size: U16<LE>,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct LVarAddrGap {
pub gap_start_offset: U16<LE>,
pub range_size: U16<LE>,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct DefRangeSymFramePointerRelFixed {
pub offset_to_frame_pointer: U32<LE>,
pub range: LVarAddrRange,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct DefRangeSymFramePointerRel<'a> {
pub fixed: &'a DefRangeSymFramePointerRelFixed,
pub gaps: &'a [LVarAddrGap],
}
impl<'a> Parse<'a> for DefRangeSymFramePointerRel<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
let fixed = p.get()?;
let gaps = p.slice(p.len() / size_of::<LVarAddrGap>())?;
Ok(Self { fixed, gaps })
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct RangeAttrLe {
pub value: U16<LE>,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct DefRangeRegisterFixed {
pub reg: U16<LE>,
pub attr: RangeAttrLe,
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct DefRangeRegister<'a> {
pub fixed: &'a DefRangeRegisterFixed,
pub gaps: &'a [u8],
}
impl<'a> Parse<'a> for DefRangeRegister<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
gaps: p.take_rest(),
})
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct DefRangeRegisterRel<'a> {
pub fixed: &'a DefRangeRegisterRelFixed,
pub gaps: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
pub struct DefRangeRegisterRelFixed {
pub base_reg: U16<LE>,
pub flags: U16<LE>,
pub base_pointer_offset: I32<LE>,
pub range: LVarAddrRange,
}
impl<'a> Parse<'a> for DefRangeRegisterRel<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
gaps: p.take_rest(),
})
}
}
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
#[repr(C)]
pub struct DefRangeFramePointerRelFullScope {
pub frame_pointer_offset: I32<LE>,
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct DefRangeSubFieldRegister<'a> {
pub fixed: &'a DefRangeSubFieldRegisterFixed,
pub gaps: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct DefRangeSubFieldRegisterFixed {
pub reg: U16<LE>,
pub attr: RangeAttrLe,
pub flags: U32<LE>,
pub range: LVarAddrRange,
}
impl<'a> Parse<'a> for DefRangeSubFieldRegister<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
gaps: p.take_rest(),
})
}
}
pub struct ManProcSym<'a> {
#[allow(missing_docs)]
pub fixed: &'a ManProcSymFixed,
#[allow(missing_docs)]
pub name: &'a BStr,
}
pub type TokenIdLe = U32<LE>;
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct ManProcSymFixed {
pub block: BlockHeader,
pub pnext: U32<LE>,
pub len: U32<LE>,
pub dbg_start: U32<LE>,
pub dbg_end: U32<LE>,
pub token: TokenIdLe,
pub off: U32<LE>,
pub seg: U16<LE>,
pub flags: u8, pub padding: u8,
pub ret_reg: U16<LE>,
}
impl<'a> Parse<'a> for ManProcSym<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
pub struct Trampoline<'a> {
pub fixed: &'a TrampolineFixed,
pub rest: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Clone, Debug)]
pub struct TrampolineFixed {
pub tramp_type: U16<LE>,
pub cb_thunk: U16<LE>,
pub off_thunk: U32<LE>,
pub off_target: U32<LE>,
pub sect_thunk: U16<LE>,
pub sect_target: U16<LE>,
}
impl<'a> Parse<'a> for Trampoline<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
rest: p.take_rest(),
})
}
}
#[derive(Clone, Debug)]
pub struct BuildInfo {
pub item: ItemId,
}
impl<'a> Parse<'a> for BuildInfo {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self { item: p.u32()? })
}
}
#[derive(Clone, Debug)]
pub struct UsingNamespace<'a> {
pub namespace: &'a BStr,
}
impl<'a> Parse<'a> for UsingNamespace<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
namespace: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Label<'a> {
pub fixed: &'a LabelFixed,
pub name: &'a BStr,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct LabelFixed {
pub offset_segment: OffsetSegment,
pub flags: u8,
}
impl<'a> Parse<'a> for Label<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
name: p.strz()?,
})
}
}
#[derive(Clone, Debug)]
pub struct FunctionList<'a> {
pub funcs: &'a [ItemIdLe],
pub invocations: &'a [U32<LE>],
}
impl<'a> Parse<'a> for FunctionList<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
let count = p.u32()?;
let funcs: &[ItemIdLe] = p.slice(count as usize)?;
let num_invocations = p.len() / size_of::<U32<LE>>();
let invocations = p.slice(num_invocations)?;
Ok(Self { funcs, invocations })
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct InlineSite<'a> {
pub fixed: &'a InlineSiteFixed,
pub binary_annotations: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct InlineSiteFixed {
pub block: BlockHeader,
pub inlinee: ItemIdLe,
}
impl<'a> Parse<'a> for InlineSite<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
binary_annotations: p.take_rest(),
})
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct InlineSite2<'a> {
pub fixed: &'a InlineSite2Fixed,
pub binary_annotations: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct InlineSite2Fixed {
pub block: BlockHeader,
pub inlinee: ItemIdLe,
pub invocations: U32<LE>,
}
impl<'a> Parse<'a> for InlineSite2<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
binary_annotations: p.take_rest(),
})
}
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct FrameCookie {
pub offset: I32<LE>,
pub reg: U16<LE>,
pub cookie_type: u8,
pub flags: u8,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct CallSiteInfo {
pub offset: OffsetSegment,
pub padding: U16<LE>,
pub func_type: TypeIndexLe,
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct HeapAllocSite {
pub offset: OffsetSegment,
pub instruction_size: U16<LE>,
pub func_type: TypeIndexLe,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub struct Annotation<'a> {
pub fixed: &'a AnnotationFixed,
pub strings: &'a [u8],
}
#[repr(C)]
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned, Debug)]
#[allow(missing_docs)]
pub struct AnnotationFixed {
pub offset: OffsetSegment,
pub num_strings: U16<LE>,
}
impl<'a> Parse<'a> for Annotation<'a> {
fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(Self {
fixed: p.get()?,
strings: p.take_rest(),
})
}
}
impl<'a> Annotation<'a> {
pub fn iter_strings(&self) -> AnnotationIterStrings<'a> {
AnnotationIterStrings {
num_strings: self.fixed.num_strings.get(),
bytes: self.strings,
}
}
}
#[allow(missing_docs)]
pub struct AnnotationIterStrings<'a> {
pub num_strings: u16,
pub bytes: &'a [u8],
}
impl<'a> Iterator for AnnotationIterStrings<'a> {
type Item = &'a BStr;
fn next(&mut self) -> Option<Self::Item> {
if self.num_strings == 0 {
return None;
}
self.num_strings -= 1;
let mut p = Parser::new(self.bytes);
let s = p.strz().ok()?;
self.bytes = p.into_rest();
Some(s)
}
}
pub const TRAMPOLINE_KIND_INCREMENTAL: u16 = 0;
pub const TRAMPOLINE_KIND_BRANCH_ISLAND: u16 = 1;
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum SymData<'a> {
Unknown,
ObjName(ObjectName<'a>),
Compile3(Compile3<'a>),
Proc(Proc<'a>),
Udt(Udt<'a>),
Constant(Constant<'a>),
ManagedConstant(ManagedConstant<'a>),
RefSym2(RefSym2<'a>),
Data(Data<'a>),
ThreadData(ThreadStorageData<'a>),
Pub(Pub<'a>),
End,
FrameProc(&'a FrameProc),
RegRel(RegRel<'a>),
Block(Block<'a>),
Local(Local<'a>),
DefRangeFramePointerRel(DefRangeSymFramePointerRel<'a>),
DefRangeRegister(DefRangeRegister<'a>),
DefRangeRegisterRel(DefRangeRegisterRel<'a>),
DefRangeFramePointerRelFullScope(&'a DefRangeFramePointerRelFullScope),
DefRangeSubFieldRegister(DefRangeSubFieldRegister<'a>),
Trampoline(Trampoline<'a>),
BuildInfo(BuildInfo),
UsingNamespace(UsingNamespace<'a>),
InlineSiteEnd,
Label(Label<'a>),
FunctionList(FunctionList<'a>),
InlineSite(InlineSite<'a>),
InlineSite2(InlineSite2<'a>),
FrameCookie(&'a FrameCookie),
CallSiteInfo(&'a CallSiteInfo),
HeapAllocSite(&'a HeapAllocSite),
ManagedProc(ManagedProc<'a>),
Annotation(Annotation<'a>),
}
impl<'a> SymData<'a> {
pub fn parse(kind: SymKind, data: &'a [u8]) -> Result<Self, ParserError> {
let mut p = Parser::new(data);
Self::from_parser(kind, &mut p)
}
pub fn from_parser(kind: SymKind, p: &mut Parser<'a>) -> Result<Self, ParserError> {
Ok(match kind {
SymKind::S_OBJNAME => Self::ObjName(p.parse()?),
SymKind::S_GPROC32 | SymKind::S_LPROC32 => Self::Proc(p.parse()?),
SymKind::S_COMPILE3 => Self::Compile3(p.parse()?),
SymKind::S_UDT => Self::Udt(p.parse()?),
SymKind::S_CONSTANT => Self::Constant(p.parse()?),
SymKind::S_MANCONSTANT => Self::Constant(p.parse()?),
SymKind::S_PUB32 => Self::Pub(p.parse()?),
SymKind::S_PUB32_ST => Self::Pub(Pub::parse_st(p)?),
SymKind::S_PROCREF
| SymKind::S_LPROCREF
| SymKind::S_DATAREF
| SymKind::S_ANNOTATIONREF => Self::RefSym2(p.parse()?),
SymKind::S_LDATA32 | SymKind::S_GDATA32 | SymKind::S_LMANDATA | SymKind::S_GMANDATA => {
Self::Data(p.parse()?)
}
SymKind::S_LTHREAD32 | SymKind::S_GTHREAD32 => Self::ThreadData(p.parse()?),
SymKind::S_END => Self::End,
SymKind::S_FRAMEPROC => Self::FrameProc(p.get()?),
SymKind::S_REGREL32 => Self::RegRel(p.parse()?),
SymKind::S_BLOCK32 => Self::Block(p.parse()?),
SymKind::S_LOCAL => Self::Local(p.parse()?),
SymKind::S_DEFRANGE_FRAMEPOINTER_REL => Self::DefRangeFramePointerRel(p.parse()?),
SymKind::S_DEFRANGE_REGISTER => Self::DefRangeRegister(p.parse()?),
SymKind::S_DEFRANGE_REGISTER_REL => Self::DefRangeRegisterRel(p.parse()?),
SymKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE => {
Self::DefRangeFramePointerRelFullScope(p.get()?)
}
SymKind::S_DEFRANGE_SUBFIELD_REGISTER => Self::DefRangeSubFieldRegister(p.parse()?),
SymKind::S_TRAMPOLINE => Self::Trampoline(p.parse()?),
SymKind::S_BUILDINFO => Self::BuildInfo(p.parse()?),
SymKind::S_UNAMESPACE => Self::UsingNamespace(p.parse()?),
SymKind::S_INLINESITE_END => Self::InlineSiteEnd,
SymKind::S_LABEL32 => Self::Label(p.parse()?),
SymKind::S_CALLEES | SymKind::S_CALLERS => Self::FunctionList(p.parse()?),
SymKind::S_INLINESITE => Self::InlineSite(p.parse()?),
SymKind::S_INLINESITE2 => Self::InlineSite2(p.parse()?),
SymKind::S_INLINEES => Self::FunctionList(p.parse()?),
SymKind::S_FRAMECOOKIE => Self::FrameCookie(p.get()?),
SymKind::S_CALLSITEINFO => Self::CallSiteInfo(p.get()?),
SymKind::S_HEAPALLOCSITE => Self::HeapAllocSite(p.get()?),
SymKind::S_GMANPROC | SymKind::S_LMANPROC => Self::ManagedProc(p.parse()?),
SymKind::S_ANNOTATION => Self::Annotation(p.parse()?),
_ => Self::Unknown,
})
}
pub fn name(&self) -> Option<&'a BStr> {
match self {
Self::Proc(proc) => Some(proc.name),
Self::Data(data) => Some(data.name),
Self::ThreadData(thread_data) => Some(thread_data.name),
Self::Udt(udt) => Some(udt.name),
Self::Local(local) => Some(local.name),
Self::RefSym2(refsym) => Some(refsym.name),
Self::Constant(c) => Some(c.name),
Self::ManagedConstant(c) => Some(c.name),
_ => None,
}
}
}