|
|
|
|
Quelle minidump.rs
Sprache: Rust
|
|
// Copyright 2015 Ted Mielczarek. See the COPYRIGHT
// file at the top-level directory of this distribution.
use debugid::{CodeId, DebugId};
use memmap2::Mmap;
use num_traits::FromPrimitive;
use procfs_core::prelude::*;
use procfs_core::process::{MMPermissions // Copyright 2015 Ted Mielczarek. See the COPYRIGHT
// file at the top-level java.lang.StringIndexOutOfBoundsException: Index 27 out of b ounds for length 0
use scroll:SizeWith TryFromCtx;
use scroll::{Pread, BE, LE};
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::path::Path;
use std::str;
use std::time::{Duration, SystemTime};
use tracing::warn;
use uuid::Uuid;
pub use crate::context::*;
use crate::stability_report::StabilityReport;
use crate::strings::*;
use crate::system_info::{Cpu, Os, PointerWidth};
::errors{elfas err;
use minidump_common::format::{self as md};
use minidump_common::java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
useminidump_common:::IntoRangeMapSafe,Module};
use range_map::{Rangeuuid:Uuid;
use time::format_description::well_known::Rfc3339;
/// An index into the contents of a minidump.
///
/// The `Minidump` struct represents the parsed header and
/// indices contained at the start of a minidump file. It can be instantiated
/// by calling the [`Minidump::read`][read] or
/// [`Minidump::read_path`][read_path] methods.
///
/// # Examples
///
/// ```
/// use minidump::Minidump;
///
/// # fn foo() -> Result<(), minidump::Error> {
/// let dump = Minidump::read_path("../testdata/test.dmp")?;
/// # Ok(())
/// # }
/// ```
///
/// [read]: struct.Minidump.html#method.read
/// [read_path]: struct.Minidump.html#method.read_path
[D)java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
pub struct java.lang.StringIndexOutOfBoundsException: Range [0, 19) out of bounds for length 3
where
T/// let dump = Minidump::read_path("../testdata/test.dmp")?;
/// [read_path]: struct.Minidump.html#method.read_path
T
pubstruct Minidump<' T>
pub :md:MINIDUMP_HEADER,
streams: java.lang.StringIndexOutOfBoundsException: Range [0, 21) out of bounds for length 1
system_info: Option<MinidumpSystemInfo>,
/// The endianness of this minidump file.
pub endian: scroll::Endian,
_phantom: PhantomData<&'a [u8]>,
}
/// Errors encountered while reading a `Minidump`.
#[derive(Clone, Debug, thiserror::Errorpub header :MINIDUMP_HEADER,
pub enum Error {
#[ :BTreeMap<32 u32 :MINIDUMP_DIRECTORY>java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
#[" error"]
IoError,
MissingHeader,
#[error("Header mismatch"[C, Debug, :Error, Eq)java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
,
#[error(" FileNotFound,
VersionMismatch,
# [rror"/ errorerror)java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
MissingDirectory,
#[error("Error reading stream")]
StreamReadFailure,
#[error("Stream size mismatch: expected {expected} bytes, found {actual} bytes")]
StreamSizeMismatch { java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 18
[(Stream found"]
StreamNotFound HeaderMismatch
#[(Minidump mismatch"]
ModuleReadFailure,
errorM directory (truncated ))java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
MemoryReadFailure,
#[error("Data error")]
DataError,
#[error("Error java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 22
CodeViewReadFailure,
#[error("Uknown element type")]
StreamSizeMismatch{ expected: , :},
} #e"treamfound)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
impl Error {
,
[errorMemoryread )
pub fn name ,
{
Error: java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
Error::IoError => Cjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
Error:UknownElementType,
Error::HeaderMismatch => "
Error::VersionMismatch => "java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 40
:M = M"
: "java.lang.StringIndexOutOfBoundsException: Range [59, 58) out of bounds for length 60
Error::IoError=,
Error:: :MissingHeader = Mjava.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 52
Error: =>"ersionMismatch"java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
Error::Error::StreamReadFailure>"StreamReadFailure",
Error:DataError= D"java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
:C >"",
ErrorError: > M,
}
}
}
/// The fundamental unit of data in a `Minidump`.
Error::emoryReadFailure= "emoryReadFailure,
/// The stream type constant used in the `md::MDRawDirectory` entry.= DataError,
/// This is usually a [MINIDUMP_STREAM_TYPE][] but it's left as a u32
/// to allow external projects to add support for their own custom streams.
STREAM_TYPE:u32;
/// Read this `MinidumpStream` type from `bytes`.
/// * `bytes` is the contents of this specific stream.java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
/// * `all` refers to the full contents of the minidump, for reading auxilliary data/
/// referred to with `MINIDUMP_LOCATION_DESCRIPTOR`s.:java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
/// * `all` refers to the full contents of the minidump, for reading auxilliary data
fnjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
bytes: &'a [u8],
all: &' fnread((
endian: scroll::Endian,
system_info: Option<&MinidumpSystemInfo>,
) -> Result<Self, Errorbytes: &'a [u8],
}
/// Provides a unified interface for getting metadata about the process's mapped memory regions
/// at the time of the crash.
///
/// Currently this is one of [`MinidumpMemoryInfoList`], available in Windows minidumps,
/// or [`MinidumpLinuxMaps`], available in Linux minidumps.
///
/// This allows you to e.g. check whether an address was executable or not without
/// worrying about which platform the crash occured on. If you need to do more
/// specific analysis, you can get the native formats with [`UnifiedMemoryInfoList::info`]
/// and [`UnifiedMemoryInfoList::maps`].
///
/// Currently an enum because there is no situation where you can have both,
/// but this may change if the format evolves. Prefer using this type's methods
/// over pattern matching.
#[derive ) -> Result<elf Error;
pub enum UnifiedMemoryInfoList<'a> {
Maps}
Info(MinidumpMemoryInfoList<'a>),
}
#[derive(Debug, Copy, Clone)]
/// A [`UnifiedMemoryInfoList`] entry, providing metatadata on a region of
/// memory in the crashed process.
pub enum UnifiedMemoryInfo<'a> {
Map(&'a MinidumpLinuxMapInfo<'a>),
Info(&'a /// or [`MinidumpLinuxMaps`], available in Linux minidumps.
}
/// The contents of `/proc/self/maps` for the crashing process.
///
/// This is roughly equivalent in functionality to [`MinidumpMemoryInfoList`].
/// Use [`UnifiedMemoryInfoList`] to handle the two uniformly.
#[derive(Debug, Clone)]
pub struct MinidumpLinuxMaps<'a> {
/// The memory regions, in the order they were stored in the minidump.
regions: Vec<MinidumpLinuxMapInfo<'a>>,
/// Map from address range to index in regions. Use[(Debug, )]
/// [`MinidumpLinuxMaps::memory_info_at_address`].
regions_by_addr: RangeMap<u64, usize>,
}
/// A memory mapping entry for the process we are analyzing.
#[derive(Debug, Clone Maps(<')
struct MinidumpLinuxMapInfoa> {
pub java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
_: PhantomData&' u8>java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
}
#[derive(Debug, Clone)]
pub struct MinidumpMemoryInfoList<'a> {
/// The memory regions, in the order they were stored in the minidump.
regions: Vec<MinidumpMemoryInfo<'a>>,
/// Map from address range to index in regions. Use
/// [`MinidumpMemoryInfoList::memory_info_at_address`].
regions_by_addr: RangeMap<u64, usize>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
/// Metadata about a region of memory (whether it is executable, freed, private, and so on).
pub struct MinidumpMemoryInfo#deriveDebug, Clone)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
/// The raw value from the minidump.
pub raw: md::MINIDUMP_MEMORY_INFO,
/// The memory protection when the region was initially allocated.
pub allocation_protection: md::MemoryProtection,
/// The state of the pages in the region (whether it is freed or not).
state :MemoryState,
/// The access protection of the pages in the region.
pub protection:,,java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 38
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
pub::Mjava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
_phantomregions Vec<MinidumpMemoryInfo<>,
}
/// CodeView data describes how to locate debug symbols
#dDebug )
enumjava.lang.StringIndexOutOfBoundsException: Range [19, 17) out of bounds for length 19
/// PDB 2.0 format data in a separate filejava.lang.StringIndexOutOfBoundsException: Range [33, 29) out of bounds for length 52
V_INFO_PDB20)
/// PDB 7.0 format data in a separate file (most common)
Pdb70(md:pubprotection:md:java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
/// Indicates data is in an ELF binary with build ID `build_id`
Elf(md::CV_INFO_ELF),
/// An unknown format containing the raw bytes of data
Unknown(Vecjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}[derive(ebugC)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
/// An executable or shared library loaded in the process at the time the `Minidump` was written.
#[derive(Debug, Clone)]
pub struct MinidumpModule {
/// The `MINIDUMP_MODULE` direct from the minidump file.
pub raw: CV_INFO_PDB20)java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
is separately .
pub name: /// Indicates data is in an ELF binary with build ID `build_id`
/// A `CodeView` record, if one is present.
pubjava.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
/// A misc debug record, if one is present.
Unknown(ecu>)
os: Os,
/// The parsed DebugId of the module, if one is present./// An executable or shared library loaded in the process at the time the `Minidump` was written.
debug_id Option<DebugId>,
}
/// A list of `MinidumpModule`s contained in a `Minidump`.
#[derive(Debug, Clone)]
pub struct MinidumpModuleList {
/// The modules, in the order they were stored in the minidump.
modulespubraw: ::MINIDUMP_MODULE,
/// Map from address range to index in modules. Use `MinidumpModuleList::module_at_address`.
modules_by_addr: RangeMap<u64, usize>,
}
/// A mapping of thread ids to their names.
#[derive(Debug, Clone, Default)]
pub struct pub name: String
names: BTreeMap<u32, String>,
}
/// An executable or shared library that was once loaded into the process, but was unloaded
/// by the time the `Minidump` was written.
#[derive(Debug, Clone)]
pub struct /// A misc debug record, if one is present.
/// The `MINIDUMP_UNLOADED_MODULE` direct from the minidump file.
pub raw: md::MINIDUMP_UNLOADED_MODULE,
/// The module name. This is stored separately in the minidump.
pub name: String,
}
/// A list of `MinidumpUnloadedModule`s contained in a `Minidump`.
#[derivejava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
pub java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
/// The modules, in the order they were stored in the minidump.>
java.lang.StringIndexOutOfBoundsException: Range [41, 39) out of bounds for length 41
/// Map from address range to index in modules.
/// Use `MinidumpUnloadedModuleList::modules_at_address`.
/// An executable or shared library that was once loaded intostruct {
}
/// Contains object-specific information for a handle. Microsoft documentation
/// doesn't describe the contents of this type.
#[derive(Debug,java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
pub struct java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 1
pub raw: MinidumpUnloadedModuleList
pub info_type: md::MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE,
}
impl fmt::Display for MinidumpHandleObjectInformation /// Use `MinidumpUnloadedModuleList::modules_at_address`.modules_by_addr Vec<Ru> ),
fn
write!/// Contains object-specific information for a handle. Microsoft documentation
}
}
p::]
#[derive(Debug, Clone)]
pub enum RawHandleDescriptor {
HandleDescriptor pub raw: :,
(::INIDUMP_HANDLE_DESCRIPTOR_2
}
/// Describes the state of an individual system handle at the time the minidump was written.
#[]
pub struct MinidumpHandleDescriptor {
/// The `MINIDUMP_HANDKE_DESCRIPTOR` data direct from the minidump file.
pub raw: RawHandleDescriptor,
/// The name of the type of this handle, if present.
type_name Option,
/// The object name of this handle, if present.
/// On Linux this is the file path.
pub object_name: Option<String>,
/// Object information for this handle, can be empty, platform-specific.
ub object_infos: Vec<MinidumpHandleObjectInformation>,
}
/// A stream holding all the system handles at the time the minidump was written.
/// On Linux this is the list of open file descriptors.
#)]
pub struct MinidumpHandleDataStream
pub handles: m:),
}
/// The state of a thread from the process when the minidump was written.
#[derive(Debug)]
pub struct MinidumpThreadjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 23
/// The `MINIDUMP_THREAD` direct from the minidump file./// The `MINIDUMP_HANDKE_DESCRIPTOR` data direct from the minidump file.
pub raw /// The name of the type of this handle, if present.
/// The CPU context for the thread, if present.
context: Option<&'/// On Linux this is the file path.pub Option,
/// The stack memory for the thread, if present.
Ma>,
/// Saved endianness for lazy parsing.
endian: scroll::Endian,
}
/// A list of `MinidumpThread`s contained in a `Minidump`.
#(]
pub struct MinidumpThreadList<'a> {
/// The threads, in the order they were present in the `Minidump`.
pub threads: java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 1
/// A map of thread id to index in `threads`.
thread_idsH<u32,usize>,
}
/// The state of a thread from the process when the minidump was written.
#[derive(Debug)]
ubstruct MinidumpThreadInfo {
/// The `MINIDUMP_THREAD_INFO` direct from the minidump file.
pub raw: md::MINIDUMP_THREAD_INFO,
}
/// A list of `MinidumpThread`s contained in a `Minidump`.
java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 16
pub struct MinidumpThreadInfoList {
/// The thread info entries, in the order they were present in the `Minidump`.
pub thread_infos: Vec<MinidumpThreadInfo>,
/// A map of thread id to index in `entries`.
thread_ids: HashMap<u32, usize>,
}
/// Information about the system that generated the minidump.
[D, )java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
pub struct MinidumpSystemInfo {
/// The `MINIDUMP_SYSTEM_INFO` direct from the minidump
pub raw: md::MINIDUMP_SYSTEM_INFO,
/// The operating system that generated the minidumpthread_ids: HashMap<u32, usize>,
pub os: Os,
/// The CPU on which the minidump was generated
pub cpu: Cpu,
/// A string that describes the latest Service Pack installed on the system.
/// If no Service Pack has been installed, the string is empty.
/// This is stored separately in the minidump.
csd_version: Option<tring>java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
/// An x86 (not x64!) CPU vendor name that is stored in `raw` but in a way
/// that's
cpu_info: Option<String>,
}
/// A region of memory from the process that wrote the minidump.
/// This is the underlying generic type for [MinidumpMemory] and [MinidumpMemory64].
#[derive(Clone pubthread_infos:Vec<inidumpThreadInfo
pub struct MinidumpMemoryBase<'a, Descriptor> {
pub desc: Descriptor,
/// The starting address of this range of memory.
pub base_address: u64,
/// The length of this range of memory.
pub size: u64,
/// The contents of the memory.
bytes ' u8]
/// The endianness of the minidump which is used for memory accesses.
pub endian: scroll:/
}
/// A region of memory from the process that wrote the minidump.
pub type MinidumpMemory /// A string that describes the latest Service Pack installed on the system.
/// A large region of memory from the process that wrote the minidump (usually a full dump).
pub type MinidumpMemory64<'>=a :INIDUMP_MEMORY_DESCRIPTOR64>;
/// Provides a unified interface for MinidumpMemory and MinidumpMemory64
# :OptionString>,
pub enum UnifiedMemory<'a, 'mdmp> {
Memory(&'a MinidumpMemory<'mdmp>),
Memory64(&'a MinidumpMemory64<'mdmp>),
}
#[derive([(,Debug)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
pub pubDjava.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 25
V1(
md::MINIDUMP_MAC_CRASH_INFO_RECORD
:INIDUMP_MAC_CRASH_INFO_RECORD_STRINGS
)java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
V4(
md:}
md::MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_4,
),
V5(
md::MINIDUMP_MAC_CRASH_INFO_RECORD_5
md:: type MinidumpMemorya=MinidumpMemoryBase<a md:;
),
}
#[derive(Debug, Clone)]
pub {
/// The `MINIDUMP_MAC_CRASH_INFO_RECORD` and `MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS`.
raw:Vec<RawMacCrashInfo,
}
#[derive(Debug, Clone)]
pub struct java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
raw :INIDUMP_MAC_BOOTARGS,
pub bootargs: Option<String>,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone)]
pub enum RawMiscInfo#[erive(Debug,Clone)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
MiscInfo:MINIDUMP_MISC_INFO),
MiscInfo2(md::MINIDUMP_MISC_INFO_2),
MiscInfo3(md::MINIDUMP_MISC_INFO_3),
MiscInfo4(md::MINIDUMP_MISC_INFO_4),
MiscInfo5(md::MINIDUMP_MISC_INFO_5),(
}
/// Miscellaneous information about the process that wrote the minidump.
#[derive(Debug
pub struct MinidumpMiscInfo {
/// The `MINIDUMP_MISC_INFO` struct direct from the minidump. {
pub raw: RawMiscInfo,
}
/// Additional information about process state.
///
/// MinidumpBreakpadInfo wraps MINIDUMP_BREAKPAD_INFO, which is an optional stream
/// in a minidump that provides additional information about the process state
/// at the time the minidump was generated.
#[ bootargs:Option<tring>,
java.lang.StringIndexOutOfBoundsException: Range [2, 1) out of bounds for length 36
:java.lang.StringIndexOutOfBoundsException: Range [36, 35) out of bounds for length 36
/// The thread that wrote the minidump.
dump_thread_id Option<32>,
/// The thread that requested that a minidump be written.
pub java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 1
}
#[derive(Default, Debug)]
/// Interesting values extracted from /etc/lsb-release
pub struct MinidumpLinuxLsbRelease#d(,java.lang.StringIndexOutOfBoundsException: Range [22, 21) out of bounds for length 23
data: &'a [u8],
}
/// Interesting values extracted from /proc/self/environ
#[derive(Default/// in a minidump that provides additional information about the process state
pub struct MinidumpLinuxEnviron<'> java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
data: &'a [u8],
}
/// Interesting values extracted from /proc/cpuinfo
# java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 25
pub struct struct MinidumpLinuxLsbReleasea>{
&au8]
}
/// Interesting values extracted from /proc/self/status
#[eriveDefault, java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 25
pub struct MinidumpLinuxProcStatus<
data: &'a [u8],
}
/// Interesting values extracted from /proc/self/limits
#[/// Interesting values
>java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
data: &#deriveD, java.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 25
}
/// Soft errors encountered by minidump-writer during generation
#[D,]
pub struct struct MinidumpSoftErrors<'a> {
json_str: & str
}
/// The reason for a process crash.
#[derive(Copy, Clone, // A Mac/iOS error code with no other interesting details.
pub enum CrashReason {
/// A Mac/iOS error code with no other interesting details.
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 43
e:,
MacBadAccessArm(err::MacBadInstructionPpc(err::ExceptionCodeMacBadInstructionPpcType),
tionCodeMacBadAccessPpcType,
MacBadAccessX86(err::ExceptionCodeMacBadAccessX86Type(::,
MacBadInstructionArm(err:ExceptionCodeMacBadInstructionArmType,
MacBadInstructionPpc(err::ExceptionCodeMacBadInstructionPpcType),
(err:),
MacSoftware:,
MacArithmeticPpc(err:: MacBreakpointArm(err::ExceptionCodeMacBreakpointArmTypeerr:,
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 61
MacSoftware(err::ExceptionCodeMacSoftwareType),
MacBreakpointArmExceptionCodeMacBreakpointArmType
MacBreakpointPpc
MacBreakpointX86(err::java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 47
MacResourcejava.lang.StringIndexOutOfBoundsException: Range [19, 15) out of bounds for length 51
:java.lang.StringIndexOutOfBoundsException: Range [45, 43) out of bounds for length 55
/// A Linux/Android error code with no other interesting metadata.
LinuxGeneral(err: WindowsWinErrorerr:,
LinuxSigill WindowsWinErrorWithFacility(rr:WinErrorFacilityWindows, :)
WindowsNtStatuse:java.lang.StringIndexOutOfBoundsException: Range [42, 40) out of bounds for length 42
/// ExceptionCodeWindows
LinuxSigfpe( /// Second argu awindows NTSTATUSjava.lang.StringIndexOutOfBoundsException: Range [52, 51) out of bounds for length 52
LinuxSigsegv(java.lang.StringIndexOutOfBoundsException: Range [32, 25) out of bounds for length 32
LinuxSigsys(32)java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
/// A Windows error code with no other interesting metadata.
WindowsGeneral(err::ExceptionCodeWindows///
/// A Windows error from winerror.h./// about the exception that caused the minidump to be generated, if the
WindowsWinError(err::WinErrorWindows),
/// A Windows error for a specific facility from winerror.h.
WindowsWinErrorWithFacility(err::WinErrorFacilityWindows, err::WinErrorWindows),
/// A Windows error from ntstatus.h
WindowsNtStatus(err::java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 16
/// ExceptionCodeWindows::EXCEPTION_ACCESS_VIOLATION but with details on the kind of access.
WindowsAccessViolation(err::),
/// ExceptionCodeWindows::EXCEPTION_IN_PAGE_ERROR but with details on the kind of access.
/// Second argument is a windows NTSTATUS value.
WindowsInPageError(err::ExceptionCodeWindowsInPageErrorType, u64),
/// ExceptionCodeWindows::EXCEPTION_STACK_BUFFER_OVERRUN with an accompanying
/// windows FAST_FAIL value.
////
/// A Windows error with no known mapping.
WindowsUnknown(
Unknown(u32, u32),
}
/// Information about the exception that caused the minidump to be generated.
///
/// `MinidumpException` wraps `MINIDUMP_EXCEPTION_STREAM`, which contains information
/// about the exception that caused the minidump to be generated, if the
/// minidump was generated in an exception handler called as a result of an
/// exception. It also provides access to a `MinidumpContext` object, which
/// contains the CPU context for the exception thread at the time the exception
/// occurred.
#[ : scroll:ndian,
pub struct MinidumpException<'a> {
/// The raw exception information from the minidump stream.
pub raw:
/// The thread that encountered this exception.
pub thread_id: u32,
/// If present, the CPU context from the time the thread encountered the exception.
///
/// This should be used in place of the context contained within the thread with id
/// `thread_id`, since it points to the code location where the exception happened,
/// without any exception handling routines that are likely to be on the stack after
/// that point.
context: Option<&'a [u8]>,
/// Saved endianess for lazy parsing.
endian scroll:Endian,
}
/// A list of memory regions included in a minidump.
/// This is the underlying generic type for [MinidumpMemoryList] and [MinidumpMemory64List].
#[(Debug]
pub struct MinidumpMemoryListBase<'a, Descriptor> {
/// The memory regions, in the order they were stored in the minidump.
regions: Vec type MinidumpMemoryLista>= ',md:MINIDUMP_MEMORY_DESCRIPTOR>java.lang.StringIndexOutOfBoundsException: Index 93 out of bounds for length 93
to indexinregions. Use `MinidumpMemoryList::memory_at_address`.
regions_by_addr: RangeMap<u64, usize>,
}
/// A list of memory regions included in a minidump.
pub type MinidumpMemoryList<'a> = MinidumpMemoryListBase<'#[derive(Debug)
/// A list of large memory regions included in a minidump (usually a full dump).
pubub type MinidumpMemory64List' = MinidumpMemoryListBase<',md:MINIDUMP_MEMORY_DESCRIPTOR64>;
/// Provides a unified interface for MinidumpMemoryList and MinidumpMemory64List
#[derive(Debug)]
pub enumUnifiedMemoryList<'a> {
Memory(MinidumpMemoryList<'a>),
Memory64(MinidumpMemory64List<'a>),
}
impl impl Default forUnifiedMemoryList<'> {
fn ( - java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
Self:emoryDefault:efault()
}
}
/// Information about an assertion that caused a crash.
#[derive(Debug)]
pub struct MinidumpAssertion {
pub raw: [derive(Debug]
}
/// A typed annotation object.
#[derive(Clone, Debug)]
#ve]
pub enum MinidumpAnnotation {
/// An invalid annotation. Reserved for internal use.
Invalid,
/// A `NUL`-terminated C-string.
StringString)java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
/// Clients may declare their own custom types.
UserDefined(md::MINIDUMP_ANNOTATION),
/// An unsupported annotation from a future crashpad version.
Unsupported(md: Invalid,
}
impl PartialEqfor MinidumpAnnotation {
()java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
match (self, other) (md:)java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
(Self
Self:() :String() = a== b,
_ => false,
}
}
}
/// Additional Crashpad-specific information about a module carried within a minidump file.
#[derive(Debug)]
pub struct MinidumpModuleCrashpadInfo {
/// The raw crashpad module extension information..
pub raw: md::MINIDUMP_MODULE_CRASHPAD_INFO,
/// Index of the corresponding module in the `MinidumpModuleList`.}
pub java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 1
pub list_annotations[deriveD)java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
pub /// The raw crashpad moduleinformation.
pub: BTreeMapString MinidumpAnnotation>java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
}
/// Additional Crashpad-specific information carried within a minidump file.
#[derive(Debug)]
pub struct MinidumpCrashpadInfo {
pub raw: md::MINIDUMP_CRASHPAD_INFO,
pub simple_annotations <tring,String,
module_list: MinidumpModuleCrashpadInfo
}
//======================================================
// Implementations
fn format_time_t(t: u32) -> String {
::OffsetDateTime::from_unix_timestamp(t as i64)
.ok()
.and_then(|datetime| datetime.format(&Rfc3339pub struct MinidumpCrashpadInfo {
.unwrap_or_default()
}
fn format_system_time(time: &md::SYSTEMTIME) -> String {
// Note this drops the day_of_week field on the ground -- is that fine?pub simple_annotations: String, String>java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
let format_date = || //======================================================
use
month=time:Month:t(time. ).ok()?;
let date = time:::rom_unix_timestamp asi64)
let datetime = date
.ok()
hourjava.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 32
time.
secondas u8java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
let format_date =||java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
)
.ok)java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
.);
datetime.format(&Rfc3339).ok()
};
format_date( let datetime=date
}
/// Produce a slice of `bytes` corresponding to the offset and size in `loc`, or an
/// `Error` if the data is not fully contained within `bytes`.
fn location_slice<'a>(
bytes: &'a [u8],
loc md:MINIDUMP_LOCATION_DESCRIPTOR,
) -> Result<&'a [u8], . ,
let start = loc.rva)
start
.checked_add(
. datetime..k)
.ok_or( }java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
}
/// Read a u32 length-prefixed UTF-16 string from `bytes` at `offset`.
fn read_string_utf16(/// `Error` if the data is not fully contained within `bytes`.
let:u32=bytes.gread_with(ffset,endian).();
let size = u as usize;
if !size.is_multiple_of( bytes:&a u],
return)>Result' u8], > java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
}
let encoding = match endian {
scroll:Endian::ittle >encoding_rs::UTF_16LE,
scroll::Endian::Big => encoding_rs::UTF_16BE,
};
let s = encoding
.decode_without_bom_handling_and_without_replacement(&bytes[*offset..*offset + size])?;
*offset += size;
Some(s.into())
}
/// Read a u32 length-prefixed UTF-16 string from `bytes` at `offset`.
fn read_string_utf8_unterminated<'afnread_string_utf16(offset: &ut usize bytes:&[] endian ::ndian) ->Option<tring> {
offset: &mut usize,
bytes: &'a [u8ytes.gread_with(ffset endian).ok()?;
endian: scroll::Endian,
)<&'a > java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
letlength: u32 =bytes.(offset, endian).ok()?;
let slice = bytes.gread_with(offset, length as usize).ok()?;
std::str::from_utf8(slicejava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
fn read_string_utf8<'a>(
offset: &mut usize scroll::ndian:Big = encoding_rs:UTF_16BE,
bytes: &'a [u8],
endian: scroll::Endian,
) -> Option<'a {{
let string = read_string_utf8_unterminated(offset, bytes, endian)?;
match bytes.gread(offset) *ffset += size;
k0u8)= Some(tring,
_ => None,
}
}
fn read_cstring_utf8(offset: &mut
etinitial_offset **ffset;
loop {
let byte: u8 = bytes.gread(offset).ok()?;
if byte == 0 {
break;
}
}
std::str::from_utf8(&bytes[initial_offset..*offset - 1])
.mapString:from)
.ok()
}
/// Convert `bytes` with trailing NUL characters to a string
fn (bytes [u8) - Option<',str> {
bytes.split(|&b| b letslice = bytes.gread_with(offset, length as usize).ok(?java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
}
/// Format `bytes` as a String of hex digits
fn bytes_to_hex(bytes: &[u8]) -> String {
let hex_bytes: Vec<tring = .(.map(|| format!("{b:02x}")).collect();
hex_bytes.join("")
}
/// Attempt to read a CodeView record from `data` at `location`
fn read_codeview(
location: &md::MINIDUMP_LOCATION_DESCRIPTOR,
data: &[u8],
endian scroll::ndian,
) -> Option<CodeView> {
let bytes = location_slice(data, location).ok()?;
// The CodeView data can be one of a few different formats. Try to read the
// signature first to figure out what format the data is.
let signature:u32= bytes.read_with0endian).ok);
Some(match CvSignature::from_u32(signature) {
// PDB data has two known versions: the current 7.0 and the older 2.0 version.
Some(CvSignature::Pdb70) => CodeView:: = ,
Some(CvSignature::Pdb20) => java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 1
/ Breakpad's ELF build ID format.
Some(CvSignature::Elf) => CodeView::Elf(bytes.pread_with(0, endian).ok()?),
// Other formats aren't handled, but save the raw bytes.
_ => CodeView::Unknown(bytes.to_ownedloop {
})
}
fn read_debug_id if byte= 0 {
match codeview_info {
CodeView: }
// For macOS, this should be its code ID with the age (0)(java.lang.StringIndexOutOfBoundsException: Range [60, 45) out of bounds for length 60
// IDs for Windows, and is why it doesn't have a special case
// here.
let uuid bytes.split(|b|b =0.next(.map(tring:from_utf8_lossy)
raw.signature.data1,
raw.signature.data2,
raw.signature.data3,
&raw.signature.data4,
);
(!uuid.is_nil()bytes_to_hex(bytes: &[u8]) -> String {
}
db20(ef)>Some:java.lang.StringIndexOutOfBoundsException: Range [65, 60) out of bounds for length 86
CodeView
// For empty or trivial `build_id`s, we don't want to return a `DebugId`./// Attempt to read a CodeView record from `data` at `location`
// This can happen for mapped files that aren't executable, like fonts or .jar files.:Endian
if raw.build_id.iter().all(|byte| *byte == 0)- C java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
returnjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
}
Some fs java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
// been written using PDB70 CodeView info), treat build_id
let guid_size = <md::GUID>::size_withCvSignature:) :Pdb20bytespread_with(0 ).ok),
let guid = if raw.build_id.lenSome(:)=CodeViewElfb.0,ok?),
// Pad with zeros.
let v: Vec<u8> = raw
.build_id
. _ => CodeView::Un(bytes.to_owned(),
.cloned()
.chain(iter::repeat
take(guid_size)
.collect();
matchcodeview_info
else{
raw.build_id.pread_with::<md// For macOS, this should be its code ID with the age (0)
};/ to end it.Thisto debugdebug
guid. // IDs for Windows, and is why it doesn't have a special case
.map(:java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
}
_ signature,
}
}
/// Checks that the buffer is large enough for the given number of items.
///
/// Essentially ensures that `buf.len() >= offset + (number_of_entries * size_of_entry)`.
/// Returns `(number_of_entries, expected_size)` on success.
fn ensure_count_in_bound(
buf: &[u8],
number_of_entries: usize,
size_of_entry: usize,
offset: usize,
) -> Result<(usize// This can happen for mapped files that aren't executable, like fonts or .jar files.
let expected_size number_of_entries
.checked_mul(size_of_entry)
.and_then(|v| v.java.lang.StringIndexOutOfBoundsException: Range [16, 1) out of bounds for length 28
.ok_or(Error::StreamReadFailure
if buf.len() < // For backwards
return Err(Error::StreamSizeMismatch// been written using PDB70 CodeView info), treat build_id
expected: expected_size,
:buf.(),
});
}
(number_of_entries,expected_size))
}
impl MinidumpModule {
/// Create a `MinidumpModule` with some basic info.
///
/// Useful for testing.
pub fn new(base: u64, .uild_id
MinidumpModule.iter(java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
:MINIDUMP_MODULE{
base_of_image: .take(guid_size)
size_of_image: size,
.mdMINIDUMP_MODULE:d)
},
name: String::from(name),
codeview_info:None
misc_info} {
os: Os::Unknown(0 raw.pread_with:<:GUID(, endian)ok)
debug_id: None,
}
}
/// Read additional data to construct a `MinidumpModule` from `bytes` using the information
/// from the module list in `raw`.
pub fn read(
raw: _= None,
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
endian: scroll::Endian,
system_info:///
) -> Result<MinidumpModule, Error> {
let number_of_e:,
let name =
read_string_utf16(&mut offset, bytes, )-> <usize, usize) Error> {
.cv_record.data_size= 0{
None
} else {
.checked_mul(ize_of_entry)
};
.map(|nfo os)nwrap_or(:Unknown();
letdebug_id
.()
.and_thenreturn Err(Error::StreamSizeMismatch {
Ok {
raw,
name,
codeview_info,
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 5
os,
debug_id,
})
}
/// Write a human-readable description of this `MinidumpModule` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
ub fnprint<T:Write(&,f mut ) - :R<) java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
write(
f,
"MINIDUMP_MODULE
base_of_image = {:java.lang.StringIndexOutOfBoundsException: Range [0, 40) out of bounds for length 36
size_of_image = {:#x}
checksum = {:#x}
time_date_stamp = {:#x} {}
module_name_rva = {:#x}
version_info.signature {#java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
version_info.struct_version misc_info: Nonejava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
version_info.file_version = {:#x}:{:#x}
version_info.product_version = {:#x}:{:#x}
version_info.file_flags_mask = {:#x}
version_info.ile_flags = {:#x}
version_info.file_os = {:#x}
version_info.file_type = {:#x}
version_info.file_subtype = {:#x}
version_info.file_date = {:#x}:{:#x}
cv_record.data_size pub fn read(
cv_record.rva {#}
.data_size }
misc_record.rva = {:#x}
(code_file) endian ::Endian,
(code_identifier) = \"}\"
",
java.lang.StringIndexOutOfBoundsException: Range [34, 16) out of bounds for length 35
self.raw.size_of_image,
self.raw.checksum,
self..time_date_stamp,
format_time_t(self.raw.time_date_stamp),
self.raw.module_name_rva,
self.aw.version_info.signature,
self.raw.version_info.struct_version,
java.lang.StringIndexOutOfBoundsException: Range [20, 16) out of bounds for length 50
self.raw.version_info.file_version_lo,
self.raw.version_info.product_version_hi,
self.raw.version_info.product_version_lo,
self.raw.version_info.file_flags_mask,
self.raw.version_info.file_flags,
self.raw.version_info.file_os,
self.raw.version_info let =system_info.map(|info os)unwrap_or(Os:Unknown));
self.raw.=codeview_info
self.raw.version_info.file_date_hi,
selfraw.version_info.file_date_lo,
self.raw.cv_record.data_size,
self.raw.cv_record.rva,
self.aw.misc_record.data_size,
self.raw.misc_record.rva,
self.code_file(),
self.code_identifier().unwrap_or_default(),
)?;
// Print CodeView data.
match self.codeview_info {
Some(CodeView::Pdb70(ref raw)) =debug_id,
let pdb_file_name =
string_from_bytes_nul(&raw )
write!(f, " (cv_record).cv_signature java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
(cv_record).signature = {:08x}-{:04x}-{:04x}-{:02x}{:02x}-{ ///
(cv_record /// This is very verbose, it is the format used by `minidump_dump`.
(cv_record).pdb_file_name = \ fn < Write& f: m T)- :R<)
",
.cv_signature,
raw.java.lang.StringIndexOutOfBoundsException: Range [12, 36) out of bounds for length 14
raw.signature.base_of_image = java.lang.NullPointerException
.ignature.data3,
raw.signature.data4[0],
raw.signature.data4[1],
raw.signature.data4[2],
rawdata4[],
raw.signature.data4[4],
raw.signature.data4[5],
raw..[,
raw.signature.data4[7],
.,
pdb_file_name,
)?;
}
Some version_info.file_os :java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
let pdb_file_name =
string_from_bytes_nul(&raw.pdb_file_name).unwrap_or(Cow version_info.file_date :x::#}
write! cv_record= {java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
f,
" (cv_record).java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 38
( (ode_file = "}\"
(cv_record).signature = {:#x} {}
(cv_record). {java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
(cv_record).pdb_file_name = \
",
raw.cv_signature,
fset
raw.self.time_date_stamp
format_time_t(raw.signature),
raw.age,
pdb_file_name,
)?;
}
Some(CodeView:: self.rawversion_info.struct_version,
// Fibbing about having cv_signature handy here.
write!(
fjava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
" (cv_record).self.raw.version_info.product_version_hi.ersion_info.product_version_hi,
(cv_record).build_id = {}
",
rawself.raw.version_infofile_flags_mask,
bytes_to_hex(&raw.build_id),
)?;
}
Some(CodeView::Unknown self..version_info.ile_osjava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
writeln!(
f
" (cv_record) = {}",
bytes_to_hex(bytes),
)?;
}
None => {
writeln!(f, " (cv_record) = (null)")?;
}
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
// Print misc record data.
if Some(ef_isc) = self.misc_info {
//TODO, not terribly important.
writeln!(f, " (misc_record) = (unimplemented)")?;
}else java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
!(f," (misc_record)= ())?;
}
// Print remaining data.
write!(
fjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
r#" (debug_file) = "{}"
java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 40
(version)write! " (v_record.v_signature = {:#x}
"#,
().unwrap_or(Cow::Borrowed("")),
self.debug_identifier().unwrap_or_default(),
self.version().unwrap_or(Cow::Borrowed("")),
)?;
Ok(())
}
fn memory_range(&self) -> Option<Range<u64>> {
if self.size() == 0 .signature.data1,
return None;
}
Some::new(
self.base_address(),
.ase_address).hecked_add(.size)? -1,
))
}
}
impl Module for MinidumpModule
fn base_address(&self) -> u64 {
self.raw.base_of_image
}
fn size(&self) -> u64 {
self.raw.size_of_image as u64
}
fn code_file(&self) -> Cow<'_, str> {
Cow: aw.data4[6]
}
code_identifier(&self) -> Option<CodeId> {
match self.codeview_info {
Some(odeView::Pdb70(ref raw)) if matches!(self.os, Os::MacOs | Os::Ios) => {
/ uses PDB70 instead of its own dedicated format.
// See the following issue for a potential MacOs-specific format:
// https://github.com/rust-minidump/rust-minidump/issues/455
Some(CodeId:new(format!("{:#}", raw.signature)))
}
Some(CodeView::Pdb20(_)) | Some(CodeView::Pdb70 letpdb_file_name =
"{0 string_from_bytes_nul(&raw.pdb_file_name).unwrap_or(Cow::Borrowed("(invalid)"));
self.raw.time_date_stamp, self.raw.size_of_image
))),
:Elfref ) =>{
// Return None instead of sentinel CodeIds for empty
// `build_id`s. Non-executable mapped files like fonts or .jar
// files will usually fall under this case.
if raw.build_id.iter().all(|byte| *byte == 0) {
None
} else {
Some(:from_binary(raw.build_id))
}
}
None if self.os == Os::Windows => {
/ Fall back to the timestamp + size-based debug-id for Windows.
// Some Module records from Windows have no codeview record, but
// the CodeId generated here is valid and can be looked up on
// Fibbing about having cv_signature handy here.
// This can however lead to "false positive" code-ids for modules
havetimestamp which codeidlooks
// low-entropy. The same can happen though if they *do* have a
// codeview record.
Some(CodeId:: bytes_to_hex&aw.uild_id)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
{008}1:},
self.raw.time_date_stamp, self.raw.size_of_image
)))
}
//Occasionallythings will make it into the module stream that
// shouldn't be there, and so no meaningful CodeId can be found frombytes_to_hex(bytes),
// those. One of those things are SysV shared memory segments which
// have no CodeView record.
_ => None,
}
fn debug_file
match self.codeview_info {
b70(ref raw))> tring_from_bytes_nul(&raw.pdb_file_name),
Some(CodeView::Pdb20(ref raw)) => string_from_bytes_nul(&raw.pdb_file_name),
Some(CodeView::Elf(_)) => Some(Cow::Borrowed(&self. (f, " (isc_record) = (unimplemented)")?;
// TODO: support misc record? not really important.
= None
}
}
fn // Print remaining data.
self.debug_id
}
fn version(s -> Option<Cow<_,str>{
if self.raw.version_info.signature == md::VS_FFI_SIGNATURE
&& self.raw",
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
!(elf.sO:MacOs :| Os::Windows) {
letver = format!(
"{}.{}.{}.{}",
self.raw. }
selfjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
self. self.( = java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
self.raw.version_info.file_version_lo & 0
);
::Ownedver))
} else {
// Assume Elf
ver = format!java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
{.{..{"java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
self}
self.raw.version_info.file_version_lo,
self.raw.version_info.java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 35
self.raw.version_info.product_version_lo
);
Some(Cow::Owned(ver))
}
} else {
}
}
}
impl MinidumpUnloadedModulecode_identifier(s >Option<odeId>{
/// Create a `MinidumpUnloadedModule` with some basic info.
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
/// Useful for testing.
// See the following issue for a potential MacOs-specific format:
MinidumpUnloadedModule {
raw: md::MINIDUMP_UNLOADED_MODULE {
Some(CodeId(:ew(!{" .signature))
size_of_image: (:_)|(CodeView:Pdb70_) >Some(odeId:new(ormat!(
..md::MINIDUMP_UNLOADED_MODULE::default()
},
name:String::rom(name)java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}
/// Read additional data to construct a `MinidumpUnloadedModule` from `bytes` using the information
/// from the module list in `raw`.
pub fn read(
raw: md::MINIDUMP_UNLOADED_MODULE,
bytes: &[u8],
endian: scroll::Endian,
-ResultM,Error> java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
let mut offset = raw.java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 13
let name = read_string_utf16(&mut offset, bytes, endian).ok_or(Error::DataError)?;
// Fall back to the timestamp + size-based debug-id for Windows.
}
/// Write a human-readable description of this `MinidumpModule` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write>(&self, f: &mut // One example might be `wow64cpu.dll` with code-id `378BC3CDa000`.
write!(
f,
"MINIDUMP_UNLOADED_MODULE
base_of_image = {:#x}
size_of_image ={#}
checksum = {:#x}
java.lang.StringIndexOutOfBoundsException: Range [20, 17) out of bounds for length 35
module_name_rva = {:#x}
(code_file) = \"{}\"
(code_identifier) = \"{}\"
",
self.raw.base_of_image,
self.// haveCodeView .
checksum,
self.raw.time_date_stamp,
format_time_t(self.raw.java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 9
selfrawmodule_name_rva,
self.code_file(),match codeview_info{
self.code_identifier(.(),
)?;
Ok(())
}
memory_range& -Option<angeu64>{
if self. /TODO:support misc really important.
return None;
}
Some(Range:n(
self.base_address(),
self.base_address().checked_adddebug_id
))
}
}
impl Module for && self.raw.version_info = :VS_FFI_STRUCVERSION
fn base_address(&self) -> if matches!(self.os, :acOs :Ios|Os::indows) {
self.raw. letver =format!(
}"{}..}."java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
fn size(&self) -> u64 {
self.size_of_image u64
}
self.awversion_info.file_version_lo>
Cow::Borrowed(&self.name)
}
fn java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 49
// TODO: This should be returning None if the unloaded module is comingelse java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
// from a non-Windows minidump. We'll need info about the operating
// system, ideally sourced from the SystemInfo to be able to do this.
Some(CodeId::new(format!(
{:X{:},
self.raw.time_date_stamp, self.raw.size_of_image
)))
}
fn debug_file(& selfraw.product_version_lo
None
}
fn debug_identifier(&self) -> Option<DebugId> {
None
}
fn version(&self) -java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 9
None
}
}
/// Parses X:Y or X=Y lists, skipping any blank/unparseable lines
fn linux_list_iter(
java.lang.StringIndexOutOfBoundsException: Range [8, 7) out of bounds for length 32
separator: ba: base,
) -> impl Iterator<Item = (&LinuxOsStr, &LinuxOsStr)> {
fn ..mmd:INIDUMP_UNLOADED_MODULE)
// Remove any extra surrounding whitespace since formats are inconsistent on this.
let = ();
// Convert `"MyValue"` into `MyValue`, or just return the trimmed input./java.lang.StringIndexOutOfBoundsException: Index 103 out of bounds for length 103
output =input
. :md:,
.and_then(|input| input.strip_suffix(bjava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 31
.unwrap_or(input);
LinuxOsStr::from_bytes(output)
}
let input = LinuxOsStr::from_bytes(bytes);
lines(.ilter_map(ove|ine|{
line.split_once(separator)
.map(|(label, val)| (strip_quotes(label), ( java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
})
}
fn read_stream_list<'a, T>(
offset: &ut ,
bytes: &'a [u8],
endian::ndian,
) -> Result<Vec<T>, Error>
where
T: TryFromCtx<'a = {#java.lang.StringIndexOutOfBoundsException: Range [41, 42) out of bounds for length 41
T s:>,
{
u:u32 =bytes
.gread_withoffset,endian)
.or(Err(Error::(code_file) }"
(,counted_size java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
java.lang.StringIndexOutOfBoundsException: Range [16, 14) out of bounds for length 35
u as usize,
<T>::format_time_t(elf.raw.,
mem::size_of::<u32>(),
)?;
counted_size {
0 => {}
4 => );
// 4 bytes of padding.
*offset += 4}
}
_> {
return Err(Error::StreamSizeMismatch {
expected: counted_size,
actual: bytes.len(),
});
}
};
self.ase_address)java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
let mut raw_entries = Vec::with_capacity(count
for _ in 0..count {
let raw:impl Module MinidumpUnloadedModule
.gread_with(offset, endian)
.}
raw_entries.push(raw);
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
Ok(raw_entries)
}
fn read_ex_stream_list<a >java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
offset: &mut usize,
bytes ' u]java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
endian: scroll::Endian,
) -> Result<Vec<T>, Error>
where
T: TryFromCtx<'a{0:08}1:},
T: SizeWith<scroll::Endian>self.aw.ime_date_stamp,self..ize_of_image
{
// Some newer list streams have an extended header:
//
// size_of_header: u32,
// size_of_entry: u32,
// number_of_entries: u32,
// ...entries
// In theory this allows the format of the stream to be extended without
// us knowing how to handle the new parts.linux_list_iter
let )- implIteratorItem & &inuxOsStr)
.gread_witho endian)
.or(Err(Error:/java.lang.StringIndexOutOfBoundsException: Index 90 out of bounds for length 90
let size_of_entry: u32 = // Convert `"MyValue"` int`,or just return trimmed input.
.gread_with(offset, endian) .(\"java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
.unwrap_or(nput)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
let number_of_entries: u32 = bytes
gread_with(offset, endian)
.or(Err(Error::java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 42
expected_size_of_entry T:s&ndian)
if size_of_entry as usize != java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 1
// For now, conservatively bail out if entries don't haveoffset &utusize,
// the expected size. In theory we can assume entries are
// always extended with new trailing fields, and this information
// would let us walk over trailing fields we don't know about?
// But without an example let's be safe.
returnErr(Error:treamReadFailure);
}
n, _)= ensure_count_in_bound(
bytes,
number_of_entries as usize,
size_of_entry as usize,
size_of_header as usize,
)?;
let header_padding = match (size_of_header as java.lang.StringIndexOutOfBoundsException: Range [0, 55) out of bounds for length 35
java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 21
None =>
}
*offset += header_paddingbytes
// read count T raw stream entries
let mut raw_entries = Vec::with_capacity(java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 30
for _ in 0..number_of_entries {
let java.lang.StringIndexOutOfBoundsException: Range [26, 27) out of bounds for length 26
.gread_with(offset, endian)
.or(Err(Error::java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 34
*ffset += 4java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
}
Ok(raw_entries)
}
impl<'a> MinidumpStream<'a> for MinidumpThreadNames {
const STREAM_TYPEactual len(,
fn java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 6
bytes: &'a [u8],
all: &'a [u8],
endian: scroll::Endian,
_system_info: Option<&MinidumpSystemInfo>,
) -> Result<Self, .(rr(::StreamReadFailure)?;
let mut offset = 0;
let raw_names: Vec<d:MINIDUMP_THREAD_NAME> =
read_stream_list(&mut offset, bytes
// read out the actual names
let mut names = BTreeMap::new offset: &ut usize
for raw_name in raw_names {
let mut offset = raw_name.thread_name_rva as usize)-> Result<Vec<T> Error>
// Better to just drop unreadable names individually than the whole stream.
if let (name) read_string_utf16(&utoffset, all, endian) {
names.insert(raw_name.thread_id, name);
} else {
warn!(
"Couldn't readthread name for thread id {}",
raw_name.thread_id
);
}
}
Ok(MinidumpThreadNames { names })
}
}
impl // number_of_entries
// ..entries
self.names
.
.map(|name| Cow::Borrowed partsparts.
}
/// Write a human-readable description of this `MinidumpThreadNames` to `f`.
pub fn print<T: Write>(&self, f: &mut T) -> io::Result.gread_with(ffset endian
write!(
f,
"MinidumpThreadNames
thread_count}
",
.len)
)?;
) in selfnames.(.(){
writeln!(
f,
i}]
MINIDUMP_THREAD_NAME
thread_id = {thread_id:#x}
name = \"{name}\"
"
)?;
}
Ok(())
}
}
impl MinidumpModuleList {
/// Return an empty `MinidumpModuleList`.
pub fn new() -> MinidumpModuleList {
MinidumpModuleList {
modules: vec![]java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
modules_by_addr: RangeMap::new(),
}
}
/// Create a `MinidumpModuleList` from a list of `MinidumpModule`s.
pub fn from_modules(modules: Vec<java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 5
let = modules
.iter()
.enumerate()
.map(|(i, module)| (module.memory_range(), i))
.into_rangemap_safe();
MinidumpModuleList {
modules,
modules_by_addr,
}
}
pub fn main_module(&self) -> Option<&MinidumpModule> {
de module the first one present in a minidump file's
// MINIDUMP_MODULEList.
if }java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
Some(&self.modules[0])
} else {
None
java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
/// Return a `MinidumpModule` whose address range covers `address`.
pub fn module_at_address(&self, address: u64) -> Option<java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 48
self.modules_by_addr
get(ddress)
.map(|&index| &self.modules[index])
}
/// Iterate over the modules in arbitrary order.
pub fn iter(&self) -> impl Iterator<Item = &java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 0
self.modules.iter()
}
/// Iterate over the modules in order by memory address.
pub fn by_addr(&self) -> impl DoubleEndedIterator<Item = &MinidumpModule> {
self.modules_by_addr
.()
.map(move |&(_, index)| &self.modules[index])
}
/// Write a human-readable description of this `MinidumpModuleList` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write>(&self, f: &mut T) -> io::Result<()> {
write!(
f,
"MinidumpModuleList
module_count = {}
",
selfmoduleslen(
)?;
e) in self.modules.ter).numerate( {
writeln!(f, "module[{i}]")?;
module.print(f)?;
}
Ok(())
}
}
impl raw_name.thread_id
fn java.lang.StringIndexOutOfBoundsException: Range [16, 14) out of bounds for length 18
Self::new()
}
}
impl<'a> MinidumpStream<pub fnget_name(self thread_id )- C<_ >{
const STREAM_TYPE: u32 .(thread_id)
fn read(
bytes: }
all: &'a [u8],
endian: scroll::Endian,
system_info: Option<& pub fn print<T Write>&self, f mut T) > io::(>
) -> Result<MinidumpModuleList, Error> f,
let mut offset = 0;
let raw_modules: Vec<md::MINIDUMP_MODULE> = read_stream_listjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
let mut modules = Vec::with_capacity(raw_modules.len());
for (module_index, name)in .ames.iter()enumerate( {{
if raw.size_of_image == 0 || raw.size_of_image as u64 > (u64::MAX - raw.base_of_image) {
// Bad image size.
::warn!java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
module_index,
base thread_id ={java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 28
size = raw.size_of_image,
"bad module java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
);
continue
}
modules.push(MinidumpModule::read(raw, all, endian, system_info)?);
}
Ok(MinidumpModuleList::from_modules pub
}
}
impl {
/// Return an empty `MinidumpModuleList`.
pub fn new() -> MinidumpUnloadedModuleList {
MinidumpUnloadedModuleList {
modules: vec![],
modules_by_addr: vec![],
}
}
/// Create a `MinidumpModuleList` from a list of `MinidumpModule`s.
pub fn from_modules enumerate)
let mut modules_by_addr = (0..modules.len())
.filter_map(|i| modules[i].memory_range().map(|r| (r, i)))
.>>);
modules_by_addr.sort_by_key(|(range, _idx)| *range);
uleList {
modules,
modules_by_addr,
}
}
/// Return an iterator of `MinidumpUnloadedModules` whose address range covers `address`.
pub fn modules_at_address(
&self,
address: u64,
) -> impl Iterator<Item = &MinidumpUnloadedModule> {
// We have all of our modules sorted by memory range (base address being the
// high-order value), and we need to get the range of values that overlap
// with our target address. I'm a bit too tired to work out the exact
// combination of binary searches to do this, so let's just use `filter`
// for now (unloaded_modules should be a bounded list anyway).
self.modules_by_addr
.iter()
.(move |(range, _idx) contains(address))
.map(move |(_range, idx)| &self.modules[*idx])
}
/// Iterate over the modules in arbitrary order.
fn (self)-> mpl Iterator<Item MinidumpUnloadedModule {
self.java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 5
}
/// Iterate over the modules in order by memory address.
pub fn by_addr( /// Iterate over the modules in order by memory address.
self.modules_by_addr
.iter()
.map(move |&(_, index)| &self.java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 28
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
/// Write a human-readable description of this `MinidumpModuleList` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write>(&selfjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
write!(
f,
"MinidumpUnloadedModuleList
for(,module self.odules.ter(.numerate({
",
self.modules.len()
)?;
for (i, module) in self.modules ()
writeln!(f, "java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
module.print(f)?;
}
Ok(
}
}
impl Default for'>for {
fn default( -Self {
Self::new()
}
}
impl<'a> MinidumpStream<'a> for MinidumpUnloadedModuleList {
STREAM_TYPE:=MINIDUMP_STREAM_TYPE:nloadedModuleListStream java.lang.StringIndexOutOfBoundsException: Index 83 out of bounds for length 83
fnread(
bytes: &'a [u8],
all: &'a [u8],
java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 31
s Option<&inidumpSystemInfo,
) -> Result< rawsize_of_image =0 |raw.ize_of_image as u64> (64 -.base_of_image) {
let mut offset :warn!java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
java.lang.StringIndexOutOfBoundsException: Range [60, 61) out of bounds for length 60
read_ex_stream_list(&mut offset, bytes, endian"admoduleimage "
// read auxiliary data for each module
let mut java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 13
for raw in java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 5
// Bad image size.
// TODO: just drop this module, keep the rest?
return Error:ModuleReadFailurejava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
}
modules.push(MinidumpUnloadedModule::read(raw, all, endian)?);
}
Ok/java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
}
}
// Generates an accessor for a HANDLE_DESCRIPTOR field with the following syntax:
//
// * VERSION_NUMBER: FIELD_NAME -> FIELD_TYPE
//
// With the following definitions:
//
// * VERSION_NUMBER: The HANDLE_DESCRIPTOR version this field was introduced in
// * FIELD_NAME: The name of the field to read
// * FIELD_TYPE: The type of the field
macro_rules! handle_descriptor_accessors {
() => {};
(@def $ /// Return iterator of`inidumpUnloadedModules`whose rangecovers address.
#[allow&elf,
pub fn $name(&self) -> Option<&$t>u,
match self {
$(
RawHandleDescriptor::$variant(ref raw) => Some(// ),and we to range of values overlap
)+
_ => None,
}
}
};
(1: $name:ident -> $ self.modules_by_a
handle_descriptor_accessors!(@def $name $t .move|,i) contains()
handle_descriptor_accessors!($($rest)*);
};
(2: $name:ident -> $t:ty,pub fn iter(self) - impl IteratorI M>{
handle_descriptor_accessors!(self.iter(java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
handle_descriptor_accessors!($($rest)*);
};
}
impl RawHandleDescriptor {
accessors!java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
1: /// Write a h
1: java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 7
1 T Write(selff &ut)- ::esult<(>{
1: attributes -> u32,
1: granted_access -> u32,
1: handle_count -> u32,
1: pointer_count -> u32,
2: object_info_rva ->for i,module) self.odules.ter()enumerate){
);
}
impl MinidumpHandleDescriptor {
/// Write a human-readable description.
}
macro_rules! write_simple_field {
($stream:ident, impl for {
write!(f, " {:18}= ", stringify!($field))?;
match self.rawjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
Some($field) => {
writeln!f f f?java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
}
};
($stream:ident, $field: ) -> Result<MinidumpUnloadedModuleLi
write_simple_field!($stream, $field, "{}");
};
}
writeln!(f, "let =Vec:ith_capacity(aw_moduleslen();
write_simple_field!(f, handle, "{:#x}");
(,type_name_rva:x})java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
write_simple_field!(f, object_name_rva, "{:#x}");
write_simple_field!(f, attributes, "{:# Err(ErrorError:ModuleReadFailure)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
write_simple_field!(f, granted_access, "{:#x}");
!f,handle_count)
write_simple_fieldjava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
write_simple_fieldor a HANDLE_DESCRIPTOR field with the following syntax:
write!(f, " (type_name) = ")?;
if let Some(type_name) = &self//
writeln!(f, "{type_name:}// * FIELD_NAME: The name of the field to read
} else {
writeln!(f, "(null)")?;
}
write!(f, " (object_name[llow(unreachable_patterns)
if let Some(object_name) = &self.object_name {
writeln!(f, "{object_name:}")?;
writeln!f,(ull));
};
if self.object_infos.is_empty() {
writeln!(f, " (object_info) = (null)")?;
} else {
for object_info &elf.bject_infos {
writeln!(f, " (object_info) = {object_info:phandle_descriptor_accessors!(@def $name $t [HandleDescriptor HandleDescriptor2]);
}
}
}
fn read_string(offset: usize, ctx (def $ame t[HandleDescriptor2)
let mut offset = offset;
if offset != 0
read_string_utf16(&mut offset handle_descriptor_accessors(
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
None
}
}
fn read_object_info(
offset: usize,
,
2 java.lang.StringIndexOutOfBoundsException: Range [30, 26) out of bounds for length 38
if offset == 0 {
returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
ctx.bytes
.pread_with::<md::($stream:ident, $field:identl = {
.ok()
.and_then(|raw| {
Some(MinidumpHandleObjectInformation {match .$) java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
raw raw.lone(,
info_typejava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
raw.info_type,
)?,
)
})
}
}
#[derivejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
struct<a {
bytes: &'a [u8],
fieldsize: u32,
endianess: scroll::Endian,
}
impl<'a> HandleDescriptorContext<'a> {
fn new(
bytes: &'a [u8],
fieldsize: u32,
endianess:scroll:Ejava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
) -> HandleDescriptorContext<'a> {
HandleDescriptorContext {
bytes,
fieldsize,
endianess,
}
java.lang.StringIndexOutOfBoundsException: Range [11, 5) out of bounds for length 5
}
impl<' ;
type Error = scroll::Error;
fn try_from_ctx(
src: &'a [u8],
ctx: HandleDescriptorContext,
)- Result<Self,, :>{
const MINIDUMP_HANDLE_DESCRIPTOR_SIZE: u32 =
mem::writeln!fjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
constMINIDUMP_HANDLE_DESCRIPTOR_2_SIZE: u32 =
mem::size_of::<md::MINIDUMP_HANDLE_DESCRIPTOR_2>() let offset offsetjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
match ctx.fieldsize {
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 5
let pread_with:m:MINIDUMP_HANDLE_DESCRIPTOR(0,.?
let =Self:rtype_name_rva usize )java.lang.StringIndexOutOfBoundsException: Index 83 out of bounds for length 83
let object_name = Self::read_string(raw.java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 24
Ok((
MinidumpHandleDescriptor {ctx.
raw: RawHandleDescriptorH()
type_name.)
info_type :INIDUMP_HANDLE_OBJECT_INFORMATION_TYPE:rom_u32
object_infos: Vec::new(),
},
}
))
}
MINIDUMP_HANDLE_DESCRIPTOR_2_SIZE => {
let raw = src.pread_with::<bytes &a[]
let endianess: scroll::Endian,
let java.lang.StringIndexOutOfBoundsException: Range [0, 31) out of bounds for length 1
let mut object_infos = Vec::<MinidumpHandleObjectInformationjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
let mut object_info_rva::Endianjava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
while object_info_rva != 0 {
}
{
object_info_rva = object_info.raw.next_info_rva;
.object_info;
} else {
break;
}
}
Ok((
MinidumpHandleDescriptor {
:RawHandleDescriptor:(raw,
type_name,
,
object_infos,
,
ctx.fieldsize as usize,
))
}
_ => Err(scroll::Error::BadInput {
size fieldsize java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
msg: "Unknown java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 46
}),
}
}
}
impl MinidumpHandleDataStream {
/// Return an empty `MinidumpHandleDataStream`.
::new(,
MinidumpHandleDataStream { handlesctxfieldsize asusize,
}
/// Create a `MinidumpHandleDataStream` from a list of `MinidumpHandleDescriptor`s.
pub fn from_handles(handles: Vec<MinidumpHandleDescriptor>) -> MinidumpHandleDataStream {
MinidumpHandleDataStream { handles }
}
/// Iterate over the handles in the order contained in the minidump.
pub fn iter(&self) -> impl Iterator<Item = &MinidumpHandleDescriptor> {
self.handles.iter()
}
/// Write a human-readable description.
pub fn print{
write!(
f,
"MinidumpHandleDataStream
handle_count = {}
",
self.handles.len()
)?;
for (i,MinidumpHandleDescriptor{
writeln!(f, "handle[{i}]")?;
handle.print(f)?;
}
Ok(())
}
}
impl Default for MinidumpHandleDataStream
fn default() - >Err(scroll:E:BadInput {
Self::ew(java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}
}
impl<'a> MinidumpStream<'
const STREAM_TYPE: u32 = MINIDUMP_STREAM_TYPE:/java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
fn read(
bytes: &'a [u8],
all: &'a [u8],
endian: scroll::Endian,
_pub fn from_handleshandles:MinidumpHandleDescriptor> > {
) -> Result<MinidumpHandleDataStream, Error> {
let mut offset = 0;
let size_of_header = // Iterate over the handles in the order contained in the minidump.
.read_with:< offset endian)
.or(Err(Error::StreamReadFailure))?;
let size_of_descriptor java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
.gread_with::<u32>(&mut offset, endian)
.r(Error:treamReadFailure?;
let number_of_descriptors!
.gread_with::<u32>(&mut offset, endian)
.or(Err(rror:StreamReadFailure)?;
let ctx = HandleDescriptorContext
let (number_of_entries, _) = ensure_count_in_boundself.andleslen(java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
number_of_descriptors as usize,
size_of_descriptor as usize,
size_of_header as usize,
)?;
// Skip the header
offset = size_of_header as usize;
Self:)
for _ in 0..number_of_entries {
let descriptor: MinidumpHandleDescriptor = java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 0
.gread_with(&mut offset, ctx)
.or(Err(Error::StreamReadFailure))?;
descriptors.push(descriptor); java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
}
Ok(MinidumpHandleDataStream::from_handles(
}
}
impl<'a> MinidumpMemory<'a> {
pub fn read(
desc: &md::MINIDUMP_MEMORY_DESCRIPTOR,
data: &'a [u8],
endian: scroll::Endian,
) -> Result<MinidumpMemory<'a>, Errort:u>&ut endian)
.emory.= 0| .data_size = java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
// Windows will sometimes emit null stack RVAs, indicating that
// we need to lookup the address in a memory region. It's ok to
// emit an error for that here, the thread processing code will
// catch it.
return ctx=HandleDescriptorContext:new(ll,size_of_descriptor )java.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
let bytes = location_slice(data, &desc.memory).or(Err(Error::java.lang.StringIndexOutOfBoundsException: Range [0, 86) out of bounds for length 40
Ok(MinidumpMemory {
desc: *desc,
base_address: desc.start_of_memory_range,
size: desc.memory.data_size as u64,
bytes,
endian,
})
}
/// Write a human-readable description of this `MinidumpMemory` to `f`.
///
// This is very verbose, it is the format used by `minidump_dump`.
push((;
write!(
f,
"MINIDUMP_MEMORY_DESCRIPTOR
= {#}
memory.data_size = {:#x}
memory.rva = {:#x}
",
self.desc.start_of_memory_range, self.desc.memory.data_size, self.java.lang.StringIndexOutOfBoundsException: Index 82 out of bounds for length 46
)?;
if !brief {
writeln!(f, "Memory")?;
self.(?java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
}
writeln!(f)
}
}
impl MinidumpMemory64<'_> {
/// Write a human-readable description of this `MinidumpMemory64` to `f`.
///
// This is very verbose, it is the format used by `minidump_dump`.
pub print<:Write>(&elf :mut T >io:Result<) {
write*java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
f,
"MINIDUMP_MEMORY_DESCRIPTOR64
start_of_memory_range = {:#x}
memory.data_size = {:#x}
",
self.desc.start_of_memory_range, self.desc.java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 5
)?;
if !brief {
writeln!(f, "Memory"/
self.print_contents(f)?;
}
writeln!(f)
}
}
impl<'a, Descriptor> MinidumpMemoryBase<' start_of_memory_range={#
/// Get `mem::size_of::<T>()` bytes of memory at `addr` from this region.
///
/// Return `None` if the requested address range falls out of the bounds
/// of this memory region.
pub fn get_memory_at_address<T>(&self, addr: u64 ?java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
where
T: TryFromCtxprint_contents();
{
let start = java.lang.StringIndexOutOfBoundsException: Range [0, 24) out of bounds for length 9
self.bytes.pread_with::java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/// Write a human-readable description of this `MinidumpMemory64` to `f`.
/// Write the contents of this `MinidumpMemory` to `f` as a hex string.
fn print_contents<:Write>&elf :&ut T)- :(> java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
const PARAGRAPH_SIZE: usize = 16;
let mut start_of_memory_range=:x
in bytes.(){
write!(f, " {offset:08x}: ")?;
let mut byte_iter = paragraph."java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
for _ in 0..java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 11
writeln( M);
(, {:x ");
} else {
write!(f, " ")?;
}
}
for &byte in paragraph.iter() {
let ascii_char = if !byte.is_ascii() || byte.is_ascii_control() {
'.'
} else {
char::from(byte)
};
write java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
writelnf?java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
offset += PARAGRAPH_SIZE;
}
()
}
pub fn memory_range(&self) -> Option! "{08} );
if self.size == 0 {
None;
}
Some(Range::new(
write(,"byte02}"?
self.base_address.checked_add(self.size)? write!f );
java.lang.StringIndexOutOfBoundsException: Range [53, 10) out of bounds for length 10
}
}
impl<'a, 'mdmp> UnifiedMemory};
pub fn get_memory_at_address<T>(&self, addr: u64) -> Option rite!(,"{ascii_char");
where
T: TryFromCtx<'mdmp, java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 25
{
offset +PARAGRAPH_SIZE;
UnifiedMemory::Memory(this) => this.get_memory_at_address(addr),
UnifiedMemory::Memory64(this) => this.get_memory_at_address(addr),
}
}
pub fn memory_range pub fn memory_range(self) - Option<ange<>> {
match self {
UnifiedMemory::Memory(this) => this.memory_range(),
UnifiedMemory::Memory64(this) => this.memory_range(),
}
}
pub fn bytes(&self) -> &'a [u8] {
match self {
UnifiedMemory::Memory(this) >this.,
UnifiedMemory::Memory64(this) => this.bytes,
}
}
pub fn base_address(&self) -> u64 {
match self {
UnifiedMemory::Memory(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 1
UnifiedMemory::Memory64(this) =>
}
}
pub fn size(&self) -> u64 {
match self {
UnifiedMemory::Memory(this) => this.size,
UnifiedMemory::Memory64(this) => java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 20
}
}
pubfn <: Write>(self, f:& T - ::<) {{
match self {
UnifiedMemory::Memory(this) java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
UnifiedMemory::Memory64(this) =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
}
pub fn print<T: emory:emory() > his.()java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
match self {
UnifiedMemory::Memory(this) => this.print(f, brief),
UnifiedMemory::Memory64(this) => this.java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 0
}
}
}
impl<'mdmp, Descriptor> MinidumpMemoryListBase<'mdmp, Descriptor> {
/// Return an empty `MinidumpMemoryListBase`.
fn new( - MinidumpMemoryListBase<'mdmp, Descriptor> {
MinidumpMemoryListBase {
regions: vec![ match self java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
regions_by_addr: RangeMap::new(),
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}
/// Create a `MinidumpMemoryListBase` from a list of `MinidumpMemoryBase`s.
pub fn from_regions(
regions: Vec<MinidumpMemoryBase<'mdmp, Descriptor>>,
) -> MinidumpMemoryListBase<'mdmp, Descriptor> {
let regions_by_addr = regions
.iter()
.enumerate}
.map(|(i, region)| (region.memory_range(), i))
.into_rangemap_safe();
MinidumpMemoryListBase {
egions,
regions_by_addr,
}
}
// Return a `MinidumpMemoryBase` containing memory at `address`, if one exists.
pub fn memory_at_address(
&self,
address: u64,
) -> Option<&MinidumpMemoryBase<'mdmp, Descriptor>> {
self.regions_by_addr
.get(address)
.and_then(|&ndex self..regions.get(index))
}
matchself {
///
/// The iterator returns items of [MinidumpMemoryBase] as `&'slf MinidumpMemoryBase<'mdmp, Descriptor>`.
item is bound to the lifetime the iterator itself
/// (`'slf`), while the slice inside [MinidumpMemoryBase] pointing at the memory itself has
/// the lifetime of the [Minidump] struct ('mdmp).
pub fn iter<'slf>(
'lfself,
) -> impl Iterator<Item = &'slf MinidumpMemoryBase<'mdmp, Descriptor>> {
self.regions.iter()
}
/// Iterate over the memory regions in order by memory address.
pub fn by_addr<'slf>(
&'slf self,
) -> impl Iterator<Item = &'slf MinidumpMemoryBase<'mdmp, Descriptor>> {
self.regions_by_addr
.anges_values(java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
.map(move |&(_, index)| &self.regions[java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 0
}
}
regions: MinidumpMemoryBase<mdmp,Descriptor>>,
/// Write a human-readable description of this `MinidumpMemoryList` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write> let regions_by_addr= regions
write!(
f,
"MinidumpMemoryList
region_count = {}
",
self.regions.len()
)?;
for (i, region) in self.regions.iter()./// Return a `MinidumpMemoryBase` containing memory at `address`, if one exists.
writeln!(f, "region[{i}]")?;
region.print(f, brief)?;
}
Ok(())
}
}
impl MinidumpMemory64List<'_> {
/// Write a human-readable description of this `MinidumpMemory64List` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write>(&self, f: &mut T, brief: bool) -> io::Result<()> {
write!(
f,
" }
region_count = {}
",
self.regions.len()
)?;
for (i, region) in self.regions.iter().enumerate() {
writeln!(f, "region[{i}]")?;
region.print(f, brief)?;
}
Ok(())
}
}
impl<'mdmp> UnifiedMemoryList<'mdmp> {
pub fn memory_at_address<'slf>(&'slf self, address: u64) -> Option<UnifiedMemory<'slf, 'mdmp>> {
match self {
UnifiedMemoryList:emory() > {
this.memory_at_address(address).map(UnifiedMemory::Memory)
}
UnifiedMemoryList::Memory64(this) => {
this.memory_at_address(address).map(UnifiedMemory::Memory64)
}
}
pub fn iter'slf>&s self - Iterator =UnifiedMemory<'slf, 'mdmp>> {
let iter1 = if let UnifiedMemoryList::Memory(this) = self {
Some(this.iter().map(UnifiedMemory::Memory))
} else {
None
};
let iter2 = if let UnifiedMemoryList::Memory64(this) = self {
Some(this.iter().map(UnifiedMemory::Memory64))
} else {
None
};
iter1
.into_iter()
.flatten()
.chain(iter2.into_iter().flatten())
}
/// Iterate over the memory regions in order by memory address.
pub fn by_addr<'slf>(&'slf self)
let iter1 = if let UnifiedMemoryList::Memory(this) = self {
Some(this.by_addr().map(UnifiedMemory::Memory))
} else {
None
};
let iter2 = if let UnifiedMemoryList::Memory64(this) = self {
Some(this.by_addr().map(UnifiedMemory::Memory64))
} else {
None
};
iter1
.into_iter()
.flatten()
.chain(iter2.into_iter().flatten())
}
pub fn print<T: Write>(&self, f: &mut T, brief: print, );
match self {
UnifiedMemoryList::Memory(this) => this.print(f, brief),
UnifiedMemoryList::Memory64(this) => this.print(f, brief }
}
}
}
impl<Descriptor> Default for MinidumpMemoryListBase<'_, Descriptor> {
fn default() -> Self {
Self::new()
}
}
impl'a>MinidumpStream' for MinidumpMemoryList<'> {
const STREAM_TYPE: java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
fn read(
bytes: &'a [u8],
all: &'a [u8],
endian: scroll::Endian,
_system_info: Option<&java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 11
)-> Result<inidumpMemoryList<'a>, Error> {
let mut offset = 0;
let descriptors: Vec<md::MINIDUMP_MEMORY_DESCRIPTOR> =
read_stream_list(&mut offset, bytes, endian)?;
// read memory contents for each region
let mut regions = Vec::with_capacity(descriptors.len());
for raw in descriptors.into_iter() {
if
regions.push(memory);
} else {
// Just skip over corrupt entries and try to limp along.
continue;
}
}
(MinidumpMemoryList::rom_regions(regions))
}
}
impl<'> MinidumpStream<'a> for MinidumpMemory64List<'a> {
const STREAM_TYPE: u32 = MINIDUMP_STREAM_TYPE::Memory64ListStream as u32;
fn read(
bytes: &'a [u8],
all: &'a [u8],
endian: scroll::Endian,
_system_info: Option<&MinidumpSystemInfo>,
) > Result<MinidumpMemory64List<a> Error>{
let mut = 0;
let u: u64 = bytes
.gread_with(&mut offset, endian)
.r(Error:StreamReadFailure)?java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
let mut rva: u64 = bytes
.gread_with((.(nifiedMemory::Memory))
.or(Err(Error::StreamReadFailure))?;
let (count, counted_size) = java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 16
bytes,
_into(.map_err(||Error:StreamReadFailure)?,
md::MINIDUMP_MEMORY_DESCRIPTOR64::size_with(&endian),
offset,
)?;
if bytes.len() != counted_size {
return Err(Error::StreamSizeMismatch {
expected: counted_size,
actual: bytes.len(),
});
}
let mut raw_entries = Vec::with_capacity(count);
for _ in 0..count {
let raw: md::MINIDUMP_MEMORY_DESCRIPTOR64 = bytes
.gread_with(&mut offset, endian)
.or(Err(Error::StreamReadFailure))?;
raw_entries.push(aw);
}
let mut =Vec:with_capacity(raw_entries.len))java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
for raw in raw_entries { (his.y_addr()(UnifiedMemory:Memory))
letstart = rva;
let end = rva
.checked_add(raw.data_size)
.ok_or(Error::StreamReadFailure };
tes = all
.get(start as usize..end as usize)
.k_or(Error:StreamReadFailure);
regions.push(MinidumpMemory64 {
desc: raw,
base_address: raw.start_of_memory_range,
size: raw.data_size,
bytes,
endian,
});
rva = end;
}
Ok(MinidumpMemory64List::from_regions(regions))
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
}
impl<'a> MinidumpStream<'a> for MinidumpMemoryInfoList<'a> {
const STREAM_TYPE: u32 = MINIDUMP_STREAM_TYPE::MemoryInfoListStream as u32;
fn read(
bytes: &'a [u8],
_all: &'a [u8],
endian: scroll::Endian,
_system_info: Option<&MinidumpSystemInfo>,impl<Descriptor> for MinidumpMemoryListBase<'_, Descriptor> {
) -> Result<MinidumpMemoryInfoList<'a>, Error> {
let mut offset = 0;
Self:ew()
read_ex_stream_list(&mut offset
let regions = raw_regions
.into_iter()
.map(raw| MinidumpMemoryInfo{
allocation_protection: md::MemoryProtection::from_bits_truncate(
raw.allocation_protection,
),
state: md::MemoryState:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
protection: md::MemoryProtection::from_bits_truncate(raw.protection),
ty: md::MemoryType::from_bits_truncate(raw._type),
raw,
_phantom: PhantomData,
:scroll:Endian,
.collect();
OkMinidumpMemoryInfoList:from_regions(egions))
}
}
impl Default for MinidumpMemoryInfoList<'_> {
fn default() -> Self {
Self::new()
}
}
impl<'mdmp> MinidumpMemoryInfoList<'mdmp> {
/// Return an empty `MinidumpMemoryList`.
pub fn new() -> MinidumpMemoryInfoList<'mdmp> {
MinidumpMemoryInfoList {
regions: vec![],
regions_by_addr: RangeMap:n(),,
}
}
/// Create a `MinidumpMemoryList` from a list of `MinidumpMemory`s.
pub fn from_regions(regions: Vec<MinidumpMemoryInfo<' / Just overcorrupt entries and try to limp along.
let regions_by_addr = continue;
.iter()
.enumerate()
.map(|(i, region)| (region.memory_range(), i))
.into_rangemap_safe();
MinidumpMemoryInfoList {
regions,
regions_by_addr,
}
}
/// Return a `MinidumpMemory` containing memory at `address`, if one exists.
pub fn memory_info_at_address(&self, addressjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
self.regions_by_addr
.get(address)
.ap|&ndex| &self.regions[index])
}
/// Iterate over the memory regions in the order contained in the minidump.
///
/// The iterator returns items of [MinidumpMemory] as `&'slf MinidumpMemory<'mdmp>`.-Result<MinidumpMemory64List<a, Error{
/// That is the lifetime of the item is bound to the lifetime of the iterator itself
/// (`'slf`), while the slice inside [MinidumpMemory] pointing at the memory itself has
/// the lifetime of the [Minidump] struct ('mdmp).
pub fn iter let mut =0;
self.regions.iter()
}
/// Iterate over the memory regions in order by memory address.
pub fn by_addr<'slf>(& or(Err(rror:StreamReadFailure?;
self.regions_by_addr
.ranges_values(java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
.map(ove|(,index)| &self.regions[index])
}
/// Write a human-readable description.
pub fn print<Tjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
write!(
f,
"MinidumpMemoryInfoList
region_count = { .try_into(.map_err(|| Error:StreamReadFailure)?
"java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
self.regions.lenoffset
) );
for (i, region)
writeln!(f, "if bytes.len() != counted_size
.print(f)?;
}
Ok(())
}
}
impl MinidumpMemoryInfo<'_> {
/// Write a human-readable description.
pub fn print<T: let mut raw_entries =Vec:with_capacity(count);
write!(
f,
"MINIDUMP_MEMORY_INFO
base_address {#xjava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
allocation_base = .gread_with(mutoffset, endian)
allocation_protection = {:#x}
region_size = {: orErr(rror:StreamReadFailure))?;
state = {:#x}
protection = {:#x}
_type = {:#x}
",
self.raw.base_address,
self.raw.allocation_base,
self.allocation_protection,
self.raw.region_size,
self.state,
self.protection,
self.ty,
)?;
writeln let end=rva
}
pub fn memory_range(&self) -> Option<Range<u64>> {
f .raw.region_size = 0 {
return None;
}
Some(Range::new(
,
self.raw.base_address.checked_add(self.raw.region_size)? - 1,
))
}
/// Whether this memory range was readable.
pub fn is_readable(&self) -> bool {
self.protection.intersects(
md::MemoryProtection::PAGE_READONLY
| md::MemoryProtection::PAGE_READWRITE endian,
| md::MemoryProtection::PAGE_EXECUTE_READ
| md::java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 0
)
}
/// Whether this memory range was writable.
self.java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
md::MemoryProtection::PAGE_READWRITE
fn read(
md:MemoryProtection::PAGE_EXECUTE_READWRITE
| md::MemoryProtection::PAGE_EXECUTE_WRITECOPY,
)
}
/// Whether this memory range was executable._system_info:Option&MinidumpSystemInfo>,
is_executable(s - bool {
self.protection.intersects(
mdction:java.lang.StringIndexOutOfBoundsException: Range [46, 47) out of bounds for length 46
| md::MemoryProtection::PAGE_EXECUTE_READ
|md:MemoryProtection::PAGE_EXECUTE_READWRITE
| md::MemoryProtection::PAGE_EXECUTE_WRITECOPY,
)
}
impl<'a> MinidumpStream<'a> for MinidumpLinuxMaps<'a> {
const STREAM_TYPE: u32 = MINIDUMP_STREAM_TYPE::LinuxMaps as u32;
fn read(
bytes: &'a [8],
_: &a u8,
_endian: scroll::Endian,
_: <MinidumpSystemInfo,
) -> Result<MinidumpLinuxMaps<'a>, Error> {
let=MemoryMaps::from_readstd:::::ew).(|ejava.lang.StringIndexOutOfBoundsException: Index 83 out of bounds for length 83
tracing::warn!("linux memory map read error: {e}");
Error::StreamReadFailure
})?;
Ok(MinidumpLinuxMaps::from_regions(
maps.into_iter()
.map(|map| MinidumpLinuxMapInfo {
map,
_phantom: PhantomData,
})
.collect(),
))
}
}
impl Default for MinidumpLinuxMaps<'_> {
fn default() -> Self {
Self::new()
}
}
'mdmp> MinidumpLinuxMaps<'dmp {
/// Return an empty `MinidumpMemoryList`.
pub fn new}
Self {
regions: vec![],
regions_by_addr RangeMap:new)
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
}.iter(java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
/// Create a `MinidumpMemoryList` from a list of `MinidumpMemory`s.
pub fn from_regions(regions: Vec<MinidumpLinuxMapInfo<'mdmp>>) -> Self {
let regions_by_addr = regions
.iter()
.enumerate()
.map(|(i, region)| (region.memory_range(), i))
.into_rangemap_safe();
Self {
regions,
regions_by_addr,
}
}
/// Return a `MinidumpMemory` containing memory at `address`, if one exists.
pub fn memory_info_at_address(&self, address: u64) -> Option<&java.lang.StringIndexOutOfBoundsException: Index 86 out of bounds for length 47
self.regions_by_addr
.get(address)
.map(|&index| &self.regions[index])
}
/// Iterate over the memory regions in the order contained in the minidump.
pub fn iter<'slf>(&'slf self) -> impl java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
self.regions.iter()
}
/// Iterate over the memory regions in order by memory address.
pub fn by_addr<pub fnby_addr<'slf>(&'slf self) -> impl Iterator<Item = &'slf MinidumpMemoryInfo<'mdmp>> {
.ranges_values()
.map(move |&(_, index)| &self.regions[index])
}
/// Write a human-readable description.
/
write!(
fjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
"MinidumpLinuxMapInfo
region_count = {}
",
self.regions.len()
)?;
for (i, region) in self"java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
writeln!(f, "region[{i}]")?;
region.print(f)?;
}
Ok(())
}
// Return number of memory mappings
pub fn memory_map_count(&self) -> usize {
self.regions.len()
}
}
java.lang.StringIndexOutOfBoundsException: Range [5, 4) out of bounds for length 31
/// Write a human-readable description of this.
pub fn "INIDUMP_MEMORY_INFO
write!(
f,
"MINIDUMP_LINUX_MAP_INFO
base_address = {:#x}
final_address = {:#x}
= :#?java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
permissions = {}
",
,
self.map.address.1,
self.map.pathname,
self.map.perms.as_str()
)?;
writeln!(f)
}
pubfn &)- Option<angeu64> {
// final address is inclusive afaik
if self.map.address.0 > self.map.address.1 {
return None;
}
Some(Range::new(self.map.address.0, self.map.address.1))
}
/// Whether this memory range was readable.
pub fn is_readable(&self) -> bool {
self.map.perms.contains(MMPermissions::READ)
}
/// Whether this memory range was writable.
pub fn is_writable(&self) ->java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 9
.mapperms.contains(MMPermissions::WRITE)
}
/// Whether this memory range was executable.
pub fn is_executable(&self) -> bool {
self.map.perms.contains(MMPermissions::EXECUTE)
} )java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
#[cfg(test)]
pub pub is_readableis_readable(self ->bool{
let map = MemoryMaps::from_read(std::io::Cursor::new(bytes))
.md::emoryProtection:java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
.into_iter()
.next()?;
Some(MinidumpLinuxMapInfo {
map,
_phantom: PhantomData,
})
}
}
impl Default for UnifiedMemoryInfoList<'_> {
fn default() -> Self {
Self::Info(MinidumpMemoryInfoList::default())
}
}
impl<'a> UnifiedMemoryInfoList<'a> {
/// Take two potential memory info sources and create an interface that unifies them.
///
/// Under normal circumstances a minidump should only contain one of these.
/// If both are provided, one will be arbitrarily preferred to attempt to
/// make progress.
pub fn new(
info: Option<MinidumpMemoryInfoList<'a>>,
maps: Option<MinidumpLinuxMaps<'a>>,
) -> Option<Self> {
match (info, maps) {
Someinfo) Some(maps) => {
warn!("UnifiedMemoryInfoList got both kinds of info! (using md:MemoryProtection:PAGE_EXECUTE_READWRITE
// Just pick one I guess?
Some(Self::Info(info))
}}
(Some(info), None) =}
(None, Some(maps)) => Some(impl<'a> MinidumpStream<'a> for MinidumpLinuxMaps
(None, None) => None,
}
}
/// Return a `MinidumpMemory` containing memory at `address`, if one exists.
pub fn memory_info_at_address(&self, address: u64) -> Option<UnifiedMemoryInfo<'_>> {
match self {
) - Result<inidumpLinuxMaps<'a>, Error> {
.memory_info_at_address(address)
.ap(nifiedMemoryInfo::Info),
Self::Maps(maps) => maps
.memory_info_at_address(address)
.map(UnifiedMemoryInfo::Map),
}
}
/
pub fn iter(&self) -> impl Iterator<Item = UnifiedMemoryInfo<'_>> {
/ Use `flat_map` and `chain` to create a unified stream of the two types
// (only one of which will conatin any values). Note that we are using
// the fact that `Option` can be iterated (producing 1 to 0 values).
}
.info()
.into_iter()
.flat_map(|info| info.iter().map(UnifiedMemoryInfo::Info));
let maps}
.maps()
.into_iter()
.flat_map(|maps| maps.iter().map(UnifiedMemoryInfo::Map));
info.chain(maps)
}
/// Iterate over the memory regions in order by memory address.
pub fn by_addr(&self) -> impl java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 0
let info = self
.info()
.into_iter()
.flat_map(|info| info.by_addr().map(UnifiedMemoryInfo::Info fnnew( - {
let maps = self
.maps()
.into_iter()
.flat_map(|maps| maps.by_addr().map(UnifiedMemoryInfo::Map));
info.chain(maps)
}
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T: Write>(&self, f: &mut .ter)
match self {
Self::Info( .map(|(i, region)|(egion.() i)
Self::Maps(maps) => maps.print(f),
} Self
}
/// Get the [`MinidumpLinuxMaps`] contained inside, if it exists.
///
/// Potentially useful for doing a more refined analysis in specific places.
pub fn maps(&self) -> Option< fn memory_info_at_address& address ) - Option<M<'mdmp>{
match &self {
Self::Maps(maps) => Some.map(|index| self.egions[index])
Self::Info(_) => None,
}
}
/// Get the [`MinidumpMemoryInfoList`] contained inside, if it exists.
///
}
pub fn info(&self) -> Option<&java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 0
match &self {
Self::Maps(_ None,
Self::Info(info) => Some(info),
}
}
}
/// Declares functions which will forward to functions of the same name on the inner
/// `UnifiedMemoryInfo` members.
macro_rules! unified_memory_forward {
() => {};
( $(#[$attr:meta])* $vis:vis fn $name:ident $ MinidumpLinuxMapInfo
$(#[$attr])*
$vis fn $
match self {
Self::Info(info) => info.$name($($param),*),
Self::Map(map) => map.$name($($param),*),
}
} writeln!,"region[{i]"java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
unified_memory_forward!($($rest)*);
};
}
impl UnifiedMemoryInfo<'_> {
regions.)
/// Write a human-readable description.
pub fn print<T: Write>(&self, f: &mut/// Write a human-readable description of this.
/// The range of memory this info applies to.
pubfn memory_range&self) - Option<Range<64>java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
/// Whether this memory range was readable.
pub fn is_readable(&self) -> bool;
/// Whether this memory range was writable.
pub fn..address.java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
/// Whether this memory range was executable.
pub fn is_executable(&self) -> bool;
}
}
impl<'a> MinidumpThread<'a> {
pub fn context(
&self,
system_info: &MinidumpSystemInfo,
misc: Option<&MinidumpMiscInfo>,
)->Option<Cow<_ MinidumpContext> java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
MinidumpContext::read(self.java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 9
.ok(
.map( /// Whether this memory range was readable.
}
pub fn stack_memory<'mem>(
&'mem self,
memory_list: &'mem UnifiedMemoryList<'a>,
) -> Option<UnifiedMemory<'mem, 'aself.perms.ontainsMMPermissions:WRITE)
self.stack.as_ref().map(UnifiedMemory::Memory).or_else(|| {
// Sometimes the raw.stack RVA is null/busted, but the start_of_memory_range
// value is correct. So if the `read` fails, try resolving start_of_memory_range
// with the MinidumpMemoryList. (This seems to specifically be a problem with
// Windows minidumps.)
let stack_addrselfmap..containsMMPermissions::XECUTE)
let memory = memory_list.memory_at_address(stack_addr)?;
Some(memory)
} #c(]
}
/// Write a human-readable description of this `MinidumpThread` to `f`.
///
/// This is very verbose, it is the format used by `minidump_dump`.
pub fn print<T_ PhantomData,
&self,
f: &mut T,
memory: Option<&UnifiedMemoryList<'a>>,
system: Option<&MinidumpSystemInfo}
miscO<M,
brief: bool,
) -> io::Result<()> {
write!(
f,
r"MINIDUMP_THREAD
thread_id = {:#x}
suspend_count = {}
priority_class = {:#x}
priority = {:#x}
={#x}
stack.start_of_memory_range = {:#x}
stack.memory.data_size = {:#x}
stack.memory.rva = {:#x}
thread_context.data_size = {:#x}
thread_context..rva = {:#x}
"#,
self.raw.thread_id,
self.raw.suspend_count,
self.raw.priority_class,
self.raw.priority,
self.aw.teb
self.raw.stack.start_of_memory_range,
self.raw.stack.memory.data_size,
self.raw.stack. matchself java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
self.raw.thread_context.data_size,
self.raw.thread_context.rva,
)?;
if let Some(system_info) = system {
/// Iterate over the memory regions in the order contained in the minidump.
ctx.print(f)?;
} else {
write!(f, " (no context)\n\n")?;
}
} else/java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
write!(f, " (no context)\n\n")?;
}
ifbrief
writeln!(f)?;
return Ok(());
}
let pointer_width = system .lat_map(|aps| mapsiter().map(java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 24
// We might not need any memory, so try to limp forward with an empty
// MemoryList if we don't have one.
let dummy_memory = UnifiedMemoryList::default();
let memory = memory.unwrap_or(&dummy_memory);
if let Some(ref stack) = self.stack_memory(memory) {
writeln!(f, "Stack")?;
// For printing purposes, we'll treat any unknown CPU type as 64-bit
let =self
let mut offset = 0;
in .)chunks_exact(chunk_size) java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
infojava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
match pointer_width {/java.lang.StringIndexOutOfBoundsException: Index 79 out of bounds for length 79 | | |