Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
[package]
name = "minidump_writer_linux"
name = "minidump-writer"
version = "0.1.0"
authors = ["Martin Sirringhaus"]
edition = "2018"
edition = "2021"
license = "MIT"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
byteorder = "1.3.2"
cfg-if = "1.0"
memoffset = "0.5.1"
tempfile = "3.1.0"
nix = "0.23"
thiserror = "1.0.21"

[target.'cfg(unix)'.dependencies]
libc = "0.2.74"
memoffset = "0.5.1"
byteorder = "1.3.2"
memmap2 = "0.2.2"
goblin = "0.1.2"
thiserror = "1.0.21"
memmap2 = "0.2.2"

[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
nix = "0.23"

[dev-dependencies]
minidump = {git = "https://github.com/luser/rust-minidump", rev="9652b3b" }
minidump-common = {git = "https://github.com/luser/rust-minidump", rev="9652b3b" }
minidump = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
minidump-common = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
41 changes: 22 additions & 19 deletions src/bin/test.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#![cfg(any(target_os = "linux", target_os = "android"))]

// This binary shouldn't be under /src, but under /tests, but that is
// currently not possible (https://github.com/rust-lang/cargo/issues/4356)
use minidump_writer_linux::linux_ptrace_dumper::{LinuxPtraceDumper, AT_SYSINFO_EHDR};
use minidump_writer_linux::{linux_ptrace_dumper, LINUX_GATE_LIBRARY_NAME};
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use nix::unistd::getppid;
use std::convert::TryInto;
use std::env;
use std::error;
use std::result;
use minidump_writer::{
ptrace_dumper::{PtraceDumper, AT_SYSINFO_EHDR},
LINUX_GATE_LIBRARY_NAME,
};
use nix::{
sys::mman::{mmap, MapFlags, ProtFlags},
unistd::getppid,
};
use std::{env, error, result};

type Error = Box<dyn error::Error + std::marker::Send + std::marker::Sync>;
pub type Result<T> = result::Result<T, Error>;
Expand All @@ -24,13 +27,13 @@ macro_rules! test {

fn test_setup() -> Result<()> {
let ppid = getppid();
linux_ptrace_dumper::LinuxPtraceDumper::new(ppid.as_raw())?;
PtraceDumper::new(ppid.as_raw())?;
Ok(())
}

fn test_thread_list() -> Result<()> {
let ppid = getppid();
let dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(ppid.as_raw())?;
let dumper = PtraceDumper::new(ppid.as_raw())?;
test!(!dumper.threads.is_empty(), "No threads")?;
test!(
dumper
Expand All @@ -46,17 +49,17 @@ fn test_thread_list() -> Result<()> {

fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {
let ppid = getppid().as_raw();
let mut dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(ppid)?;
let mut dumper = PtraceDumper::new(ppid)?;
dumper.suspend_threads()?;
let stack_res = LinuxPtraceDumper::copy_from_process(ppid, stack_var as *mut libc::c_void, 1)?;
let stack_res = PtraceDumper::copy_from_process(ppid, stack_var as *mut libc::c_void, 1)?;

let expected_stack: libc::c_long = 0x11223344;
test!(
stack_res == expected_stack.to_ne_bytes(),
"stack var not correct"
)?;

let heap_res = LinuxPtraceDumper::copy_from_process(ppid, heap_var as *mut libc::c_void, 1)?;
let heap_res = PtraceDumper::copy_from_process(ppid, heap_var as *mut libc::c_void, 1)?;
let expected_heap: libc::c_long = 0x55667788;
test!(
heap_res == expected_heap.to_ne_bytes(),
Expand All @@ -68,7 +71,7 @@ fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {

fn test_find_mappings(addr1: usize, addr2: usize) -> Result<()> {
let ppid = getppid();
let dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(ppid.as_raw())?;
let dumper = PtraceDumper::new(ppid.as_raw())?;
dumper
.find_mapping(addr1)
.ok_or("No mapping for addr1 found")?;
Expand All @@ -85,7 +88,7 @@ fn test_file_id() -> Result<()> {
let ppid = getppid().as_raw();
let exe_link = format!("/proc/{}/exe", ppid);
let exe_name = std::fs::read_link(&exe_link)?.into_os_string();
let mut dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(getppid().as_raw())?;
let mut dumper = PtraceDumper::new(getppid().as_raw())?;
let mut found_exe = None;
for (idx, mapping) in dumper.mappings.iter().enumerate() {
if mapping.name.as_ref().map(|x| x.into()).as_ref() == Some(&exe_name) {
Expand All @@ -102,7 +105,7 @@ fn test_file_id() -> Result<()> {

fn test_merged_mappings(path: String, mapped_mem: usize, mem_size: usize) -> Result<()> {
// Now check that LinuxPtraceDumper interpreted the mappings properly.
let dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(getppid().as_raw())?;
let dumper = PtraceDumper::new(getppid().as_raw())?;
let mut mapping_count = 0;
for map in &dumper.mappings {
if map.name == Some(path.clone()) {
Expand All @@ -120,13 +123,13 @@ fn test_merged_mappings(path: String, mapped_mem: usize, mem_size: usize) -> Res

fn test_linux_gate_mapping_id() -> Result<()> {
let ppid = getppid().as_raw();
let mut dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(ppid)?;
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) {
found_linux_gate = true;
dumper.suspend_threads()?;
let id = LinuxPtraceDumper::elf_identifier_for_mapping(&mut mapping, ppid)?;
let id = PtraceDumper::elf_identifier_for_mapping(&mut mapping, ppid)?;
test!(!id.is_empty(), "id-vec is empty")?;
test!(id.iter().any(|&x| x > 0), "all id elements are 0")?;
dumper.resume_threads()?;
Expand All @@ -139,7 +142,7 @@ fn test_linux_gate_mapping_id() -> Result<()> {

fn test_mappings_include_linux_gate() -> Result<()> {
let ppid = getppid().as_raw();
let dumper = linux_ptrace_dumper::LinuxPtraceDumper::new(ppid)?;
let dumper = PtraceDumper::new(ppid)?;
let linux_gate_loc = dumper.auxv[&AT_SYSINFO_EHDR];
test!(linux_gate_loc != 0, "linux_gate_loc == 0")?;
let mut found_linux_gate = false;
Expand Down
12 changes: 0 additions & 12 deletions src/crash_context/crash_context_mips.rs

This file was deleted.

65 changes: 0 additions & 65 deletions src/crash_context/mod.rs

This file was deleted.

23 changes: 8 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
#[cfg(target_os = "android")]
mod android;
pub mod app_memory;
mod auxv_reader;
pub mod crash_context;
mod dso_debug;
mod dumper_cpu_info;
pub mod errors;
pub mod linux_ptrace_dumper;
pub mod maps_reader;
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "android"))] {
mod linux;

pub use linux::*;
}
}

pub mod minidump_cpu;
pub mod minidump_format;
pub mod minidump_writer;
mod sections;
pub mod thread_info;

pub use maps_reader::LINUX_GATE_LIBRARY_NAME;
15 changes: 15 additions & 0 deletions src/linux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[cfg(target_os = "android")]
mod android;
pub mod app_memory;
pub(crate) mod auxv_reader;
pub mod crash_context;
mod dso_debug;
mod dumper_cpu_info;
pub mod errors;
pub mod maps_reader;
pub mod minidump_writer;
pub mod ptrace_dumper;
pub(crate) mod sections;
pub mod thread_info;

pub use maps_reader::LINUX_GATE_LIBRARY_NAME;
File renamed without changes.
File renamed without changes.
File renamed without changes.
37 changes: 37 additions & 0 deletions src/linux/crash_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Minidump defines register structures which are different from the raw
//! structures which we get from the kernel. These are platform specific
//! functions to juggle the ucontext_t and user structures into minidump format.

#![allow(non_camel_case_types)]

cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
pub(crate) mod x86_64;

pub type fpstate_t = libc::user_fpregs_struct;
} else if #[cfg(target_arch = "x86")] {
pub(crate) mod x86;

pub type fpstate_t = libc::_libc_fpstate;
} else if #[cfg(target_arch = "arm")] {
pub(crate) mod arm;
} else if #[cfg(target_arch = "aarch64")] {
pub(crate) mod aarch64;

pub type fpstate_t = libc::fpsimd_context; // Currently not part of libc! This will produce an error.
}
}

#[repr(C)]
#[derive(Clone)]
pub struct CrashContext {
pub siginfo: libc::siginfo_t,
pub tid: libc::pid_t, // the crashing thread.
#[cfg(not(target_arch = "arm"))]
pub context: libc::ucontext_t,
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
// In case of MIPS Linux FP state is already part of ucontext_t so
// 'float_state' is not required.
#[cfg(not(target_arch = "arm"))]
pub float_state: fpstate_t,
}
Loading