Skip to content

Commit 1c0cd5b

Browse files
committed
more refactor
1 parent d314f5a commit 1c0cd5b

File tree

1 file changed

+64
-55
lines changed

1 file changed

+64
-55
lines changed

src/shims/native_lib/trace/parent.rs

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,70 @@ fn wait_for_signal(
361361
}
362362
}
363363

364+
/// Add the memory events from `op` being executed while there is a memory access at `addr` to
365+
/// `acc_events`. Return whether this was a memory operand.
366+
fn capstone_find_events(
367+
addr: usize,
368+
op: &capstone::arch::ArchOperand,
369+
acc_events: &mut Vec<AccessEvent>,
370+
) -> bool {
371+
use capstone::prelude::*;
372+
match op {
373+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
374+
arch::ArchOperand::X86Operand(x86_operand) => {
375+
match x86_operand.op_type {
376+
// We only care about memory accesses
377+
arch::x86::X86OperandType::Mem(_) => {
378+
let push = AccessRange { addr, size: x86_operand.size.into() };
379+
// It's called a "RegAccessType" but it also applies to memory
380+
let acc_ty = x86_operand.access.unwrap();
381+
if acc_ty.is_readable() {
382+
acc_events.push(AccessEvent::Read(push.clone()));
383+
}
384+
if acc_ty.is_writable() {
385+
acc_events.push(AccessEvent::Write(push));
386+
}
387+
388+
return true;
389+
}
390+
_ => (),
391+
}
392+
}
393+
// FIXME: arm64
394+
_ => unimplemented!(),
395+
}
396+
397+
false
398+
}
399+
400+
/// Extract the events from the given instruction.
401+
fn capstone_disassemble(
402+
instr: &[u8],
403+
addr: usize,
404+
cs: &capstone::Capstone,
405+
acc_events: &mut Vec<AccessEvent>,
406+
) -> capstone::CsResult<()> {
407+
// The arch_detail is what we care about, but it relies on these temporaries
408+
// that we can't drop. 0x1000 is the default base address for Captsone, and
409+
// we're expecting 1 instruction.
410+
let insns = cs.disasm_count(instr, 0x1000, 1)?;
411+
let ins_detail = cs.insn_detail(&insns[0])?;
412+
let arch_detail = ins_detail.arch_detail();
413+
414+
let mut found_mem_op = false;
415+
416+
for op in arch_detail.operands() {
417+
if capstone_find_events(addr, &op, acc_events) {
418+
if found_mem_op {
419+
panic!("more than one memory operand found; we don't know which one accessed what");
420+
}
421+
found_mem_op = true;
422+
}
423+
}
424+
425+
Ok(())
426+
}
427+
364428
/// Grabs the access that caused a segfault and logs it down if it's to our memory,
365429
/// or kills the child and returns the appropriate error otherwise.
366430
fn handle_segfault(
@@ -371,61 +435,6 @@ fn handle_segfault(
371435
cs: &capstone::Capstone,
372436
acc_events: &mut Vec<AccessEvent>,
373437
) -> Result<(), ExecEnd> {
374-
/// This is just here to not pollute the main namespace with `capstone::prelude::*`.
375-
#[inline]
376-
fn capstone_disassemble(
377-
instr: &[u8],
378-
addr: usize,
379-
cs: &capstone::Capstone,
380-
acc_events: &mut Vec<AccessEvent>,
381-
) -> capstone::CsResult<()> {
382-
use capstone::prelude::*;
383-
384-
// The arch_detail is what we care about, but it relies on these temporaries
385-
// that we can't drop. 0x1000 is the default base address for Captsone, and
386-
// we're expecting 1 instruction.
387-
let insns = cs.disasm_count(instr, 0x1000, 1)?;
388-
let ins_detail = cs.insn_detail(&insns[0])?;
389-
let arch_detail = ins_detail.arch_detail();
390-
391-
let mut found_mem_op = false;
392-
393-
for op in arch_detail.operands() {
394-
match op {
395-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
396-
arch::ArchOperand::X86Operand(x86_operand) => {
397-
match x86_operand.op_type {
398-
// We only care about memory accesses
399-
arch::x86::X86OperandType::Mem(_) => {
400-
if found_mem_op {
401-
panic!(
402-
"more than one memory operand in a single operation is not supported"
403-
);
404-
}
405-
406-
let push = AccessRange { addr, size: x86_operand.size.into() };
407-
// It's called a "RegAccessType" but it also applies to memory
408-
let acc_ty = x86_operand.access.unwrap();
409-
if acc_ty.is_readable() {
410-
acc_events.push(AccessEvent::Read(push.clone()));
411-
}
412-
if acc_ty.is_writable() {
413-
acc_events.push(AccessEvent::Write(push));
414-
}
415-
416-
found_mem_op = true;
417-
}
418-
_ => (),
419-
}
420-
}
421-
// FIXME: arm64
422-
_ => unimplemented!(),
423-
}
424-
}
425-
426-
Ok(())
427-
}
428-
429438
// Get information on what caused the segfault. This contains the address
430439
// that triggered it.
431440
let siginfo = ptrace::getsiginfo(pid).unwrap();

0 commit comments

Comments
 (0)