diff options
Diffstat (limited to 'third_party/rust/minidump-common/src/traits.rs')
-rw-r--r-- | third_party/rust/minidump-common/src/traits.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/third_party/rust/minidump-common/src/traits.rs b/third_party/rust/minidump-common/src/traits.rs new file mode 100644 index 0000000000..33de6b8468 --- /dev/null +++ b/third_party/rust/minidump-common/src/traits.rs @@ -0,0 +1,119 @@ +//! Some common traits used by minidump-related crates. + +use debugid::{CodeId, DebugId}; +use range_map::{Range, RangeMap}; + +use std::borrow::Cow; +use std::cmp; +use std::fmt::Debug; + +/// An executable or shared library loaded in a process. +pub trait Module { + /// The base address of this code module as it was loaded by the process. + fn base_address(&self) -> u64; + /// The size of the code module. + fn size(&self) -> u64; + /// The path or file name that the code module was loaded from. + fn code_file(&self) -> Cow<str>; + /// An identifying string used to discriminate between multiple versions and + /// builds of the same code module. This may contain a uuid, timestamp, + /// version number, or any combination of this or other information, in an + /// implementation-defined format. + fn code_identifier(&self) -> Option<CodeId>; + /// The filename containing debugging information associated with the code + /// module. If debugging information is stored in a file separate from the + /// code module itself (as is the case when .pdb or .dSYM files are used), + /// this will be different from code_file. If debugging information is + /// stored in the code module itself (possibly prior to stripping), this + /// will be the same as code_file. + fn debug_file(&self) -> Option<Cow<str>>; + /// An identifying string similar to code_identifier, but identifies a + /// specific version and build of the associated debug file. This may be + /// the same as code_identifier when the debug_file and code_file are + /// identical or when the same identifier is used to identify distinct + /// debug and code files. + fn debug_identifier(&self) -> Option<DebugId>; + /// A human-readable representation of the code module's version. + fn version(&self) -> Option<Cow<str>>; +} + +/// Implement Module for 2-tuples of (&str, DebugId) for convenience. +/// `breakpad-symbols`' `Symbolizer::get_symbol_at_address` uses this. +impl<'a> Module for (&'a str, DebugId) { + fn base_address(&self) -> u64 { + 0 + } + fn size(&self) -> u64 { + 0 + } + fn code_file(&self) -> Cow<str> { + Cow::Borrowed("") + } + fn code_identifier(&self) -> Option<CodeId> { + None + } + fn debug_file(&self) -> Option<Cow<str>> { + let &(file, _id) = self; + Some(Cow::Borrowed(file)) + } + fn debug_identifier(&self) -> Option<DebugId> { + let &(_file, id) = self; + Some(id) + } + fn version(&self) -> Option<Cow<str>> { + None + } +} + +/// This trait exists to allow creating `RangeMap`s from possibly-overlapping input data. +/// +/// The `RangeMap` struct will panic if you attempt to initialize it with overlapping data, +/// and we deal with many sources of untrusted input data that could run afoul of this. +/// [Upstream issue](https://github.com/jneem/range-map/issues/1) +pub trait IntoRangeMapSafe<V>: IntoIterator<Item = (Option<Range<u64>>, V)> + Sized +where + V: Clone + Debug + Eq, +{ + fn into_rangemap_safe(self) -> RangeMap<u64, V> { + let mut input: Vec<_> = self.into_iter().collect(); + input.sort_by_key(|x| x.0); + let mut vec: Vec<(Range<u64>, V)> = Vec::with_capacity(input.len()); + for (range, val) in input.into_iter() { + if range.is_none() { + // warn!("Unable to create valid range for {:?}", val); + continue; + } + let range = range.unwrap(); + + if let Some(&mut (ref mut last_range, ref last_val)) = vec.last_mut() { + if range.start <= last_range.end && &val != last_val { + // This logging is nice to have but some symbol files are absolutely + // horribly polluted with duplicate entries with different values(!!!) + // and this generates literally a gigabyte of logs, yikes! + + /* + warn!("overlapping ranges {:?} and {:?}", last_range, range); + warn!(" value1: {:?}", last_val); + warn!(" value2: {:?}\n", val); + */ + continue; + } + + if range.start <= last_range.end.saturating_add(1) && &val == last_val { + last_range.end = cmp::max(range.end, last_range.end); + continue; + } + } + + vec.push((range, val)); + } + RangeMap::try_from_iter(vec).unwrap() + } +} + +impl<I, V> IntoRangeMapSafe<V> for I +where + I: IntoIterator<Item = (Option<Range<u64>>, V)> + Sized, + V: Clone + Debug + Eq, +{ +} |