use std::fmt::Debug; use super::format::{ CompactUnwindInfoHeader, CompressedPage, Opcode, PageEntry, RegularFunctionEntry, RegularPage, }; use super::unaligned::U32; use crate::error::ReadError; use crate::num_display::HexNum; use crate::reader::Reader; type Result = std::result::Result; impl CompactUnwindInfoHeader { pub fn parse(data: &[u8]) -> Result<&Self> { data.read_at::(0) .ok_or(ReadError::Header) } pub fn global_opcodes_offset(&self) -> u32 { self.global_opcodes_offset.into() } pub fn global_opcodes_len(&self) -> u32 { self.global_opcodes_len.into() } pub fn pages_offset(&self) -> u32 { self.pages_offset.into() } pub fn pages_len(&self) -> u32 { self.pages_len.into() } /// Return the list of global opcodes. pub fn global_opcodes<'data>(&self, data: &'data [u8]) -> Result<&'data [Opcode]> { data.read_slice_at::( self.global_opcodes_offset().into(), self.global_opcodes_len() as usize, ) .ok_or(ReadError::GlobalOpcodes) } /// Return the list of pages. pub fn pages<'data>(&self, data: &'data [u8]) -> Result<&'data [PageEntry]> { data.read_slice_at::(self.pages_offset().into(), self.pages_len() as usize) .ok_or(ReadError::Pages) } } impl RegularPage { pub fn parse(data: &[u8], page_offset: u64) -> Result<&Self> { data.read_at::(page_offset) .ok_or(ReadError::RegularPage) } pub fn functions_offset(&self) -> u16 { self.functions_offset.into() } pub fn functions_len(&self) -> u16 { self.functions_len.into() } pub fn functions<'data>( &self, data: &'data [u8], page_offset: u32, ) -> Result<&'data [RegularFunctionEntry]> { let relative_functions_offset = self.functions_offset(); let functions_len: usize = self.functions_len().into(); let functions_offset = page_offset as u64 + relative_functions_offset as u64; data.read_slice_at::(functions_offset, functions_len) .ok_or(ReadError::RegularPageFunctions) } } impl CompressedPage { pub fn parse(data: &[u8], page_offset: u64) -> Result<&Self> { data.read_at::(page_offset) .ok_or(ReadError::CompressedPage) } pub fn functions_offset(&self) -> u16 { self.functions_offset.into() } pub fn functions_len(&self) -> u16 { self.functions_len.into() } pub fn local_opcodes_offset(&self) -> u16 { self.local_opcodes_offset.into() } pub fn local_opcodes_len(&self) -> u16 { self.local_opcodes_len.into() } pub fn functions<'data>(&self, data: &'data [u8], page_offset: u32) -> Result<&'data [U32]> { let relative_functions_offset = self.functions_offset(); let functions_len: usize = self.functions_len().into(); let functions_offset = page_offset as u64 + relative_functions_offset as u64; data.read_slice_at::(functions_offset, functions_len) .ok_or(ReadError::CompressedPageFunctions) } /// Return the list of local opcodes. pub fn local_opcodes<'data>( &self, data: &'data [u8], page_offset: u32, ) -> Result<&'data [Opcode]> { let relative_local_opcodes_offset = self.local_opcodes_offset(); let local_opcodes_len: usize = self.local_opcodes_len().into(); let local_opcodes_offset = page_offset as u64 + relative_local_opcodes_offset as u64; data.read_slice_at::(local_opcodes_offset, local_opcodes_len) .ok_or(ReadError::LocalOpcodes) } } impl Opcode { pub fn opcode(&self) -> u32 { self.0.into() } } impl RegularFunctionEntry { pub fn address(&self) -> u32 { self.address.into() } pub fn opcode(&self) -> u32 { self.opcode.opcode() } } impl PageEntry { pub fn page_offset(&self) -> u32 { self.page_offset.into() } pub fn first_address(&self) -> u32 { self.first_address.into() } pub fn lsda_index_offset(&self) -> u32 { self.lsda_index_offset.into() } pub fn page_kind(&self, data: &[u8]) -> Result { let kind = *data .read_at::(self.page_offset().into()) .ok_or(ReadError::PageKind)?; Ok(kind.into()) } } impl Debug for PageEntry { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PageEntry") .field("first_address", &HexNum(self.first_address())) .field("page_offset", &HexNum(self.page_offset())) .field("lsda_index_offset", &HexNum(self.lsda_index_offset())) .finish() } }