Skip to content

Commit b6ed779

Browse files
Merge pull request #155 from marti4d/merge_dumper_writer
Merge PtraceDumper and MinidumpWriter
2 parents d0c91bd + c35af12 commit b6ed779

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2066
-2097
lines changed

examples/synthetic.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Emits default minidump with no streams to specified path
22
3-
use std::fs::File;
4-
5-
use minidump_writer::{
6-
dir_section::DirSection,
7-
mem_writer::{Buffer, MemoryWriter},
8-
minidump_format::{MDRawHeader, MD_HEADER_SIGNATURE, MD_HEADER_VERSION},
3+
use {
4+
minidump_writer::{
5+
dir_section::DirSection,
6+
mem_writer::{Buffer, MemoryWriter},
7+
minidump_format::{MDRawHeader, MD_HEADER_SIGNATURE, MD_HEADER_VERSION},
8+
},
9+
std::fs::File,
910
};
1011

1112
// usage: `cargo run --example synthetic /tmp/micro-minidump.dmp`

src/bin/test.rs

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ mod linux {
1010
super::*,
1111
error_graph::ErrorList,
1212
minidump_writer::{
13-
minidump_writer::STOP_TIMEOUT, module_reader, ptrace_dumper::PtraceDumper,
14-
LINUX_GATE_LIBRARY_NAME,
13+
minidump_writer::{MinidumpWriter, MinidumpWriterConfig},
14+
module_reader, LINUX_GATE_LIBRARY_NAME,
1515
},
1616
nix::{
1717
sys::mman::{mmap_anonymous, MapFlags, ProtFlags},
@@ -40,12 +40,8 @@ mod linux {
4040
let ppid = getppid();
4141
fail_on_soft_error!(
4242
soft_errors,
43-
PtraceDumper::new_report_soft_errors(
44-
ppid.as_raw(),
45-
STOP_TIMEOUT,
46-
Default::default(),
47-
&mut soft_errors,
48-
)?
43+
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
44+
.build_for_testing(&mut soft_errors)?
4945
);
5046
Ok(())
5147
}
@@ -54,12 +50,8 @@ mod linux {
5450
let ppid = getppid();
5551
let dumper = fail_on_soft_error!(
5652
soft_errors,
57-
PtraceDumper::new_report_soft_errors(
58-
ppid.as_raw(),
59-
STOP_TIMEOUT,
60-
Default::default(),
61-
&mut soft_errors,
62-
)?
53+
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
54+
.build_for_testing(&mut soft_errors)?
6355
);
6456
test!(!dumper.threads.is_empty(), "No threads");
6557
test!(
@@ -87,18 +79,11 @@ mod linux {
8779
use minidump_writer::mem_reader::MemReader;
8880

8981
let ppid = getppid().as_raw();
90-
let mut dumper = fail_on_soft_error!(
82+
let dumper = fail_on_soft_error!(
9183
soft_errors,
92-
PtraceDumper::new_report_soft_errors(
93-
ppid,
94-
STOP_TIMEOUT,
95-
Default::default(),
96-
&mut soft_errors
97-
)?
84+
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
9885
);
9986

100-
fail_on_soft_error!(soft_errors, dumper.suspend_threads(&mut soft_errors));
101-
10287
// We support 3 different methods of reading memory from another
10388
// process, ensure they all function and give the same results
10489

@@ -141,30 +126,27 @@ mod linux {
141126
}
142127

143128
let stack_res =
144-
PtraceDumper::copy_from_process(ppid, stack_var, std::mem::size_of::<usize>())?;
129+
MinidumpWriter::copy_from_process(ppid, stack_var, std::mem::size_of::<usize>())?;
145130

146131
test!(stack_res == expected_stack, "stack var not correct");
147132

148133
let heap_res =
149-
PtraceDumper::copy_from_process(ppid, heap_var, std::mem::size_of::<usize>())?;
134+
MinidumpWriter::copy_from_process(ppid, heap_var, std::mem::size_of::<usize>())?;
150135

151136
test!(heap_res == expected_heap, "heap var not correct");
152137

153-
fail_on_soft_error!(soft_errors, dumper.resume_threads(&mut soft_errors));
138+
drop(dumper);
154139

155140
Ok(())
156141
}
157142

158143
fn test_find_mappings(addr1: usize, addr2: usize) -> Result<()> {
159144
let ppid = getppid();
145+
160146
let dumper = fail_on_soft_error!(
161147
soft_errors,
162-
PtraceDumper::new_report_soft_errors(
163-
ppid.as_raw(),
164-
STOP_TIMEOUT,
165-
Default::default(),
166-
&mut soft_errors,
167-
)?
148+
MinidumpWriterConfig::new(ppid.as_raw(), ppid.as_raw())
149+
.build_for_testing(&mut soft_errors)?
168150
);
169151
dumper
170152
.find_mapping(addr1)
@@ -185,16 +167,9 @@ mod linux {
185167

186168
let mut dumper = fail_on_soft_error!(
187169
soft_errors,
188-
PtraceDumper::new_report_soft_errors(
189-
ppid,
190-
STOP_TIMEOUT,
191-
Default::default(),
192-
&mut soft_errors
193-
)?
170+
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
194171
);
195172

196-
fail_on_soft_error!(soft_errors, dumper.suspend_threads(&mut soft_errors));
197-
198173
let mut found_exe = None;
199174
for (idx, mapping) in dumper.mappings.iter().enumerate() {
200175
if mapping.name.as_ref().map(|x| x.into()).as_ref() == Some(&exe_name) {
@@ -205,7 +180,7 @@ mod linux {
205180
let idx = found_exe.unwrap();
206181
let module_reader::BuildId(id) = dumper.from_process_memory_for_index(idx)?;
207182

208-
fail_on_soft_error!(soft_errors, dumper.resume_threads(&mut soft_errors));
183+
drop(dumper);
209184

210185
assert!(!id.is_empty());
211186
assert!(id.iter().any(|&x| x > 0));
@@ -216,12 +191,8 @@ mod linux {
216191
// Now check that PtraceDumper interpreted the mappings properly.
217192
let dumper = fail_on_soft_error!(
218193
soft_errors,
219-
PtraceDumper::new_report_soft_errors(
220-
getppid().as_raw(),
221-
STOP_TIMEOUT,
222-
Default::default(),
223-
&mut soft_errors,
224-
)?
194+
MinidumpWriterConfig::new(getppid().as_raw(), getppid().as_raw())
195+
.build_for_testing(&mut soft_errors)?
225196
);
226197
let mut mapping_count = 0;
227198
for map in &dumper.mappings {
@@ -244,29 +215,20 @@ mod linux {
244215

245216
fn test_linux_gate_mapping_id() -> Result<()> {
246217
let ppid = getppid().as_raw();
247-
let mut dumper = fail_on_soft_error!(
218+
let dumper = fail_on_soft_error!(
248219
soft_errors,
249-
PtraceDumper::new_report_soft_errors(
250-
ppid,
251-
STOP_TIMEOUT,
252-
Default::default(),
253-
&mut soft_errors
254-
)?
220+
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
255221
);
256222
let mut found_linux_gate = false;
257223
for mapping in dumper.mappings.clone() {
258224
if mapping.name == Some(LINUX_GATE_LIBRARY_NAME.into()) {
259225
found_linux_gate = true;
260226

261-
fail_on_soft_error!(soft_errors, dumper.suspend_threads(&mut soft_errors));
262-
263227
let module_reader::BuildId(id) =
264-
PtraceDumper::from_process_memory_for_mapping(&mapping, ppid)?;
228+
MinidumpWriter::from_process_memory_for_mapping(&mapping, ppid)?;
265229
test!(!id.is_empty(), "id-vec is empty");
266230
test!(id.iter().any(|&x| x > 0), "all id elements are 0");
267-
268-
fail_on_soft_error!(soft_errors, dumper.resume_threads(&mut soft_errors));
269-
231+
drop(dumper);
270232
break;
271233
}
272234
}
@@ -278,12 +240,7 @@ mod linux {
278240
let ppid = getppid().as_raw();
279241
let dumper = fail_on_soft_error!(
280242
soft_errors,
281-
PtraceDumper::new_report_soft_errors(
282-
ppid,
283-
STOP_TIMEOUT,
284-
Default::default(),
285-
&mut soft_errors
286-
)?
243+
MinidumpWriterConfig::new(ppid, ppid).build_for_testing(&mut soft_errors)?
287244
);
288245
let linux_gate_loc = dumper.auxv.get_linux_gate_address().unwrap();
289246
test!(linux_gate_loc != 0, "linux_gate_loc == 0");
@@ -332,7 +289,7 @@ mod linux {
332289
// One less than the requested amount, as the main thread counts as well
333290
for id in 1..num {
334291
std::thread::Builder::new()
335-
.name(format!("thread_{}", id))
292+
.name(format!("thread_{id}"))
336293
.spawn(|| {
337294
println!("1");
338295
loop {

src/linux/android.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use crate::errors::AndroidError;
2-
use crate::maps_reader::MappingInfo;
3-
use crate::ptrace_dumper::PtraceDumper;
4-
use crate::Pid;
5-
use goblin::elf;
1+
use {
2+
super::{
3+
maps_reader::MappingInfo, mem_reader::CopyFromProcessError,
4+
minidump_writer::MinidumpWriter, Pid,
5+
},
6+
goblin::elf,
7+
};
68

79
cfg_if::cfg_if! {
810
if #[cfg(target_pointer_width = "32")] {
@@ -26,6 +28,20 @@ cfg_if::cfg_if! {
2628

2729
type Result<T> = std::result::Result<T, AndroidError>;
2830

31+
#[derive(Debug, thiserror::Error, serde::Serialize)]
32+
pub enum AndroidError {
33+
#[error("Failed to copy memory from process")]
34+
CopyFromProcessError(#[from] CopyFromProcessError),
35+
#[error("Failed slice conversion")]
36+
TryFromSliceError(
37+
#[from]
38+
#[serde(skip)]
39+
std::array::TryFromSliceError,
40+
),
41+
#[error("No Android rel found")]
42+
NoRelFound,
43+
}
44+
2945
struct DynVaddresses {
3046
min_vaddr: usize,
3147
dyn_vaddr: usize,
@@ -36,7 +52,7 @@ fn has_android_packed_relocations(pid: Pid, load_bias: usize, vaddrs: DynVaddres
3652
let dyn_addr = load_bias + vaddrs.dyn_vaddr;
3753
for idx in 0..vaddrs.dyn_count {
3854
let addr = dyn_addr + SIZEOF_DYN * idx;
39-
let dyn_data = PtraceDumper::copy_from_process(pid, addr, SIZEOF_DYN)?;
55+
let dyn_data = MinidumpWriter::copy_from_process(pid, addr, SIZEOF_DYN)?;
4056
// TODO: Couldn't find a nice way to use goblin for that, to avoid the unsafe-block
4157
let dyn_obj: Dyn;
4258
unsafe {
@@ -76,7 +92,7 @@ fn parse_loaded_elf_program_headers(
7692
let mut dyn_vaddr = 0;
7793
let mut dyn_count = 0;
7894

79-
let phdr_opt = PtraceDumper::copy_from_process(
95+
let phdr_opt = MinidumpWriter::copy_from_process(
8096
pid,
8197
phdr_addr,
8298
elf_header::SIZEOF_EHDR * ehdr.e_phnum as usize,
@@ -114,7 +130,7 @@ pub fn late_process_mappings(pid: Pid, mappings: &mut [MappingInfo]) -> Result<(
114130
.filter(|m| m.is_executable() && m.name_is_path())
115131
{
116132
let ehdr_opt =
117-
PtraceDumper::copy_from_process(pid, map.start_address, elf_header::SIZEOF_EHDR)
133+
MinidumpWriter::copy_from_process(pid, map.start_address, elf_header::SIZEOF_EHDR)
118134
.ok()
119135
.and_then(|x| elf_header::Header::parse(&x).ok());
120136

src/linux/auxv/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use {
22
self::reader::ProcfsAuxvIter,
3-
crate::{serializers::*, Pid},
3+
super::Pid,
4+
crate::serializers::*,
45
error_graph::WriteErrorList,
56
failspot::failspot,
67
std::{fs::File, io::BufReader},

src/linux/auxv/reader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,6 @@ fn read_long(reader: &mut dyn Read) -> std::io::Result<AuxvType> {
9999
match std::mem::size_of::<AuxvType>() {
100100
4 => reader.read_u32::<NativeEndian>().map(|u| u as AuxvType),
101101
8 => reader.read_u64::<NativeEndian>().map(|u| u as AuxvType),
102-
x => panic!("Unexpected type width: {}", x),
102+
x => panic!("Unexpected type width: {x}"),
103103
}
104104
}

src/linux/crash_context/aarch64.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
use super::CrashContext;
2-
use crate::{
3-
minidump_cpu::{RawContextCPU, FP_REG_COUNT, GP_REG_COUNT},
4-
minidump_format::format,
1+
use {
2+
super::CrashContext,
3+
crate::{
4+
minidump_cpu::{RawContextCPU, FP_REG_COUNT, GP_REG_COUNT},
5+
minidump_format::format,
6+
},
57
};
68

79
impl CrashContext {

src/linux/crash_context/arm.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use super::CrashContext;
2-
use crate::minidump_cpu::RawContextCPU;
1+
use {super::CrashContext, crate::minidump_cpu::RawContextCPU};
32

43
impl CrashContext {
54
pub fn get_instruction_pointer(&self) -> usize {

src/linux/crash_context.rs renamed to src/linux/crash_context/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ pub struct CrashContext {
66
pub inner: crash_context::CrashContext,
77
}
88

9+
impl std::fmt::Debug for CrashContext {
10+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11+
f.debug_struct("CrashContext")
12+
.field("siginfo", &self.inner.siginfo)
13+
.field("pid", &self.inner.pid)
14+
.field("tid", &self.inner.tid)
15+
.finish_non_exhaustive()
16+
}
17+
}
18+
919
cfg_if::cfg_if! {
1020
if #[cfg(target_arch = "x86_64")] {
1121
mod x86_64;

src/linux/crash_context/x86.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use super::CrashContext;
2-
use crate::{minidump_cpu::RawContextCPU, minidump_format::format::ContextFlagsX86};
3-
use libc::{
4-
REG_CS, REG_DS, REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP, REG_ES,
5-
REG_ESI, REG_ESP, REG_FS, REG_GS, REG_SS, REG_UESP,
1+
use {
2+
super::CrashContext,
3+
crate::{minidump_cpu::RawContextCPU, minidump_format::format::ContextFlagsX86},
4+
libc::{
5+
REG_CS, REG_DS, REG_EAX, REG_EBP, REG_EBX, REG_ECX, REG_EDI, REG_EDX, REG_EFL, REG_EIP,
6+
REG_ES, REG_ESI, REG_ESP, REG_FS, REG_GS, REG_SS, REG_UESP,
7+
},
68
};
79
impl CrashContext {
810
pub fn get_instruction_pointer(&self) -> usize {

src/linux/crash_context/x86_64.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use super::CrashContext;
2-
use crate::{
3-
minidump_cpu::RawContextCPU, minidump_format::format, thread_info::copy_u32_registers,
1+
use {
2+
super::{super::thread_info::copy_u32_registers, CrashContext},
3+
crate::{minidump_cpu::RawContextCPU, minidump_format::format},
4+
libc::{
5+
REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
6+
REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
7+
},
8+
scroll::Pwrite,
49
};
5-
use libc::{
6-
REG_CSGSFS, REG_EFL, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9,
7-
REG_RAX, REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
8-
};
9-
use scroll::Pwrite;
1010

1111
impl CrashContext {
1212
pub fn get_instruction_pointer(&self) -> usize {

0 commit comments

Comments
 (0)