@@ -8,20 +8,26 @@ use crate::helpers::ToU64;
88use crate :: shims:: trace:: { AccessEvent , FAKE_STACK_SIZE , MemEvents , StartFfiInfo , TraceRequest } ;
99
1010/// The flags to use when calling `waitid()`.
11- /// FIXME: bitwise OR for the ` nix` versions of these types is not `const`, but
12- /// it should be!
11+ /// Since bitwise or on the nix version of these flags is implemented as a trait,
12+ /// this cannot be const directly so we do it this way
1313const WAIT_FLAGS : wait:: WaitPidFlag =
1414 wait:: WaitPidFlag :: from_bits_truncate ( libc:: WUNTRACED | libc:: WEXITED ) ;
1515
1616/// Arch-specific maximum size a single access might perform. x86 value is set
1717/// assuming nothing bigger than AVX-512 is available.
18- /// FIXME: For certain architectures (e.g. ARM) we may be able to tell apart
19- /// SIMD from non-SIMD instructions, and thus put a much lower bound on the
20- /// access size.
2118#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
2219const ARCH_MAX_ACCESS_SIZE : u64 = 64 ;
2320#[ cfg( any( target_arch = "arm" , target_arch = "aarch64" ) ) ]
2421const ARCH_MAX_ACCESS_SIZE : u64 = 16 ;
22+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
23+ const ARCH_MAX_ACCESS_SIZE : u64 = 16 ;
24+
25+ /// The default word size on a given platform, in bytes. Only for targets where
26+ /// this is actually used.
27+ #[ cfg( target_arch = "arm" ) ]
28+ const ARCH_WORD_SIZE : u64 = 4 ;
29+ #[ cfg( target_arch = "aarch64" ) ]
30+ const ARCH_WORD_SIZE : u64 = 8 ;
2531
2632/// The address of the page set to be edited, initialised to a sentinel null
2733/// pointer.
@@ -37,7 +43,7 @@ static PAGE_COUNT: AtomicU64 = AtomicU64::new(1);
3743/// consist of functions with a small number of register-sized integer arguments.
3844/// See <https://man7.org/linux/man-pages/man2/syscall.2.html> for sources
3945trait ArchIndependentRegs {
40- /// The instruction pointer.
46+ /// Gets the address of the instruction pointer.
4147 fn ip ( & self ) -> usize ;
4248 /// Set the instruction pointer; remember to also set the stack pointer, or
4349 /// else the stack might get messed up!
@@ -75,7 +81,14 @@ impl ArchIndependentRegs for libc::user_regs_struct {
7581 fn set_sp ( & mut self , sp : usize ) { self . sp = sp as _ }
7682}
7783
78- // TODO: add more architectures!
84+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
85+ #[ expect( clippy:: as_conversions) ]
86+ #[ rustfmt:: skip]
87+ impl ArchIndependentRegs for libc:: user_regs_struct {
88+ fn ip ( & self ) -> usize { self . pc as _ }
89+ fn set_ip ( & mut self , ip : usize ) { self . pc = ip as _ }
90+ fn set_sp ( & mut self , sp : usize ) { self . sp = sp as _ }
91+ }
7992
8093/// A unified event representing something happening on the child process. Wraps
8194/// `nix`'s `WaitStatus` and our custom signals so it can all be done with one
@@ -432,8 +445,8 @@ fn handle_segfault(
432445 } ;
433446
434447 for op in arch_detail. operands ( ) {
435- // TODO: cfg() parts out?
436448 match op {
449+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
437450 arch:: ArchOperand :: X86Operand ( x86_operand) => {
438451 match x86_operand. op_type {
439452 // We only care about memory accesses
@@ -463,18 +476,39 @@ fn handle_segfault(
463476 _ => ( ) ,
464477 }
465478 }
479+ #[ cfg( target_arch = "aarch64" ) ]
466480 arch:: ArchOperand :: Arm64Operand ( arm64_operand) => {
467- // Annoyingly, we don't get the size here, so just be pessimistic for now
481+ // Annoyingly, we don't always get the size here, so just be pessimistic for now
468482 match arm64_operand. op_type {
469483 arch:: arm64:: Arm64OperandType :: Mem ( _) => {
470- let append = get_ranges ( addr, ARCH_MAX_ACCESS_SIZE , page_size) ;
484+ // B = 1 byte, H = 2 bytes, S = 4 bytes, D = 8 bytes, Q = 16 bytes
485+ let size = match arm64_operand. vas {
486+ // Not an fp/simd instruction
487+ arch:: arm64:: Arm64Vas :: ARM64_VAS_INVALID => ARCH_WORD_SIZE ,
488+ // 1 byte
489+ arch:: arm64:: Arm64Vas :: ARM64_VAS_1B => 1 ,
490+ // 2 bytes
491+ arch:: arm64:: Arm64Vas :: ARM64_VAS_1H => 2 ,
492+ // 4 bytes
493+ arch:: arm64:: Arm64Vas :: ARM64_VAS_4B
494+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_2H
495+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_1S => 4 ,
496+ // 8 bytes
497+ arch:: arm64:: Arm64Vas :: ARM64_VAS_8B
498+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_4H
499+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_2S
500+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_1D => 8 ,
501+ // 16 bytes
502+ arch:: arm64:: Arm64Vas :: ARM64_VAS_16B
503+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_8H
504+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_4S
505+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_2D
506+ | arch:: arm64:: Arm64Vas :: ARM64_VAS_1Q => 16 ,
507+ } ;
508+ let append = get_ranges ( addr, size, page_size) ;
471509 // FIXME: This now has access type info in the latest
472510 // git version of capstone because this pissed me off
473511 // and I added it. Change this when it updates
474-
475- // Also FIXME: We do get some info on whether this
476- // is a vector instruction, maybe we can limit the
477- // max size based on that?
478512 acc_events. append (
479513 & mut append. clone ( ) . into_iter ( ) . map ( AccessEvent :: Read ) . collect ( ) ,
480514 ) ;
@@ -485,10 +519,18 @@ fn handle_segfault(
485519 _ => ( ) ,
486520 }
487521 }
522+ #[ cfg( target_arch = "arm" ) ]
488523 arch:: ArchOperand :: ArmOperand ( arm_operand) =>
489524 match arm_operand. op_type {
490525 arch:: arm:: ArmOperandType :: Mem ( _) => {
491- let append = get_ranges ( addr, ARCH_MAX_ACCESS_SIZE , page_size) ;
526+ // We don't get info on the size of the access, but
527+ // we're at least told if it's a vector inssizetruction
528+ let size = if arm_operand. vector_index . is_some ( ) {
529+ ARCH_MAX_ACCESS_SIZE
530+ } else {
531+ ARCH_WORD_SIZE
532+ } ;
533+ let append = get_ranges ( addr, size, page_size) ;
492534 let acc_ty = arm_operand. access . unwrap ( ) ;
493535 if acc_ty. is_readable ( ) {
494536 acc_events. append (
@@ -511,7 +553,22 @@ fn handle_segfault(
511553 }
512554 _ => ( ) ,
513555 } ,
514- arch:: ArchOperand :: RiscVOperand ( _risc_voperand) => todo ! ( ) ,
556+ #[ cfg( any( target_arch = "riscv32" , target_arch = "riscv64" ) ) ]
557+ arch:: ArchOperand :: RiscVOperand ( risc_voperand) => {
558+ match risc_voperand {
559+ arch:: riscv:: RiscVOperand :: Mem ( _) => {
560+ // We get basically no info here
561+ let append = get_ranges ( addr, ARCH_MAX_ACCESS_SIZE , page_size) ;
562+ acc_events. append (
563+ & mut append. clone ( ) . into_iter ( ) . map ( AccessEvent :: Read ) . collect ( ) ,
564+ ) ;
565+ acc_events. append (
566+ & mut append. clone ( ) . into_iter ( ) . map ( AccessEvent :: Write ) . collect ( ) ,
567+ ) ;
568+ }
569+ _ => ( ) ,
570+ }
571+ }
515572 _ => unimplemented ! ( ) ,
516573 }
517574 }
0 commit comments