@@ -361,6 +361,70 @@ fn wait_for_signal(
361
361
}
362
362
}
363
363
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
+
364
428
/// Grabs the access that caused a segfault and logs it down if it's to our memory,
365
429
/// or kills the child and returns the appropriate error otherwise.
366
430
fn handle_segfault (
@@ -371,61 +435,6 @@ fn handle_segfault(
371
435
cs : & capstone:: Capstone ,
372
436
acc_events : & mut Vec < AccessEvent > ,
373
437
) -> 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
-
429
438
// Get information on what caused the segfault. This contains the address
430
439
// that triggered it.
431
440
let siginfo = ptrace:: getsiginfo ( pid) . unwrap ( ) ;
0 commit comments