@@ -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.
366430fn 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