Skip to content

Commit

Permalink
Write a MemoryInfoListStream on linux.
Browse files Browse the repository at this point in the history
This makes it easier for consumers to read the minidumps, rather than
needing to parse linux-specific information.

Closes rust-minidump#8.
  • Loading branch information
afranchuk committed Apr 19, 2023
1 parent 59179c8 commit 98b2395
Show file tree
Hide file tree
Showing 11 changed files with 347 additions and 335 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Expand Up @@ -13,7 +13,9 @@ byteorder = "1.3.2"
cfg-if = "1.0"
crash-context = "0.5"
memoffset = "0.8"
minidump-common = "0.15"
#minidump-common = "0.15"
# XXX temporary for development
minidump-common = { path = "../rust-minidump/minidump-common" }
scroll = "0.11"
tempfile = "3.1.0"
thiserror = "1.0.21"
Expand All @@ -30,6 +32,8 @@ nix = { version = "0.26", default-features = false, features = [
"ptrace",
"user",
] }
# Used for parsing procfs info.
procfs = "0.15.1"

[target.'cfg(target_os = "macos")'.dependencies]
# Binds some additional mac specifics not in libc
Expand Down
6 changes: 3 additions & 3 deletions src/bin/test.rs
Expand Up @@ -109,7 +109,7 @@ mod linux {
let dumper = PtraceDumper::new(getppid().as_raw())?;
let mut mapping_count = 0;
for map in &dumper.mappings {
if map.name == Some(path.clone()) {
if map.name == Some(path.clone().into()) {
mapping_count += 1;
// This mapping should encompass the entire original mapped
// range.
Expand All @@ -127,7 +127,7 @@ mod linux {
let mut dumper = PtraceDumper::new(ppid)?;
let mut found_linux_gate = false;
for mut mapping in dumper.mappings.clone() {
if mapping.name.as_deref() == Some(LINUX_GATE_LIBRARY_NAME) {
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
found_linux_gate = true;
dumper.suspend_threads()?;
let id = PtraceDumper::elf_identifier_for_mapping(&mut mapping, ppid)?;
Expand All @@ -148,7 +148,7 @@ mod linux {
test!(linux_gate_loc != 0, "linux_gate_loc == 0")?;
let mut found_linux_gate = false;
for mapping in &dumper.mappings {
if mapping.name.as_deref() == Some(LINUX_GATE_LIBRARY_NAME) {
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
found_linux_gate = true;
test!(
linux_gate_loc == mapping.start_address.try_into()?,
Expand Down
29 changes: 21 additions & 8 deletions src/linux/errors.rs
Expand Up @@ -3,6 +3,7 @@ use crate::maps_reader::MappingInfo;
use crate::mem_writer::MemoryWriterError;
use crate::thread_info::Pid;
use goblin;
use std::ffi::OsString;
use thiserror::Error;

#[derive(Debug, Error)]
Expand All @@ -28,20 +29,22 @@ pub enum MapsReaderError {
LinuxGateNotConvertable(#[from] std::num::TryFromIntError),

// get_mmap()
#[error("Not safe to open mapping {0}")]
NotSafeToOpenMapping(String),
#[error("Not safe to open mapping {}", .0.to_string_lossy())]
NotSafeToOpenMapping(OsString),
#[error("IO Error")]
FileError(#[from] std::io::Error),
#[error("Mmapped file empty or not an ELF file")]
MmapSanityCheckFailed,
#[error("Symlink does not match ({0} vs. {1}")]
#[error("Symlink does not match ({0} vs. {1})")]
SymlinkError(std::path::PathBuf, std::path::PathBuf),

// handle_deleted_file_in_mapping()
// fixup_deleted_file()
#[error("Couldn't parse as ELF file")]
ELFParsingFailed(#[from] goblin::error::Error),
#[error("No soname found (filename: {0}")]
NoSoName(String),
#[error("An anonymous mapping has no associated file")]
AnonymousMapping,
#[error("No soname found (filename: {})", .0.to_string_lossy())]
NoSoName(OsString),
}

#[derive(Debug, Error)]
Expand Down Expand Up @@ -114,8 +117,8 @@ pub enum DumperError {
ELFParsingFailed(#[from] goblin::error::Error),
#[error("No build-id found")]
NoBuildIDFound,
#[error("Not safe to open mapping: {0}")]
NotSafeToOpenMapping(String),
#[error("Not safe to open mapping: {}", .0.to_string_lossy())]
NotSafeToOpenMapping(OsString),
#[error("Failed integer conversion")]
TryFromIntError(#[from] std::num::TryFromIntError),
#[error("Maps reader error")]
Expand Down Expand Up @@ -144,6 +147,14 @@ pub enum SectionMappingsError {
GetEffectivePathError(MappingInfo, #[source] MapsReaderError),
}

#[derive(Debug, Error)]
pub enum SectionMemInfoListError {
#[error("Failed to write to memory")]
MemoryWriterError(#[from] MemoryWriterError),
#[error("Failed to read from procfs")]
ProcfsError(#[from] procfs::ProcError),
}

#[derive(Debug, Error)]
pub enum SectionMemListError {
#[error("Failed to write to memory")]
Expand Down Expand Up @@ -210,6 +221,8 @@ pub enum WriterError {
SectionMemListError(#[from] SectionMemListError),
#[error("Failed when writing section SystemInfo")]
SectionSystemInfoError(#[from] SectionSystemInfoError),
#[error("Failed when writing section MemoryInfoList")]
SectionMemoryInfoListError(#[from] SectionMemInfoListError),
#[error("Failed when writing section ThreadList")]
SectionThreadListError(#[from] SectionThreadListError),
#[error("Failed when writing section ThreadNameList")]
Expand Down

0 comments on commit 98b2395

Please sign in to comment.