diff --git a/symbolic-debuginfo/src/base.rs b/symbolic-debuginfo/src/base.rs index 7c8abb58d..c8923fe72 100644 --- a/symbolic-debuginfo/src/base.rs +++ b/symbolic-debuginfo/src/base.rs @@ -625,13 +625,16 @@ pub trait DebugSession { } /// An object containing debug information. -pub trait ObjectLike { +pub trait ObjectLike<'data, 'object> { /// Errors thrown when reading information from this object. type Error; /// A session that allows optimized access to debugging information. type Session: DebugSession; + /// The iterator over the symbols in the public symbol table. + type SymbolIterator: Iterator>; + /// The container format of this file. fn file_format(&self) -> FileFormat; @@ -657,10 +660,10 @@ pub trait ObjectLike { fn has_symbols(&self) -> bool; /// Returns an iterator over symbols in the public symbol table. - fn symbols(&self) -> DynIterator<'_, Symbol<'_>>; + fn symbols(&'object self) -> Self::SymbolIterator; /// Returns an ordered map of symbols in the symbol table. - fn symbol_map(&self) -> SymbolMap<'_>; + fn symbol_map(&self) -> SymbolMap<'data>; /// Determines whether this object contains debug information. fn has_debug_info(&self) -> bool; @@ -674,7 +677,7 @@ pub trait ObjectLike { /// Constructing this session will also work if the object does not contain debugging /// information, in which case the session will be a no-op. This can be checked via /// [`has_debug_info`](trait.ObjectLike.html#tymethod.has_debug_info). - fn debug_session(&self) -> Result; + fn debug_session(&'object self) -> Result; /// Determines whether this object contains stack unwinding information. fn has_unwind_info(&self) -> bool; diff --git a/symbolic-debuginfo/src/breakpad.rs b/symbolic-debuginfo/src/breakpad.rs index c33e4294f..512f0a565 100644 --- a/symbolic-debuginfo/src/breakpad.rs +++ b/symbolic-debuginfo/src/breakpad.rs @@ -734,21 +734,21 @@ impl<'d> Iterator for BreakpadStackRecords<'d> { /// > compactness. /// /// The full documentation resides [here](https://chromium.googlesource.com/breakpad/breakpad/+/refs/heads/master/docs/symbol_files.md). -pub struct BreakpadObject<'d> { +pub struct BreakpadObject<'data> { id: DebugId, arch: Arch, - module: BreakpadModuleRecord<'d>, - data: &'d [u8], + module: BreakpadModuleRecord<'data>, + data: &'data [u8], } -impl<'d> BreakpadObject<'d> { +impl<'data> BreakpadObject<'data> { /// Tests whether the buffer could contain a Breakpad object. pub fn test(data: &[u8]) -> bool { data.starts_with(b"MODULE ") } /// Tries to parse a Breakpad object from the given slice. - pub fn parse(data: &'d [u8]) -> Result { + pub fn parse(data: &'data [u8]) -> Result { // Ensure that we do not read the entire file at once. let header = if data.len() > BREAKPAD_HEADER_CAP { match str::from_utf8(&data[..BREAKPAD_HEADER_CAP]) { @@ -813,7 +813,7 @@ impl<'d> BreakpadObject<'d> { /// This is the name of the original debug file that was used to create the Breakpad file. On /// Windows, this will have a `.pdb` extension, on other platforms that name is likely /// equivalent to the name of the code file (shared library or executable). - pub fn name(&self) -> &'d str { + pub fn name(&self) -> &'data str { self.module.name } @@ -836,14 +836,14 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> BreakpadSymbolIterator<'d> { + pub fn symbols(&self) -> BreakpadSymbolIterator<'data> { BreakpadSymbolIterator { records: self.public_records(), } } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { self.symbols().collect() } @@ -861,7 +861,7 @@ impl<'d> BreakpadObject<'d> { /// Constructing this session will also work if the object does not contain debugging /// information, in which case the session will be a no-op. This can be checked via /// [`has_debug_info`](struct.BreakpadObject.html#method.has_debug_info). - pub fn debug_session(&self) -> Result, BreakpadError> { + pub fn debug_session(&self) -> Result, BreakpadError> { Ok(BreakpadDebugSession { file_map: self.file_map(), func_records: self.func_records(), @@ -879,7 +879,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over info records. - pub fn info_records(&self) -> BreakpadInfoRecords<'d> { + pub fn info_records(&self) -> BreakpadInfoRecords<'data> { BreakpadInfoRecords { lines: Lines::new(self.data), finished: false, @@ -887,7 +887,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over file records. - pub fn file_records(&self) -> BreakpadFileRecords<'d> { + pub fn file_records(&self) -> BreakpadFileRecords<'data> { BreakpadFileRecords { lines: Lines::new(self.data), finished: false, @@ -895,7 +895,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns a map for file name lookups by id. - pub fn file_map(&self) -> BreakpadFileMap<'d> { + pub fn file_map(&self) -> BreakpadFileMap<'data> { self.file_records() .filter_map(Result::ok) .map(|file| (file.id, file.name)) @@ -903,7 +903,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over public symbol records. - pub fn public_records(&self) -> BreakpadPublicRecords<'d> { + pub fn public_records(&self) -> BreakpadPublicRecords<'data> { BreakpadPublicRecords { lines: Lines::new(self.data), finished: false, @@ -911,7 +911,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over function records. - pub fn func_records(&self) -> BreakpadFuncRecords<'d> { + pub fn func_records(&self) -> BreakpadFuncRecords<'data> { BreakpadFuncRecords { lines: Lines::new(self.data), finished: false, @@ -919,7 +919,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns an iterator over stack frame records. - pub fn stack_records(&self) -> BreakpadStackRecords<'d> { + pub fn stack_records(&self) -> BreakpadStackRecords<'data> { BreakpadStackRecords { lines: Lines::new(self.data), finished: false, @@ -927,7 +927,7 @@ impl<'d> BreakpadObject<'d> { } /// Returns the raw data of the Breakpad file. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { self.data } } @@ -946,7 +946,7 @@ impl fmt::Debug for BreakpadObject<'_> { } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for BreakpadObject<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for BreakpadObject<'data> { type Ref = BreakpadObject<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -954,21 +954,22 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for BreakpadObject<'d> { } } -impl<'d> Parse<'d> for BreakpadObject<'d> { +impl<'data> Parse<'data> for BreakpadObject<'data> { type Error = BreakpadError; fn test(data: &[u8]) -> bool { Self::test(data) } - fn parse(data: &'d [u8]) -> Result { + fn parse(data: &'data [u8]) -> Result { Self::parse(data) } } -impl<'d> ObjectLike for BreakpadObject<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for BreakpadObject<'data> { type Error = BreakpadError; - type Session = BreakpadDebugSession<'d>; + type Session = BreakpadDebugSession<'data>; + type SymbolIterator = BreakpadSymbolIterator<'data>; fn file_format(&self) -> FileFormat { self.file_format() @@ -998,11 +999,11 @@ impl<'d> ObjectLike for BreakpadObject<'d> { self.has_symbols() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - Box::new(self.symbols()) + fn symbols(&self) -> Self::SymbolIterator { + self.symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } @@ -1026,12 +1027,12 @@ impl<'d> ObjectLike for BreakpadObject<'d> { /// An iterator over symbols in the Breakpad object. /// /// Returned by [`BreakpadObject::symbols`](struct.BreakpadObject.html#method.symbols). -pub struct BreakpadSymbolIterator<'d> { - records: BreakpadPublicRecords<'d>, +pub struct BreakpadSymbolIterator<'data> { + records: BreakpadPublicRecords<'data>, } -impl<'d> Iterator for BreakpadSymbolIterator<'d> { - type Item = Symbol<'d>; +impl<'data> Iterator for BreakpadSymbolIterator<'data> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { while let Some(result) = self.records.next() { diff --git a/symbolic-debuginfo/src/dwarf.rs b/symbolic-debuginfo/src/dwarf.rs index a4d14aa3b..32d224860 100644 --- a/symbolic-debuginfo/src/dwarf.rs +++ b/symbolic-debuginfo/src/dwarf.rs @@ -1161,7 +1161,7 @@ impl<'d> DwarfDebugSession<'d> { } } -impl<'d> DebugSession for DwarfDebugSession<'d> { +impl<'data> DebugSession for DwarfDebugSession<'data> { type Error = DwarfError; fn functions(&self) -> DynIterator<'_, Result, Self::Error>> { diff --git a/symbolic-debuginfo/src/elf.rs b/symbolic-debuginfo/src/elf.rs index 7688b1270..362ba870d 100644 --- a/symbolic-debuginfo/src/elf.rs +++ b/symbolic-debuginfo/src/elf.rs @@ -48,12 +48,12 @@ pub enum ElfError { } /// Executable and Linkable Format, used for executables and libraries on Linux. -pub struct ElfObject<'d> { - elf: elf::Elf<'d>, - data: &'d [u8], +pub struct ElfObject<'data> { + elf: elf::Elf<'data>, + data: &'data [u8], } -impl<'d> ElfObject<'d> { +impl<'data> ElfObject<'data> { /// Tests whether the buffer could contain an ELF object. pub fn test(data: &[u8]) -> bool { match goblin::peek(&mut Cursor::new(data)) { @@ -63,7 +63,7 @@ impl<'d> ElfObject<'d> { } /// Tries to parse an ELF object from the given slice. - pub fn parse(data: &'d [u8]) -> Result { + pub fn parse(data: &'data [u8]) -> Result { Ok(elf::Elf::parse(data).map(|elf| ElfObject { elf, data })?) } @@ -84,7 +84,7 @@ impl<'d> ElfObject<'d> { } /// The binary's soname, if any. - pub fn name(&self) -> Option<&'d str> { + pub fn name(&self) -> Option<&'data str> { self.elf.soname } @@ -208,7 +208,7 @@ impl<'d> ElfObject<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> ElfSymbolIterator<'d, '_> { + pub fn symbols(&self) -> ElfSymbolIterator<'data, '_> { ElfSymbolIterator { symbols: self.elf.syms.iter(), strtab: &self.elf.strtab, @@ -218,7 +218,7 @@ impl<'d> ElfObject<'d> { } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { self.symbols().collect() } @@ -239,7 +239,7 @@ impl<'d> ElfObject<'d> { /// Constructing this session will also work if the object does not contain debugging /// information, in which case the session will be a no-op. This can be checked via /// [`has_debug_info`](struct.ElfObject.html#method.has_debug_info). - pub fn debug_session(&self) -> Result, DwarfError> { + pub fn debug_session(&self) -> Result, DwarfError> { let symbols = self.symbol_map(); DwarfDebugSession::parse(self, symbols, self.load_address(), self.kind()) } @@ -255,7 +255,7 @@ impl<'d> ElfObject<'d> { } /// Returns the raw data of the ELF file. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { self.data } @@ -295,7 +295,7 @@ impl<'d> ElfObject<'d> { } /// Locates and reads a section in an ELF binary. - fn find_section(&self, name: &str) -> Option<(bool, DwarfSection<'d>)> { + fn find_section(&self, name: &str) -> Option<(bool, DwarfSection<'data>)> { for header in &self.elf.section_headers { // NB: Symbolic does not support MIPS, but if it did we would also need to check // SHT_MIPS_DWARF sections. @@ -350,7 +350,7 @@ impl<'d> ElfObject<'d> { /// Depending on the compiler and linker, the build ID can be declared in a /// PT_NOTE program header entry, the ".note.gnu.build-id" section, or even /// both. - fn find_build_id(&self) -> Option<&'d [u8]> { + fn find_build_id(&self) -> Option<&'data [u8]> { // First, search the note program headers (PT_NOTE) for a NT_GNU_BUILD_ID. // We swallow all errors during this process and simply fall back to the // next method below. @@ -423,7 +423,7 @@ impl fmt::Debug for ElfObject<'_> { } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for ElfObject<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for ElfObject<'data> { type Ref = ElfObject<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -431,21 +431,22 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for ElfObject<'d> { } } -impl<'d> Parse<'d> for ElfObject<'d> { +impl<'data> Parse<'data> for ElfObject<'data> { type Error = ElfError; fn test(data: &[u8]) -> bool { Self::test(data) } - fn parse(data: &'d [u8]) -> Result { + fn parse(data: &'data [u8]) -> Result { Self::parse(data) } } -impl<'d> ObjectLike for ElfObject<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for ElfObject<'data> { type Error = DwarfError; - type Session = DwarfDebugSession<'d>; + type Session = DwarfDebugSession<'data>; + type SymbolIterator = ElfSymbolIterator<'data, 'object>; fn file_format(&self) -> FileFormat { self.file_format() @@ -475,11 +476,11 @@ impl<'d> ObjectLike for ElfObject<'d> { self.has_symbols() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - Box::new(self.symbols()) + fn symbols(&'object self) -> Self::SymbolIterator { + self.symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } @@ -500,7 +501,7 @@ impl<'d> ObjectLike for ElfObject<'d> { } } -impl<'d> Dwarf<'d> for ElfObject<'d> { +impl<'data> Dwarf<'data> for ElfObject<'data> { fn endianity(&self) -> Endian { if self.elf.little_endian { Endian::Little @@ -509,12 +510,12 @@ impl<'d> Dwarf<'d> for ElfObject<'d> { } } - fn raw_section(&self, name: &str) -> Option> { + fn raw_section(&self, name: &str) -> Option> { let (_, section) = self.find_section(name)?; Some(section) } - fn section(&self, name: &str) -> Option> { + fn section(&self, name: &str) -> Option> { let (compressed, mut section) = self.find_section(name)?; if compressed { @@ -529,15 +530,15 @@ impl<'d> Dwarf<'d> for ElfObject<'d> { /// An iterator over symbols in the ELF file. /// /// Returned by [`ElfObject::symbols`](struct.ElfObject.html#method.symbols). -pub struct ElfSymbolIterator<'d, 'o> { - symbols: elf::sym::SymIterator<'d>, - strtab: &'o strtab::Strtab<'d>, - sections: &'o [elf::SectionHeader], +pub struct ElfSymbolIterator<'data, 'object> { + symbols: elf::sym::SymIterator<'data>, + strtab: &'object strtab::Strtab<'data>, + sections: &'object [elf::SectionHeader], load_addr: u64, } -impl<'d, 'o> Iterator for ElfSymbolIterator<'d, 'o> { - type Item = Symbol<'d>; +impl<'data, 'object> Iterator for ElfSymbolIterator<'data, 'object> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { while let Some(symbol) = self.symbols.next() { diff --git a/symbolic-debuginfo/src/macho.rs b/symbolic-debuginfo/src/macho.rs index c7d1dc0b7..7df684360 100644 --- a/symbolic-debuginfo/src/macho.rs +++ b/symbolic-debuginfo/src/macho.rs @@ -279,9 +279,10 @@ impl<'d> Parse<'d> for MachObject<'d> { } } -impl<'d> ObjectLike for MachObject<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for MachObject<'data> { type Error = DwarfError; - type Session = DwarfDebugSession<'d>; + type Session = DwarfDebugSession<'data>; + type SymbolIterator = MachOSymbolIterator<'data>; fn file_format(&self) -> FileFormat { self.file_format() @@ -311,11 +312,11 @@ impl<'d> ObjectLike for MachObject<'d> { self.has_symbols() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - Box::new(self.symbols()) + fn symbols(&self) -> Self::SymbolIterator { + self.symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } @@ -336,7 +337,7 @@ impl<'d> ObjectLike for MachObject<'d> { } } -impl<'d> Dwarf<'d> for MachObject<'d> { +impl<'data> Dwarf<'data> for MachObject<'data> { fn endianity(&self) -> Endian { if self.macho.little_endian { Endian::Little @@ -345,7 +346,7 @@ impl<'d> Dwarf<'d> for MachObject<'d> { } } - fn raw_section(&self, section_name: &str) -> Option> { + fn raw_section(&self, section_name: &str) -> Option> { for segment in &self.macho.segments { for section in segment { if let Ok((header, data)) = section { @@ -378,14 +379,14 @@ impl<'d> Dwarf<'d> for MachObject<'d> { /// An iterator over symbols in the MachO file. /// /// Returned by [`MachObject::symbols`](struct.MachObject.html#method.symbols). -pub struct MachOSymbolIterator<'d> { - symbols: mach::symbols::SymbolIterator<'d>, +pub struct MachOSymbolIterator<'data> { + symbols: mach::symbols::SymbolIterator<'data>, sections: SmallVec<[usize; 2]>, vmaddr: u64, } -impl<'d> Iterator for MachOSymbolIterator<'d> { - type Item = Symbol<'d>; +impl<'data> Iterator for MachOSymbolIterator<'data> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { while let Some(next) = self.symbols.next() { diff --git a/symbolic-debuginfo/src/object.rs b/symbolic-debuginfo/src/object.rs index 81229aa23..a26519cb0 100644 --- a/symbolic-debuginfo/src/object.rs +++ b/symbolic-debuginfo/src/object.rs @@ -131,22 +131,22 @@ pub fn peek(data: &[u8], archive: bool) -> FileFormat { /// A generic object file providing uniform access to various file formats. #[allow(clippy::large_enum_variant)] #[derive(Debug)] -pub enum Object<'d> { +pub enum Object<'data> { /// Breakpad ASCII symbol. - Breakpad(BreakpadObject<'d>), + Breakpad(BreakpadObject<'data>), /// Executable and Linkable Format, used on Linux. - Elf(ElfObject<'d>), + Elf(ElfObject<'data>), /// Mach Objects, used on macOS and iOS derivatives. - MachO(MachObject<'d>), + MachO(MachObject<'data>), /// Program Database, the debug companion format on Windows. - Pdb(PdbObject<'d>), + Pdb(PdbObject<'data>), /// Portable Executable, an extension of COFF used on Windows. - Pe(PeObject<'d>), + Pe(PeObject<'data>), /// A source bundle - SourceBundle(SourceBundle<'d>), + SourceBundle(SourceBundle<'data>), } -impl<'d> Object<'d> { +impl<'data> Object<'data> { /// Tests whether the buffer could contain an object. pub fn test(data: &[u8]) -> bool { Self::peek(data) != FileFormat::Unknown @@ -158,7 +158,7 @@ impl<'d> Object<'d> { } /// Tries to parse a supported object from the given slice. - pub fn parse(data: &'d [u8]) -> Result { + pub fn parse(data: &'data [u8]) -> Result { macro_rules! parse_object { ($kind:ident, $file:ident, $data:expr) => { Object::$kind($file::parse(data).map_err(ObjectError::$kind)?) @@ -228,12 +228,12 @@ impl<'d> Object<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> SymbolIterator<'d, '_> { + pub fn symbols(&self) -> SymbolIterator<'data, '_> { map_inner!(self, Object(ref o) => SymbolIterator(o.symbols())) } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { match_inner!(self, Object(ref o) => o.symbol_map()) } @@ -255,7 +255,7 @@ impl<'d> Object<'d> { /// Constructing this session will also work if the object does not contain debugging /// information, in which case the session will be a no-op. This can be checked via /// [`has_debug_info`](enum.Object.html#method.has_debug_info). - pub fn debug_session(&self) -> Result, ObjectError> { + pub fn debug_session(&self) -> Result, ObjectError> { match *self { Object::Breakpad(ref o) => o .debug_session() @@ -295,12 +295,12 @@ impl<'d> Object<'d> { } /// Returns the raw data of the underlying buffer. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { match_inner!(self, Object(ref o) => o.data()) } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for Object<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for Object<'data> { type Ref = Object<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -308,9 +308,10 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for Object<'d> { } } -impl<'d> ObjectLike for Object<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for Object<'data> { type Error = ObjectError; - type Session = ObjectDebugSession<'d>; + type Session = ObjectDebugSession<'data>; + type SymbolIterator = SymbolIterator<'data, 'object>; fn file_format(&self) -> FileFormat { self.file_format() @@ -340,12 +341,12 @@ impl<'d> ObjectLike for Object<'d> { self.has_symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - unsafe { std::mem::transmute(Box::new(self.symbols()) as DynIterator<'_, _>) } + fn symbols(&'object self) -> Self::SymbolIterator { + self.symbols() } fn has_debug_info(&self) -> bool { @@ -500,17 +501,17 @@ impl<'s> Iterator for ObjectFileIterator<'s> { /// A generic symbol iterator #[allow(missing_docs)] -pub enum SymbolIterator<'d, 'o> { - Breakpad(BreakpadSymbolIterator<'d>), - Elf(ElfSymbolIterator<'d, 'o>), - MachO(MachOSymbolIterator<'d>), - Pdb(PdbSymbolIterator<'d, 'o>), - Pe(PeSymbolIterator<'d, 'o>), - SourceBundle(SourceBundleSymbolIterator<'d>), +pub enum SymbolIterator<'data, 'object> { + Breakpad(BreakpadSymbolIterator<'data>), + Elf(ElfSymbolIterator<'data, 'object>), + MachO(MachOSymbolIterator<'data>), + Pdb(PdbSymbolIterator<'data, 'object>), + Pe(PeSymbolIterator<'data, 'object>), + SourceBundle(SourceBundleSymbolIterator<'data>), } -impl<'d, 'o> Iterator for SymbolIterator<'d, 'o> { - type Item = Symbol<'d>; +impl<'data, 'object> Iterator for SymbolIterator<'data, 'object> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { match_inner!(self, SymbolIterator(ref mut iter) => iter.next()) diff --git a/symbolic-debuginfo/src/pdb.rs b/symbolic-debuginfo/src/pdb.rs index c3228171b..91cc9496d 100644 --- a/symbolic-debuginfo/src/pdb.rs +++ b/symbolic-debuginfo/src/pdb.rs @@ -22,7 +22,7 @@ use symbolic_common::{Arch, AsSelf, CodeId, CpuFamily, DebugId, Name, SelfCell, use crate::base::*; use crate::private::{FunctionStack, Parse}; -type Pdb<'d> = pdb::PDB<'d, Cursor<&'d [u8]>>; +type Pdb<'data> = pdb::PDB<'data, Cursor<&'data [u8]>>; const MAGIC_BIG: &[u8] = b"Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\x00\x00\x00"; @@ -50,12 +50,12 @@ pub enum PdbError { /// Program Database, the debug companion format on Windows. /// /// This object is a sole debug companion to [`PeObject`](../pdb/struct.PdbObject.html). -pub struct PdbObject<'d> { - pdb: Arc>>, - debug_info: Arc>, - pdb_info: pdb::PDBInformation<'d>, - public_syms: pdb::SymbolTable<'d>, - data: &'d [u8], +pub struct PdbObject<'data> { + pdb: Arc>>, + debug_info: Arc>, + pdb_info: pdb::PDBInformation<'data>, + public_syms: pdb::SymbolTable<'data>, + data: &'data [u8], } // NB: The pdb crate simulates mmap behavior on any Read + Seek type. This implementation requires @@ -65,7 +65,7 @@ pub struct PdbObject<'d> { unsafe impl Send for PdbObject<'_> {} unsafe impl Sync for PdbObject<'_> {} -impl<'d> PdbObject<'d> { +impl<'data> PdbObject<'data> { /// Tests whether the buffer could contain an PDB object. pub fn test(data: &[u8]) -> bool { // NB: "Microsoft C/C++ program database 2.00" is not supported by the pdb crate, so there @@ -74,7 +74,7 @@ impl<'d> PdbObject<'d> { } /// Tries to parse a PDB object from the given slice. - pub fn parse(data: &'d [u8]) -> Result { + pub fn parse(data: &'data [u8]) -> Result { let mut pdb = Pdb::open(Cursor::new(data))?; let dbi = pdb.debug_information()?; let pdbi = pdb.pdb_information()?; @@ -155,7 +155,7 @@ impl<'d> PdbObject<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> PdbSymbolIterator<'d, '_> { + pub fn symbols(&self) -> PdbSymbolIterator<'data, '_> { PdbSymbolIterator { symbols: self.public_syms.iter(), address_map: self.pdb.write().address_map().ok(), @@ -163,7 +163,7 @@ impl<'d> PdbObject<'d> { } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { self.symbols().collect() } @@ -182,7 +182,7 @@ impl<'d> PdbObject<'d> { } /// Constructs a debugging session. - pub fn debug_session(&self) -> Result, PdbError> { + pub fn debug_session(&self) -> Result, PdbError> { PdbDebugSession::build(self) } @@ -196,12 +196,12 @@ impl<'d> PdbObject<'d> { } /// Returns the raw data of the ELF file. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { self.data } #[doc(hidden)] - pub fn inner(&self) -> &RwLock> { + pub fn inner(&self) -> &RwLock> { &self.pdb } } @@ -219,7 +219,7 @@ impl fmt::Debug for PdbObject<'_> { } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for PdbObject<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for PdbObject<'data> { type Ref = PdbObject<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -227,21 +227,22 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for PdbObject<'d> { } } -impl<'d> Parse<'d> for PdbObject<'d> { +impl<'data> Parse<'data> for PdbObject<'data> { type Error = PdbError; fn test(data: &[u8]) -> bool { Self::test(data) } - fn parse(data: &'d [u8]) -> Result { + fn parse(data: &'data [u8]) -> Result { Self::parse(data) } } -impl<'d> ObjectLike for PdbObject<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for PdbObject<'data> { type Error = PdbError; - type Session = PdbDebugSession<'d>; + type Session = PdbDebugSession<'data>; + type SymbolIterator = PdbSymbolIterator<'data, 'object>; fn file_format(&self) -> FileFormat { self.file_format() @@ -271,12 +272,11 @@ impl<'d> ObjectLike for PdbObject<'d> { self.has_symbols() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - // TODO: Avoid this transmute by introducing explicit lifetimes on the trait. - unsafe { std::mem::transmute(Box::new(self.symbols()) as DynIterator<'_, _>) } + fn symbols(&'object self) -> Self::SymbolIterator { + self.symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } @@ -311,13 +311,13 @@ pub(crate) fn arch_from_machine(machine: MachineType) -> Arch { /// An iterator over symbols in the PDB file. /// /// Returned by [`PdbObject::symbols`](struct.PdbObject.html#method.symbols). -pub struct PdbSymbolIterator<'d, 'o> { - symbols: pdb::SymbolIter<'o>, - address_map: Option>, +pub struct PdbSymbolIterator<'data, 'object> { + symbols: pdb::SymbolIter<'object>, + address_map: Option>, } -impl<'d, 'o> Iterator for PdbSymbolIterator<'d, 'o> { - type Item = Symbol<'d>; +impl<'data, 'object> Iterator for PdbSymbolIterator<'data, 'object> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { let address_map = self.address_map.as_ref()?; @@ -336,7 +336,7 @@ impl<'d, 'o> Iterator for PdbSymbolIterator<'d, 'o> { let cow = public.name.to_string(); // pdb::SymbolIter offers data bound to its own lifetime since it holds the // buffer containing public symbols. The contract requires that we return - // `Symbol<'d>`, so we cannot return zero-copy symbols here. + // `Symbol<'data>`, so we cannot return zero-copy symbols here. let name = Cow::from(String::from(if cow.starts_with('_') { &cow[1..] } else { diff --git a/symbolic-debuginfo/src/pe.rs b/symbolic-debuginfo/src/pe.rs index 0d33ae460..57220e5c6 100644 --- a/symbolic-debuginfo/src/pe.rs +++ b/symbolic-debuginfo/src/pe.rs @@ -52,13 +52,13 @@ fn is_pe_stub(pe: &pe::PE<'_>) -> bool { /// While in rare instances, PE files might contain debug information, this case is not supported. /// /// [`PdbObject`]: ../pdb/struct.PdbObject.html -pub struct PeObject<'d> { - pe: pe::PE<'d>, - data: &'d [u8], +pub struct PeObject<'data> { + pe: pe::PE<'data>, + data: &'data [u8], is_stub: bool, } -impl<'d> PeObject<'d> { +impl<'data> PeObject<'data> { /// Tests whether the buffer could contain an PE object. pub fn test(data: &[u8]) -> bool { match goblin::peek(&mut Cursor::new(data)) { @@ -68,7 +68,7 @@ impl<'d> PeObject<'d> { } /// Tries to parse a PE object from the given slice. - pub fn parse(data: &'d [u8]) -> Result { + pub fn parse(data: &'data [u8]) -> Result { let pe = pe::PE::parse(data).map_err(PeError::BadObject)?; let is_stub = is_pe_stub(&pe); Ok(PeObject { pe, data, is_stub }) @@ -168,14 +168,14 @@ impl<'d> PeObject<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> PeSymbolIterator<'d, '_> { + pub fn symbols(&self) -> PeSymbolIterator<'data, '_> { PeSymbolIterator { exports: self.pe.exports.iter(), } } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { self.symbols().collect() } @@ -192,7 +192,7 @@ impl<'d> PeObject<'d> { } /// Constructs a no-op debugging session. - pub fn debug_session(&self) -> Result, PeError> { + pub fn debug_session(&self) -> Result, PeError> { Ok(PeDebugSession { _ph: PhantomData }) } @@ -202,7 +202,7 @@ impl<'d> PeObject<'d> { } /// Returns the raw data of the PE file. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { self.data } @@ -237,7 +237,7 @@ impl fmt::Debug for PeObject<'_> { } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for PeObject<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for PeObject<'data> { type Ref = PeObject<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -245,21 +245,22 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for PeObject<'d> { } } -impl<'d> Parse<'d> for PeObject<'d> { +impl<'data> Parse<'data> for PeObject<'data> { type Error = PeError; fn test(data: &[u8]) -> bool { Self::test(data) } - fn parse(data: &'d [u8]) -> Result { + fn parse(data: &'data [u8]) -> Result { Self::parse(data) } } -impl<'d> ObjectLike for PeObject<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for PeObject<'data> { type Error = PeError; - type Session = PeDebugSession<'d>; + type Session = PeDebugSession<'data>; + type SymbolIterator = PeSymbolIterator<'data, 'object>; fn file_format(&self) -> FileFormat { self.file_format() @@ -289,11 +290,11 @@ impl<'d> ObjectLike for PeObject<'d> { self.has_symbols() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - Box::new(self.symbols()) + fn symbols(&'object self) -> Self::SymbolIterator { + self.symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } @@ -317,12 +318,12 @@ impl<'d> ObjectLike for PeObject<'d> { /// An iterator over symbols in the PE file. /// /// Returned by [`PeObject::symbols`](struct.PeObject.html#method.symbols). -pub struct PeSymbolIterator<'d, 'o> { - exports: std::slice::Iter<'o, pe::export::Export<'d>>, +pub struct PeSymbolIterator<'data, 'object> { + exports: std::slice::Iter<'object, pe::export::Export<'data>>, } -impl<'d, 'o> Iterator for PeSymbolIterator<'d, 'o> { - type Item = Symbol<'d>; +impl<'data, 'object> Iterator for PeSymbolIterator<'data, 'object> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { self.exports.next().map(|export| Symbol { @@ -338,11 +339,11 @@ impl<'d, 'o> Iterator for PeSymbolIterator<'d, 'o> { /// Since debug information in PE containers is not supported, this session consists of NoOps and /// always returns empty results. #[derive(Debug)] -pub struct PeDebugSession<'d> { - _ph: PhantomData<&'d ()>, +pub struct PeDebugSession<'data> { + _ph: PhantomData<&'data ()>, } -impl<'d> PeDebugSession<'d> { +impl<'data> PeDebugSession<'data> { /// Returns an iterator over all functions in this debug file. pub fn functions(&self) -> PeFunctionIterator<'_> { std::iter::empty() diff --git a/symbolic-debuginfo/src/sourcebundle.rs b/symbolic-debuginfo/src/sourcebundle.rs index d561ffc17..6b23133f0 100644 --- a/symbolic-debuginfo/src/sourcebundle.rs +++ b/symbolic-debuginfo/src/sourcebundle.rs @@ -286,10 +286,10 @@ struct SourceBundleManifest { /// /// [`SourceBundleWriter`]: struct.SourceBundleWriter.html /// [module level documentation]: index.html -pub struct SourceBundle<'d> { +pub struct SourceBundle<'data> { manifest: Arc, - archive: Arc>>>, - data: &'d [u8], + archive: Arc>>>, + data: &'data [u8], } impl fmt::Debug for SourceBundle<'_> { @@ -308,14 +308,14 @@ impl fmt::Debug for SourceBundle<'_> { } } -impl<'d> SourceBundle<'d> { +impl<'data> SourceBundle<'data> { /// Tests whether the buffer could contain a `SourceBundle`. pub fn test(bytes: &[u8]) -> bool { bytes.starts_with(&BUNDLE_MAGIC) } /// Tries to parse a `SourceBundle` from the given slice. - pub fn parse(data: &'d [u8]) -> Result, SourceBundleError> { + pub fn parse(data: &'data [u8]) -> Result, SourceBundleError> { let mut archive = zip::read::ZipArchive::new(std::io::Cursor::new(data)) .map_err(SourceBundleError::BadZip)?; let manifest_file = archive @@ -420,14 +420,14 @@ impl<'d> SourceBundle<'d> { } /// Returns an iterator over symbols in the public symbol table. - pub fn symbols(&self) -> SourceBundleSymbolIterator<'d> { + pub fn symbols(&self) -> SourceBundleSymbolIterator<'data> { SourceBundleSymbolIterator { _marker: std::marker::PhantomData, } } /// Returns an ordered map of symbols in the symbol table. - pub fn symbol_map(&self) -> SymbolMap<'d> { + pub fn symbol_map(&self) -> SymbolMap<'data> { self.symbols().collect() } @@ -443,7 +443,7 @@ impl<'d> SourceBundle<'d> { /// A debugging session loads certain information from the object file and creates caches for /// efficient access to various records in the debug information. Since this can be quite a /// costly process, try to reuse the debugging session as long as possible. - pub fn debug_session(&self) -> Result, SourceBundleError> { + pub fn debug_session(&self) -> Result, SourceBundleError> { Ok(SourceBundleDebugSession { manifest: self.manifest.clone(), archive: self.archive.clone(), @@ -462,7 +462,7 @@ impl<'d> SourceBundle<'d> { } /// Returns the raw data of the source bundle. - pub fn data(&self) -> &'d [u8] { + pub fn data(&self) -> &'data [u8] { self.data } @@ -472,7 +472,7 @@ impl<'d> SourceBundle<'d> { } } -impl<'slf, 'd: 'slf> AsSelf<'slf> for SourceBundle<'d> { +impl<'slf, 'data: 'slf> AsSelf<'slf> for SourceBundle<'data> { type Ref = SourceBundle<'slf>; fn as_self(&'slf self) -> &Self::Ref { @@ -480,21 +480,22 @@ impl<'slf, 'd: 'slf> AsSelf<'slf> for SourceBundle<'d> { } } -impl<'d> Parse<'d> for SourceBundle<'d> { +impl<'data> Parse<'data> for SourceBundle<'data> { type Error = SourceBundleError; - fn parse(data: &'d [u8]) -> Result { + fn parse(data: &'data [u8]) -> Result { SourceBundle::parse(data) } - fn test(data: &'d [u8]) -> bool { + fn test(data: &'data [u8]) -> bool { SourceBundle::test(data) } } -impl<'d> ObjectLike for SourceBundle<'d> { +impl<'data: 'object, 'object> ObjectLike<'data, 'object> for SourceBundle<'data> { type Error = SourceBundleError; - type Session = SourceBundleDebugSession<'d>; + type Session = SourceBundleDebugSession<'data>; + type SymbolIterator = SourceBundleSymbolIterator<'data>; fn file_format(&self) -> FileFormat { self.file_format() @@ -524,12 +525,12 @@ impl<'d> ObjectLike for SourceBundle<'d> { self.has_symbols() } - fn symbol_map(&self) -> SymbolMap<'_> { + fn symbol_map(&self) -> SymbolMap<'data> { self.symbol_map() } - fn symbols(&self) -> DynIterator<'_, Symbol<'_>> { - Box::new(self.symbols()) + fn symbols(&self) -> Self::SymbolIterator { + self.symbols() } fn has_debug_info(&self) -> bool { @@ -552,12 +553,12 @@ impl<'d> ObjectLike for SourceBundle<'d> { /// An iterator yielding symbols from a source bundle /// /// This is always yielding no results. -pub struct SourceBundleSymbolIterator<'d> { - _marker: std::marker::PhantomData<&'d [u8]>, +pub struct SourceBundleSymbolIterator<'data> { + _marker: std::marker::PhantomData<&'data [u8]>, } -impl<'d> Iterator for SourceBundleSymbolIterator<'d> { - type Item = Symbol<'d>; +impl<'data> Iterator for SourceBundleSymbolIterator<'data> { + type Item = Symbol<'data>; fn next(&mut self) -> Option { None @@ -567,13 +568,13 @@ impl<'d> Iterator for SourceBundleSymbolIterator<'d> { impl std::iter::FusedIterator for SourceBundleSymbolIterator<'_> {} /// Debug session for SourceBundle objects. -pub struct SourceBundleDebugSession<'d> { +pub struct SourceBundleDebugSession<'data> { manifest: Arc, - archive: Arc>>>, + archive: Arc>>>, files_by_path: LazyCell>, } -impl<'d> SourceBundleDebugSession<'d> { +impl<'data> SourceBundleDebugSession<'data> { /// Returns an iterator over all source files in this debug file. pub fn files(&self) -> SourceBundleFileIterator<'_> { SourceBundleFileIterator { @@ -637,7 +638,7 @@ impl<'d> SourceBundleDebugSession<'d> { } } -impl<'d> DebugSession for SourceBundleDebugSession<'d> { +impl<'data> DebugSession for SourceBundleDebugSession<'data> { type Error = SourceBundleError; fn functions(&self) -> DynIterator<'_, Result, Self::Error>> { @@ -862,10 +863,14 @@ where /// sources could be resolved. Otherwise, an error is returned if writing the bundle fails. /// /// This finishes the source bundle and flushes the underlying writer. - pub fn write_object(self, object: &O, object_name: &str) -> Result + pub fn write_object<'data, 'object, O, E>( + self, + object: &'object O, + object_name: &str, + ) -> Result where - O: ObjectLike, - O::Error: std::error::Error + Send + Sync + 'static, + O: ObjectLike<'data, 'object, Error = E>, + E: std::error::Error + Send + Sync + 'static, { self.write_object_with_filter(object, object_name, |_| true) } @@ -878,14 +883,14 @@ where /// This finishes the source bundle and flushes the underlying writer. /// /// Before a file is written a callback is invoked which can return `false` to skip a file. - pub fn write_object_with_filter( + pub fn write_object_with_filter<'data, 'object, O, F>( mut self, - object: &O, + object: &'object O, object_name: &str, mut filter: F, ) -> Result where - O: ObjectLike, + O: ObjectLike<'data, 'object>, O::Error: std::error::Error + Send + Sync + 'static, F: FnMut(&FileEntry) -> bool, { diff --git a/symbolic-minidump/src/cfi.rs b/symbolic-minidump/src/cfi.rs index c067ea6c4..5615f64bd 100644 --- a/symbolic-minidump/src/cfi.rs +++ b/symbolic-minidump/src/cfi.rs @@ -131,9 +131,9 @@ struct UnwindInfo { } impl UnwindInfo { - pub fn new(object: &O, addr: u64, mut section: U) -> Self + pub fn new<'d: 'o, 'o, O, R>(object: &O, addr: u64, mut section: U) -> Self where - O: ObjectLike, + O: ObjectLike<'d, 'o>, R: Reader, U: UnwindSectionExt, { @@ -236,9 +236,9 @@ impl AsciiCfiWriter { Ok(()) } - fn process_dwarf<'o, O>(&mut self, object: &O) -> Result<(), CfiError> + fn process_dwarf<'d: 'o, 'o, O>(&mut self, object: &O) -> Result<(), CfiError> where - O: ObjectLike + Dwarf<'o>, + O: ObjectLike<'d, 'o> + Dwarf<'o>, { let endian = object.endianity(); diff --git a/symbolic-symcache/src/writer.rs b/symbolic-symcache/src/writer.rs index b3abd5193..617151298 100644 --- a/symbolic-symcache/src/writer.rs +++ b/symbolic-symcache/src/writer.rs @@ -194,9 +194,9 @@ where W: Write + Seek, { /// Converts an entire object into a SymCache. - pub fn write_object(object: &O, target: W) -> Result + pub fn write_object<'d, 'o, O>(object: &'o O, target: W) -> Result where - O: ObjectLike, + O: ObjectLike<'d, 'o>, O::Error: std::error::Error + Send + Sync + 'static, { let mut writer = SymCacheWriter::new(target)?;