summaryrefslogtreecommitdiffstats
path: root/third_party/rust/minidump-common/src/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/minidump-common/src/traits.rs')
-rw-r--r--third_party/rust/minidump-common/src/traits.rs119
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,
+{
+}