From f1f808901021a4b31912a31fc9e10ba118713970 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 9 Nov 2021 11:52:49 +0100
Subject: [PATCH 01/21] These do exist in arm
---
src/crash_context/mod.rs | 1 -
src/minidump_writer.rs | 2 --
2 files changed, 3 deletions(-)
diff --git a/src/crash_context/mod.rs b/src/crash_context/mod.rs
index 2be8fb15..7714b18d 100644
--- a/src/crash_context/mod.rs
+++ b/src/crash_context/mod.rs
@@ -55,7 +55,6 @@ pub type fpstate_t = libc::user_fpregs_struct;
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
diff --git a/src/minidump_writer.rs b/src/minidump_writer.rs
index 644843d9..4a910e14 100644
--- a/src/minidump_writer.rs
+++ b/src/minidump_writer.rs
@@ -165,8 +165,6 @@ impl MinidumpWriter {
self
}
- // Has to be deactivated for ARM for now, as libc doesn't include ucontext_t for ARM yet
- #[cfg(not(target_arch = "arm"))]
pub fn set_crash_context(&mut self, crash_context: CrashContext) -> &mut Self {
self.crash_context = Some(crash_context);
self
From b711755c78b7ebc1ca57d7510cb9620c11f2bed5 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 9 Nov 2021 12:20:42 +0100
Subject: [PATCH 02/21] Use nix's siginfo instead of libc's
---
src/crash_context/mod.rs | 2 +-
src/sections/exception_stream.rs | 6 +++---
tests/minidump_writer.rs | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/crash_context/mod.rs b/src/crash_context/mod.rs
index 7714b18d..3b65d9d6 100644
--- a/src/crash_context/mod.rs
+++ b/src/crash_context/mod.rs
@@ -53,7 +53,7 @@ pub type fpstate_t = libc::user_fpregs_struct;
#[repr(C)]
#[derive(Clone)]
pub struct CrashContext {
- pub siginfo: libc::siginfo_t,
+ pub siginfo: nix::sys::signalfd::siginfo,
pub tid: libc::pid_t, // the crashing thread.
pub context: libc::ucontext_t,
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
diff --git a/src/sections/exception_stream.rs b/src/sections/exception_stream.rs
index 65e14119..d3c49ece 100644
--- a/src/sections/exception_stream.rs
+++ b/src/sections/exception_stream.rs
@@ -67,11 +67,11 @@ pub fn write(config: &mut MinidumpWriter, buffer: &mut DumpBuf) -> Result Result {
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
fn get_crash_context(tid: Pid) -> CrashContext {
- let siginfo: libc::siginfo_t = unsafe { std::mem::zeroed() };
+ let siginfo = unsafe { std::mem::zeroed() };
let context = get_ucontext().expect("Failed to get ucontext");
let float_state: fpstate_t = unsafe { std::mem::zeroed() };
CrashContext {
From f429cba877f390ee8c88e7be34a6796a045e7503 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 11 Nov 2021 12:27:05 +0100
Subject: [PATCH 03/21] Update dependencies
---
Cargo.toml | 22 +++++++++++-----------
src/lib.rs | 2 ++
src/linux_ptrace_dumper.rs | 36 +++++++++++++++++++-----------------
src/thread_info/mod.rs | 2 +-
4 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 237afe6a..c1d02bf6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,21 +2,21 @@
name = "minidump_writer_linux"
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]
-tempfile = "3.1.0"
-nix = "0.15"
-libc = "0.2.74"
-memoffset = "0.5.1"
byteorder = "1.3.2"
-memmap2 = "0.2.2"
-goblin = "0.1.2"
+exception-handler = { path = "../crash-handling/exception-handler" }
+goblin = "0.4"
+libc = "0.2.74"
+memmap2 = "0.5"
+memoffset = "0.6"
+nix = "0.23"
+tempfile = "3.1.0"
thiserror = "1.0.21"
+uctx = { path = "../crash-handling/uctx" }
[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" }
diff --git a/src/lib.rs b/src/lib.rs
index 1a774cd8..5c60acc8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,5 @@
+#![allow(unsafe_code)]
+
#[cfg(target_os = "android")]
mod android;
pub mod app_memory;
diff --git a/src/linux_ptrace_dumper.rs b/src/linux_ptrace_dumper.rs
index f1e249b0..0b5c4242 100644
--- a/src/linux_ptrace_dumper.rs
+++ b/src/linux_ptrace_dumper.rs
@@ -1,21 +1,23 @@
// use libc::c_void;
#[cfg(target_os = "android")]
use crate::android::late_process_mappings;
-use crate::auxv_reader::{AuxvType, ProcfsAuxvIter};
-use crate::errors::{DumperError, InitError, ThreadInfoError};
-use crate::maps_reader::{MappingInfo, MappingInfoParsingResult, DELETED_SUFFIX};
-use crate::minidump_format::MDGUID;
-use crate::thread_info::{Pid, ThreadInfo};
-use crate::LINUX_GATE_LIBRARY_NAME;
+use crate::{
+ auxv_reader::{AuxvType, ProcfsAuxvIter},
+ errors::{DumperError, InitError, ThreadInfoError},
+ maps_reader::{MappingInfo, MappingInfoParsingResult, DELETED_SUFFIX},
+ minidump_format::MDGUID,
+ thread_info::{Pid, ThreadInfo},
+ LINUX_GATE_LIBRARY_NAME,
+};
use goblin::elf;
-use nix::errno::Errno;
use nix::sys::{ptrace, wait};
-use std::collections::HashMap;
-use std::convert::TryInto;
-use std::ffi::c_void;
-use std::io::{BufRead, BufReader};
-use std::path;
-use std::result::Result;
+use std::{
+ collections::HashMap,
+ ffi::c_void,
+ io::{BufRead, BufReader},
+ path,
+ result::Result,
+};
#[derive(Debug, Clone)]
pub struct Thread {
@@ -107,8 +109,8 @@ impl LinuxPtraceDumper {
loop {
match wait::waitpid(pid, Some(wait::WaitPidFlag::__WALL)) {
Ok(_) => break,
- Err(e @ nix::Error::Sys(Errno::EINTR)) => {
- ptrace::detach(pid).map_err(|e| DetachErr(child, e))?;
+ Err(e @ nix::Error::EINTR) => {
+ ptrace::detach(pid, None).map_err(|e| DetachErr(child, e))?;
return Err(DumperError::WaitPidError(child, e));
}
Err(_) => continue,
@@ -138,7 +140,7 @@ impl LinuxPtraceDumper {
skip_thread = true;
}
if skip_thread {
- ptrace::detach(pid).map_err(|e| DetachErr(child, e))?;
+ ptrace::detach(pid, None).map_err(|e| DetachErr(child, e))?;
return Err(DumperError::DetachSkippedThread(child));
}
}
@@ -149,7 +151,7 @@ impl LinuxPtraceDumper {
pub fn resume_thread(child: Pid) -> Result<(), DumperError> {
use DumperError::PtraceDetachError as DetachErr;
let pid = nix::unistd::Pid::from_raw(child);
- ptrace::detach(pid).map_err(|e| DetachErr(child, e))?;
+ ptrace::detach(pid, None).map_err(|e| DetachErr(child, e))?;
Ok(())
}
diff --git a/src/thread_info/mod.rs b/src/thread_info/mod.rs
index 18a9ecb0..cb918b50 100644
--- a/src/thread_info/mod.rs
+++ b/src/thread_info/mod.rs
@@ -166,7 +166,7 @@ trait CommonThreadInfo {
)
};
match Errno::result(ret) {
- Ok(..) | Err(nix::Error::Sys(Errno::UnknownErrno)) => Ok(ret),
+ Ok(..) | Err(nix::Error::UnknownErrno) => Ok(ret),
err @ Err(..) => err,
}
}
From 40e967b14a0d959749b02b040ac4c3ef9da076ad Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 18 Nov 2021 08:50:38 +0100
Subject: [PATCH 04/21] Remove unneeded TryInto imports
---
src/android.rs | 1 -
src/bin/test.rs | 1 -
src/dumper_cpu_info/cpu_info_x86_mips.rs | 1 -
src/maps_reader.rs | 1 -
src/sections/mod.rs | 1 -
src/sections/thread_names_stream.rs | 1 -
src/thread_info/mod.rs | 1 -
src/thread_info/thread_info_x86.rs | 2 --
tests/ptrace_dumper.rs | 1 -
9 files changed, 10 deletions(-)
diff --git a/src/android.rs b/src/android.rs
index b605b6ce..917b4ea1 100644
--- a/src/android.rs
+++ b/src/android.rs
@@ -15,7 +15,6 @@ use goblin::elf::header::header64 as elf_header;
use goblin::elf::program_header::program_header32::ProgramHeader;
#[cfg(target_pointer_width = "64")]
use goblin::elf::program_header::program_header64::ProgramHeader;
-use std::convert::TryInto;
use std::ffi::c_void;
type Result = std::result::Result;
diff --git a/src/bin/test.rs b/src/bin/test.rs
index 9899e8f9..7ae13dc8 100644
--- a/src/bin/test.rs
+++ b/src/bin/test.rs
@@ -4,7 +4,6 @@ use minidump_writer_linux::linux_ptrace_dumper::{LinuxPtraceDumper, AT_SYSINFO_E
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;
diff --git a/src/dumper_cpu_info/cpu_info_x86_mips.rs b/src/dumper_cpu_info/cpu_info_x86_mips.rs
index c37fa94f..ea9cfe07 100644
--- a/src/dumper_cpu_info/cpu_info_x86_mips.rs
+++ b/src/dumper_cpu_info/cpu_info_x86_mips.rs
@@ -1,6 +1,5 @@
use crate::errors::CpuInfoError;
use crate::minidump_format::*;
-use std::convert::TryInto;
use std::io::{BufRead, BufReader};
use std::path;
diff --git a/src/maps_reader.rs b/src/maps_reader.rs
index ec0b4543..f81f67de 100644
--- a/src/maps_reader.rs
+++ b/src/maps_reader.rs
@@ -4,7 +4,6 @@ use crate::thread_info::Pid;
use byteorder::{NativeEndian, ReadBytesExt};
use goblin::elf;
use memmap2::{Mmap, MmapOptions};
-use std::convert::TryInto;
use std::fs::File;
use std::mem::size_of;
use std::path::PathBuf;
diff --git a/src/sections/mod.rs b/src/sections/mod.rs
index 086e7e23..7d56d7be 100644
--- a/src/sections/mod.rs
+++ b/src/sections/mod.rs
@@ -8,7 +8,6 @@ pub mod thread_names_stream;
use crate::errors::MemoryWriterError;
use crate::minidump_format::*;
-use std::convert::TryInto;
use std::io::{Cursor, Write};
type Result = std::result::Result;
diff --git a/src/sections/thread_names_stream.rs b/src/sections/thread_names_stream.rs
index decb1674..9a5526dc 100644
--- a/src/sections/thread_names_stream.rs
+++ b/src/sections/thread_names_stream.rs
@@ -4,7 +4,6 @@ use crate::minidump_format::*;
use crate::minidump_writer::DumpBuf;
use crate::sections::write_string_to_location;
use crate::sections::{MemoryArrayWriter, MemoryWriter};
-use std::convert::TryInto;
type Result = std::result::Result;
diff --git a/src/thread_info/mod.rs b/src/thread_info/mod.rs
index cb918b50..60f4d328 100644
--- a/src/thread_info/mod.rs
+++ b/src/thread_info/mod.rs
@@ -2,7 +2,6 @@ use crate::errors::ThreadInfoError;
use nix::errno::Errno;
use nix::sys::ptrace;
use nix::unistd;
-use std::convert::TryInto;
use std::io::{self, BufRead};
use std::path;
diff --git a/src/thread_info/thread_info_x86.rs b/src/thread_info/thread_info_x86.rs
index 6dbf6c2d..d6fdfe2c 100644
--- a/src/thread_info/thread_info_x86.rs
+++ b/src/thread_info/thread_info_x86.rs
@@ -10,8 +10,6 @@ use libc::user;
use memoffset;
use nix::sys::ptrace;
use nix::unistd;
-#[cfg(target_arch = "x86")]
-use std::convert::TryInto;
type Result = std::result::Result;
diff --git a/tests/ptrace_dumper.rs b/tests/ptrace_dumper.rs
index c2e8fccf..d2002686 100644
--- a/tests/ptrace_dumper.rs
+++ b/tests/ptrace_dumper.rs
@@ -1,7 +1,6 @@
use minidump_writer_linux::linux_ptrace_dumper;
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use nix::sys::signal::Signal;
-use std::convert::TryInto;
use std::io::{BufRead, BufReader};
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
From 6bdab6b746f96530968da19456c2e037742cb723 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 18 Nov 2021 08:51:07 +0100
Subject: [PATCH 05/21] Cleanup imports
---
src/minidump_writer.rs | 20 ++++++++++--------
src/sections/thread_list_stream.rs | 16 ++++++++-------
tests/minidump_writer.rs | 33 +++++++++++++++---------------
3 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/src/minidump_writer.rs b/src/minidump_writer.rs
index 4a910e14..b9805470 100644
--- a/src/minidump_writer.rs
+++ b/src/minidump_writer.rs
@@ -1,12 +1,14 @@
-use crate::app_memory::AppMemoryList;
-use crate::crash_context::CrashContext;
-use crate::dso_debug;
-use crate::errors::{FileWriterError, InitError, MemoryWriterError, WriterError};
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::maps_reader::{MappingInfo, MappingList};
-use crate::minidump_format::*;
-use crate::sections::*;
-use crate::thread_info::Pid;
+use crate::{
+ app_memory::AppMemoryList,
+ crash_context::{CpuContext, CrashContext},
+ dso_debug,
+ errors::{FileWriterError, InitError, MemoryWriterError, WriterError},
+ linux_ptrace_dumper::LinuxPtraceDumper,
+ maps_reader::{MappingInfo, MappingList},
+ minidump_format::*,
+ sections::*,
+ thread_info::Pid,
+};
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
pub type DumpBuf = Cursor>;
diff --git a/src/sections/thread_list_stream.rs b/src/sections/thread_list_stream.rs
index d3672d99..f4cb3c07 100644
--- a/src/sections/thread_list_stream.rs
+++ b/src/sections/thread_list_stream.rs
@@ -1,10 +1,12 @@
-use crate::errors::SectionThreadListError;
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::minidump_cpu::RawContextCPU;
-use crate::minidump_format::*;
-use crate::minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter};
-use crate::sections::{MemoryArrayWriter, MemoryWriter};
-use std::convert::TryInto;
+use crate::{
+ crash_context::CpuContext,
+ errors::SectionThreadListError,
+ linux_ptrace_dumper::LinuxPtraceDumper,
+ minidump_cpu::RawContextCPU,
+ minidump_format::*,
+ minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter},
+ sections::{MemoryArrayWriter, MemoryWriter},
+};
use std::io::Write;
type Result = std::result::Result;
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index 38445a21..d6c307a8 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -1,22 +1,21 @@
use minidump::*;
use minidump_common::format::{GUID, MINIDUMP_STREAM_TYPE::*};
-use minidump_writer_linux::app_memory::AppMemory;
-#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
-use minidump_writer_linux::crash_context::fpstate_t;
-use minidump_writer_linux::crash_context::CrashContext;
-use minidump_writer_linux::errors::*;
-use minidump_writer_linux::linux_ptrace_dumper::LinuxPtraceDumper;
-use minidump_writer_linux::maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo};
-use minidump_writer_linux::minidump_writer::MinidumpWriter;
-use minidump_writer_linux::thread_info::Pid;
-use nix::errno::Errno;
-use nix::sys::signal::Signal;
-use std::collections::HashSet;
-use std::convert::TryInto;
-use std::io::{BufRead, BufReader};
-use std::os::unix::process::ExitStatusExt;
-use std::process::{Command, Stdio};
-use std::str::FromStr;
+use minidump_writer_linux::{
+ app_memory::AppMemory,
+ crash_context::CrashContext,
+ errors::*,
+ linux_ptrace_dumper::LinuxPtraceDumper,
+ maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo},
+ minidump_writer::MinidumpWriter,
+ thread_info::Pid,
+};
+use nix::{errno::Errno, sys::signal::Signal};
+use std::{
+ collections::HashSet,
+ io::{BufRead, BufReader},
+ os::unix::process::ExitStatusExt,
+ process::{Command, Stdio},
+};
mod common;
use common::*;
From 40ca0a5f83656b188b8e156ddad538489d4d4ca3 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 18 Nov 2021 08:51:59 +0100
Subject: [PATCH 06/21] Use exception_handler::CrashContext
---
Cargo.toml | 1 +
src/crash_context/crash_context_x86_64.rs | 94 ++++++++++++-----------
src/crash_context/mod.rs | 85 ++++++++------------
tests/minidump_writer.rs | 52 ++++++++++---
4 files changed, 124 insertions(+), 108 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index c1d02bf6..d0a3966a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ license = "MIT"
[dependencies]
byteorder = "1.3.2"
+cfg-if = "1.0"
exception-handler = { path = "../crash-handling/exception-handler" }
goblin = "0.4"
libc = "0.2.74"
diff --git a/src/crash_context/crash_context_x86_64.rs b/src/crash_context/crash_context_x86_64.rs
index dd82d29a..87bccc77 100644
--- a/src/crash_context/crash_context_x86_64.rs
+++ b/src/crash_context/crash_context_x86_64.rs
@@ -1,69 +1,75 @@
-use super::CrashContext;
use crate::minidump_cpu::imp::*;
-use crate::minidump_cpu::RawContextCPU;
+
use crate::thread_info::to_u128;
use libc::{
REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
};
-impl CrashContext {
- pub fn get_instruction_pointer(&self) -> usize {
+impl super::CpuContext for super::CrashContext {
+ fn get_instruction_pointer(&self) -> usize {
self.context.uc_mcontext.gregs[REG_RIP as usize] as usize
}
- pub fn get_stack_pointer(&self) -> usize {
+ fn get_stack_pointer(&self) -> usize {
self.context.uc_mcontext.gregs[REG_RSP as usize] as usize
}
- pub fn fill_cpu_context(&self, out: &mut RawContextCPU) {
+ fn fill_cpu_context(&self, out: &mut super::RawContextCPU) {
out.context_flags = MD_CONTEXT_AMD64_FULL;
- out.cs = (self.context.uc_mcontext.gregs[REG_CSGSFS as usize] & 0xffff) as u16;
-
- out.fs = ((self.context.uc_mcontext.gregs[REG_CSGSFS as usize] >> 32) & 0xffff) as u16;
- out.gs = ((self.context.uc_mcontext.gregs[REG_CSGSFS as usize] >> 16) & 0xffff) as u16;
- out.eflags = self.context.uc_mcontext.gregs[REG_EFL as usize] as u32;
+ {
+ let gregs = &self.context.uc_mcontext.gregs;
+ out.cs = (gregs[REG_CSGSFS as usize] & 0xffff) as u16;
- out.rax = self.context.uc_mcontext.gregs[REG_RAX as usize] as u64;
- out.rcx = self.context.uc_mcontext.gregs[REG_RCX as usize] as u64;
- out.rdx = self.context.uc_mcontext.gregs[REG_RDX as usize] as u64;
- out.rbx = self.context.uc_mcontext.gregs[REG_RBX as usize] as u64;
+ out.fs = ((gregs[REG_CSGSFS as usize] >> 32) & 0xffff) as u16;
+ out.gs = ((gregs[REG_CSGSFS as usize] >> 16) & 0xffff) as u16;
- out.rsp = self.context.uc_mcontext.gregs[REG_RSP as usize] as u64;
- out.rbp = self.context.uc_mcontext.gregs[REG_RBP as usize] as u64;
- out.rsi = self.context.uc_mcontext.gregs[REG_RSI as usize] as u64;
- out.rdi = self.context.uc_mcontext.gregs[REG_RDI as usize] as u64;
- out.r8 = self.context.uc_mcontext.gregs[REG_R8 as usize] as u64;
- out.r9 = self.context.uc_mcontext.gregs[REG_R9 as usize] as u64;
- out.r10 = self.context.uc_mcontext.gregs[REG_R10 as usize] as u64;
- out.r11 = self.context.uc_mcontext.gregs[REG_R11 as usize] as u64;
- out.r12 = self.context.uc_mcontext.gregs[REG_R12 as usize] as u64;
- out.r13 = self.context.uc_mcontext.gregs[REG_R13 as usize] as u64;
- out.r14 = self.context.uc_mcontext.gregs[REG_R14 as usize] as u64;
- out.r15 = self.context.uc_mcontext.gregs[REG_R15 as usize] as u64;
+ out.eflags = gregs[REG_EFL as usize] as u32;
- out.rip = self.context.uc_mcontext.gregs[REG_RIP as usize] as u64;
+ out.rax = gregs[REG_RAX as usize] as u64;
+ out.rcx = gregs[REG_RCX as usize] as u64;
+ out.rdx = gregs[REG_RDX as usize] as u64;
+ out.rbx = gregs[REG_RBX as usize] as u64;
- out.flt_save.control_word = self.float_state.cwd;
- out.flt_save.status_word = self.float_state.swd;
- out.flt_save.tag_word = self.float_state.ftw as u8;
- out.flt_save.error_opcode = self.float_state.fop;
- out.flt_save.error_offset = self.float_state.rip as u32;
- out.flt_save.data_offset = self.float_state.rdp as u32;
- out.flt_save.error_selector = 0; // We don't have this.
- out.flt_save.data_selector = 0; // We don't have this.
- out.flt_save.mx_csr = self.float_state.mxcsr;
- out.flt_save.mx_csr_mask = self.float_state.mxcr_mask;
+ out.rsp = gregs[REG_RSP as usize] as u64;
+ out.rbp = gregs[REG_RBP as usize] as u64;
+ out.rsi = gregs[REG_RSI as usize] as u64;
+ out.rdi = gregs[REG_RDI as usize] as u64;
+ out.r8 = gregs[REG_R8 as usize] as u64;
+ out.r9 = gregs[REG_R9 as usize] as u64;
+ out.r10 = gregs[REG_R10 as usize] as u64;
+ out.r11 = gregs[REG_R11 as usize] as u64;
+ out.r12 = gregs[REG_R12 as usize] as u64;
+ out.r13 = gregs[REG_R13 as usize] as u64;
+ out.r14 = gregs[REG_R14 as usize] as u64;
+ out.r15 = gregs[REG_R15 as usize] as u64;
- let data = to_u128(&self.float_state.st_space);
- for idx in 0..data.len() {
- out.flt_save.float_registers[idx] = data[idx];
+ out.rip = gregs[REG_RIP as usize] as u64;
}
- let data = to_u128(&self.float_state.xmm_space);
- for idx in 0..data.len() {
- out.flt_save.xmm_registers[idx] = data[idx];
+ {
+ let fs = &self.float_state;
+ out.flt_save.control_word = fs.cwd;
+ out.flt_save.status_word = fs.swd;
+ out.flt_save.tag_word = fs.ftw as u8;
+ out.flt_save.error_opcode = fs.fop;
+ out.flt_save.error_offset = fs.rip as u32;
+ out.flt_save.data_offset = fs.rdp as u32;
+ out.flt_save.error_selector = 0; // We don't have this.
+ out.flt_save.data_selector = 0; // We don't have this.
+ out.flt_save.mx_csr = fs.mxcsr;
+ out.flt_save.mx_csr_mask = fs.mxcr_mask;
+
+ let data = to_u128(&fs.st_space);
+ for idx in 0..data.len() {
+ out.flt_save.float_registers[idx] = data[idx];
+ }
+
+ let data = to_u128(&fs.xmm_space);
+ for idx in 0..data.len() {
+ out.flt_save.xmm_registers[idx] = data[idx];
+ }
}
}
}
diff --git a/src/crash_context/mod.rs b/src/crash_context/mod.rs
index 3b65d9d6..2dc37c08 100644
--- a/src/crash_context/mod.rs
+++ b/src/crash_context/mod.rs
@@ -1,64 +1,41 @@
-use libc;
-
// 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.
-#[cfg(target_arch = "x86_64")]
-#[path = "crash_context_x86_64.rs"]
-pub mod imp;
-#[cfg(target_arch = "x86")]
-#[path = "crash_context_x86.rs"]
-pub mod imp;
-// Deactivated for now, as ucontext_t is missing from libc
-// #[cfg(target_arch = "arm")]
-// #[path = "crash_context_arm.rs"]
-// pub mod imp;
-#[cfg(target_arch = "arm")]
-use crate::minidump_cpu::RawContextCPU;
-#[cfg(target_arch = "arm")]
-impl CrashContext {
- pub fn get_instruction_pointer(&self) -> usize {
- 0
- }
-
- pub fn get_stack_pointer(&self) -> usize {
- 0
+cfg_if::cfg_if! {
+ if #[cfg(target_arch = "x86_64")] {
+ mod crash_context_x86_64;
+ } else if #[cfg(target_arch = "x86")] {
+ mod crash_context_x86;
+ } else if #[cfg(target_arch = "aarch64")] {
+ mod crash_context_aarch64;
+ } else if #[cfg(target_arch = "arm")] {
+ mod crash_context_arm;
+ } else if #[cfg(target_arch = "mips")] {
+ mod crash_context_mips;
}
-
- pub fn fill_cpu_context(&self, _: &mut RawContextCPU) {}
}
-#[cfg(target_arch = "aarch64")]
-#[path = "crash_context_aarch64.rs"]
-pub mod imp;
-#[cfg(target_arch = "mips")]
-#[path = "crash_context_mips.rs"]
-pub mod imp;
+use crate::minidump_cpu::RawContextCPU;
+
+// #[cfg(target_arch = "aarch64")]
+// pub type fpstate_t = libc::fpsimd_context; // Currently not part of libc! This will produce an error.
+// #[cfg(not(any(
+// target_arch = "aarch64",
+// target_arch = "mips",
+// target_arch = "arm-eabi"
+// )))]
+// #[cfg(target_arch = "x86")]
+// #[allow(non_camel_case_types)]
+// pub type fpstate_t = libc::_libc_fpstate;
+// #[cfg(target_arch = "x86_64")]
+// #[allow(non_camel_case_types)]
+// pub type fpstate_t = libc::user_fpregs_struct;
-#[cfg(target_arch = "aarch64")]
-pub type fpstate_t = libc::fpsimd_context; // Currently not part of libc! This will produce an error.
-#[cfg(not(any(
- target_arch = "aarch64",
- target_arch = "mips",
- target_arch = "arm-eabi"
-)))]
-#[cfg(target_arch = "x86")]
-#[allow(non_camel_case_types)]
-pub type fpstate_t = libc::_libc_fpstate;
-#[cfg(target_arch = "x86_64")]
-#[allow(non_camel_case_types)]
-pub type fpstate_t = libc::user_fpregs_struct;
+pub use exception_handler::CrashContext;
-#[repr(C)]
-#[derive(Clone)]
-pub struct CrashContext {
- pub siginfo: nix::sys::signalfd::siginfo,
- pub tid: libc::pid_t, // the crashing thread.
- 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(any(target_arch = "mips", target_arch = "arm")))]
- pub float_state: fpstate_t,
+pub trait CpuContext {
+ fn get_instruction_pointer(&self) -> usize;
+ fn get_stack_pointer(&self) -> usize;
+ fn fill_cpu_context(&self, cpu_ctx: &mut RawContextCPU);
}
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index d6c307a8..9cfc37e4 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -27,18 +27,21 @@ enum Context {
}
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
-fn get_ucontext() -> Result {
- let mut context = std::mem::MaybeUninit::::uninit();
- let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
- Errno::result(res)?;
- unsafe { Ok(context.assume_init()) }
+fn get_ucontext() -> Result {
+ let mut context = std::mem::MaybeUninit::uninit();
+ unsafe {
+ let res = uctx::getcontext(context.as_mut_ptr());
+ Errno::result(res)?;
+
+ Ok(context.assume_init())
+ }
}
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
fn get_crash_context(tid: Pid) -> CrashContext {
let siginfo = unsafe { std::mem::zeroed() };
let context = get_ucontext().expect("Failed to get ucontext");
- let float_state: fpstate_t = unsafe { std::mem::zeroed() };
+ let float_state = unsafe { std::mem::zeroed() };
CrashContext {
siginfo,
tid,
@@ -83,6 +86,7 @@ fn test_write_dump_helper(context: Context) {
fn test_write_dump() {
test_write_dump_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_write_dump_with_context() {
@@ -104,8 +108,16 @@ fn test_write_and_read_dump_from_parent_helper(context: Context) {
.read_line(&mut buf)
.expect("Couldn't read address provided by child");
let mut output = buf.split_whitespace();
- let mmap_addr = usize::from_str(output.next().unwrap()).expect("unable to parse mmap_addr");
- let memory_size = usize::from_str(output.next().unwrap()).expect("unable to parse memory_size");
+ let mmap_addr: usize = output
+ .next()
+ .unwrap()
+ .parse()
+ .expect("unable to parse mmap_addr");
+ let memory_size: usize = output
+ .next()
+ .unwrap()
+ .parse()
+ .expect("unable to parse memory_size");
// Add information about the mapped memory.
let mapping = MappingInfo {
start_address: mmap_addr,
@@ -188,10 +200,12 @@ fn test_write_and_read_dump_from_parent_helper(context: Context) {
.get_raw_stream(LinuxDsoDebug)
.expect("Couldn't find LinuxDsoDebug");
}
+
#[test]
fn test_write_and_read_dump_from_parent() {
test_write_and_read_dump_from_parent_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_write_and_read_dump_from_parent_with_context() {
@@ -215,7 +229,11 @@ fn test_write_with_additional_memory_helper(context: Context) {
let mut output = buf.split_whitespace();
let memory_addr = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
.expect("unable to parse mmap_addr");
- let memory_size = usize::from_str(output.next().unwrap()).expect("unable to parse memory_size");
+ let memory_size: usize = output
+ .next()
+ .unwrap()
+ .parse()
+ .expect("unable to parse memory_size");
let app_memory = AppMemory {
ptr: memory_addr,
@@ -259,10 +277,12 @@ fn test_write_with_additional_memory_helper(context: Context) {
// Verify memory contents.
assert_eq!(region.bytes, values);
}
+
#[test]
fn test_write_with_additional_memory() {
test_write_with_additional_memory_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_write_with_additional_memory_with_context() {
@@ -535,10 +555,12 @@ fn test_skip_if_requested_helper(context: Context) {
assert!(res.is_err());
}
+
#[test]
fn test_skip_if_requested() {
test_skip_if_requested_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_skip_if_requested_with_context() {
@@ -599,10 +621,12 @@ fn test_sanitized_stacks_helper(context: Context) {
.is_some());
}
}
+
#[test]
fn test_sanitized_stacks() {
test_sanitized_stacks_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_sanitized_stacks_with_context() {
@@ -629,7 +653,11 @@ fn test_write_early_abort_helper(context: Context) {
let _ = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
.expect("unable to parse mmap_addr");
let memory_addr = 0;
- let memory_size = usize::from_str(output.next().unwrap()).expect("unable to parse memory_size");
+ let memory_size: usize = output
+ .next()
+ .unwrap()
+ .parse()
+ .expect("unable to parse memory_size");
let app_memory = AppMemory {
ptr: memory_addr,
@@ -665,10 +693,12 @@ fn test_write_early_abort_helper(context: Context) {
// Should be missing:
assert!(dump.get_stream::().is_err());
}
+
#[test]
fn test_write_early_abort() {
test_write_early_abort_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_write_early_abort_with_context() {
@@ -722,10 +752,12 @@ fn test_named_threads_helper(context: Context) {
}
assert_eq!(expected, names);
}
+
#[test]
fn test_named_threads() {
test_named_threads_helper(Context::Without)
}
+
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
#[test]
fn test_named_threads_with_context() {
From e10b5549d4265f2b29991e96ec72d17ec9ec4637 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 18 Nov 2021 09:58:12 +0100
Subject: [PATCH 07/21] Refactor layout
---
Cargo.toml | 2 +-
src/bin/test.rs | 28 +++++------
src/lib.rs | 23 ++++------
src/linux.rs | 15 ++++++
src/{ => linux}/android.rs | 0
src/{ => linux}/app_memory.rs | 0
src/{ => linux}/auxv_reader.rs | 0
.../crash_context/crash_context_aarch64.rs | 0
.../crash_context/crash_context_arm.rs | 0
.../crash_context/crash_context_mips.rs | 0
.../crash_context/crash_context_x86.rs | 0
.../crash_context/crash_context_x86_64.rs | 0
src/{ => linux}/crash_context/mod.rs | 0
src/{ => linux}/dso_debug.rs | 30 ++++++------
.../mod.rs => linux/dumper_cpu_info.rs} | 38 +++++++++------
.../dumper_cpu_info/arm.rs} | 0
.../dumper_cpu_info/x86_mips.rs} | 0
src/{ => linux}/errors.rs | 6 +--
src/{ => linux}/maps_reader.rs | 13 ++----
src/{ => linux}/minidump_writer.rs | 26 ++++++-----
.../ptrace_dumper.rs} | 22 +++++----
src/{sections/mod.rs => linux/sections.rs} | 10 +++-
src/{ => linux}/sections/app_memory.rs | 15 +++---
src/{ => linux}/sections/exception_stream.rs | 13 +++---
src/{ => linux}/sections/mappings.rs | 21 +++++----
.../sections/memory_list_stream.rs | 7 +--
src/{ => linux}/sections/systeminfo_stream.rs | 9 ++--
.../sections/thread_list_stream.rs | 29 +++++++-----
.../sections/thread_names_stream.rs | 11 ++---
.../mod.rs => linux/thread_info.rs} | 46 ++++++++-----------
.../thread_info/aarch64.rs} | 0
.../thread_info/arm.rs} | 0
.../thread_info/mips.rs} | 0
.../thread_info/x86.rs} | 0
src/minidump_cpu.rs | 25 ++++++++++
.../{minidump_cpu_aarch64.rs => aarch64.rs} | 0
.../{minidump_cpu_amd64.rs => amd64.rs} | 0
.../{minidump_cpu_arm.rs => arm.rs} | 0
.../{minidump_cpu_mips.rs => mips.rs} | 0
src/minidump_cpu/mod.rs | 26 -----------
.../{minidump_cpu_ppc.rs => ppc.rs} | 0
.../{minidump_cpu_ppc64.rs => ppc64.rs} | 0
.../{minidump_cpu_sparc.rs => sparc.rs} | 0
.../{minidump_cpu_x86.rs => x86.rs} | 0
tests/minidump_writer.rs | 6 +--
tests/ptrace_dumper.rs | 8 ++--
46 files changed, 220 insertions(+), 209 deletions(-)
create mode 100644 src/linux.rs
rename src/{ => linux}/android.rs (100%)
rename src/{ => linux}/app_memory.rs (100%)
rename src/{ => linux}/auxv_reader.rs (100%)
rename src/{ => linux}/crash_context/crash_context_aarch64.rs (100%)
rename src/{ => linux}/crash_context/crash_context_arm.rs (100%)
rename src/{ => linux}/crash_context/crash_context_mips.rs (100%)
rename src/{ => linux}/crash_context/crash_context_x86.rs (100%)
rename src/{ => linux}/crash_context/crash_context_x86_64.rs (100%)
rename src/{ => linux}/crash_context/mod.rs (100%)
rename src/{ => linux}/dso_debug.rs (92%)
rename src/{dumper_cpu_info/mod.rs => linux/dumper_cpu_info.rs} (57%)
rename src/{dumper_cpu_info/cpu_info_arm.rs => linux/dumper_cpu_info/arm.rs} (100%)
rename src/{dumper_cpu_info/cpu_info_x86_mips.rs => linux/dumper_cpu_info/x86_mips.rs} (100%)
rename src/{ => linux}/errors.rs (98%)
rename src/{ => linux}/maps_reader.rs (98%)
rename src/{ => linux}/minidump_writer.rs (96%)
rename src/{linux_ptrace_dumper.rs => linux/ptrace_dumper.rs} (98%)
rename src/{sections/mod.rs => linux/sections.rs} (97%)
rename src/{ => linux}/sections/app_memory.rs (54%)
rename src/{ => linux}/sections/exception_stream.rs (93%)
rename src/{ => linux}/sections/mappings.rs (84%)
rename src/{ => linux}/sections/memory_list_stream.rs (69%)
rename src/{ => linux}/sections/systeminfo_stream.rs (63%)
rename src/{ => linux}/sections/thread_list_stream.rs (93%)
rename src/{ => linux}/sections/thread_names_stream.rs (70%)
rename src/{thread_info/mod.rs => linux/thread_info.rs} (86%)
rename src/{thread_info/thread_info_aarch64.rs => linux/thread_info/aarch64.rs} (100%)
rename src/{thread_info/thread_info_arm.rs => linux/thread_info/arm.rs} (100%)
rename src/{thread_info/thread_info_mips.rs => linux/thread_info/mips.rs} (100%)
rename src/{thread_info/thread_info_x86.rs => linux/thread_info/x86.rs} (100%)
create mode 100644 src/minidump_cpu.rs
rename src/minidump_cpu/{minidump_cpu_aarch64.rs => aarch64.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_amd64.rs => amd64.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_arm.rs => arm.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_mips.rs => mips.rs} (100%)
delete mode 100644 src/minidump_cpu/mod.rs
rename src/minidump_cpu/{minidump_cpu_ppc.rs => ppc.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_ppc64.rs => ppc64.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_sparc.rs => sparc.rs} (100%)
rename src/minidump_cpu/{minidump_cpu_x86.rs => x86.rs} (100%)
diff --git a/Cargo.toml b/Cargo.toml
index d0a3966a..c243f519 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "minidump_writer_linux"
+name = "minidump-writer"
version = "0.1.0"
authors = ["Martin Sirringhaus"]
edition = "2021"
diff --git a/src/bin/test.rs b/src/bin/test.rs
index 7ae13dc8..bbfe2fe8 100644
--- a/src/bin/test.rs
+++ b/src/bin/test.rs
@@ -1,7 +1,9 @@
// 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 minidump_writer::{
+ ptrace_dumper::{PtraceDumper, AT_SYSINFO_EHDR},
+ LINUX_GATE_LIBRARY_NAME,
+};
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use nix::unistd::getppid;
use std::env;
@@ -23,13 +25,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
@@ -45,9 +47,9 @@ 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!(
@@ -55,7 +57,7 @@ fn test_copy_from_process(stack_var: usize, heap_var: usize) -> Result<()> {
"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(),
@@ -67,7 +69,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")?;
@@ -84,7 +86,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) {
@@ -101,7 +103,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()) {
@@ -119,13 +121,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()?;
@@ -138,7 +140,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;
diff --git a/src/lib.rs b/src/lib.rs
index 5c60acc8..de193a2e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,19 +1,12 @@
#![allow(unsafe_code)]
-#[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;
diff --git a/src/linux.rs b/src/linux.rs
new file mode 100644
index 00000000..3e9dde8a
--- /dev/null
+++ b/src/linux.rs
@@ -0,0 +1,15 @@
+#[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 maps_reader;
+pub mod minidump_writer;
+pub mod ptrace_dumper;
+mod sections;
+pub mod thread_info;
+
+pub use maps_reader::LINUX_GATE_LIBRARY_NAME;
diff --git a/src/android.rs b/src/linux/android.rs
similarity index 100%
rename from src/android.rs
rename to src/linux/android.rs
diff --git a/src/app_memory.rs b/src/linux/app_memory.rs
similarity index 100%
rename from src/app_memory.rs
rename to src/linux/app_memory.rs
diff --git a/src/auxv_reader.rs b/src/linux/auxv_reader.rs
similarity index 100%
rename from src/auxv_reader.rs
rename to src/linux/auxv_reader.rs
diff --git a/src/crash_context/crash_context_aarch64.rs b/src/linux/crash_context/crash_context_aarch64.rs
similarity index 100%
rename from src/crash_context/crash_context_aarch64.rs
rename to src/linux/crash_context/crash_context_aarch64.rs
diff --git a/src/crash_context/crash_context_arm.rs b/src/linux/crash_context/crash_context_arm.rs
similarity index 100%
rename from src/crash_context/crash_context_arm.rs
rename to src/linux/crash_context/crash_context_arm.rs
diff --git a/src/crash_context/crash_context_mips.rs b/src/linux/crash_context/crash_context_mips.rs
similarity index 100%
rename from src/crash_context/crash_context_mips.rs
rename to src/linux/crash_context/crash_context_mips.rs
diff --git a/src/crash_context/crash_context_x86.rs b/src/linux/crash_context/crash_context_x86.rs
similarity index 100%
rename from src/crash_context/crash_context_x86.rs
rename to src/linux/crash_context/crash_context_x86.rs
diff --git a/src/crash_context/crash_context_x86_64.rs b/src/linux/crash_context/crash_context_x86_64.rs
similarity index 100%
rename from src/crash_context/crash_context_x86_64.rs
rename to src/linux/crash_context/crash_context_x86_64.rs
diff --git a/src/crash_context/mod.rs b/src/linux/crash_context/mod.rs
similarity index 100%
rename from src/crash_context/mod.rs
rename to src/linux/crash_context/mod.rs
diff --git a/src/dso_debug.rs b/src/linux/dso_debug.rs
similarity index 92%
rename from src/dso_debug.rs
rename to src/linux/dso_debug.rs
index 781c34ab..d724cc04 100644
--- a/src/dso_debug.rs
+++ b/src/linux/dso_debug.rs
@@ -1,11 +1,13 @@
-use crate::auxv_reader::AuxvType;
-use crate::errors::SectionDsoDebugError;
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::minidump_format::*;
-use crate::sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter};
-use libc;
-use std::collections::HashMap;
-use std::io::Cursor;
+use crate::{
+ linux::{
+ auxv_reader::AuxvType,
+ errors::SectionDsoDebugError,
+ ptrace_dumper::PtraceDumper,
+ sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter},
+ },
+ minidump_format::*,
+};
+use std::{collections::HashMap, io::Cursor};
type Result = std::result::Result;
@@ -95,7 +97,7 @@ pub fn write_dso_debug_stream(
.get(&at_phdr)
.ok_or(SectionDsoDebugError::CouldNotFind("AT_PHDR in auxv"))? as usize;
- let ph = LinuxPtraceDumper::copy_from_process(
+ let ph = PtraceDumper::copy_from_process(
blamed_thread,
phdr as *mut libc::c_void,
SIZEOF_PHDR * phnum_max,
@@ -145,7 +147,7 @@ pub fn write_dso_debug_stream(
// DSOs loaded into the program. If this information is indeed available,
// dump it to a MD_LINUX_DSO_DEBUG stream.
loop {
- let dyn_data = LinuxPtraceDumper::copy_from_process(
+ let dyn_data = PtraceDumper::copy_from_process(
blamed_thread,
(dyn_addr as usize + dynamic_length) as *mut libc::c_void,
dyn_size,
@@ -178,7 +180,7 @@ pub fn write_dso_debug_stream(
// See for a more detailed discussion of the how the dynamic
// loader communicates with debuggers.
- let debug_entry_data = LinuxPtraceDumper::copy_from_process(
+ let debug_entry_data = PtraceDumper::copy_from_process(
blamed_thread,
r_debug as *mut libc::c_void,
std::mem::size_of::(),
@@ -193,7 +195,7 @@ pub fn write_dso_debug_stream(
let mut dso_vec = Vec::new();
let mut curr_map = debug_entry.r_map;
while curr_map != 0 {
- let link_map_data = LinuxPtraceDumper::copy_from_process(
+ let link_map_data = PtraceDumper::copy_from_process(
blamed_thread,
curr_map as *mut libc::c_void,
std::mem::size_of::(),
@@ -219,7 +221,7 @@ pub fn write_dso_debug_stream(
for (idx, map) in dso_vec.iter().enumerate() {
let mut filename = String::new();
if map.l_name > 0 {
- let filename_data = LinuxPtraceDumper::copy_from_process(
+ let filename_data = PtraceDumper::copy_from_process(
blamed_thread,
map.l_name as *mut libc::c_void,
256,
@@ -258,7 +260,7 @@ pub fn write_dso_debug_stream(
};
dirent.location.data_size += dynamic_length as u32;
- let dso_debug_data = LinuxPtraceDumper::copy_from_process(
+ let dso_debug_data = PtraceDumper::copy_from_process(
blamed_thread,
dyn_addr as *mut libc::c_void,
dynamic_length,
diff --git a/src/dumper_cpu_info/mod.rs b/src/linux/dumper_cpu_info.rs
similarity index 57%
rename from src/dumper_cpu_info/mod.rs
rename to src/linux/dumper_cpu_info.rs
index 248ae4c2..80902b62 100644
--- a/src/dumper_cpu_info/mod.rs
+++ b/src/linux/dumper_cpu_info.rs
@@ -1,20 +1,30 @@
-#[cfg(any(
- target_arch = "x86_64",
- target_arch = "x86",
- target_arch = "mips",
- target_arch = "mips64"
-))]
-#[path = "cpu_info_x86_mips.rs"]
-pub mod imp;
-#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
-#[path = "cpu_info_arm.rs"]
-pub mod imp;
+cfg_if::cfg_if! {
+ if #[cfg(any(
+ target_arch = "x86_64",
+ target_arch = "x86",
+ target_arch = "mips",
+ target_arch = "mips64"
+ ))]
+ {
+ pub mod x86_mips;
+ pub use x86_mips as imp;
+ } else if #[cfg(any(
+ target_arch = "arm",
+ target_arch = "aarch64",
+ ))]
+ {
+ pub mod arm;
+ pub use arm as imp;
+ }
+}
pub use imp::write_cpu_information;
-use crate::errors::MemoryWriterError;
-use crate::minidump_format::{MDOSPlatform, MDRawSystemInfo};
-use crate::sections::write_string_to_location;
+use crate::{
+ errors::MemoryWriterError,
+ linux::sections::write_string_to_location,
+ minidump_format::{MDOSPlatform, MDRawSystemInfo},
+};
use nix::sys::utsname::uname;
use std::io::Cursor;
diff --git a/src/dumper_cpu_info/cpu_info_arm.rs b/src/linux/dumper_cpu_info/arm.rs
similarity index 100%
rename from src/dumper_cpu_info/cpu_info_arm.rs
rename to src/linux/dumper_cpu_info/arm.rs
diff --git a/src/dumper_cpu_info/cpu_info_x86_mips.rs b/src/linux/dumper_cpu_info/x86_mips.rs
similarity index 100%
rename from src/dumper_cpu_info/cpu_info_x86_mips.rs
rename to src/linux/dumper_cpu_info/x86_mips.rs
diff --git a/src/errors.rs b/src/linux/errors.rs
similarity index 98%
rename from src/errors.rs
rename to src/linux/errors.rs
index 4a540916..e35e10b0 100644
--- a/src/errors.rs
+++ b/src/linux/errors.rs
@@ -1,6 +1,4 @@
-use crate::maps_reader::MappingInfo;
-use crate::thread_info::Pid;
-use goblin;
+use crate::{maps_reader::MappingInfo, thread_info::Pid};
use thiserror::Error;
#[derive(Debug, Error)]
@@ -11,6 +9,7 @@ pub enum InitError {
NoAuxvEntryFound(Pid),
#[error("crash thread does not reference principal mapping")]
PrincipalMappingNotReferenced,
+ #[cfg(target_os = "android")]
#[error("Failed Android specific late init")]
AndroidLateInitError(#[from] AndroidError),
}
@@ -78,6 +77,7 @@ pub enum ThreadInfoError {
InvalidProcStatusFile(Pid, String),
}
+#[cfg(target_os = "android")]
#[derive(Debug, Error)]
pub enum AndroidError {
#[error("Failed to copy memory from process")]
diff --git a/src/maps_reader.rs b/src/linux/maps_reader.rs
similarity index 98%
rename from src/maps_reader.rs
rename to src/linux/maps_reader.rs
index f81f67de..99bfe6a1 100644
--- a/src/maps_reader.rs
+++ b/src/linux/maps_reader.rs
@@ -1,12 +1,8 @@
-use crate::auxv_reader::AuxvType;
-use crate::errors::MapsReaderError;
-use crate::thread_info::Pid;
+use crate::linux::{auxv_reader::AuxvType, errors::MapsReaderError, thread_info::Pid};
use byteorder::{NativeEndian, ReadBytesExt};
use goblin::elf;
use memmap2::{Mmap, MmapOptions};
-use std::fs::File;
-use std::mem::size_of;
-use std::path::PathBuf;
+use std::{fs::File, mem::size_of, path::PathBuf};
pub const LINUX_GATE_LIBRARY_NAME: &str = "linux-gate.so";
pub const DELETED_SUFFIX: &str = " (deleted)";
@@ -57,6 +53,7 @@ pub enum MappingInfoParsingResult {
Success(MappingInfo),
}
+#[inline]
fn is_mapping_a_path(pathname: Option<&str>) -> bool {
match pathname {
Some(x) => x.contains('/'),
@@ -300,7 +297,6 @@ impl MappingInfo {
pub fn get_mapping_effective_name_and_path(&self) -> Result<(String, String)> {
let mut file_path = self.name.clone().unwrap_or_default();
- let file_name;
// Tools such as minidump_stackwalk use the name of the module to look up
// symbols produced by dump_syms. dump_syms will prefer to use a module's
@@ -313,8 +309,7 @@ impl MappingInfo {
Err(_) => {
// file_path := /path/to/libname.so
// file_name := libname.so
- let split: Vec<_> = file_path.rsplitn(2, '/').collect();
- file_name = split.first().unwrap().to_string();
+ let file_name = file_path.rsplitn(2, '/').next().unwrap().to_owned();
return Ok((file_path, file_name));
}
};
diff --git a/src/minidump_writer.rs b/src/linux/minidump_writer.rs
similarity index 96%
rename from src/minidump_writer.rs
rename to src/linux/minidump_writer.rs
index b9805470..d83dd20a 100644
--- a/src/minidump_writer.rs
+++ b/src/linux/minidump_writer.rs
@@ -1,13 +1,15 @@
use crate::{
- app_memory::AppMemoryList,
- crash_context::{CpuContext, CrashContext},
- dso_debug,
- errors::{FileWriterError, InitError, MemoryWriterError, WriterError},
- linux_ptrace_dumper::LinuxPtraceDumper,
- maps_reader::{MappingInfo, MappingList},
+ linux::{
+ app_memory::AppMemoryList,
+ crash_context::{CpuContext, CrashContext},
+ dso_debug,
+ errors::{FileWriterError, InitError, MemoryWriterError, WriterError},
+ maps_reader::{MappingInfo, MappingList},
+ ptrace_dumper::PtraceDumper,
+ sections::*,
+ thread_info::Pid,
+ },
minidump_format::*,
- sections::*,
- thread_info::Pid,
};
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
@@ -185,7 +187,7 @@ impl MinidumpWriter {
/// Generates a minidump and writes to the destination provided. Returns the in-memory
/// version of the minidump as well.
pub fn dump(&mut self, destination: &mut (impl Write + Seek)) -> Result> {
- let mut dumper = LinuxPtraceDumper::new(self.process_id)?;
+ let mut dumper = PtraceDumper::new(self.process_id)?;
dumper.suspend_threads()?;
dumper.late_init()?;
@@ -209,7 +211,7 @@ impl MinidumpWriter {
Ok(buffer.into_inner())
}
- fn crash_thread_references_principal_mapping(&self, dumper: &LinuxPtraceDumper) -> bool {
+ fn crash_thread_references_principal_mapping(&self, dumper: &PtraceDumper) -> bool {
if self.crash_context.is_none() || self.principal_mapping.is_none() {
return false;
}
@@ -244,7 +246,7 @@ impl MinidumpWriter {
return false;
}
};
- let stack_copy = match LinuxPtraceDumper::copy_from_process(
+ let stack_copy = match PtraceDumper::copy_from_process(
self.blamed_thread,
stack_ptr as *mut libc::c_void,
stack_len,
@@ -265,7 +267,7 @@ impl MinidumpWriter {
fn generate_dump(
&mut self,
buffer: &mut DumpBuf,
- dumper: &mut LinuxPtraceDumper,
+ dumper: &mut PtraceDumper,
destination: &mut (impl Write + Seek),
) -> Result<()> {
// A minidump file contains a number of tagged streams. This is the number
diff --git a/src/linux_ptrace_dumper.rs b/src/linux/ptrace_dumper.rs
similarity index 98%
rename from src/linux_ptrace_dumper.rs
rename to src/linux/ptrace_dumper.rs
index 0b5c4242..a33d023a 100644
--- a/src/linux_ptrace_dumper.rs
+++ b/src/linux/ptrace_dumper.rs
@@ -1,13 +1,15 @@
// use libc::c_void;
#[cfg(target_os = "android")]
-use crate::android::late_process_mappings;
+use crate::linux::android::late_process_mappings;
use crate::{
- auxv_reader::{AuxvType, ProcfsAuxvIter},
- errors::{DumperError, InitError, ThreadInfoError},
- maps_reader::{MappingInfo, MappingInfoParsingResult, DELETED_SUFFIX},
+ linux::{
+ auxv_reader::{AuxvType, ProcfsAuxvIter},
+ errors::{DumperError, InitError, ThreadInfoError},
+ maps_reader::{MappingInfo, MappingInfoParsingResult, DELETED_SUFFIX},
+ thread_info::{Pid, ThreadInfo},
+ LINUX_GATE_LIBRARY_NAME,
+ },
minidump_format::MDGUID,
- thread_info::{Pid, ThreadInfo},
- LINUX_GATE_LIBRARY_NAME,
};
use goblin::elf;
use nix::sys::{ptrace, wait};
@@ -26,7 +28,7 @@ pub struct Thread {
}
#[derive(Debug)]
-pub struct LinuxPtraceDumper {
+pub struct PtraceDumper {
pub pid: Pid,
threads_suspended: bool,
pub threads: Vec,
@@ -39,18 +41,18 @@ pub const AT_SYSINFO_EHDR: u32 = 33;
#[cfg(target_pointer_width = "64")]
pub const AT_SYSINFO_EHDR: u64 = 33;
-impl Drop for LinuxPtraceDumper {
+impl Drop for PtraceDumper {
fn drop(&mut self) {
// Always try to resume all threads (e.g. in case of error)
let _ = self.resume_threads();
}
}
-impl LinuxPtraceDumper {
+impl PtraceDumper {
/// Constructs a dumper for extracting information of a given process
/// with a process ID of |pid|.
pub fn new(pid: Pid) -> Result {
- let mut dumper = LinuxPtraceDumper {
+ let mut dumper = Self {
pid,
threads_suspended: false,
threads: Vec::new(),
diff --git a/src/sections/mod.rs b/src/linux/sections.rs
similarity index 97%
rename from src/sections/mod.rs
rename to src/linux/sections.rs
index 7d56d7be..9e29c96b 100644
--- a/src/sections/mod.rs
+++ b/src/linux/sections.rs
@@ -6,8 +6,14 @@ pub mod systeminfo_stream;
pub mod thread_list_stream;
pub mod thread_names_stream;
-use crate::errors::MemoryWriterError;
-use crate::minidump_format::*;
+use crate::{
+ errors::{self, MemoryWriterError},
+ linux::{
+ minidump_writer::{self, DumpBuf, MinidumpWriter},
+ ptrace_dumper::PtraceDumper,
+ },
+ minidump_format::*,
+};
use std::io::{Cursor, Write};
type Result = std::result::Result;
diff --git a/src/sections/app_memory.rs b/src/linux/sections/app_memory.rs
similarity index 54%
rename from src/sections/app_memory.rs
rename to src/linux/sections/app_memory.rs
index cbc28ba2..36efcd4a 100644
--- a/src/sections/app_memory.rs
+++ b/src/linux/sections/app_memory.rs
@@ -1,15 +1,12 @@
-use crate::errors::SectionAppMemoryError;
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::minidump_format::*;
-use crate::minidump_writer::{DumpBuf, MinidumpWriter};
-use crate::sections::MemoryArrayWriter;
-
-type Result = std::result::Result;
+use super::*;
/// Write application-provided memory regions.
-pub fn write(config: &mut MinidumpWriter, buffer: &mut DumpBuf) -> Result<()> {
+pub fn write(
+ config: &mut MinidumpWriter,
+ buffer: &mut DumpBuf,
+) -> std::result::Result<(), crate::linux::errors::SectionAppMemoryError> {
for app_memory in &config.app_memory {
- let data_copy = LinuxPtraceDumper::copy_from_process(
+ let data_copy = PtraceDumper::copy_from_process(
config.blamed_thread,
app_memory.ptr as *mut libc::c_void,
app_memory.length,
diff --git a/src/sections/exception_stream.rs b/src/linux/sections/exception_stream.rs
similarity index 93%
rename from src/sections/exception_stream.rs
rename to src/linux/sections/exception_stream.rs
index d3c49ece..0e912ec3 100644
--- a/src/sections/exception_stream.rs
+++ b/src/linux/sections/exception_stream.rs
@@ -1,9 +1,5 @@
-use crate::errors::SectionExceptionStreamError;
-use crate::minidump_format::*;
-use crate::minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter};
-use crate::sections::MemoryWriter;
-
-type Result = std::result::Result;
+use super::*;
+use minidump_writer::CrashingThreadContext;
#[allow(non_camel_case_types, unused)]
#[repr(u32)]
@@ -45,7 +41,10 @@ enum MDExceptionCodeLinux {
dump requested. */
}
-pub fn write(config: &mut MinidumpWriter, buffer: &mut DumpBuf) -> Result {
+pub fn write(
+ config: &mut MinidumpWriter,
+ buffer: &mut DumpBuf,
+) -> std::result::Result {
let exception = if let Some(context) = &config.crash_context {
let sig_addr;
#[cfg(target_arch = "arm")]
diff --git a/src/sections/mappings.rs b/src/linux/sections/mappings.rs
similarity index 84%
rename from src/sections/mappings.rs
rename to src/linux/sections/mappings.rs
index d95741d0..42dde91e 100644
--- a/src/sections/mappings.rs
+++ b/src/linux/sections/mappings.rs
@@ -1,11 +1,14 @@
-use crate::errors::SectionMappingsError;
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::maps_reader::MappingInfo;
-use crate::minidump_format::*;
-use crate::minidump_writer::{DumpBuf, MinidumpWriter};
-use crate::sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter};
+use super::*;
+use crate::linux::maps_reader::MappingInfo;
-type Result = std::result::Result;
+// use crate::errors::SectionMappingsError;
+// use crate::linux_ptrace_dumper::LinuxPtraceDumper;
+// use crate::maps_reader::MappingInfo;
+// use crate::minidump_format::*;
+// use crate::minidump_writer::{DumpBuf, MinidumpWriter};
+// use crate::sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter};
+
+type Result = std::result::Result;
/// Write information about the mappings in effect. Because we are using the
/// minidump format, the information about the mappings is pretty limited.
@@ -14,7 +17,7 @@ type Result = std::result::Result;
pub fn write(
config: &mut MinidumpWriter,
buffer: &mut DumpBuf,
- dumper: &mut LinuxPtraceDumper,
+ dumper: &mut PtraceDumper,
) -> Result {
let mut modules = Vec::new();
@@ -92,7 +95,7 @@ fn fill_raw_module(
let (file_path, _) = mapping
.get_mapping_effective_name_and_path()
- .map_err(|e| SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
+ .map_err(|e| errors::SectionMappingsError::GetEffectivePathError(mapping.clone(), e))?;
let name_header = write_string_to_location(buffer, &file_path)?;
Ok(MDRawModule {
diff --git a/src/sections/memory_list_stream.rs b/src/linux/sections/memory_list_stream.rs
similarity index 69%
rename from src/sections/memory_list_stream.rs
rename to src/linux/sections/memory_list_stream.rs
index 4f090831..572049ea 100644
--- a/src/sections/memory_list_stream.rs
+++ b/src/linux/sections/memory_list_stream.rs
@@ -1,9 +1,6 @@
-use crate::errors::SectionMemListError;
-use crate::minidump_format::*;
-use crate::minidump_writer::{DumpBuf, MinidumpWriter};
-use crate::sections::{MemoryArrayWriter, MemoryWriter};
+use super::*;
-type Result = std::result::Result;
+type Result = std::result::Result;
pub fn write(config: &mut MinidumpWriter, buffer: &mut DumpBuf) -> Result {
let list_header =
diff --git a/src/sections/systeminfo_stream.rs b/src/linux/sections/systeminfo_stream.rs
similarity index 63%
rename from src/sections/systeminfo_stream.rs
rename to src/linux/sections/systeminfo_stream.rs
index dabd7793..18af398d 100644
--- a/src/sections/systeminfo_stream.rs
+++ b/src/linux/sections/systeminfo_stream.rs
@@ -1,10 +1,7 @@
-use crate::dumper_cpu_info::{write_cpu_information, write_os_information};
-use crate::errors::SectionSystemInfoError;
-use crate::minidump_format::*;
-use crate::minidump_writer::DumpBuf;
-use crate::sections::MemoryWriter;
+use super::*;
+use crate::linux::dumper_cpu_info::{write_cpu_information, write_os_information};
-type Result = std::result::Result;
+type Result = std::result::Result;
pub fn write(buffer: &mut DumpBuf) -> Result {
let mut info_section = MemoryWriter::::alloc(buffer)?;
diff --git a/src/sections/thread_list_stream.rs b/src/linux/sections/thread_list_stream.rs
similarity index 93%
rename from src/sections/thread_list_stream.rs
rename to src/linux/sections/thread_list_stream.rs
index f4cb3c07..a5646723 100644
--- a/src/sections/thread_list_stream.rs
+++ b/src/linux/sections/thread_list_stream.rs
@@ -1,15 +1,20 @@
+// use crate::{
+// crash_context::CpuContext,
+// errors::SectionThreadListError,
+// linux_ptrace_dumper::LinuxPtraceDumper,
+// minidump_cpu::RawContextCPU,
+// minidump_format::*,
+// minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter},
+// sections::{MemoryArrayWriter, MemoryWriter},
+// };
+use super::*;
use crate::{
- crash_context::CpuContext,
- errors::SectionThreadListError,
- linux_ptrace_dumper::LinuxPtraceDumper,
- minidump_cpu::RawContextCPU,
- minidump_format::*,
- minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter},
- sections::{MemoryArrayWriter, MemoryWriter},
+ linux::crash_context::CpuContext, minidump_cpu::RawContextCPU,
+ minidump_writer::CrashingThreadContext,
};
use std::io::Write;
-type Result = std::result::Result;
+type Result = std::result::Result;
// The following kLimit* constants are for when minidump_size_limit_ is set
// and the minidump size might exceed it.
@@ -36,7 +41,7 @@ enum MaxStackLen {
pub fn write(
config: &mut MinidumpWriter,
buffer: &mut DumpBuf,
- dumper: &LinuxPtraceDumper,
+ dumper: &PtraceDumper,
) -> Result {
let num_threads = dumper.threads.len();
// Memory looks like this:
@@ -118,7 +123,7 @@ pub fn write(
ip_memory_d.memory.data_size =
(end_of_range - ip_memory_d.start_of_memory_range) as u32;
- let memory_copy = LinuxPtraceDumper::copy_from_process(
+ let memory_copy = PtraceDumper::copy_from_process(
thread.thread_id as i32,
ip_memory_d.start_of_memory_range as *mut libc::c_void,
ip_memory_d.memory.data_size as usize,
@@ -180,7 +185,7 @@ pub fn write(
fn fill_thread_stack(
config: &mut MinidumpWriter,
buffer: &mut DumpBuf,
- dumper: &LinuxPtraceDumper,
+ dumper: &PtraceDumper,
thread: &mut MDRawThread,
instruction_ptr: usize,
stack_ptr: usize,
@@ -205,7 +210,7 @@ fn fill_thread_stack(
}
}
- let mut stack_bytes = LinuxPtraceDumper::copy_from_process(
+ let mut stack_bytes = PtraceDumper::copy_from_process(
thread.thread_id.try_into()?,
stack as *mut libc::c_void,
stack_len,
diff --git a/src/sections/thread_names_stream.rs b/src/linux/sections/thread_names_stream.rs
similarity index 70%
rename from src/sections/thread_names_stream.rs
rename to src/linux/sections/thread_names_stream.rs
index 9a5526dc..51b23435 100644
--- a/src/sections/thread_names_stream.rs
+++ b/src/linux/sections/thread_names_stream.rs
@@ -1,13 +1,8 @@
-use crate::errors::SectionThreadNamesError;
-use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-use crate::minidump_format::*;
-use crate::minidump_writer::DumpBuf;
-use crate::sections::write_string_to_location;
-use crate::sections::{MemoryArrayWriter, MemoryWriter};
+use super::*;
-type Result = std::result::Result;
+type Result = std::result::Result;
-pub fn write(buffer: &mut DumpBuf, dumper: &LinuxPtraceDumper) -> Result {
+pub fn write(buffer: &mut DumpBuf, dumper: &PtraceDumper) -> Result {
// Only count threads that have a name
let num_threads = dumper.threads.iter().filter(|t| t.name.is_some()).count();
// Memory looks like this:
diff --git a/src/thread_info/mod.rs b/src/linux/thread_info.rs
similarity index 86%
rename from src/thread_info/mod.rs
rename to src/linux/thread_info.rs
index 60f4d328..79cedbbd 100644
--- a/src/thread_info/mod.rs
+++ b/src/linux/thread_info.rs
@@ -1,35 +1,29 @@
use crate::errors::ThreadInfoError;
-use nix::errno::Errno;
-use nix::sys::ptrace;
-use nix::unistd;
-use std::io::{self, BufRead};
-use std::path;
+use nix::{errno::Errno, sys::ptrace, unistd};
+use std::{
+ io::{self, BufRead},
+ path,
+};
type Result = std::result::Result;
pub type Pid = i32;
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-#[path = "thread_info_x86.rs"]
-mod imp;
-#[cfg(target_arch = "arm")]
-#[path = "thread_info_arm.rs"]
-mod imp;
-#[cfg(target_arch = "aarch64")]
-#[path = "thread_info_aarch64.rs"]
-mod imp;
-#[cfg(target_arch = "mips")]
-#[path = "thread_info_mips.rs"]
-mod imp;
-
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-pub type ThreadInfo = imp::ThreadInfoX86;
-#[cfg(target_arch = "arm")]
-pub type ThreadInfo = imp::ThreadInfoArm;
-#[cfg(target_arch = "aarch64")]
-pub type ThreadInfo = imp::ThreadInfoAarch64;
-#[cfg(target_arch = "mips")]
-pub type ThreadInfo = imp::ThreadInfoMips;
+cfg_if::cfg_if! {
+ if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
+ mod x86;
+ pub type ThreadInfo = x86::ThreadInfoX86;
+ } else if #[cfg(target_arch = "arm")] {
+ mod arm;
+ pub type ThreadInfo = arm::ThreadInfoArm;
+ } else if #[cfg(target_arch = "aarch64")] {
+ mod aarch64;
+ pub type ThreadInfo = aarch64::ThreadInfoAarch64;
+ } else if #[cfg(target_arch = "mips")] {
+ mod mips;
+ pub type ThreadInfo = mips::ThreadInfoMips;
+ }
+}
#[derive(Debug)]
#[allow(non_camel_case_types)]
diff --git a/src/thread_info/thread_info_aarch64.rs b/src/linux/thread_info/aarch64.rs
similarity index 100%
rename from src/thread_info/thread_info_aarch64.rs
rename to src/linux/thread_info/aarch64.rs
diff --git a/src/thread_info/thread_info_arm.rs b/src/linux/thread_info/arm.rs
similarity index 100%
rename from src/thread_info/thread_info_arm.rs
rename to src/linux/thread_info/arm.rs
diff --git a/src/thread_info/thread_info_mips.rs b/src/linux/thread_info/mips.rs
similarity index 100%
rename from src/thread_info/thread_info_mips.rs
rename to src/linux/thread_info/mips.rs
diff --git a/src/thread_info/thread_info_x86.rs b/src/linux/thread_info/x86.rs
similarity index 100%
rename from src/thread_info/thread_info_x86.rs
rename to src/linux/thread_info/x86.rs
diff --git a/src/minidump_cpu.rs b/src/minidump_cpu.rs
new file mode 100644
index 00000000..104553eb
--- /dev/null
+++ b/src/minidump_cpu.rs
@@ -0,0 +1,25 @@
+cfg_if::cfg_if! {
+ if #[cfg(target_arch = "x86_64")] {
+ pub mod amd64;
+ pub use amd64 as imp;
+ pub type RawContextCPU = amd64::MDRawContextAMD64;
+ } else if #[cfg(target_arch = "x86")] {
+ pub mod x86;
+ pub use x86 as imp;
+ pub type RawContextCPU = amd64::MDRawContextX86;
+ } else if #[cfg(target_arch = "arm")] {
+ pub mod arm;
+ pub use arm as imp;
+ pub type RawContextCPU = arm::MDRawContextARM;
+ } else if #[cfg(target_arch = "aarch64")] {
+ pub mod aarch64;
+ pub use aarch64 as imp;
+
+ compile_error!("flesh me out");
+ //pub type RawContextCPU = aarch64::MDRawContextX86;
+ } else if #[cfg(target_arch = "mips")] {
+ compile_error!("flesh me out");
+ } else {
+ compile_error!("unsupported target architecture");
+ }
+}
diff --git a/src/minidump_cpu/minidump_cpu_aarch64.rs b/src/minidump_cpu/aarch64.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_aarch64.rs
rename to src/minidump_cpu/aarch64.rs
diff --git a/src/minidump_cpu/minidump_cpu_amd64.rs b/src/minidump_cpu/amd64.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_amd64.rs
rename to src/minidump_cpu/amd64.rs
diff --git a/src/minidump_cpu/minidump_cpu_arm.rs b/src/minidump_cpu/arm.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_arm.rs
rename to src/minidump_cpu/arm.rs
diff --git a/src/minidump_cpu/minidump_cpu_mips.rs b/src/minidump_cpu/mips.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_mips.rs
rename to src/minidump_cpu/mips.rs
diff --git a/src/minidump_cpu/mod.rs b/src/minidump_cpu/mod.rs
deleted file mode 100644
index ebce0ad5..00000000
--- a/src/minidump_cpu/mod.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#[cfg(target_arch = "x86_64")]
-#[path = "minidump_cpu_amd64.rs"]
-pub mod imp;
-#[cfg(target_arch = "x86")]
-#[path = "minidump_cpu_x86.rs"]
-pub mod imp;
-#[cfg(target_arch = "arm")]
-#[path = "minidump_cpu_arm.rs"]
-pub mod imp;
-#[cfg(target_arch = "aarch64")]
-#[path = "minidump_cpu_aarch64.rs"]
-pub mod imp;
-#[cfg(target_arch = "mips")]
-#[path = "minidump_cpu_mips.rs"]
-pub mod imp;
-
-#[cfg(target_arch = "x86_64")]
-pub type RawContextCPU = imp::MDRawContextAMD64;
-#[cfg(target_arch = "x86")]
-pub type RawContextCPU = imp::MDRawContextX86;
-#[cfg(target_arch = "arm")]
-pub type RawContextCPU = imp::MDRawContextARM;
-#[cfg(target_arch = "aarch64")]
-pub type RawContextCPU = imp::MDRawContextX86;
-#[cfg(target_arch = "mips")]
-pub type RawContextCPU = i32;
diff --git a/src/minidump_cpu/minidump_cpu_ppc.rs b/src/minidump_cpu/ppc.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_ppc.rs
rename to src/minidump_cpu/ppc.rs
diff --git a/src/minidump_cpu/minidump_cpu_ppc64.rs b/src/minidump_cpu/ppc64.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_ppc64.rs
rename to src/minidump_cpu/ppc64.rs
diff --git a/src/minidump_cpu/minidump_cpu_sparc.rs b/src/minidump_cpu/sparc.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_sparc.rs
rename to src/minidump_cpu/sparc.rs
diff --git a/src/minidump_cpu/minidump_cpu_x86.rs b/src/minidump_cpu/x86.rs
similarity index 100%
rename from src/minidump_cpu/minidump_cpu_x86.rs
rename to src/minidump_cpu/x86.rs
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index 9cfc37e4..a235ae85 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -1,12 +1,12 @@
use minidump::*;
use minidump_common::format::{GUID, MINIDUMP_STREAM_TYPE::*};
-use minidump_writer_linux::{
+use minidump_writer::{
app_memory::AppMemory,
crash_context::CrashContext,
errors::*,
- linux_ptrace_dumper::LinuxPtraceDumper,
maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo},
minidump_writer::MinidumpWriter,
+ ptrace_dumper::PtraceDumper,
thread_info::Pid,
};
use nix::{errno::Errno, sys::signal::Signal};
@@ -448,7 +448,7 @@ fn test_with_deleted_binary() {
let pid = child.id() as i32;
- let build_id = LinuxPtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
+ let build_id = PtraceDumper::elf_file_identifier_from_mapped_file(&mem_slice)
.expect("Failed to get build_id");
let guid = GUID {
diff --git a/tests/ptrace_dumper.rs b/tests/ptrace_dumper.rs
index d2002686..8d6fb648 100644
--- a/tests/ptrace_dumper.rs
+++ b/tests/ptrace_dumper.rs
@@ -1,4 +1,4 @@
-use minidump_writer_linux::linux_ptrace_dumper;
+use minidump_writer::ptrace_dumper;
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use nix::sys::signal::Signal;
use std::io::{BufRead, BufReader};
@@ -25,8 +25,7 @@ fn test_thread_list_from_parent() {
let num_of_threads = 5;
let mut child = start_child_and_wait_for_threads(num_of_threads);
let pid = child.id() as i32;
- let mut dumper =
- linux_ptrace_dumper::LinuxPtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = ptrace_dumper::PtraceDumper::new(pid).expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
@@ -195,8 +194,7 @@ fn test_sanitize_stack_copy() {
let heap_addr = usize::from_str_radix(output.next().unwrap().trim_start_matches("0x"), 16)
.expect("unable to parse mmap_addr");
- let mut dumper =
- linux_ptrace_dumper::LinuxPtraceDumper::new(pid).expect("Couldn't init dumper");
+ let mut dumper = ptrace_dumper::PtraceDumper::new(pid).expect("Couldn't init dumper");
assert_eq!(dumper.threads.len(), num_of_threads);
dumper.suspend_threads().expect("Could not suspend threads");
let thread_info = dumper
From 7695c64b59e1d99f2ce1840586a6c43f79e0af2b Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Fri, 19 Nov 2021 06:41:45 +0100
Subject: [PATCH 08/21] Fixup crash_context
---
.../mod.rs => crash_context.rs} | 25 ++++---------------
.../{crash_context_aarch64.rs => aarch64.rs} | 0
.../{crash_context_arm.rs => arm.rs} | 0
.../{crash_context_mips.rs => mips.rs} | 0
.../{crash_context_x86.rs => x86.rs} | 0
.../{crash_context_x86_64.rs => x86_64.rs} | 0
6 files changed, 5 insertions(+), 20 deletions(-)
rename src/linux/{crash_context/mod.rs => crash_context.rs} (52%)
rename src/linux/crash_context/{crash_context_aarch64.rs => aarch64.rs} (100%)
rename src/linux/crash_context/{crash_context_arm.rs => arm.rs} (100%)
rename src/linux/crash_context/{crash_context_mips.rs => mips.rs} (100%)
rename src/linux/crash_context/{crash_context_x86.rs => x86.rs} (100%)
rename src/linux/crash_context/{crash_context_x86_64.rs => x86_64.rs} (100%)
diff --git a/src/linux/crash_context/mod.rs b/src/linux/crash_context.rs
similarity index 52%
rename from src/linux/crash_context/mod.rs
rename to src/linux/crash_context.rs
index 2dc37c08..8e68574b 100644
--- a/src/linux/crash_context/mod.rs
+++ b/src/linux/crash_context.rs
@@ -4,34 +4,19 @@
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
- mod crash_context_x86_64;
+ mod x86_64;
} else if #[cfg(target_arch = "x86")] {
- mod crash_context_x86;
+ mod x86;
} else if #[cfg(target_arch = "aarch64")] {
- mod crash_context_aarch64;
+ mod aarch64;
} else if #[cfg(target_arch = "arm")] {
- mod crash_context_arm;
+ mod arm;
} else if #[cfg(target_arch = "mips")] {
- mod crash_context_mips;
+ mod mips;
}
}
use crate::minidump_cpu::RawContextCPU;
-
-// #[cfg(target_arch = "aarch64")]
-// pub type fpstate_t = libc::fpsimd_context; // Currently not part of libc! This will produce an error.
-// #[cfg(not(any(
-// target_arch = "aarch64",
-// target_arch = "mips",
-// target_arch = "arm-eabi"
-// )))]
-// #[cfg(target_arch = "x86")]
-// #[allow(non_camel_case_types)]
-// pub type fpstate_t = libc::_libc_fpstate;
-// #[cfg(target_arch = "x86_64")]
-// #[allow(non_camel_case_types)]
-// pub type fpstate_t = libc::user_fpregs_struct;
-
pub use exception_handler::CrashContext;
pub trait CpuContext {
diff --git a/src/linux/crash_context/crash_context_aarch64.rs b/src/linux/crash_context/aarch64.rs
similarity index 100%
rename from src/linux/crash_context/crash_context_aarch64.rs
rename to src/linux/crash_context/aarch64.rs
diff --git a/src/linux/crash_context/crash_context_arm.rs b/src/linux/crash_context/arm.rs
similarity index 100%
rename from src/linux/crash_context/crash_context_arm.rs
rename to src/linux/crash_context/arm.rs
diff --git a/src/linux/crash_context/crash_context_mips.rs b/src/linux/crash_context/mips.rs
similarity index 100%
rename from src/linux/crash_context/crash_context_mips.rs
rename to src/linux/crash_context/mips.rs
diff --git a/src/linux/crash_context/crash_context_x86.rs b/src/linux/crash_context/x86.rs
similarity index 100%
rename from src/linux/crash_context/crash_context_x86.rs
rename to src/linux/crash_context/x86.rs
diff --git a/src/linux/crash_context/crash_context_x86_64.rs b/src/linux/crash_context/x86_64.rs
similarity index 100%
rename from src/linux/crash_context/crash_context_x86_64.rs
rename to src/linux/crash_context/x86_64.rs
From 6cd9fcab11500632ec3a4e8c5d64326c8b47eac8 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 25 Nov 2021 17:52:07 +0100
Subject: [PATCH 09/21] Show result of attach
---
src/linux/ptrace_dumper.rs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/linux/ptrace_dumper.rs b/src/linux/ptrace_dumper.rs
index a33d023a..80546777 100644
--- a/src/linux/ptrace_dumper.rs
+++ b/src/linux/ptrace_dumper.rs
@@ -65,6 +65,8 @@ impl PtraceDumper {
// TODO: late_init for chromeos and android
pub fn init(&mut self) -> Result<(), InitError> {
+ unsafe { println!("UID: {} GID: {}", libc::getuid(), libc::getgid()) };
+
self.read_auxv()?;
self.enumerate_threads()?;
self.enumerate_mappings()?;
@@ -162,7 +164,8 @@ impl PtraceDumper {
// If the thread either disappeared before we could attach to it, or if
// it was part of the seccomp sandbox's trusted code, it is OK to
// silently drop it from the minidump.
- self.threads.retain(|x| Self::suspend_thread(x.tid).is_ok());
+ self.threads
+ .retain(|x| dbg!(Self::suspend_thread(x.tid)).is_ok());
if self.threads.is_empty() {
Err(DumperError::SuspendNoThreadsLeft)
From 2f70e45ee3cb57f6cb86de7eea4648cd042cef7d Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 9 Dec 2021 08:10:20 +0100
Subject: [PATCH 10/21] Revert debug code
---
src/linux/ptrace_dumper.rs | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/linux/ptrace_dumper.rs b/src/linux/ptrace_dumper.rs
index 80546777..a33d023a 100644
--- a/src/linux/ptrace_dumper.rs
+++ b/src/linux/ptrace_dumper.rs
@@ -65,8 +65,6 @@ impl PtraceDumper {
// TODO: late_init for chromeos and android
pub fn init(&mut self) -> Result<(), InitError> {
- unsafe { println!("UID: {} GID: {}", libc::getuid(), libc::getgid()) };
-
self.read_auxv()?;
self.enumerate_threads()?;
self.enumerate_mappings()?;
@@ -164,8 +162,7 @@ impl PtraceDumper {
// If the thread either disappeared before we could attach to it, or if
// it was part of the seccomp sandbox's trusted code, it is OK to
// silently drop it from the minidump.
- self.threads
- .retain(|x| dbg!(Self::suspend_thread(x.tid)).is_ok());
+ self.threads.retain(|x| Self::suspend_thread(x.tid).is_ok());
if self.threads.is_empty() {
Err(DumperError::SuspendNoThreadsLeft)
From 7e6f130a4a6a497c1d6ad823534bb726c232b6a9 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 9 Dec 2021 08:13:55 +0100
Subject: [PATCH 11/21] Remove commented out imports
---
src/linux/sections/mappings.rs | 7 -------
src/linux/sections/thread_list_stream.rs | 9 ---------
2 files changed, 16 deletions(-)
diff --git a/src/linux/sections/mappings.rs b/src/linux/sections/mappings.rs
index 42dde91e..d15be725 100644
--- a/src/linux/sections/mappings.rs
+++ b/src/linux/sections/mappings.rs
@@ -1,13 +1,6 @@
use super::*;
use crate::linux::maps_reader::MappingInfo;
-// use crate::errors::SectionMappingsError;
-// use crate::linux_ptrace_dumper::LinuxPtraceDumper;
-// use crate::maps_reader::MappingInfo;
-// use crate::minidump_format::*;
-// use crate::minidump_writer::{DumpBuf, MinidumpWriter};
-// use crate::sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter};
-
type Result = std::result::Result;
/// Write information about the mappings in effect. Because we are using the
diff --git a/src/linux/sections/thread_list_stream.rs b/src/linux/sections/thread_list_stream.rs
index a5646723..6d30e2c1 100644
--- a/src/linux/sections/thread_list_stream.rs
+++ b/src/linux/sections/thread_list_stream.rs
@@ -1,12 +1,3 @@
-// use crate::{
-// crash_context::CpuContext,
-// errors::SectionThreadListError,
-// linux_ptrace_dumper::LinuxPtraceDumper,
-// minidump_cpu::RawContextCPU,
-// minidump_format::*,
-// minidump_writer::{CrashingThreadContext, DumpBuf, MinidumpWriter},
-// sections::{MemoryArrayWriter, MemoryWriter},
-// };
use super::*;
use crate::{
linux::crash_context::CpuContext, minidump_cpu::RawContextCPU,
From 786bc1fc628d9b4229965d3a554066386d4ef49c Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 9 Dec 2021 09:37:22 +0100
Subject: [PATCH 12/21] Prep for submodule
---
Cargo.toml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index c243f519..663761f6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT"
[dependencies]
byteorder = "1.3.2"
cfg-if = "1.0"
-exception-handler = { path = "../crash-handling/exception-handler" }
+exception-handler = { path = "../exception-handler" }
goblin = "0.4"
libc = "0.2.74"
memmap2 = "0.5"
@@ -16,8 +16,8 @@ memoffset = "0.6"
nix = "0.23"
tempfile = "3.1.0"
thiserror = "1.0.21"
-uctx = { path = "../crash-handling/uctx" }
[dev-dependencies]
minidump = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
minidump-common = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
+uctx = { path = "../uctx" }
From a8a0ab361ab5da0c647ea7a56adb4459265630e8 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 8 Mar 2022 10:37:44 +0100
Subject: [PATCH 13/21] Update goblin
---
Cargo.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Cargo.toml b/Cargo.toml
index 663761f6..f4a281c3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT"
byteorder = "1.3.2"
cfg-if = "1.0"
exception-handler = { path = "../exception-handler" }
-goblin = "0.4"
+goblin = "0.5"
libc = "0.2.74"
memmap2 = "0.5"
memoffset = "0.6"
From 03dfae420a44793e305af5c06c7e42521b2e4563 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 8 Mar 2022 10:37:51 +0100
Subject: [PATCH 14/21] Fix docs compilation
---
src/linux/sections/exception_stream.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/linux/sections/exception_stream.rs b/src/linux/sections/exception_stream.rs
index 0e912ec3..da0b1d05 100644
--- a/src/linux/sections/exception_stream.rs
+++ b/src/linux/sections/exception_stream.rs
@@ -1,5 +1,5 @@
+use super::minidump_writer::CrashingThreadContext;
use super::*;
-use minidump_writer::CrashingThreadContext;
#[allow(non_camel_case_types, unused)]
#[repr(u32)]
From 040769fd556e5cf9ab29e353e1d9a50723686dbf Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 8 Mar 2022 12:57:21 +0100
Subject: [PATCH 15/21] Fix clippy lints in tests
---
src/linux/maps_reader.rs | 38 +++++++++++++++++++++-----------------
tests/common/mod.rs | 2 +-
tests/minidump_writer.rs | 5 +----
3 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/linux/maps_reader.rs b/src/linux/maps_reader.rs
index 99bfe6a1..fc54f3f4 100644
--- a/src/linux/maps_reader.rs
+++ b/src/linux/maps_reader.rs
@@ -418,10 +418,11 @@ mod tests {
let (lines, linux_gate_loc) = get_lines_and_loc();
// Only /usr/bin/cat and [heap]
for line in lines {
- match MappingInfo::parse_from_line(&line, linux_gate_loc, mappings.last_mut()) {
- Ok(MappingInfoParsingResult::Success(map)) => mappings.push(map),
- Ok(MappingInfoParsingResult::SkipLine) => continue,
- Err(_) => assert!(false),
+ match MappingInfo::parse_from_line(line, linux_gate_loc, mappings.last_mut())
+ .expect("unexpected parse failure")
+ {
+ MappingInfoParsingResult::Success(map) => mappings.push(map),
+ MappingInfoParsingResult::SkipLine => continue,
}
}
assert_eq!(mappings.len(), 23);
@@ -434,10 +435,11 @@ mod tests {
let (lines, linux_gate_loc) = get_lines_and_loc();
// Only /usr/bin/cat and [heap]
for line in lines[0..=6].iter() {
- match MappingInfo::parse_from_line(&line, linux_gate_loc, mappings.last_mut()) {
- Ok(MappingInfoParsingResult::Success(map)) => mappings.push(map),
- Ok(MappingInfoParsingResult::SkipLine) => continue,
- Err(_) => assert!(false),
+ match MappingInfo::parse_from_line(line, linux_gate_loc, mappings.last_mut())
+ .expect("unexpected parse failure")
+ {
+ MappingInfoParsingResult::Success(map) => mappings.push(map),
+ MappingInfoParsingResult::SkipLine => continue,
}
}
@@ -575,10 +577,11 @@ mod tests {
let linux_gate_loc = 0x7ffe091bf000;
let mut mappings: Vec = Vec::new();
for line in lines {
- match MappingInfo::parse_from_line(&line, linux_gate_loc, mappings.last_mut()) {
- Ok(MappingInfoParsingResult::Success(map)) => mappings.push(map),
- Ok(MappingInfoParsingResult::SkipLine) => continue,
- Err(_) => assert!(false),
+ match MappingInfo::parse_from_line(line, linux_gate_loc, mappings.last_mut())
+ .expect("unexpected parse failure")
+ {
+ MappingInfoParsingResult::Success(map) => mappings.push(map),
+ MappingInfoParsingResult::SkipLine => continue,
}
}
assert_eq!(mappings.len(), 1);
@@ -600,7 +603,7 @@ mod tests {
let linux_gate_loc = 0x7ffe091bf000;
let mut mappings: Vec = Vec::new();
for line in lines {
- match MappingInfo::parse_from_line(&line, linux_gate_loc, mappings.last_mut()) {
+ match MappingInfo::parse_from_line(line, linux_gate_loc, mappings.last_mut()) {
Ok(MappingInfoParsingResult::Success(map)) => mappings.push(map),
Ok(MappingInfoParsingResult::SkipLine) => continue,
Err(x) => panic!("{:?}", x),
@@ -634,10 +637,11 @@ mod tests {
let linux_gate_loc = 0x7ffe091bf000;
let mut mappings: Vec = Vec::new();
for line in lines {
- match MappingInfo::parse_from_line(&line, linux_gate_loc, mappings.last_mut()) {
- Ok(MappingInfoParsingResult::Success(map)) => mappings.push(map),
- Ok(MappingInfoParsingResult::SkipLine) => continue,
- Err(_) => assert!(false),
+ match MappingInfo::parse_from_line(line, linux_gate_loc, mappings.last_mut())
+ .expect("unexpected parse failure")
+ {
+ MappingInfoParsingResult::Success(map) => mappings.push(map),
+ MappingInfoParsingResult::SkipLine => continue,
}
}
assert_eq!(mappings.len(), 4);
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index 3775bcc3..bb262601 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -86,7 +86,7 @@ pub fn start_child_and_return(command: &str) -> Child {
.arg("--bin")
.arg("test")
.arg("--")
- .arg(format!("{}", command))
+ .arg(command)
.stdout(Stdio::piped())
.spawn()
.expect("failed to execute child");
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index a235ae85..3e568fb2 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -615,10 +615,7 @@ fn test_sanitized_stacks_helper(context: Context) {
let start = mem.rva as usize;
let end = (mem.rva + mem.data_size) as usize;
let slice = &dump_array.as_slice()[start..end];
- assert!(slice
- .windows(defaced.len())
- .position(|window| window == defaced)
- .is_some());
+ assert!(slice.windows(defaced.len()).any(|window| window == defaced));
}
}
From 1101eff38f8223349178cb30151da84931031080 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Tue, 8 Mar 2022 14:37:09 +0100
Subject: [PATCH 16/21] Cleanup more lints
---
src/lib.rs | 79 ++++++++++++++++++
src/linux/crash_context/x86_64.rs | 13 +--
src/linux/dso_debug.rs | 2 +-
src/linux/dumper_cpu_info/x86_mips.rs | 8 +-
src/linux/maps_reader.rs | 17 ++--
src/linux/minidump_writer.rs | 11 ++-
src/linux/ptrace_dumper.rs | 99 +++++++++++------------
src/linux/sections.rs | 10 +--
src/linux/sections/exception_stream.rs | 4 +-
src/linux/sections/mappings.rs | 11 ++-
src/linux/sections/thread_names_stream.rs | 2 +-
src/linux/thread_info.rs | 44 +++++-----
src/linux/thread_info/x86.rs | 21 ++---
src/minidump_format.rs | 2 +-
14 files changed, 188 insertions(+), 135 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index de193a2e..3bcb07e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,82 @@
+// BEGIN - Embark standard lints v6 for Rust 1.55+
+// do not change or add/remove here, but one can add exceptions after this section
+// for more info see:
+#![deny(unsafe_code)]
+#![warn(
+ clippy::all,
+ clippy::await_holding_lock,
+ clippy::char_lit_as_u8,
+ clippy::checked_conversions,
+ clippy::dbg_macro,
+ clippy::debug_assert_with_mut_call,
+ clippy::doc_markdown,
+ clippy::empty_enum,
+ clippy::enum_glob_use,
+ clippy::exit,
+ clippy::expl_impl_clone_on_copy,
+ clippy::explicit_deref_methods,
+ clippy::explicit_into_iter_loop,
+ clippy::fallible_impl_from,
+ clippy::filter_map_next,
+ clippy::flat_map_option,
+ clippy::float_cmp_const,
+ clippy::fn_params_excessive_bools,
+ clippy::from_iter_instead_of_collect,
+ clippy::if_let_mutex,
+ clippy::implicit_clone,
+ clippy::imprecise_flops,
+ clippy::inefficient_to_string,
+ clippy::invalid_upcast_comparisons,
+ clippy::large_digit_groups,
+ clippy::large_stack_arrays,
+ clippy::large_types_passed_by_value,
+ clippy::let_unit_value,
+ clippy::linkedlist,
+ clippy::lossy_float_literal,
+ clippy::macro_use_imports,
+ clippy::manual_ok_or,
+ clippy::map_err_ignore,
+ clippy::map_flatten,
+ clippy::map_unwrap_or,
+ clippy::match_on_vec_items,
+ clippy::match_same_arms,
+ clippy::match_wild_err_arm,
+ clippy::match_wildcard_for_single_variants,
+ clippy::mem_forget,
+ clippy::mismatched_target_os,
+ clippy::missing_enforced_import_renames,
+ clippy::mut_mut,
+ clippy::mutex_integer,
+ clippy::needless_borrow,
+ clippy::needless_continue,
+ clippy::needless_for_each,
+ clippy::option_option,
+ clippy::path_buf_push_overwrite,
+ clippy::ptr_as_ptr,
+ clippy::rc_mutex,
+ clippy::ref_option_ref,
+ clippy::rest_pat_in_fully_bound_structs,
+ clippy::same_functions_in_if_condition,
+ clippy::semicolon_if_nothing_returned,
+ clippy::single_match_else,
+ clippy::string_add_assign,
+ clippy::string_add,
+ clippy::string_lit_as_bytes,
+ clippy::string_to_string,
+ clippy::todo,
+ clippy::trait_duplication_in_bounds,
+ clippy::unimplemented,
+ clippy::unnested_or_patterns,
+ clippy::unused_self,
+ clippy::useless_transmute,
+ clippy::verbose_file_reads,
+ clippy::zero_sized_map_values,
+ future_incompatible,
+ nonstandard_style,
+ rust_2018_idioms
+)]
+// END - Embark standard lints v6 for Rust 1.55+
+// crate-specific exceptions:
#![allow(unsafe_code)]
cfg_if::cfg_if! {
diff --git a/src/linux/crash_context/x86_64.rs b/src/linux/crash_context/x86_64.rs
index 87bccc77..879005ca 100644
--- a/src/linux/crash_context/x86_64.rs
+++ b/src/linux/crash_context/x86_64.rs
@@ -1,6 +1,6 @@
use crate::minidump_cpu::imp::*;
-use crate::thread_info::to_u128;
+use crate::thread_info::copy_u32_registers;
use libc::{
REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
@@ -61,15 +61,8 @@ impl super::CpuContext for super::CrashContext {
out.flt_save.mx_csr = fs.mxcsr;
out.flt_save.mx_csr_mask = fs.mxcr_mask;
- let data = to_u128(&fs.st_space);
- for idx in 0..data.len() {
- out.flt_save.float_registers[idx] = data[idx];
- }
-
- let data = to_u128(&fs.xmm_space);
- for idx in 0..data.len() {
- out.flt_save.xmm_registers[idx] = data[idx];
- }
+ copy_u32_registers(&mut out.flt_save.float_registers, &fs.st_space);
+ copy_u32_registers(&mut out.flt_save.xmm_registers, &fs.xmm_space);
}
}
}
diff --git a/src/linux/dso_debug.rs b/src/linux/dso_debug.rs
index d724cc04..aa2703c5 100644
--- a/src/linux/dso_debug.rs
+++ b/src/linux/dso_debug.rs
@@ -211,7 +211,7 @@ pub fn write_dso_debug_stream(
}
let mut linkmap_rva = u32::MAX;
- if dso_vec.len() > 0 {
+ if !dso_vec.is_empty() {
// If we have at least one DSO, create an array of MDRawLinkMap
// entries in the minidump file.
let mut linkmap = MemoryArrayWriter::::alloc_array(buffer, dso_vec.len())?;
diff --git a/src/linux/dumper_cpu_info/x86_mips.rs b/src/linux/dumper_cpu_info/x86_mips.rs
index ea9cfe07..cc38ffa6 100644
--- a/src/linux/dumper_cpu_info/x86_mips.rs
+++ b/src/linux/dumper_cpu_info/x86_mips.rs
@@ -46,7 +46,7 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
let cpuinfo_file = std::fs::File::open(path::PathBuf::from("/proc/cpuinfo"))?;
- let mut vendor_id = String::new();
+ let mut vendor_id = None;
for line in BufReader::new(cpuinfo_file).lines() {
let line = line?;
// Expected format: + ':'
@@ -83,8 +83,8 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
}
// special case for vendor_id
- if field == vendor_id_name && value.is_some() && !value.unwrap().is_empty() {
- vendor_id = value.unwrap().to_string();
+ if field == vendor_id_name {
+ vendor_id = value.filter(|v| !v.is_empty()).map(|v| (*v).to_owned());
}
}
}
@@ -104,7 +104,7 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
sys_info.processor_revision =
(cpu_info_table[1].value << 8 | cpu_info_table[2].value) as u16;
}
- if !vendor_id.is_empty() {
+ if let Some(vendor_id) = vendor_id {
let mut slice = vendor_id.as_bytes();
for id_part in sys_info.cpu.vendor_id.iter_mut() {
let (int_bytes, rest) = slice.split_at(std::mem::size_of::());
diff --git a/src/linux/maps_reader.rs b/src/linux/maps_reader.rs
index fc54f3f4..f31bca3f 100644
--- a/src/linux/maps_reader.rs
+++ b/src/linux/maps_reader.rs
@@ -181,7 +181,7 @@ impl MappingInfo {
}
pub fn get_mmap(name: &Option, offset: usize) -> Result {
- if !MappingInfo::is_mapped_file_safe_to_open(&name) {
+ if !MappingInfo::is_mapped_file_safe_to_open(name) {
return Err(MapsReaderError::NotSafeToOpenMapping(
name.clone().unwrap_or_default(),
));
@@ -304,14 +304,13 @@ impl MappingInfo {
// filesystem name of the module.
// Just use the filesystem name if no SONAME is present.
- let file_name = match self.elf_file_so_name() {
- Ok(name) => name,
- Err(_) => {
- // file_path := /path/to/libname.so
- // file_name := libname.so
- let file_name = file_path.rsplitn(2, '/').next().unwrap().to_owned();
- return Ok((file_path, file_name));
- }
+ let file_name = if let Ok(name) = self.elf_file_so_name() {
+ name
+ } else {
+ // file_path := /path/to/libname.so
+ // file_name := libname.so
+ let file_name = file_path.rsplit('/').next().unwrap().to_owned();
+ return Ok((file_path, file_name));
};
if self.executable && self.offset != 0 {
diff --git a/src/linux/minidump_writer.rs b/src/linux/minidump_writer.rs
index d83dd20a..39abd9b5 100644
--- a/src/linux/minidump_writer.rs
+++ b/src/linux/minidump_writer.rs
@@ -11,7 +11,7 @@ use crate::{
},
minidump_format::*,
};
-use std::io::{Cursor, Read, Seek, SeekFrom, Write};
+use std::io::{Cursor, Seek, SeekFrom, Write};
pub type DumpBuf = Cursor>;
@@ -297,7 +297,7 @@ impl MinidumpWriter {
// we should have a mostly-intact dump
dir_section.write_to_file(buffer, None)?;
- let dirent = thread_list_stream::write(self, buffer, &dumper)?;
+ let dirent = thread_list_stream::write(self, buffer, dumper)?;
// Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
@@ -305,7 +305,7 @@ impl MinidumpWriter {
// Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
- let _ = app_memory::write(self, buffer)?;
+ app_memory::write(self, buffer)?;
// Write section to file
dir_section.write_to_file(buffer, None)?;
@@ -411,14 +411,13 @@ impl MinidumpWriter {
Ok(())
}
+ #[allow(clippy::unused_self)]
fn write_file(
&self,
buffer: &mut DumpBuf,
filename: &str,
) -> std::result::Result {
- let mut file = std::fs::File::open(std::path::PathBuf::from(filename))?;
- let mut content = Vec::new();
- file.read_to_end(&mut content)?;
+ let content = std::fs::read(filename)?;
let section = MemoryArrayWriter::::alloc_from_array(buffer, &content)?;
Ok(section.location())
diff --git a/src/linux/ptrace_dumper.rs b/src/linux/ptrace_dumper.rs
index a33d023a..61c37c98 100644
--- a/src/linux/ptrace_dumper.rs
+++ b/src/linux/ptrace_dumper.rs
@@ -71,6 +71,7 @@ impl PtraceDumper {
Ok(())
}
+ #[cfg_attr(not(target_os = "android"), allow(clippy::unused_self))]
pub fn late_init(&mut self) -> Result<(), InitError> {
#[cfg(target_os = "android")]
{
@@ -213,7 +214,7 @@ impl PtraceDumper {
.ok();
(tid, name)
})
- .for_each(|(tid, name)| self.threads.push(Thread { tid, name }))
+ .for_each(|(tid, name)| self.threads.push(Thread { tid, name }));
}
Ok(())
}
@@ -271,8 +272,7 @@ impl PtraceDumper {
let line = line.map_err(errmap)?;
match MappingInfo::parse_from_line(&line, linux_gate_loc, self.mappings.last_mut()) {
Ok(MappingInfoParsingResult::Success(map)) => self.mappings.push(map),
- Ok(MappingInfoParsingResult::SkipLine) => continue,
- Err(_) => continue,
+ Ok(MappingInfoParsingResult::SkipLine) | Err(_) => continue,
}
}
@@ -351,12 +351,12 @@ impl PtraceDumper {
let defaced;
#[cfg(target_pointer_width = "64")]
{
- defaced = 0x0defaced0defacedusize.to_ne_bytes()
+ defaced = 0x0defaced0defacedusize.to_ne_bytes();
}
#[cfg(target_pointer_width = "32")]
{
- defaced = 0x0defacedusize.to_ne_bytes()
- };
+ defaced = 0x0defacedusize.to_ne_bytes();
+ }
// the bitfield length is 2^test_bits long.
let test_bits = 11;
// byte length of the corresponding array.
@@ -443,28 +443,24 @@ impl PtraceDumper {
Ok(())
}
- // Find the mapping which the given memory address falls in.
+ /// Find the mapping which the given memory address falls in.
+ #[inline]
pub fn find_mapping(&self, address: usize) -> Option<&MappingInfo> {
- for map in &self.mappings {
- if address >= map.start_address && address - map.start_address < map.size {
- return Some(&map);
- }
- }
- None
+ self.mappings
+ .iter()
+ .find(|map| address >= map.start_address && address - map.start_address < map.size)
}
- // Find the mapping which the given memory address falls in. Uses the
- // unadjusted mapping address range from the kernel, rather than the
- // biased range.
+ /// Find the mapping which the given memory address falls in.
+ ///
+ /// Uses the unadjusted mapping address range from the kernel, rather than
+ /// the biased range.
+ #[inline]
pub fn find_mapping_no_bias(&self, address: usize) -> Option<&MappingInfo> {
- for map in &self.mappings {
- if address >= map.system_mapping_info.start_address
+ self.mappings.iter().find(|map| {
+ address >= map.system_mapping_info.start_address
&& address < map.system_mapping_info.end_address
- {
- return Some(&map);
- }
- }
- None
+ })
}
fn parse_build_id<'data>(
@@ -490,41 +486,40 @@ impl PtraceDumper {
pub fn elf_file_identifier_from_mapped_file(mem_slice: &[u8]) -> Result, DumperError> {
let elf_obj = elf::Elf::parse(mem_slice)?;
- match Self::parse_build_id(&elf_obj, mem_slice) {
+ if let Some(build_id) = Self::parse_build_id(&elf_obj, mem_slice) {
// Look for a build id note first.
- Some(build_id) => Ok(build_id.to_vec()),
+ Ok(build_id.to_vec())
+ } else {
// Fall back on hashing the first page of the text section.
- None => {
- // Attempt to locate the .text section of an ELF binary and generate
- // a simple hash by XORing the first page worth of bytes into |result|.
- for section in elf_obj.section_headers {
- if section.sh_type != elf::section_header::SHT_PROGBITS {
- continue;
- }
- if section.sh_flags & u64::from(elf::section_header::SHF_ALLOC) != 0 {
- if section.sh_flags & u64::from(elf::section_header::SHF_EXECINSTR) != 0 {
- let text_section = &mem_slice[section.sh_offset as usize..]
- [..section.sh_size as usize];
- // Only provide mem::size_of(MDGUID) bytes to keep identifiers produced by this
- // function backwards-compatible.
- let max_len = std::cmp::min(text_section.len(), 4096);
- let mut result = vec![0u8; std::mem::size_of::()];
- let mut offset = 0;
- while offset < max_len {
- for idx in 0..std::mem::size_of::() {
- if offset + idx >= text_section.len() {
- break;
- }
- result[idx] ^= text_section[offset + idx];
- }
- offset += std::mem::size_of::();
+ // Attempt to locate the .text section of an ELF binary and generate
+ // a simple hash by XORing the first page worth of bytes into |result|.
+ for section in elf_obj.section_headers {
+ if section.sh_type != elf::section_header::SHT_PROGBITS {
+ continue;
+ }
+ if section.sh_flags & elf::section_header::SHF_ALLOC as u64 != 0
+ && section.sh_flags & elf::section_header::SHF_EXECINSTR as u64 != 0
+ {
+ let text_section =
+ &mem_slice[section.sh_offset as usize..][..section.sh_size as usize];
+ // Only provide mem::size_of(MDGUID) bytes to keep identifiers produced by this
+ // function backwards-compatible.
+ let max_len = std::cmp::min(text_section.len(), 4096);
+ let mut result = vec![0u8; std::mem::size_of::()];
+ let mut offset = 0;
+ while offset < max_len {
+ for idx in 0..std::mem::size_of::() {
+ if offset + idx >= text_section.len() {
+ break;
}
- return Ok(result);
+ result[idx] ^= text_section[offset + idx];
}
+ offset += std::mem::size_of::();
}
+ return Ok(result);
}
- Err(DumperError::NoBuildIDFound)
}
+ Err(DumperError::NoBuildIDFound)
}
}
@@ -561,7 +556,7 @@ impl PtraceDumper {
}
}
let new_name = MappingInfo::handle_deleted_file_in_mapping(
- &mapping.name.as_ref().unwrap_or(&String::new()),
+ mapping.name.as_deref().unwrap_or(""),
pid,
)?;
diff --git a/src/linux/sections.rs b/src/linux/sections.rs
index 9e29c96b..af1ef1b6 100644
--- a/src/linux/sections.rs
+++ b/src/linux/sections.rs
@@ -34,7 +34,7 @@ where
// Get position of this value (e.g. before we add ourselves there)
let position = buffer.position();
let size = std::mem::size_of::();
- let bytes = unsafe { std::slice::from_raw_parts(&val as *const T as *const u8, size) };
+ let bytes = unsafe { std::slice::from_raw_parts((&val as *const T).cast(), size) };
buffer.write_all(bytes)?;
Ok(MemoryWriter {
@@ -62,7 +62,7 @@ where
// was determined by `alloc()` into the buffer
buffer.set_position(self.position as u64);
let bytes = unsafe {
- std::slice::from_raw_parts(&val as *const T as *const u8, std::mem::size_of::())
+ std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
};
let res = buffer.write_all(bytes);
@@ -99,7 +99,7 @@ where
let position = buffer.position();
for val in array {
let bytes = unsafe {
- std::slice::from_raw_parts(val as *const T as *const u8, std::mem::size_of::())
+ std::slice::from_raw_parts((val as *const T).cast(), std::mem::size_of::())
};
buffer.write_all(bytes)?;
}
@@ -121,7 +121,7 @@ where
// Filling out the buffer with default-values
let val: T = Default::default();
let bytes = unsafe {
- std::slice::from_raw_parts(&val as *const T as *const u8, std::mem::size_of::())
+ std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
};
buffer.write_all(bytes)?;
}
@@ -147,7 +147,7 @@ where
// was determined by `alloc()` into the buffer
buffer.set_position(self.position as u64 + (std::mem::size_of::() * index) as u64);
let bytes = unsafe {
- std::slice::from_raw_parts(&val as *const T as *const u8, std::mem::size_of::())
+ std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
};
let res = buffer.write_all(bytes);
diff --git a/src/linux/sections/exception_stream.rs b/src/linux/sections/exception_stream.rs
index da0b1d05..4cddc3e8 100644
--- a/src/linux/sections/exception_stream.rs
+++ b/src/linux/sections/exception_stream.rs
@@ -94,8 +94,8 @@ pub fn write(
};
let thread_context = match config.crashing_thread_context {
- CrashingThreadContext::CrashContextPlusAddress((ctx, _)) => ctx,
- CrashingThreadContext::CrashContext(ctx) => ctx,
+ CrashingThreadContext::CrashContextPlusAddress((ctx, _))
+ | CrashingThreadContext::CrashContext(ctx) => ctx,
CrashingThreadContext::None => MDLocationDescriptor {
data_size: 0,
rva: 0,
diff --git a/src/linux/sections/mappings.rs b/src/linux/sections/mappings.rs
index d15be725..642e9736 100644
--- a/src/linux/sections/mappings.rs
+++ b/src/linux/sections/mappings.rs
@@ -43,7 +43,7 @@ pub fn write(
for user in &config.user_mapping_list {
// GUID was provided by caller.
let module = fill_raw_module(buffer, &user.mapping, &user.identifier)?;
- modules.push(module)
+ modules.push(module);
}
let list_header = MemoryWriter::::alloc_with_val(buffer, modules.len() as u32)?;
@@ -66,10 +66,9 @@ fn fill_raw_module(
mapping: &MappingInfo,
identifier: &[u8],
) -> Result {
- let cv_record: MDLocationDescriptor;
- if identifier.is_empty() {
+ let cv_record = if identifier.is_empty() {
// Just zeroes
- cv_record = Default::default();
+ Default::default()
} else {
let cv_signature = MD_CVINFOELF_SIGNATURE;
let array_size = std::mem::size_of_val(&cv_signature) + identifier.len();
@@ -83,8 +82,8 @@ fn fill_raw_module(
{
sig_section.set_value_at(buffer, *val, index)?;
}
- cv_record = sig_section.location();
- }
+ sig_section.location()
+ };
let (file_path, _) = mapping
.get_mapping_effective_name_and_path()
diff --git a/src/linux/sections/thread_names_stream.rs b/src/linux/sections/thread_names_stream.rs
index 51b23435..2e97f3cf 100644
--- a/src/linux/sections/thread_names_stream.rs
+++ b/src/linux/sections/thread_names_stream.rs
@@ -20,7 +20,7 @@ pub fn write(buffer: &mut DumpBuf, dumper: &PtraceDumper) -> Result Vec {
- let mut res = Vec::new();
- for chunk in slice.chunks_exact(4) {
- let value = u128::from_ne_bytes(
- chunk
- .iter()
- .map(|x| x.to_ne_bytes().to_vec())
- .flatten()
- .collect::>()
- .as_slice()
- .try_into() // Make slice into fixed size array
- .unwrap(), // Which has to work as we know the numbers work out
- );
- res.push(value)
- }
- res
+#[inline]
+pub fn to_u128(slice: &[u32]) -> &[u128] {
+ unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), slice.len().saturating_div(4)) }
+}
+
+#[inline]
+pub fn copy_registers(dst: &mut [u128], src: &[u128]) {
+ let to_copy = std::cmp::min(dst.len(), src.len());
+ dst[..to_copy].copy_from_slice(&src[..to_copy]);
+}
+
+#[inline]
+pub fn copy_u32_registers(dst: &mut [u128], src: &[u32]) {
+ copy_registers(dst, to_u128(src));
}
trait CommonThreadInfo {
@@ -71,13 +69,13 @@ trait CommonThreadInfo {
tgid = l
.get(6..)
.ok_or_else(|| ThreadInfoError::InvalidProcStatusFile(tid, l.clone()))?
- .parse::()?
+ .parse::()?;
}
"PPid:\t" => {
ppid = l
.get(6..)
.ok_or_else(|| ThreadInfoError::InvalidProcStatusFile(tid, l.clone()))?
- .parse::()?
+ .parse::()?;
}
_ => continue,
}
@@ -102,13 +100,13 @@ trait CommonThreadInfo {
flag: Option,
pid: nix::unistd::Pid,
) -> Result {
- let mut data = std::mem::MaybeUninit::uninit();
+ let mut data = std::mem::MaybeUninit::::uninit();
let res = unsafe {
libc::ptrace(
request as ptrace::RequestType,
libc::pid_t::from(pid),
flag.unwrap_or(NT_Elf::NT_NONE),
- data.as_mut_ptr() as *const _ as *const libc::c_void,
+ data.as_mut_ptr(),
)
};
Errno::result(res)?;
@@ -125,9 +123,9 @@ trait CommonThreadInfo {
flag: Option,
pid: nix::unistd::Pid,
) -> Result {
- let mut data = std::mem::MaybeUninit::uninit();
+ let mut data = std::mem::MaybeUninit::::uninit();
let io = libc::iovec {
- iov_base: data.as_mut_ptr() as *mut libc::c_void,
+ iov_base: data.as_mut_ptr().cast(),
iov_len: std::mem::size_of::(),
};
let res = unsafe {
@@ -135,7 +133,7 @@ trait CommonThreadInfo {
request as ptrace::RequestType,
libc::pid_t::from(pid),
flag.unwrap_or(NT_Elf::NT_NONE),
- &io as *const _ as *const libc::c_void,
+ (&io as *const libc::iovec).cast::(),
)
};
Errno::result(res)?;
diff --git a/src/linux/thread_info/x86.rs b/src/linux/thread_info/x86.rs
index d6fdfe2c..04db7b4d 100644
--- a/src/linux/thread_info/x86.rs
+++ b/src/linux/thread_info/x86.rs
@@ -3,7 +3,7 @@ use crate::errors::ThreadInfoError;
use crate::minidump_cpu::imp::*;
use crate::minidump_cpu::RawContextCPU;
#[cfg(target_arch = "x86_64")]
-use crate::thread_info::to_u128;
+use crate::thread_info::copy_u32_registers;
use core::mem::size_of_val;
use libc;
use libc::user;
@@ -100,18 +100,18 @@ impl ThreadInfoX86 {
let debug_offset = memoffset::offset_of!(user, u_debugreg);
let elem_offset = size_of_val(&dregs[0]);
- for idx in 0..NUM_DEBUG_REGISTERS {
+ for (idx, dreg) in dregs.iter_mut().enumerate() {
let chunk = Self::peek_user(
tid,
(debug_offset + idx * elem_offset) as ptrace::AddressType,
)?;
#[cfg(target_arch = "x86_64")]
{
- dregs[idx] = chunk as u64; // libc / ptrace is very messy wrt int types used...
+ *dreg = chunk as u64; // libc / ptrace is very messy wrt int types used...
}
#[cfg(target_arch = "x86")]
{
- dregs[idx] = chunk as i32; // libc / ptrace is very messy wrt int types used...
+ *dreg = chunk as i32; // libc / ptrace is very messy wrt int types used...
}
}
@@ -197,17 +197,8 @@ impl ThreadInfoX86 {
out.flt_save.mx_csr = self.fpregs.mxcsr;
out.flt_save.mx_csr_mask = self.fpregs.mxcr_mask;
- let data = to_u128(&self.fpregs.st_space);
- for idx in 0..data.len() {
- out.flt_save.float_registers[idx] = data[idx];
- }
-
- let data = to_u128(&self.fpregs.xmm_space);
- for idx in 0..data.len() {
- out.flt_save.xmm_registers[idx] = data[idx];
- }
- // my_memcpy(&out.flt_save.float_registers, &self.fpregs.st_space, 8 * 16);
- // my_memcpy(&out.flt_save.xmm_registers, &self.fpregs.xmm_space, 16 * 16);
+ copy_u32_registers(&mut out.flt_save.float_registers, &self.fpregs.st_space);
+ copy_u32_registers(&mut out.flt_save.xmm_registers, &self.fpregs.xmm_space);
}
#[cfg(target_arch = "x86")]
diff --git a/src/minidump_format.rs b/src/minidump_format.rs
index cd6910c8..a14026b3 100644
--- a/src/minidump_format.rs
+++ b/src/minidump_format.rs
@@ -67,7 +67,7 @@ pub const MD_HEADER_SIGNATURE: u32 = 0x504d444d; /* 'PMDM' */
pub const MD_HEADER_VERSION: u32 = 0x0000a793; /* 42899 */
/* MINIDUMP_VERSION */
-/// The name of a thread, found in the ThreadNamesStream.
+/// The name of a thread, found in the [`MDStreamType::ThreadNamesStream`].
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct MDRawThreadName {
From 04d22cfd030bf1df2705cf250f13b4a3f0771656 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Wed, 9 Mar 2022 18:41:38 +0100
Subject: [PATCH 17/21] Giant refactor to use minidump types
There was a _ton_ of duplication of minidump types between this crate
and minidump-common, so this refactors the code to remove basically all
types that minidump-common already had, and changed the minidump_writer
code to use scroll pwrite instead of relying on repr(C) and byte
transmutes
---
Cargo.toml | 16 +-
src/linux/crash_context.rs | 2 +-
src/linux/crash_context/x86_64.rs | 39 +-
src/linux/dso_debug.rs | 8 +-
src/linux/dumper_cpu_info.rs | 40 +-
src/linux/dumper_cpu_info/arm.rs | 44 +--
src/linux/dumper_cpu_info/x86_mips.rs | 150 ++++----
src/linux/errors.rs | 2 +
src/linux/minidump_writer.rs | 40 +-
src/linux/ptrace_dumper.rs | 8 +-
src/linux/sections.rs | 257 ++++++++-----
src/linux/sections/app_memory.rs | 2 +-
src/linux/sections/mappings.rs | 4 +-
src/linux/sections/systeminfo_stream.rs | 13 +-
src/linux/sections/thread_list_stream.rs | 10 +-
src/linux/thread_info/x86.rs | 49 ++-
src/minidump_cpu.rs | 5 +-
src/minidump_cpu/amd64.rs | 179 ---------
src/minidump_format.rs | 461 ++---------------------
tests/minidump_writer.rs | 4 +-
20 files changed, 416 insertions(+), 917 deletions(-)
delete mode 100644 src/minidump_cpu/amd64.rs
diff --git a/Cargo.toml b/Cargo.toml
index f4a281c3..14bd0e9a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,16 +8,24 @@ license = "MIT"
[dependencies]
byteorder = "1.3.2"
cfg-if = "1.0"
-exception-handler = { path = "../exception-handler" }
+exception-handler = { path = "../crash-handling/exception-handler" }
goblin = "0.5"
libc = "0.2.74"
memmap2 = "0.5"
memoffset = "0.6"
+minidump = "*"
+minidump-common = "*"
nix = "0.23"
+scroll = "0.11"
tempfile = "3.1.0"
thiserror = "1.0.21"
[dev-dependencies]
-minidump = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
-minidump-common = { git = "https://github.com/luser/rust-minidump", rev = "9652b3b" }
-uctx = { path = "../uctx" }
+uctx = { path = "../crash-handling/uctx" }
+debugid = "0.7.3"
+
+[patch.crates-io]
+#minidump = { git = "https://github.com/EmbarkStudios/rust-minidump", rev = "228c5d0" }
+#minidump-common = { git = "https://github.com/EmbarkStudios/rust-minidump", rev = "228c5d0" }
+minidump = { path = "../rust-minidump/minidump" }
+minidump-common = { path = "../rust-minidump/minidump-common" }
diff --git a/src/linux/crash_context.rs b/src/linux/crash_context.rs
index 8e68574b..ce70a954 100644
--- a/src/linux/crash_context.rs
+++ b/src/linux/crash_context.rs
@@ -16,7 +16,7 @@ cfg_if::cfg_if! {
}
}
-use crate::minidump_cpu::RawContextCPU;
+use crate::minidump_cpu::{FloatStateCPU, RawContextCPU};
pub use exception_handler::CrashContext;
pub trait CpuContext {
diff --git a/src/linux/crash_context/x86_64.rs b/src/linux/crash_context/x86_64.rs
index 879005ca..f699e469 100644
--- a/src/linux/crash_context/x86_64.rs
+++ b/src/linux/crash_context/x86_64.rs
@@ -1,5 +1,3 @@
-use crate::minidump_cpu::imp::*;
-
use crate::thread_info::copy_u32_registers;
use libc::{
REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
@@ -16,7 +14,8 @@ impl super::CpuContext for super::CrashContext {
}
fn fill_cpu_context(&self, out: &mut super::RawContextCPU) {
- out.context_flags = MD_CONTEXT_AMD64_FULL;
+ out.context_flags =
+ crate::minidump_format::format::ContextFlagsAmd64::CONTEXT_AMD64_FULL.bits();
{
let gregs = &self.context.uc_mcontext.gregs;
@@ -50,19 +49,29 @@ impl super::CpuContext for super::CrashContext {
{
let fs = &self.float_state;
- out.flt_save.control_word = fs.cwd;
- out.flt_save.status_word = fs.swd;
- out.flt_save.tag_word = fs.ftw as u8;
- out.flt_save.error_opcode = fs.fop;
- out.flt_save.error_offset = fs.rip as u32;
- out.flt_save.data_offset = fs.rdp as u32;
- out.flt_save.error_selector = 0; // We don't have this.
- out.flt_save.data_selector = 0; // We don't have this.
- out.flt_save.mx_csr = fs.mxcsr;
- out.flt_save.mx_csr_mask = fs.mxcr_mask;
- copy_u32_registers(&mut out.flt_save.float_registers, &fs.st_space);
- copy_u32_registers(&mut out.flt_save.xmm_registers, &fs.xmm_space);
+ let mut float_save = super::FloatStateCPU {
+ control_word: fs.cwd,
+ status_word: fs.swd,
+ tag_word: fs.ftw as u8,
+ error_opcode: fs.fop,
+ error_offset: fs.rip as u32,
+ data_offset: fs.rdp as u32,
+ error_selector: 0, // We don't have this.
+ data_selector: 0, // We don't have this.
+ mx_csr: fs.mxcsr,
+ mx_csr_mask: fs.mxcr_mask,
+ ..Default::default()
+ };
+
+ copy_u32_registers(&mut float_save.float_registers, &fs.st_space);
+ copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space);
+
+ use scroll::Pwrite;
+ // TODO: handle errors
+ out.float_save
+ .pwrite_with(float_save, 0, scroll::Endian::Little)
+ .unwrap();
}
}
}
diff --git a/src/linux/dso_debug.rs b/src/linux/dso_debug.rs
index aa2703c5..d842a926 100644
--- a/src/linux/dso_debug.rs
+++ b/src/linux/dso_debug.rs
@@ -3,11 +3,11 @@ use crate::{
auxv_reader::AuxvType,
errors::SectionDsoDebugError,
ptrace_dumper::PtraceDumper,
- sections::{write_string_to_location, MemoryArrayWriter, MemoryWriter},
+ sections::{write_string_to_location, Buffer, MemoryArrayWriter, MemoryWriter},
},
minidump_format::*,
};
-use std::{collections::HashMap, io::Cursor};
+use std::collections::HashMap;
type Result = std::result::Result;
@@ -73,7 +73,7 @@ pub struct RDebug {
}
pub fn write_dso_debug_stream(
- buffer: &mut Cursor>,
+ buffer: &mut Buffer,
blamed_thread: i32,
auxv: &HashMap,
) -> Result {
@@ -265,7 +265,7 @@ pub fn write_dso_debug_stream(
dyn_addr as *mut libc::c_void,
dynamic_length,
)?;
- MemoryArrayWriter::::alloc_from_array(buffer, &dso_debug_data)?;
+ MemoryArrayWriter::write_bytes(buffer, &dso_debug_data);
Ok(dirent)
}
diff --git a/src/linux/dumper_cpu_info.rs b/src/linux/dumper_cpu_info.rs
index 80902b62..bbe22e7c 100644
--- a/src/linux/dumper_cpu_info.rs
+++ b/src/linux/dumper_cpu_info.rs
@@ -20,36 +20,26 @@ cfg_if::cfg_if! {
pub use imp::write_cpu_information;
-use crate::{
- errors::MemoryWriterError,
- linux::sections::write_string_to_location,
- minidump_format::{MDOSPlatform, MDRawSystemInfo},
-};
+use crate::minidump_format::PlatformId;
use nix::sys::utsname::uname;
-use std::io::Cursor;
-type Result = std::result::Result;
-
-pub fn write_os_information(
- buffer: &mut Cursor>,
- sys_info: &mut MDRawSystemInfo,
-) -> Result<()> {
+/// Retrieves the [`MDOSPlatform`] and synthesized version information
+pub fn os_information() -> (PlatformId, String) {
let info = uname();
- if cfg!(target_os = "android") {
- sys_info.platform_id = MDOSPlatform::Android as u32;
- } else {
- sys_info.platform_id = MDOSPlatform::Linux as u32;
- }
- let merged = vec![
+ let vers = format!(
+ "{} {} {} {}",
info.sysname(),
info.release(),
info.version(),
- info.machine(),
- ]
- .join(" ");
-
- let location = write_string_to_location(buffer, &merged)?;
- sys_info.csd_version_rva = location.rva;
+ info.machine()
+ );
- Ok(())
+ (
+ if cfg!(target_os = "android") {
+ PlatformId::Android
+ } else {
+ PlatformId::Linux
+ },
+ vers,
+ )
}
diff --git a/src/linux/dumper_cpu_info/arm.rs b/src/linux/dumper_cpu_info/arm.rs
index ab7da7ae..7d5b1ad5 100644
--- a/src/linux/dumper_cpu_info/arm.rs
+++ b/src/linux/dumper_cpu_info/arm.rs
@@ -90,30 +90,26 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
#[cfg(target_arch = "arm")]
{
cpu_features_entries = [
- CpuFeaturesEntry::new("swp", MDCPUInformationARMElfHwCaps::Swp as u32),
- CpuFeaturesEntry::new("half", MDCPUInformationARMElfHwCaps::Half as u32),
- CpuFeaturesEntry::new("thumb", MDCPUInformationARMElfHwCaps::Thumb as u32),
- CpuFeaturesEntry::new("bit26", MDCPUInformationARMElfHwCaps::Bit26 as u32),
- CpuFeaturesEntry::new("fastmult", MDCPUInformationARMElfHwCaps::FastMult as u32),
- CpuFeaturesEntry::new("fpa", MDCPUInformationARMElfHwCaps::Fpa as u32),
- CpuFeaturesEntry::new("vfp", MDCPUInformationARMElfHwCaps::Vfp as u32),
- CpuFeaturesEntry::new("edsp", MDCPUInformationARMElfHwCaps::Edsp as u32),
- CpuFeaturesEntry::new("java", MDCPUInformationARMElfHwCaps::Java as u32),
- CpuFeaturesEntry::new("iwmmxt", MDCPUInformationARMElfHwCaps::Iwmmxt as u32),
- CpuFeaturesEntry::new("crunch", MDCPUInformationARMElfHwCaps::Crunch as u32),
- CpuFeaturesEntry::new("thumbee", MDCPUInformationARMElfHwCaps::Thumbee as u32),
- CpuFeaturesEntry::new("neon", MDCPUInformationARMElfHwCaps::Neon as u32),
- CpuFeaturesEntry::new("vfpv3", MDCPUInformationARMElfHwCaps::Vfpv3 as u32),
- CpuFeaturesEntry::new("vfpv3d16", MDCPUInformationARMElfHwCaps::Vfpv3d16 as u32),
- CpuFeaturesEntry::new("tls", MDCPUInformationARMElfHwCaps::Tls as u32),
- CpuFeaturesEntry::new("vfpv4", MDCPUInformationARMElfHwCaps::Vfpv4 as u32),
- CpuFeaturesEntry::new("idiva", MDCPUInformationARMElfHwCaps::Idiva as u32),
- CpuFeaturesEntry::new("idivt", MDCPUInformationARMElfHwCaps::Idivt as u32),
- CpuFeaturesEntry::new(
- "idiv",
- MDCPUInformationARMElfHwCaps::Idiva as u32
- | MDCPUInformationARMElfHwCaps::Idivt as u32,
- ),
+ CpuFeaturesEntry::new("swp", MDCPUInformationARMElfHwCaps::HWCAP_SWP),
+ CpuFeaturesEntry::new("half", MDCPUInformationARMElfHwCaps::HWCAP_HALF),
+ CpuFeaturesEntry::new("thumb", MDCPUInformationARMElfHwCaps::HWCAP_THUMB),
+ CpuFeaturesEntry::new("bit26", MDCPUInformationARMElfHwCaps::HWCAP_26BIT),
+ CpuFeaturesEntry::new("fastmult", MDCPUInformationARMElfHwCaps::HWCAP_FAST_MULT),
+ CpuFeaturesEntry::new("fpa", MDCPUInformationARMElfHwCaps::HWCAP_FPA),
+ CpuFeaturesEntry::new("vfp", MDCPUInformationARMElfHwCaps::HWCAP_VFP),
+ CpuFeaturesEntry::new("edsp", MDCPUInformationARMElfHwCaps::HWCAP_EDSP),
+ CpuFeaturesEntry::new("java", MDCPUInformationARMElfHwCaps::HWCAP_JAVA),
+ CpuFeaturesEntry::new("iwmmxt", MDCPUInformationARMElfHwCaps::HWCAP_IWMMXT),
+ CpuFeaturesEntry::new("crunch", MDCPUInformationARMElfHwCaps::HWCAP_CRUNCH),
+ CpuFeaturesEntry::new("thumbee", MDCPUInformationARMElfHwCaps::HWCAP_THUMBEE),
+ CpuFeaturesEntry::new("neon", MDCPUInformationARMElfHwCaps::HWCAP_NEON),
+ CpuFeaturesEntry::new("vfpv3", MDCPUInformationARMElfHwCaps::HWCAP_VFPv3),
+ CpuFeaturesEntry::new("vfpv3d16", MDCPUInformationARMElfHwCaps::HWCAP_VFPv3D16),
+ CpuFeaturesEntry::new("tls", MDCPUInformationARMElfHwCaps::HWCAP_TLS),
+ CpuFeaturesEntry::new("vfpv4", MDCPUInformationARMElfHwCaps::HWCAP_VFPv4),
+ CpuFeaturesEntry::new("idiva", MDCPUInformationARMElfHwCaps::HWCAP_IDIVA),
+ CpuFeaturesEntry::new("idivt", MDCPUInformationARMElfHwCaps::HWCAP_IDIVT),
+ CpuFeaturesEntry::new("idiv", HWCAP_IDIV),
];
}
#[cfg(target_arch = "aarch64")]
diff --git a/src/linux/dumper_cpu_info/x86_mips.rs b/src/linux/dumper_cpu_info/x86_mips.rs
index cc38ffa6..05e7fc95 100644
--- a/src/linux/dumper_cpu_info/x86_mips.rs
+++ b/src/linux/dumper_cpu_info/x86_mips.rs
@@ -5,48 +5,28 @@ use std::path;
type Result = std::result::Result;
-struct CpuInfoEntry {
- info_name: &'static str,
- value: i32,
- found: bool,
-}
-
-impl CpuInfoEntry {
- fn new(info_name: &'static str, value: i32, found: bool) -> Self {
- CpuInfoEntry {
- info_name,
- value,
- found,
- }
- }
-}
-
pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
- let vendor_id_name = "vendor_id";
- let mut cpu_info_table = [
- CpuInfoEntry::new("processor", -1, false),
- #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
- CpuInfoEntry::new("model", 0, false),
- #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
- CpuInfoEntry::new("stepping", 0, false),
- #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
- CpuInfoEntry::new("cpu family", 0, false),
- ];
-
// processor_architecture should always be set, do this first
- if cfg!(target_arch = "mips") {
- sys_info.processor_architecture = MDCPUArchitecture::Mips as u16;
+ sys_info.processor_architecture = if cfg!(target_arch = "mips") {
+ MDCPUArchitecture::PROCESSOR_ARCHITECTURE_MIPS
} else if cfg!(target_arch = "mips64") {
- sys_info.processor_architecture = MDCPUArchitecture::Mips64 as u16;
+ MDCPUArchitecture::PROCESSOR_ARCHITECTURE_MIPS64
} else if cfg!(target_arch = "x86") {
- sys_info.processor_architecture = MDCPUArchitecture::X86 as u16;
+ MDCPUArchitecture::PROCESSOR_ARCHITECTURE_INTEL
} else {
- sys_info.processor_architecture = MDCPUArchitecture::Amd64 as u16;
- }
+ MDCPUArchitecture::PROCESSOR_ARCHITECTURE_AMD64
+ } as u16;
let cpuinfo_file = std::fs::File::open(path::PathBuf::from("/proc/cpuinfo"))?;
+ let mut processor = None;
+ // x86/_64 specific
let mut vendor_id = None;
+ let mut model = None;
+ let mut stepping = None;
+ let mut family = None;
+ //
+
for line in BufReader::new(cpuinfo_file).lines() {
let line = line?;
// Expected format: + ':'
@@ -58,63 +38,71 @@ pub fn write_cpu_information(sys_info: &mut MDRawSystemInfo) -> Result<()> {
continue;
}
- let split: Vec<_> = line.split(':').map(|x| x.trim()).collect();
- let field = split[0];
- let value = split.get(1); // Option, might be missing
+ let mut liter = line.split(':').map(|x| x.trim());
+ let field = liter.next().unwrap(); // guaranteed to have at least one item
+ let value = if let Some(val) = liter.next() {
+ val
+ } else {
+ continue;
+ };
- let mut is_first_entry = true;
- for mut entry in cpu_info_table.iter_mut() {
- if !is_first_entry && entry.found {
- // except for the 'processor' field, ignore repeated values.
- continue;
- }
- is_first_entry = false;
- if field == entry.info_name {
- if let Some(val) = value {
- if let Ok(v) = val.parse() {
- entry.value = v;
- entry.found = true;
- } else {
- continue;
- }
- } else {
- continue;
+ let entry = match field {
+ "processor" => &mut processor,
+ "model" => &mut model,
+ "stepping" => &mut stepping,
+ "cpu family" => &mut family,
+ "vendor_id" => {
+ if vendor_id.is_none() && !value.is_empty() {
+ vendor_id = Some(value.to_owned());
}
+ continue;
}
+ _ => continue,
+ };
- // special case for vendor_id
- if field == vendor_id_name {
- vendor_id = value.filter(|v| !v.is_empty()).map(|v| (*v).to_owned());
- }
+ if entry.is_some() && field != "processor" {
+ continue;
+ }
+
+ if let Ok(v) = value.parse::() {
+ *entry = Some(v);
}
}
- // make sure we got everything we wanted
- if !cpu_info_table.iter().all(|x| x.found) {
- return Err(CpuInfoError::NotAllProcEntriesFound);
- }
- // cpu_info_table[0] holds the last cpu id listed in /proc/cpuinfo,
- // assuming this is the highest id, change it to the number of CPUs
- // by adding one.
- cpu_info_table[0].value += 1;
- sys_info.number_of_processors = cpu_info_table[0].value as u8; // TODO: might not work on special machines with LOTS of CPUs
+ // This holds the highest processor id which start from 0 so add 1 to get the actual count
+ // This field is only a u8 which means it will not work great in high (artificially or otherwise)
+ // contexts
+ sys_info.number_of_processors = std::cmp::max(
+ (processor.ok_or(CpuInfoError::NotAllProcEntriesFound)? + 1) as u8,
+ u8::MAX,
+ );
+
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
- sys_info.processor_level = cpu_info_table[3].value as u16;
- sys_info.processor_revision =
- (cpu_info_table[1].value << 8 | cpu_info_table[2].value) as u16;
- }
- if let Some(vendor_id) = vendor_id {
- let mut slice = vendor_id.as_bytes();
- for id_part in sys_info.cpu.vendor_id.iter_mut() {
- let (int_bytes, rest) = slice.split_at(std::mem::size_of::());
- slice = rest;
- *id_part = match int_bytes.try_into() {
- Ok(x) => u32::from_ne_bytes(x),
- Err(_) => {
- continue;
- }
- };
+ sys_info.processor_level = family.ok_or(CpuInfoError::NotAllProcEntriesFound)? as u16;
+ sys_info.processor_revision = (model.ok_or(CpuInfoError::NotAllProcEntriesFound)? << 8
+ | stepping.ok_or(CpuInfoError::NotAllProcEntriesFound)?)
+ as u16;
+
+ if let Some(vendor_id) = vendor_id {
+ let mut slice = vendor_id.as_bytes();
+
+ // SAFETY: CPU_INFORMATION is a block of bytes, which is actually
+ // a union, including the X86 information that we actually want to
+ // set
+ let cpu_info: &mut MDCPUInformation =
+ unsafe { &mut *sys_info.cpu.data.as_mut_ptr().cast() };
+
+ for id_part in cpu_info.vendor_id.iter_mut() {
+ let (int_bytes, rest) = slice.split_at(std::mem::size_of::());
+ slice = rest;
+ *id_part = match int_bytes.try_into() {
+ Ok(x) => u32::from_ne_bytes(x),
+ Err(_) => {
+ continue;
+ }
+ };
+ }
}
}
diff --git a/src/linux/errors.rs b/src/linux/errors.rs
index e35e10b0..2ce25037 100644
--- a/src/linux/errors.rs
+++ b/src/linux/errors.rs
@@ -126,6 +126,8 @@ pub enum MemoryWriterError {
IOError(#[from] std::io::Error),
#[error("Failed integer conversion")]
TryFromIntError(#[from] std::num::TryFromIntError),
+ #[error("Failed to write to buffer")]
+ Scroll(#[from] scroll::Error),
}
#[derive(Debug, Error)]
diff --git a/src/linux/minidump_writer.rs b/src/linux/minidump_writer.rs
index 39abd9b5..c2a1e4ec 100644
--- a/src/linux/minidump_writer.rs
+++ b/src/linux/minidump_writer.rs
@@ -11,9 +11,9 @@ use crate::{
},
minidump_format::*,
};
-use std::io::{Cursor, Seek, SeekFrom, Write};
+use std::io::{Seek, SeekFrom, Write};
-pub type DumpBuf = Cursor>;
+pub type DumpBuf = Buffer;
#[derive(Debug)]
pub struct DirSection<'a, W>
@@ -37,17 +37,18 @@ where
index_length: u32,
destination: &'a mut W,
) -> std::result::Result {
- let dir_section =
+ let section =
MemoryArrayWriter::::alloc_array(buffer, index_length as usize)?;
Ok(DirSection {
curr_idx: 0,
- section: dir_section,
+ section,
destination_start_offset: destination.seek(SeekFrom::Current(0))?,
destination,
last_position_written_to_file: 0,
})
}
+ #[inline]
fn position(&self) -> u32 {
self.section.position
}
@@ -66,16 +67,15 @@ where
let idx_pos = self.section.location_of_index(self.curr_idx);
self.curr_idx += 1;
- self.destination.seek(std::io::SeekFrom::Start(
+ self.destination.seek(SeekFrom::Start(
self.destination_start_offset + idx_pos.rva as u64,
))?;
let start = idx_pos.rva as usize;
let end = (idx_pos.rva + idx_pos.data_size) as usize;
- self.destination.write_all(&buffer.get_ref()[start..end])?;
+ self.destination.write_all(&buffer[start..end])?;
// Reset file-position
- self.destination
- .seek(std::io::SeekFrom::Start(curr_file_pos))?;
+ self.destination.seek(SeekFrom::Start(curr_file_pos))?;
Ok(())
}
@@ -93,7 +93,7 @@ where
}
let start_pos = self.last_position_written_to_file as usize;
- self.destination.write_all(&buffer.get_ref()[start_pos..])?;
+ self.destination.write_all(&buffer[start_pos..])?;
self.last_position_written_to_file = buffer.position();
Ok(())
}
@@ -201,14 +201,14 @@ impl MinidumpWriter {
}
}
- let mut buffer = Cursor::new(Vec::new());
+ let mut buffer = Buffer::with_capacity(4 * 1024);
self.generate_dump(&mut buffer, &mut dumper, destination)?;
// dumper would resume threads in drop() automatically,
// but in case there is an error, we want to catch it
dumper.resume_threads()?;
- Ok(buffer.into_inner())
+ Ok(buffer.into())
}
fn crash_thread_references_principal_mapping(&self, dumper: &PtraceDumper) -> bool {
@@ -282,7 +282,6 @@ impl MinidumpWriter {
signature: MD_HEADER_SIGNATURE,
version: MD_HEADER_VERSION,
stream_count: num_writers,
- // header.get()->stream_directory_rva = dir.position();
stream_directory_rva: dir_section.position(),
checksum: 0, /* Can be 0. In fact, that's all that's
* been found in minidump files. */
@@ -298,27 +297,21 @@ impl MinidumpWriter {
dir_section.write_to_file(buffer, None)?;
let dirent = thread_list_stream::write(self, buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = mappings::write(self, buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
app_memory::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, None)?;
let dirent = memory_list_stream::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = exception_stream::write(self, buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = systeminfo_stream::write(buffer)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, "/proc/cpuinfo") {
@@ -328,7 +321,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/status", self.blamed_thread))
@@ -339,7 +331,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self
@@ -352,7 +343,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/cmdline", self.blamed_thread))
@@ -363,7 +353,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/environ", self.blamed_thread))
@@ -374,7 +363,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/auxv", self.blamed_thread)) {
@@ -384,7 +372,6 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = match self.write_file(buffer, &format!("/proc/{}/maps", self.blamed_thread)) {
@@ -394,16 +381,13 @@ impl MinidumpWriter {
},
Err(_) => Default::default(),
};
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = dso_debug::write_dso_debug_stream(buffer, self.blamed_thread, &dumper.auxv)
.unwrap_or_default();
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
let dirent = thread_names_stream::write(buffer, dumper)?;
- // Write section to file
dir_section.write_to_file(buffer, Some(dirent))?;
// If you add more directory entries, don't forget to update kNumWriters,
@@ -419,7 +403,7 @@ impl MinidumpWriter {
) -> std::result::Result {
let content = std::fs::read(filename)?;
- let section = MemoryArrayWriter::::alloc_from_array(buffer, &content)?;
+ let section = MemoryArrayWriter::write_bytes(buffer, &content);
Ok(section.location())
}
}
diff --git a/src/linux/ptrace_dumper.rs b/src/linux/ptrace_dumper.rs
index 61c37c98..3f192ed5 100644
--- a/src/linux/ptrace_dumper.rs
+++ b/src/linux/ptrace_dumper.rs
@@ -9,7 +9,7 @@ use crate::{
thread_info::{Pid, ThreadInfo},
LINUX_GATE_LIBRARY_NAME,
},
- minidump_format::MDGUID,
+ minidump_format::GUID,
};
use goblin::elf;
use nix::sys::{ptrace, wait};
@@ -505,16 +505,16 @@ impl PtraceDumper {
// Only provide mem::size_of(MDGUID) bytes to keep identifiers produced by this
// function backwards-compatible.
let max_len = std::cmp::min(text_section.len(), 4096);
- let mut result = vec![0u8; std::mem::size_of::()];
+ let mut result = vec![0u8; std::mem::size_of::()];
let mut offset = 0;
while offset < max_len {
- for idx in 0..std::mem::size_of::() {
+ for idx in 0..std::mem::size_of::() {
if offset + idx >= text_section.len() {
break;
}
result[idx] ^= text_section[offset + idx];
}
- offset += std::mem::size_of::();
+ offset += std::mem::size_of::();
}
return Ok(result);
}
diff --git a/src/linux/sections.rs b/src/linux/sections.rs
index af1ef1b6..b7850ac0 100644
--- a/src/linux/sections.rs
+++ b/src/linux/sections.rs
@@ -14,12 +14,87 @@ use crate::{
},
minidump_format::*,
};
-use std::io::{Cursor, Write};
+use scroll::ctx::{SizeWith, TryIntoCtx};
-type Result = std::result::Result;
+type WriteResult = std::result::Result;
+
+macro_rules! size {
+ ($t:ty) => {
+ <$t>::size_with(&scroll::Endian::Little)
+ };
+}
+
+pub struct Buffer {
+ inner: Vec,
+}
+
+impl Buffer {
+ pub fn with_capacity(cap: usize) -> Self {
+ Self {
+ inner: Vec::with_capacity(cap),
+ }
+ }
+
+ #[inline]
+ pub fn position(&self) -> u64 {
+ self.inner.len() as u64
+ }
+
+ #[inline]
+ #[must_use]
+ fn reserve(&mut self, len: usize) -> usize {
+ let mark = self.inner.len();
+ self.inner.resize(self.inner.len() + len, 0);
+ mark
+ }
+
+ #[inline]
+ fn write(&mut self, val: N) -> Result
+ where
+ N: TryIntoCtx + SizeWith,
+ E: From,
+ {
+ self.write_at(self.inner.len(), val)
+ }
+
+ fn write_at(&mut self, offset: usize, val: N) -> Result
+ where
+ N: TryIntoCtx + SizeWith,
+ E: From,
+ {
+ let to_write = size!(N);
+ let remainder = self.inner.len() - offset;
+ if remainder < to_write {
+ self.inner
+ .resize(self.inner.len() + to_write - remainder, 0);
+ }
+
+ let dst = &mut self.inner[offset..offset + to_write];
+ val.try_into_ctx(dst, scroll::Endian::Little)
+ }
+
+ #[inline]
+ pub fn write_all(&mut self, buffer: &[u8]) {
+ self.inner.extend_from_slice(buffer);
+ }
+}
+
+impl From for Vec {
+ fn from(b: Buffer) -> Self {
+ b.inner
+ }
+}
+
+impl std::ops::Deref for Buffer {
+ type Target = [u8];
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
#[derive(Debug, PartialEq)]
-pub struct MemoryWriter {
+pub struct MemoryWriter {
pub position: MDRVA,
pub size: usize,
phantom: std::marker::PhantomData,
@@ -27,157 +102,159 @@ pub struct MemoryWriter {
impl MemoryWriter
where
- T: Default + Sized,
+ T: TryIntoCtx + SizeWith,
{
/// Create a slot for a type T in the buffer, we can fill right now with real values.
- pub fn alloc_with_val(buffer: &mut Cursor>, val: T) -> Result {
- // Get position of this value (e.g. before we add ourselves there)
+ pub fn alloc_with_val(buffer: &mut Buffer, val: T) -> WriteResult {
+ // Mark the position as we may overwrite later
let position = buffer.position();
- let size = std::mem::size_of::();
- let bytes = unsafe { std::slice::from_raw_parts((&val as *const T).cast(), size) };
- buffer.write_all(bytes)?;
+ let size = buffer.write(val)?;
- Ok(MemoryWriter {
+ Ok(Self {
position: position as u32,
size,
- phantom: std::marker::PhantomData:: {},
+ phantom: std::marker::PhantomData,
})
}
/// Create a slot for a type T in the buffer, we can fill later with real values.
- /// This function fills it with `Default::default()`, which is less performant than
- /// using uninitialized memory, but safe.
- pub fn alloc(buffer: &mut Cursor>) -> Result {
- // Filling out the buffer with default-values
- let val: T = Default::default();
- Self::alloc_with_val(buffer, val)
+ pub fn alloc(buffer: &mut Buffer) -> WriteResult {
+ let size = size!(T);
+ let position = buffer.reserve(size) as u32;
+
+ Ok(Self {
+ position: position as u32,
+ size,
+ phantom: std::marker::PhantomData,
+ })
}
/// Write actual values in the buffer-slot we got during `alloc()`
- pub fn set_value(&mut self, buffer: &mut Cursor>, val: T) -> Result<()> {
- // Save whereever the current cursor stands in the buffer
- let curr_pos = buffer.position();
-
- // Write the actual value we want at our position that
- // was determined by `alloc()` into the buffer
- buffer.set_position(self.position as u64);
- let bytes = unsafe {
- std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
- };
- let res = buffer.write_all(bytes);
-
- // Resetting whereever we were before updating this
- // regardless of the write-result
- buffer.set_position(curr_pos);
-
- res?;
- Ok(())
+ #[inline]
+ pub fn set_value(&mut self, buffer: &mut Buffer, val: T) -> WriteResult<()> {
+ Ok(buffer.write_at(self.position as usize, val).map(|_sz| ())?)
}
+ #[inline]
pub fn location(&self) -> MDLocationDescriptor {
MDLocationDescriptor {
- data_size: std::mem::size_of::() as u32,
+ data_size: size!(T) as u32,
rva: self.position,
}
}
}
#[derive(Debug, PartialEq)]
-pub struct MemoryArrayWriter {
+pub struct MemoryArrayWriter {
pub position: MDRVA,
array_size: usize,
phantom: std::marker::PhantomData,
}
+impl MemoryArrayWriter {
+ #[inline]
+ pub fn write_bytes(buffer: &mut Buffer, slice: &[u8]) -> Self {
+ let position = buffer.position();
+ buffer.write_all(slice);
+
+ Self {
+ position: position as u32,
+ array_size: slice.len(),
+ phantom: std::marker::PhantomData,
+ }
+ }
+}
+
+impl MemoryArrayWriter
+where
+ T: TryIntoCtx + SizeWith + Copy,
+{
+ pub fn alloc_from_array(buffer: &mut Buffer, array: &[T]) -> WriteResult {
+ let array_size = array.len();
+ let position = buffer.reserve(array_size * size!(T));
+
+ for (idx, val) in array.iter().enumerate() {
+ buffer.write_at(position + idx * size!(T), *val)?;
+ }
+
+ Ok(Self {
+ position: position as u32,
+ array_size,
+ phantom: std::marker::PhantomData,
+ })
+ }
+}
+
impl MemoryArrayWriter
where
- T: Default + Sized,
+ T: TryIntoCtx + SizeWith,
{
/// Create a slot for a type T in the buffer, we can fill in the values in one go.
- pub fn alloc_from_array(buffer: &mut Cursor>, array: &[T]) -> Result {
- // Get position of this value (e.g. before we add ourselves there)
- let position = buffer.position();
- for val in array {
- let bytes = unsafe {
- std::slice::from_raw_parts((val as *const T).cast(), std::mem::size_of::())
- };
- buffer.write_all(bytes)?;
+ pub fn alloc_from_iter(
+ buffer: &mut Buffer,
+ iter: impl IntoIterator- ,
+ ) -> WriteResult
+ where
+ I: std::iter::ExactSizeIterator
- ,
+ {
+ let iter = iter.into_iter();
+ let array_size = iter.len();
+ let size = size!(T);
+ let position = buffer.reserve(array_size * size);
+
+ for (idx, val) in iter.enumerate() {
+ buffer.write_at(position + idx * size, val)?;
}
- Ok(MemoryArrayWriter {
+ Ok(Self {
position: position as u32,
- array_size: array.len(),
- phantom: std::marker::PhantomData:: {},
+ array_size,
+ phantom: std::marker::PhantomData,
})
}
/// Create a slot for a type T in the buffer, we can fill later with real values.
/// This function fills it with `Default::default()`, which is less performant than
/// using uninitialized memory, but safe.
- pub fn alloc_array(buffer: &mut Cursor>, array_size: usize) -> Result {
- // Get position of this value (e.g. before we add ourselves there)
- let position = buffer.position();
- for _ in 0..array_size {
- // Filling out the buffer with default-values
- let val: T = Default::default();
- let bytes = unsafe {
- std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
- };
- buffer.write_all(bytes)?;
- }
+ pub fn alloc_array(buffer: &mut Buffer, array_size: usize) -> WriteResult {
+ let position = buffer.reserve(array_size * size!(T));
- Ok(MemoryArrayWriter {
+ Ok(Self {
position: position as u32,
array_size,
- phantom: std::marker::PhantomData:: {},
+ phantom: std::marker::PhantomData,
})
}
/// Write actual values in the buffer-slot we got during `alloc()`
- pub fn set_value_at(
- &mut self,
- buffer: &mut Cursor>,
- val: T,
- index: usize,
- ) -> Result<()> {
- // Save whereever the current cursor stands in the buffer
- let curr_pos = buffer.position();
-
- // Write the actual value we want at our position that
- // was determined by `alloc()` into the buffer
- buffer.set_position(self.position as u64 + (std::mem::size_of::() * index) as u64);
- let bytes = unsafe {
- std::slice::from_raw_parts((&val as *const T).cast(), std::mem::size_of::())
- };
- let res = buffer.write_all(bytes);
-
- // Resetting whereever we were before updating this
- // regardless of the write-result
- buffer.set_position(curr_pos);
-
- res?;
- Ok(())
+ #[inline]
+ pub fn set_value_at(&mut self, buffer: &mut Buffer, val: T, index: usize) -> WriteResult<()> {
+ Ok(buffer
+ .write_at(self.position as usize + size!(T) * index, val)
+ .map(|_sz| ())?)
}
+ #[inline]
pub fn location(&self) -> MDLocationDescriptor {
MDLocationDescriptor {
- data_size: (self.array_size * std::mem::size_of::()) as u32,
+ data_size: (self.array_size * size!(T)) as u32,
rva: self.position,
}
}
+ #[inline]
pub fn location_of_index(&self, idx: usize) -> MDLocationDescriptor {
MDLocationDescriptor {
- data_size: std::mem::size_of::() as u32,
- rva: self.position + (std::mem::size_of::() * idx) as u32,
+ data_size: size!(T) as u32,
+ rva: self.position + (size!(T) * idx) as u32,
}
}
}
pub fn write_string_to_location(
- buffer: &mut Cursor>,
+ buffer: &mut Buffer,
text: &str,
-) -> Result {
+) -> WriteResult {
let letters: Vec = text.encode_utf16().collect();
// First write size of the string (x letters in u16, times the size of u16)
diff --git a/src/linux/sections/app_memory.rs b/src/linux/sections/app_memory.rs
index 36efcd4a..824e0cf5 100644
--- a/src/linux/sections/app_memory.rs
+++ b/src/linux/sections/app_memory.rs
@@ -12,7 +12,7 @@ pub fn write(
app_memory.length,
)?;
- let section = MemoryArrayWriter::::alloc_from_array(buffer, &data_copy)?;
+ let section = MemoryArrayWriter::write_bytes(buffer, &data_copy);
let desc = MDMemoryDescriptor {
start_of_memory_range: app_memory.ptr as u64,
memory: section.location(),
diff --git a/src/linux/sections/mappings.rs b/src/linux/sections/mappings.rs
index 642e9736..6fb875fc 100644
--- a/src/linux/sections/mappings.rs
+++ b/src/linux/sections/mappings.rs
@@ -54,7 +54,7 @@ pub fn write(
};
if !modules.is_empty() {
- let mapping_list = MemoryArrayWriter::::alloc_from_array(buffer, &modules)?;
+ let mapping_list = MemoryArrayWriter::::alloc_from_iter(buffer, modules)?;
dirent.location.data_size += mapping_list.location().data_size;
}
@@ -70,7 +70,7 @@ fn fill_raw_module(
// Just zeroes
Default::default()
} else {
- let cv_signature = MD_CVINFOELF_SIGNATURE;
+ let cv_signature = minidump_common::format::CvSignature::Elf as u32;
let array_size = std::mem::size_of_val(&cv_signature) + identifier.len();
let mut sig_section = MemoryArrayWriter::::alloc_array(buffer, array_size)?;
diff --git a/src/linux/sections/systeminfo_stream.rs b/src/linux/sections/systeminfo_stream.rs
index 18af398d..5fc68eff 100644
--- a/src/linux/sections/systeminfo_stream.rs
+++ b/src/linux/sections/systeminfo_stream.rs
@@ -1,5 +1,5 @@
use super::*;
-use crate::linux::dumper_cpu_info::{write_cpu_information, write_os_information};
+use crate::linux::dumper_cpu_info::{os_information, write_cpu_information};
type Result = std::result::Result;
@@ -9,9 +9,16 @@ pub fn write(buffer: &mut DumpBuf) -> Result {
stream_type: MDStreamType::SystemInfoStream as u32,
location: info_section.location(),
};
- let mut info: MDRawSystemInfo = Default::default();
+
+ let (platform_id, os_version) = os_information();
+ let os_version_loc = write_string_to_location(buffer, &os_version)?;
+
+ // SAFETY: POD
+ let mut info = unsafe { std::mem::zeroed::() };
+ info.platform_id = platform_id as u32;
+ info.csd_version_rva = os_version_loc.rva;
+
write_cpu_information(&mut info)?;
- write_os_information(buffer, &mut info)?;
info_section.set_value(buffer, info)?;
Ok(dirent)
diff --git a/src/linux/sections/thread_list_stream.rs b/src/linux/sections/thread_list_stream.rs
index 6d30e2c1..24fff508 100644
--- a/src/linux/sections/thread_list_stream.rs
+++ b/src/linux/sections/thread_list_stream.rs
@@ -3,7 +3,6 @@ use crate::{
linux::crash_context::CpuContext, minidump_cpu::RawContextCPU,
minidump_writer::CrashingThreadContext,
};
-use std::io::Write;
type Result = std::result::Result;
@@ -66,7 +65,12 @@ pub fn write(
for (idx, item) in dumper.threads.clone().iter().enumerate() {
let mut thread = MDRawThread {
thread_id: item.tid.try_into()?,
- ..Default::default()
+ suspend_count: 0,
+ priority_class: 0,
+ priority: 0,
+ teb: 0,
+ stack: MDMemoryDescriptor::default(),
+ thread_context: MDLocationDescriptor::default(),
};
// We have a different source of information for the crashing thread. If
@@ -230,7 +234,7 @@ fn fill_thread_stack(
data_size: stack_bytes.len() as u32,
rva: buffer.position() as u32,
};
- buffer.write_all(&stack_bytes)?;
+ buffer.write_all(&stack_bytes);
thread.stack.start_of_memory_range = stack as u64;
thread.stack.memory = stack_location;
config.memory_blocks.push(thread.stack.clone());
diff --git a/src/linux/thread_info/x86.rs b/src/linux/thread_info/x86.rs
index 04db7b4d..944a4e47 100644
--- a/src/linux/thread_info/x86.rs
+++ b/src/linux/thread_info/x86.rs
@@ -1,15 +1,12 @@
use super::{CommonThreadInfo, NT_Elf, Pid};
use crate::errors::ThreadInfoError;
-use crate::minidump_cpu::imp::*;
use crate::minidump_cpu::RawContextCPU;
#[cfg(target_arch = "x86_64")]
use crate::thread_info::copy_u32_registers;
use core::mem::size_of_val;
-use libc;
-use libc::user;
+use libc::{self, user};
use memoffset;
-use nix::sys::ptrace;
-use nix::unistd;
+use nix::{sys::ptrace, unistd};
type Result = std::result::Result;
@@ -144,7 +141,9 @@ impl ThreadInfoX86 {
#[cfg(target_arch = "x86_64")]
pub fn fill_cpu_context(&self, out: &mut RawContextCPU) {
- out.context_flags = MD_CONTEXT_AMD64_FULL | MD_CONTEXT_AMD64_SEGMENTS;
+ out.context_flags = crate::minidump_format::format::ContextFlagsAmd64::CONTEXT_AMD64_FULL
+ .bits()
+ | crate::minidump_format::format::ContextFlagsAmd64::CONTEXT_AMD64_SEGMENTS.bits();
out.cs = self.regs.cs as u16; // TODO: This is u64, do we loose information by doing this?
@@ -186,19 +185,31 @@ impl ThreadInfoX86 {
out.rip = self.regs.rip;
- out.flt_save.control_word = self.fpregs.cwd;
- out.flt_save.status_word = self.fpregs.swd;
- out.flt_save.tag_word = self.fpregs.ftw as u8; // TODO: This is u16, do we loose information by doing this?
- out.flt_save.error_opcode = self.fpregs.fop;
- out.flt_save.error_offset = self.fpregs.rip as u32; // TODO: This is u64, do we loose information by doing this?
- out.flt_save.error_selector = 0; // We don't have this.
- out.flt_save.data_offset = self.fpregs.rdp as u32; // TODO: This is u64, do we loose information by doing this?
- out.flt_save.data_selector = 0; // We don't have this.
- out.flt_save.mx_csr = self.fpregs.mxcsr;
- out.flt_save.mx_csr_mask = self.fpregs.mxcr_mask;
-
- copy_u32_registers(&mut out.flt_save.float_registers, &self.fpregs.st_space);
- copy_u32_registers(&mut out.flt_save.xmm_registers, &self.fpregs.xmm_space);
+ {
+ let fs = self.fpregs;
+ let mut float_save = crate::minidump_cpu::FloatStateCPU {
+ control_word: fs.cwd,
+ status_word: fs.swd,
+ tag_word: fs.ftw as u8,
+ error_opcode: fs.fop,
+ error_offset: fs.rip as u32,
+ data_offset: fs.rdp as u32,
+ error_selector: 0, // We don't have this.
+ data_selector: 0, // We don't have this.
+ mx_csr: fs.mxcsr,
+ mx_csr_mask: fs.mxcr_mask,
+ ..Default::default()
+ };
+
+ copy_u32_registers(&mut float_save.float_registers, &fs.st_space);
+ copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space);
+
+ use scroll::Pwrite;
+ // TODO: handle errors
+ out.float_save
+ .pwrite_with(float_save, 0, scroll::Endian::Little)
+ .unwrap();
+ }
}
#[cfg(target_arch = "x86")]
diff --git a/src/minidump_cpu.rs b/src/minidump_cpu.rs
index 104553eb..7bd08c06 100644
--- a/src/minidump_cpu.rs
+++ b/src/minidump_cpu.rs
@@ -1,8 +1,7 @@
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
- pub mod amd64;
- pub use amd64 as imp;
- pub type RawContextCPU = amd64::MDRawContextAMD64;
+ pub type RawContextCPU = minidump_common::format::CONTEXT_AMD64;
+ pub type FloatStateCPU = minidump_common::format::XMM_SAVE_AREA32;
} else if #[cfg(target_arch = "x86")] {
pub mod x86;
pub use x86 as imp;
diff --git a/src/minidump_cpu/amd64.rs b/src/minidump_cpu/amd64.rs
deleted file mode 100644
index 3924d792..00000000
--- a/src/minidump_cpu/amd64.rs
+++ /dev/null
@@ -1,179 +0,0 @@
-#[repr(C)]
-pub struct MDXmmSaveArea32AMD64 {
- pub control_word: u16,
- pub status_word: u16,
- pub tag_word: u8,
- pub reserved1: u8,
- pub error_opcode: u16,
- pub error_offset: u32,
- pub error_selector: u16,
- pub reserved2: u16,
- pub data_offset: u32,
- pub data_selector: u16,
- pub reserved3: u16,
- pub mx_csr: u32,
- pub mx_csr_mask: u32,
- pub float_registers: [u128; 8],
- pub xmm_registers: [u128; 16],
- pub reserved4: [u8; 96],
-}
-
-// The std library doesn't provide "Default" for all
-// array-lengths. Only up to 32. So we have to implement
-// our own default, because of `reserved4: [u8; 96]`
-impl Default for MDXmmSaveArea32AMD64 {
- #[inline]
- fn default() -> Self {
- MDXmmSaveArea32AMD64 {
- control_word: 0,
- status_word: 0,
- tag_word: 0,
- reserved1: 0,
- error_opcode: 0,
- error_offset: 0,
- error_selector: 0,
- reserved2: 0,
- data_offset: 0,
- data_selector: 0,
- reserved3: 0,
- mx_csr: 0,
- mx_csr_mask: 0,
- float_registers: [0; 8],
- xmm_registers: [0; 16],
- reserved4: [0; 96],
- }
- }
-}
-
-const MD_CONTEXT_AMD64_VR_COUNT: usize = 26;
-
-#[repr(C)]
-#[derive(Default)]
-pub struct MDRawContextAMD64 {
- /*
- * Register parameter home addresses.
- */
- pub p1_home: u64,
- pub p2_home: u64,
- pub p3_home: u64,
- pub p4_home: u64,
- pub p5_home: u64,
- pub p6_home: u64,
-
- /* The next field determines the layout of the structure, and which parts
- * of it are populated */
- pub context_flags: u32,
- pub mx_csr: u32,
-
- /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
- pub cs: u16,
-
- /* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */
- pub ds: u16,
- pub es: u16,
- pub fs: u16,
- pub gs: u16,
-
- /* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
- pub ss: u16,
- pub eflags: u32,
-
- /* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
- pub dr0: u64,
- pub dr1: u64,
- pub dr2: u64,
- pub dr3: u64,
- pub dr6: u64,
- pub dr7: u64,
-
- /* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */
- pub rax: u64,
- pub rcx: u64,
- pub rdx: u64,
- pub rbx: u64,
-
- /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
- pub rsp: u64,
-
- /* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */
- pub rbp: u64,
- pub rsi: u64,
- pub rdi: u64,
- pub r8: u64,
- pub r9: u64,
- pub r10: u64,
- pub r11: u64,
- pub r12: u64,
- pub r13: u64,
- pub r14: u64,
- pub r15: u64,
-
- /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
- pub rip: u64,
-
- /* The next set of registers are included with
- * MD_CONTEXT_AMD64_FLOATING_POINT
- */
- pub flt_save: MDXmmSaveArea32AMD64,
- // union {
- // MDXmmSaveArea32AMD64 flt_save;
- // struct {
- // uint128_struct header[2];
- // uint128_struct legacy[8];
- // uint128_struct xmm0;
- // uint128_struct xmm1;
- // uint128_struct xmm2;
- // uint128_struct xmm3;
- // uint128_struct xmm4;
- // uint128_struct xmm5;
- // uint128_struct xmm6;
- // uint128_struct xmm7;
- // uint128_struct xmm8;
- // uint128_struct xmm9;
- // uint128_struct xmm10;
- // uint128_struct xmm11;
- // uint128_struct xmm12;
- // uint128_struct xmm13;
- // uint128_struct xmm14;
- // uint128_struct xmm15;
- // } sse_registers;
- // };
- pub vector_register: [u128; MD_CONTEXT_AMD64_VR_COUNT],
- pub vector_control: u64,
-
- /* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
- pub debug_control: u64,
- pub last_branch_to_rip: u64,
- pub last_branch_from_rip: u64,
- pub last_exception_to_rip: u64,
- pub last_exception_from_rip: u64,
-}
-
-/* For (MDRawContextAMD64).context_flags. These values indicate the type of
-* context stored in the structure. The high 24 bits identify the CPU, the
-* low 8 bits identify the type of context saved. */
-pub const MD_CONTEXT_AMD64: u32 = 0x00100000; /* CONTEXT_AMD64 */
-pub const MD_CONTEXT_AMD64_CONTROL: u32 = MD_CONTEXT_AMD64 | 0x00000001;
-/* CONTEXT_CONTROL */
-pub const MD_CONTEXT_AMD64_INTEGER: u32 = MD_CONTEXT_AMD64 | 0x00000002;
-/* CONTEXT_INTEGER */
-pub const MD_CONTEXT_AMD64_SEGMENTS: u32 = MD_CONTEXT_AMD64 | 0x00000004;
-/* CONTEXT_SEGMENTS */
-pub const MD_CONTEXT_AMD64_FLOATING_POINT: u32 = MD_CONTEXT_AMD64 | 0x00000008;
-/* CONTEXT_FLOATING_POINT */
-pub const MD_CONTEXT_AMD64_DEBUG_REGISTERS: u32 = MD_CONTEXT_AMD64 | 0x00000010;
-/* CONTEXT_DEBUG_REGISTERS */
-pub const MD_CONTEXT_AMD64_XSTATE: u32 = MD_CONTEXT_AMD64 | 0x00000040;
-/* CONTEXT_XSTATE */
-
-/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it
-* I think it really means CONTEXT_FLOATING_POINT.
-*/
-
-pub const MD_CONTEXT_AMD64_FULL: u32 =
- MD_CONTEXT_AMD64_CONTROL | MD_CONTEXT_AMD64_INTEGER | MD_CONTEXT_AMD64_FLOATING_POINT;
-/* CONTEXT_FULL */
-
-pub const MD_CONTEXT_AMD64_ALL: u32 =
- MD_CONTEXT_AMD64_FULL | MD_CONTEXT_AMD64_SEGMENTS | MD_CONTEXT_AMD64_DEBUG_REGISTERS;
-/* CONTEXT_ALL */
diff --git a/src/minidump_format.rs b/src/minidump_format.rs
index a14026b3..8ffa40fc 100644
--- a/src/minidump_format.rs
+++ b/src/minidump_format.rs
@@ -1,437 +1,40 @@
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDGUID {
- data1: u32,
- data2: u16,
- data3: u16,
- data4: [u8; 8],
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq, Clone, Copy)]
-pub struct MDVSFixedFileInfo {
- pub signature: u32,
- pub struct_version: u32,
- pub file_version_hi: u32,
- pub file_version_lo: u32,
- pub product_version_hi: u32,
- pub product_version_lo: u32,
- pub file_flags_mask: u32, /* Identifies valid bits in fileFlags */
- pub file_flags: u32,
- pub file_os: u32,
- pub file_type: u32,
- pub file_subtype: u32,
- pub file_date_hi: u32,
- pub file_date_lo: u32,
-}
+pub use minidump_common::format::{
+ self, ArmElfHwCaps as MDCPUInformationARMElfHwCaps, PlatformId,
+ ProcessorArchitecture as MDCPUArchitecture, GUID, MINIDUMP_DIRECTORY as MDRawDirectory,
+ MINIDUMP_EXCEPTION as MDException, MINIDUMP_EXCEPTION_STREAM as MDRawExceptionStream,
+ MINIDUMP_HEADER as MDRawHeader, MINIDUMP_LOCATION_DESCRIPTOR as MDLocationDescriptor,
+ MINIDUMP_MEMORY_DESCRIPTOR as MDMemoryDescriptor, MINIDUMP_MODULE as MDRawModule,
+ MINIDUMP_SIGNATURE as MD_HEADER_SIGNATURE, MINIDUMP_STREAM_TYPE as MDStreamType,
+ MINIDUMP_SYSTEM_INFO as MDRawSystemInfo, MINIDUMP_THREAD as MDRawThread,
+ MINIDUMP_THREAD_NAME as MDRawThreadName, MINIDUMP_VERSION as MD_HEADER_VERSION,
+ VS_FIXEDFILEINFO as MDVSFixedFileInfo,
+};
/* An MDRVA is an offset into the minidump file. The beginning of the
* MDRawHeader is at offset 0. */
pub type MDRVA = u32;
-#[repr(C)]
-#[derive(Debug, Default, Clone, Copy, PartialEq)]
-pub struct MDLocationDescriptor {
- pub data_size: u32,
- pub rva: MDRVA,
-}
-
-#[repr(C)]
-#[derive(Debug, Default, Clone, PartialEq)]
-pub struct MDMemoryDescriptor {
- /* The base address of the memory range on the host that produced the
- * minidump. */
- pub start_of_memory_range: u64,
- pub memory: MDLocationDescriptor,
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawHeader {
- pub signature: u32,
- pub version: u32,
- pub stream_count: u32,
- pub stream_directory_rva: MDRVA, /* A |stream_count|-sized array of
- * MDRawDirectory structures. */
- pub checksum: u32, /* Can be 0. In fact, that's all that's
- * been found in minidump files. */
- pub time_date_stamp: u32, /* time_t */
- pub flags: u64,
-}
-
-/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the
- * low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION. Per the
- * documentation, the high 16 bits are implementation-specific. */
-pub const MD_HEADER_SIGNATURE: u32 = 0x504d444d; /* 'PMDM' */
-/* MINIDUMP_SIGNATURE */
-pub const MD_HEADER_VERSION: u32 = 0x0000a793; /* 42899 */
-/* MINIDUMP_VERSION */
-
-/// The name of a thread, found in the [`MDStreamType::ThreadNamesStream`].
-#[repr(C, packed)]
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub struct MDRawThreadName {
- /// The id of the thread.
- pub thread_id: u32,
- /// Where the name of the thread is stored (yes, the legendary RVA64 is real!!).
- pub thread_name_rva: u64,
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawThread {
- pub thread_id: u32,
- pub suspend_count: u32,
- pub priority_class: u32,
- pub priority: u32,
- pub teb: u64, /* Thread environment block */
- pub stack: MDMemoryDescriptor,
- pub thread_context: MDLocationDescriptor, /* MDRawContext[CPU] */
-}
-
pub type MDRawThreadList = Vec;
-/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to
- * be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC).
- * This doesn't occur on systems that don't tail-pad in this manner. Define
- * this macro to be the usable size of the MDRawModule struct, and use it in
- * place of sizeof(MDRawModule). */
-// pub const MD_MODULE_SIZE: usize = 108;
-// NOTE: We use "packed" here instead, to size_of::() == 108
-// "packed" should be safe here, as we don't address reserved{0,1} at all
-// and padding should happen only at the tail
-#[repr(C, packed)]
-#[derive(Clone, Copy, Debug, Default, PartialEq)]
-pub struct MDRawModule {
- pub base_of_image: u64,
- pub size_of_image: u32,
- pub checksum: u32, /* 0 if unknown */
- pub time_date_stamp: u32, /* time_t */
- pub module_name_rva: MDRVA, /* MDString, pathname or filename */
- pub version_info: MDVSFixedFileInfo,
-
- /* The next field stores a CodeView record and is populated when a module's
- * debug information resides in a PDB file. It identifies the PDB file. */
- pub cv_record: MDLocationDescriptor,
-
- /* The next field is populated when a module's debug information resides
- * in a DBG file. It identifies the DBG file. This field is effectively
- * obsolete with modules built by recent toolchains. */
- pub misc_record: MDLocationDescriptor,
-
- /* Alignment problem: reserved0 and reserved1 are defined by the platform
- * SDK as 64-bit quantities. However, that results in a structure whose
- * alignment is unpredictable on different CPUs and ABIs. If the ABI
- * specifies full alignment of 64-bit quantities in structures (as ppc
- * does), there will be padding between miscRecord and reserved0. If
- * 64-bit quantities can be aligned on 32-bit boundaries (as on x86),
- * this padding will not exist. (Note that the structure up to this point
- * contains 1 64-bit member followed by 21 32-bit members.)
- * As a workaround, reserved0 and reserved1 are instead defined here as
- * four 32-bit quantities. This should be harmless, as there are
- * currently no known uses for these fields. */
- pub reserved0: [u32; 2],
- pub reserved1: [u32; 2],
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq, Clone)]
-pub struct MDRawDirectory {
- pub stream_type: u32,
- pub location: MDLocationDescriptor,
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDException {
- pub exception_code: u32, /* Windows: MDExceptionCodeWin,
- * Mac OS X: MDExceptionMac,
- * Linux: MDExceptionCodeLinux. */
- pub exception_flags: u32, /* Windows: 1 if noncontinuable,
- Mac OS X: MDExceptionCodeMac. */
- pub exception_record: u64, /* Address (in the minidump-producing host's
- * memory) of another MDException, for
- * nested exceptions. */
- pub exception_address: u64, /* The address that caused the exception.
- * Mac OS X: exception subcode (which is
- * typically the address). */
- pub number_parameters: u32, /* Number of valid elements in
- * exception_information. */
- pub __align: u32,
- pub exception_information: [u64; 15],
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawExceptionStream {
- pub thread_id: u32, /* Thread in which the exception
- * occurred. Corresponds to
- * (MDRawThread).thread_id. */
- pub __align: u32,
- pub exception_record: MDException,
- pub thread_context: MDLocationDescriptor, /* MDRawContext[CPU] */
-}
-
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDCPUInformation {
- pub vendor_id: [u32; 3], /* cpuid 0: ebx, edx, ecx */
- pub version_information: u32, /* cpuid 1: eax */
- pub feature_information: u32, /* cpuid 1: edx */
- pub amd_extended_cpu_features: u32, /* cpuid 0x80000001, ebx */
-}
-
-#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDCPUInformation {
- pub cpuid: u32,
- pub elf_hwcaps: u32, /* linux specific, 0 otherwise */
- _padding: [u32; 4],
-}
-
-#[cfg(target_arch = "mips")]
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDCPUInformation {
- pub cpuid: [u64; 2],
- _padding: [u32; 2],
-}
-
-/* For (MDCPUInformation).arm_cpu_info.elf_hwcaps.
- * This matches the Linux kernel definitions from */
-#[repr(u32)]
-pub enum MDCPUInformationARMElfHwCaps {
- Swp = 1 << 0,
- Half = 1 << 1,
- Thumb = 1 << 2,
- Bit26 = 1 << 3,
- FastMult = 1 << 4,
- Fpa = 1 << 5,
- Vfp = 1 << 6,
- Edsp = 1 << 7,
- Java = 1 << 8,
- Iwmmxt = 1 << 9,
- Crunch = 1 << 10,
- Thumbee = 1 << 11,
- Neon = 1 << 12,
- Vfpv3 = 1 << 13,
- Vfpv3d16 = 1 << 14,
- Tls = 1 << 15,
- Vfpv4 = 1 << 16,
- Idiva = 1 << 17,
- Idivt = 1 << 18,
-}
-
-#[repr(C)]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawSystemInfo {
- /* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO
- * structure as returned by GetSystemInfo */
- pub processor_architecture: u16,
- pub processor_level: u16, /* x86: 5 = 586, 6 = 686, ... */
- /* ARM: 6 = ARMv6, 7 = ARMv7 ... */
- pub processor_revision: u16, /* x86: 0xMMSS, where MM=model,
- * SS=stepping */
- /* ARM: 0 */
- pub number_of_processors: u8,
- pub product_type: u8, /* Windows: VER_NT_* from WinNT.h */
-
- /* The next 5 fields are from the OSVERSIONINFO structure as returned
- * by GetVersionEx */
- pub major_version: u32,
- pub minor_version: u32,
- pub build_number: u32,
- pub platform_id: u32,
- pub csd_version_rva: MDRVA, /* MDString further identifying the
- * host OS.
- * Windows: name of the installed OS
- * service pack.
- * Mac OS X: the Apple OS build number
- * (sw_vers -buildVersion).
- * Linux: uname -srvmo */
-
- pub suite_mask: u16, /* Windows: VER_SUITE_* from WinNT.h */
- pub reserved2: u16,
-
- pub cpu: MDCPUInformation,
-}
-
-#[cfg(target_pointer_width = "64")]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawLinkMap {
- pub addr: u64,
- pub name: MDRVA,
- pub ld: u64,
-}
-
-#[cfg(target_pointer_width = "64")]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawDebug {
- pub version: u32,
- pub map: MDRVA, /* array of MDRawLinkMap64 */
- pub dso_count: u32,
- pub brk: u64,
- pub ldbase: u64,
- pub dynamic: u64,
-}
-
-#[cfg(target_pointer_width = "32")]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawLinkMap {
- pub addr: u32,
- pub name: MDRVA,
- pub ld: u32,
-}
-
-#[cfg(target_pointer_width = "32")]
-#[derive(Debug, Default, PartialEq)]
-pub struct MDRawDebug {
- pub version: u32,
- pub map: MDRVA, /* array of MDRawLinkMap32 */
- pub dso_count: u32,
- pub brk: u32,
- pub ldbase: u32,
- pub dynamic: u32,
-}
-
-/* For (MDRawSystemInfo).processor_architecture: */
-#[repr(u16)]
-pub enum MDCPUArchitecture {
- X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
- Mips = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
- Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
- Ppc = 3, /* PROCESSOR_ARCHITECTURE_PPC */
- Shx = 4, /* PROCESSOR_ARCHITECTURE_SHX
- * (Super-H) */
- Arm = 5, /* PROCESSOR_ARCHITECTURE_ARM */
- Ia64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
- Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
- Msil = 8, /* PROCESSOR_ARCHITECTURE_MSIL
- * (Microsoft Intermediate Language) */
- Amd64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
- X86Win64 = 10,
- /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
- Arm64 = 12, /* PROCESSOR_ARCHITECTURE_ARM64 */
- Sparc = 0x8001, /* Breakpad-defined value for SPARC */
- Ppc64 = 0x8002, /* Breakpad-defined value for PPC64 */
- Arm64Old = 0x8003, /* Breakpad-defined value for ARM64 */
- Mips64 = 0x8004, /* Breakpad-defined value for MIPS64 */
- Unknown = 0xffff, /* PROCESSOR_ARCHITECTURE_UNKNOWN */
-}
-
-/* For (MDRawSystemInfo).platform_id: */
-#[repr(u32)]
-pub enum MDOSPlatform {
- Win32s = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
- Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
- Win32Nt = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
- Win32Ce = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
- * (Windows CE, Windows Mobile, "Handheld") */
- /* The following values are Breakpad-defined. */
- Unix = 0x8000, /* Generic Unix-ish */
- MacOsX = 0x8101, /* Mac OS X/Darwin */
- Ios = 0x8102, /* iOS */
- Linux = 0x8201, /* Linux */
- Solaris = 0x8202, /* Solaris */
- Android = 0x8203, /* Android */
- Ps3 = 0x8204, /* PS3 */
- Nacl = 0x8205, /* Native Client (NaCl) */
- Fuchsia = 0x8206, /* Fuchsia */
-}
-
-/*
- * Modern ELF toolchains insert a "build id" into the ELF headers that
- * usually contains a hash of some ELF headers + sections to uniquely
- * identify a binary.
- *
- * https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Developer_Guide/compiling-build-id.html
- * https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292
- */
-pub const MD_CVINFOELF_SIGNATURE: u32 = 0x4270454c; /* cvSignature = 'BpEL' */
-/* Signature is followed by the bytes of the
- * build id from GNU_BUILD_ID ELF note.
- * This is variable-length, but usually 20 bytes
- * as the binutils ld default is a SHA-1 hash. */
-
-/* For (MDRawHeader).flags: */
-pub enum MDType {
- /* MD_NORMAL is the standard type of minidump. It includes full
- * streams for the thread list, module list, exception, system info,
- * and miscellaneous info. A memory list stream is also present,
- * pointing to the same stack memory contained in the thread list,
- * as well as a 256-byte region around the instruction address that
- * was executing when the exception occurred. Stack memory is from
- * 4 bytes below a thread's stack pointer up to the top of the
- * memory region encompassing the stack. */
- Normal = 0x00000000,
- WithDataSegs = 0x00000001,
- WithFullMemory = 0x00000002,
- WithHandleData = 0x00000004,
- FilterMemory = 0x00000008,
- ScanMemory = 0x00000010,
- WithUnloadedModules = 0x00000020,
- WithIndirectlyReferencedMemory = 0x00000040,
- FilterModulePaths = 0x00000080,
- WithProcessThreadData = 0x00000100,
- WithPrivateReadWriteMemory = 0x00000200,
- WithoutOptionalData = 0x00000400,
- WithFullMemoryInfo = 0x00000800,
- WithThreadInfo = 0x00001000,
- WithCodeSegs = 0x00002000,
- WithoutAuxilliarySegs = 0x00004000,
- WithFullAuxilliaryState = 0x00008000,
- WithPrivateWriteCopyMemory = 0x00010000,
- IgnoreInaccessibleMemory = 0x00020000,
- WithTokenInformation = 0x00040000,
-}
-
-/* For (MDRawDirectory).stream_type */
-#[repr(u32)]
-pub enum MDStreamType {
- UnusedStream = 0,
- ReservedStream0 = 1,
- ReservedStream1 = 2,
- ThreadListStream = 3, /* MDRawThreadList */
- ModuleListStream = 4, /* MDRawModuleList */
- MemoryListStream = 5, /* MDRawMemoryList */
- ExceptionStream = 6, /* MDRawExceptionStream */
- SystemInfoStream = 7, /* MDRawSystemInfo */
- ThreadExListStream = 8,
- Memory64ListStream = 9,
- CommentStreamA = 10,
- CommentStreamW = 11,
- HandleDataStream = 12,
- FunctionTableStream = 13,
- UnloadedModuleListStream = 14,
- MiscInfoStream = 15, /* MDRawMiscInfo */
- MemoryInfoListStream = 16, /* MDRawMemoryInfoList */
- ThreadInfoListStream = 17,
- HandleOperationListStream = 18,
- TokenStream = 19,
- JavascriptDataStream = 20,
- SystemMemoryInfoStream = 21,
- ProcessVmCountersStream = 22,
- IptTraceStream = 23,
- ThreadNamesStream = 24,
- LastReservedStream = 0x0000ffff,
-
- /* Breakpad extension types. 0x4767 = "Gg" */
- BreakpadInfoStream = 0x47670001, /* MDRawBreakpadInfo */
- AssertionInfoStream = 0x47670002, /* MDRawAssertionInfo */
- /* These are additional minidump stream values which are specific to
- * the linux breakpad implementation. */
- LinuxCpuInfo = 0x47670003, /* /proc/cpuinfo */
- LinuxProcStatus = 0x47670004, /* /proc/$x/status */
- LinuxLsbRelease = 0x47670005, /* /etc/lsb-release */
- LinuxCmdLine = 0x47670006, /* /proc/$x/cmdline */
- LinuxEnviron = 0x47670007, /* /proc/$x/environ */
- LinuxAuxv = 0x47670008, /* /proc/$x/auxv */
- LinuxMaps = 0x47670009, /* /proc/$x/maps */
- LinuxDsoDebug = 0x4767000A, /* MDRawDebug{32,64} */
-
- /* Crashpad extension types. 0x4350 = "CP"
- * See Crashpad's minidump/minidump_extensions.h. */
- CrashpadInfoStream = 0x43500001, /* MDRawCrashpadInfo */
+cfg_if::cfg_if! {
+ if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
+ pub use format::X86CpuInfo as MDCPUInformation;
+ } else if #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] {
+ pub use format::ARMCpuInfo as MDCPUInformation;
+ } else if #[cfg(target_arch = "mips")] {
+ pub struct MDCPUInformation {
+ pub cpuid: [u64; 2],
+ _padding: [u32; 2],
+ }
+ }
+}
+
+cfg_if::cfg_if! {
+ if #[cfg(target_pointer_width = "64")] {
+ pub use format::LINK_MAP_64 as MDRawLinkMap;
+ pub use format::DSO_DEBUG_64 as MDRawDebug;
+ } else if #[cfg(target_pointer_width = "32")] {
+ pub use format::LINK_MAP_32 as MDRawLinkMap;
+ pub use format::DSO_DEBUG_32 as MDRawDebug;
+ }
}
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index 3e568fb2..c2752af3 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -170,7 +170,7 @@ fn test_write_and_read_dump_from_parent_helper(context: Context) {
assert_eq!(module.code_file(), "a fake mapping");
assert_eq!(
module.debug_identifier(),
- Some("33221100554477668899AABBCCDDEEFF0".into())
+ Some("33221100554477668899AABBCCDDEEFF0".parse().unwrap())
);
let _: MinidumpException = dump.get_stream().expect("Couldn't find MinidumpException");
@@ -511,7 +511,7 @@ fn test_with_deleted_binary() {
assert_eq!(main_module.code_file(), binary_copy.to_string_lossy());
assert_eq!(
main_module.debug_identifier(),
- Some(std::borrow::Cow::from(filtered.as_str()))
+ Some(filtered.parse().unwrap())
);
}
From 0dc99fc07d63e8c62019bb992cdbcb3407c09911 Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 10 Mar 2022 07:27:01 +0100
Subject: [PATCH 18/21] Fixup
---
Cargo.toml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 14bd0e9a..ab8cce96 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,24 +8,24 @@ license = "MIT"
[dependencies]
byteorder = "1.3.2"
cfg-if = "1.0"
-exception-handler = { path = "../crash-handling/exception-handler" }
+exception-handler = { path = "../exception-handler" }
goblin = "0.5"
libc = "0.2.74"
memmap2 = "0.5"
memoffset = "0.6"
-minidump = "*"
-minidump-common = "*"
+minidump-common = "0.9"
nix = "0.23"
scroll = "0.11"
tempfile = "3.1.0"
thiserror = "1.0.21"
[dev-dependencies]
-uctx = { path = "../crash-handling/uctx" }
debugid = "0.7.3"
+minidump = "0.9"
+uctx = { path = "../uctx" }
[patch.crates-io]
-#minidump = { git = "https://github.com/EmbarkStudios/rust-minidump", rev = "228c5d0" }
-#minidump-common = { git = "https://github.com/EmbarkStudios/rust-minidump", rev = "228c5d0" }
-minidump = { path = "../rust-minidump/minidump" }
-minidump-common = { path = "../rust-minidump/minidump-common" }
+minidump = { git = "https://github.com/luser/rust-minidump", rev = "b8e6b18c3164c124c12d9ce9819e4cb9809b5e09" }
+minidump-common = { git = "https://github.com/luser/rust-minidump", rev = "b8e6b18c3164c124c12d9ce9819e4cb9809b5e09" }
+#minidump = { path = "../rust-minidump/minidump" }
+#minidump-common = { path = "../rust-minidump/minidump-common" }
From 31e1bca905665bc99cea93434348ef7911a2032e Mon Sep 17 00:00:00 2001
From: Jake Shadle
Date: Thu, 10 Mar 2022 16:23:21 +0100
Subject: [PATCH 19/21] Replace x86_64 CrashContext with
crash_context::CrashContext
---
Cargo.toml | 14 +++--
src/linux.rs | 1 -
src/linux/crash_context.rs | 26 --------
src/linux/crash_context/x86_64.rs | 77 ------------------------
src/linux/minidump_writer.rs | 10 +--
src/linux/sections/thread_list_stream.rs | 10 ++-
src/linux/thread_info/x86.rs | 18 +++---
tests/minidump_writer.rs | 6 +-
8 files changed, 27 insertions(+), 135 deletions(-)
delete mode 100644 src/linux/crash_context.rs
delete mode 100644 src/linux/crash_context/x86_64.rs
diff --git a/Cargo.toml b/Cargo.toml
index ab8cce96..38c109c5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,6 @@ license = "MIT"
[dependencies]
byteorder = "1.3.2"
cfg-if = "1.0"
-exception-handler = { path = "../exception-handler" }
goblin = "0.5"
libc = "0.2.74"
memmap2 = "0.5"
@@ -19,13 +18,16 @@ scroll = "0.11"
tempfile = "3.1.0"
thiserror = "1.0.21"
+[dependencies.crash-context]
+git = "https://github.com/EmbarkStudios/crash-handling"
+branch = "impl"
+#path = "../crash-handling/crash-context"
+features = ["fill-minidump"]
+
[dev-dependencies]
debugid = "0.7.3"
minidump = "0.9"
-uctx = { path = "../uctx" }
[patch.crates-io]
-minidump = { git = "https://github.com/luser/rust-minidump", rev = "b8e6b18c3164c124c12d9ce9819e4cb9809b5e09" }
-minidump-common = { git = "https://github.com/luser/rust-minidump", rev = "b8e6b18c3164c124c12d9ce9819e4cb9809b5e09" }
-#minidump = { path = "../rust-minidump/minidump" }
-#minidump-common = { path = "../rust-minidump/minidump-common" }
+minidump = { git = "https://github.com/EmbarkStudios/rust-minidump", branch = "master" }
+minidump-common = { git = "https://github.com/EmbarkStudios/rust-minidump", branch = "master" }
diff --git a/src/linux.rs b/src/linux.rs
index 3e9dde8a..8f8c649b 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -2,7 +2,6 @@
mod android;
pub mod app_memory;
mod auxv_reader;
-pub mod crash_context;
mod dso_debug;
mod dumper_cpu_info;
pub mod errors;
diff --git a/src/linux/crash_context.rs b/src/linux/crash_context.rs
deleted file mode 100644
index ce70a954..00000000
--- a/src/linux/crash_context.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.
-
-cfg_if::cfg_if! {
- if #[cfg(target_arch = "x86_64")] {
- mod x86_64;
- } else if #[cfg(target_arch = "x86")] {
- mod x86;
- } else if #[cfg(target_arch = "aarch64")] {
- mod aarch64;
- } else if #[cfg(target_arch = "arm")] {
- mod arm;
- } else if #[cfg(target_arch = "mips")] {
- mod mips;
- }
-}
-
-use crate::minidump_cpu::{FloatStateCPU, RawContextCPU};
-pub use exception_handler::CrashContext;
-
-pub trait CpuContext {
- fn get_instruction_pointer(&self) -> usize;
- fn get_stack_pointer(&self) -> usize;
- fn fill_cpu_context(&self, cpu_ctx: &mut RawContextCPU);
-}
diff --git a/src/linux/crash_context/x86_64.rs b/src/linux/crash_context/x86_64.rs
deleted file mode 100644
index f699e469..00000000
--- a/src/linux/crash_context/x86_64.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use crate::thread_info::copy_u32_registers;
-use libc::{
- REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
- REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
-};
-
-impl super::CpuContext for super::CrashContext {
- fn get_instruction_pointer(&self) -> usize {
- self.context.uc_mcontext.gregs[REG_RIP as usize] as usize
- }
-
- fn get_stack_pointer(&self) -> usize {
- self.context.uc_mcontext.gregs[REG_RSP as usize] as usize
- }
-
- fn fill_cpu_context(&self, out: &mut super::RawContextCPU) {
- out.context_flags =
- crate::minidump_format::format::ContextFlagsAmd64::CONTEXT_AMD64_FULL.bits();
-
- {
- let gregs = &self.context.uc_mcontext.gregs;
- out.cs = (gregs[REG_CSGSFS as usize] & 0xffff) as u16;
-
- out.fs = ((gregs[REG_CSGSFS as usize] >> 32) & 0xffff) as u16;
- out.gs = ((gregs[REG_CSGSFS as usize] >> 16) & 0xffff) as u16;
-
- out.eflags = gregs[REG_EFL as usize] as u32;
-
- out.rax = gregs[REG_RAX as usize] as u64;
- out.rcx = gregs[REG_RCX as usize] as u64;
- out.rdx = gregs[REG_RDX as usize] as u64;
- out.rbx = gregs[REG_RBX as usize] as u64;
-
- out.rsp = gregs[REG_RSP as usize] as u64;
- out.rbp = gregs[REG_RBP as usize] as u64;
- out.rsi = gregs[REG_RSI as usize] as u64;
- out.rdi = gregs[REG_RDI as usize] as u64;
- out.r8 = gregs[REG_R8 as usize] as u64;
- out.r9 = gregs[REG_R9 as usize] as u64;
- out.r10 = gregs[REG_R10 as usize] as u64;
- out.r11 = gregs[REG_R11 as usize] as u64;
- out.r12 = gregs[REG_R12 as usize] as u64;
- out.r13 = gregs[REG_R13 as usize] as u64;
- out.r14 = gregs[REG_R14 as usize] as u64;
- out.r15 = gregs[REG_R15 as usize] as u64;
-
- out.rip = gregs[REG_RIP as usize] as u64;
- }
-
- {
- let fs = &self.float_state;
-
- let mut float_save = super::FloatStateCPU {
- control_word: fs.cwd,
- status_word: fs.swd,
- tag_word: fs.ftw as u8,
- error_opcode: fs.fop,
- error_offset: fs.rip as u32,
- data_offset: fs.rdp as u32,
- error_selector: 0, // We don't have this.
- data_selector: 0, // We don't have this.
- mx_csr: fs.mxcsr,
- mx_csr_mask: fs.mxcr_mask,
- ..Default::default()
- };
-
- copy_u32_registers(&mut float_save.float_registers, &fs.st_space);
- copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space);
-
- use scroll::Pwrite;
- // TODO: handle errors
- out.float_save
- .pwrite_with(float_save, 0, scroll::Endian::Little)
- .unwrap();
- }
- }
-}
diff --git a/src/linux/minidump_writer.rs b/src/linux/minidump_writer.rs
index c2a1e4ec..86bbeaba 100644
--- a/src/linux/minidump_writer.rs
+++ b/src/linux/minidump_writer.rs
@@ -1,7 +1,6 @@
use crate::{
linux::{
app_memory::AppMemoryList,
- crash_context::{CpuContext, CrashContext},
dso_debug,
errors::{FileWriterError, InitError, MemoryWriterError, WriterError},
maps_reader::{MappingInfo, MappingList},
@@ -11,6 +10,7 @@ use crate::{
},
minidump_format::*,
};
+use crash_context::{CpuContext, CrashContext};
use std::io::{Seek, SeekFrom, Write};
pub type DumpBuf = Buffer;
@@ -229,12 +229,8 @@ impl MinidumpWriter {
.system_mapping_info
.end_address;
- let pc = self
- .crash_context
- .as_ref()
- .unwrap()
- .get_instruction_pointer();
- let stack_pointer = self.crash_context.as_ref().unwrap().get_stack_pointer();
+ let pc = self.crash_context.as_ref().unwrap().instruction_pointer();
+ let stack_pointer = self.crash_context.as_ref().unwrap().stack_pointer();
if pc >= low_addr && pc < high_addr {
return true;
diff --git a/src/linux/sections/thread_list_stream.rs b/src/linux/sections/thread_list_stream.rs
index 24fff508..3d6ac0ef 100644
--- a/src/linux/sections/thread_list_stream.rs
+++ b/src/linux/sections/thread_list_stream.rs
@@ -1,8 +1,6 @@
use super::*;
-use crate::{
- linux::crash_context::CpuContext, minidump_cpu::RawContextCPU,
- minidump_writer::CrashingThreadContext,
-};
+use crate::{minidump_cpu::RawContextCPU, minidump_writer::CrashingThreadContext};
+use crash_context::CpuContext;
type Result = std::result::Result;
@@ -79,8 +77,8 @@ pub fn write(
// unhelpful.
if config.crash_context.is_some() && thread.thread_id == config.blamed_thread as u32 {
let crash_context = config.crash_context.as_ref().unwrap();
- let instruction_ptr = crash_context.get_instruction_pointer() as usize;
- let stack_pointer = crash_context.get_stack_pointer() as usize;
+ let instruction_ptr = crash_context.instruction_pointer();
+ let stack_pointer = crash_context.stack_pointer();
fill_thread_stack(
config,
buffer,
diff --git a/src/linux/thread_info/x86.rs b/src/linux/thread_info/x86.rs
index 944a4e47..a680946f 100644
--- a/src/linux/thread_info/x86.rs
+++ b/src/linux/thread_info/x86.rs
@@ -145,15 +145,16 @@ impl ThreadInfoX86 {
.bits()
| crate::minidump_format::format::ContextFlagsAmd64::CONTEXT_AMD64_SEGMENTS.bits();
- out.cs = self.regs.cs as u16; // TODO: This is u64, do we loose information by doing this?
+ // TODO: These are all u64, do we lose information by doing this?
+ out.cs = self.regs.cs as u16;
- out.ds = self.regs.ds as u16; // TODO: This is u64, do we loose information by doing this?
- out.es = self.regs.es as u16; // TODO: This is u64, do we loose information by doing this?
- out.fs = self.regs.fs as u16; // TODO: This is u64, do we loose information by doing this?
- out.gs = self.regs.gs as u16; // TODO: This is u64, do we loose information by doing this?
+ out.ds = self.regs.ds as u16;
+ out.es = self.regs.es as u16;
+ out.fs = self.regs.fs as u16;
+ out.gs = self.regs.gs as u16;
- out.ss = self.regs.ss as u16; // TODO: This is u64, do we loose information by doing this?
- out.eflags = self.regs.eflags as u32; // TODO: This is u64, do we loose information by doing this?
+ out.ss = self.regs.ss as u16;
+ out.eflags = self.regs.eflags as u32;
out.dr0 = self.dregs[0];
out.dr1 = self.dregs[1];
@@ -205,10 +206,9 @@ impl ThreadInfoX86 {
copy_u32_registers(&mut float_save.xmm_registers, &fs.xmm_space);
use scroll::Pwrite;
- // TODO: handle errors
out.float_save
.pwrite_with(float_save, 0, scroll::Endian::Little)
- .unwrap();
+ .expect("this is impossible");
}
}
diff --git a/tests/minidump_writer.rs b/tests/minidump_writer.rs
index c2752af3..4f4d907b 100644
--- a/tests/minidump_writer.rs
+++ b/tests/minidump_writer.rs
@@ -1,8 +1,8 @@
+use crash_context::CrashContext;
use minidump::*;
use minidump_common::format::{GUID, MINIDUMP_STREAM_TYPE::*};
use minidump_writer::{
app_memory::AppMemory,
- crash_context::CrashContext,
errors::*,
maps_reader::{MappingEntry, MappingInfo, SystemMappingInfo},
minidump_writer::MinidumpWriter,
@@ -27,10 +27,10 @@ enum Context {
}
#[cfg(not(any(target_arch = "mips", target_arch = "arm")))]
-fn get_ucontext() -> Result {
+fn get_ucontext() -> Result