@@ -8,20 +8,26 @@ use crate::helpers::ToU64;
8
8
use crate :: shims:: trace:: { AccessEvent , FAKE_STACK_SIZE , MemEvents , StartFfiInfo , TraceRequest } ;
9
9
10
10
/// 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
13
13
const WAIT_FLAGS : wait:: WaitPidFlag =
14
14
wait:: WaitPidFlag :: from_bits_truncate ( libc:: WUNTRACED | libc:: WEXITED ) ;
15
15
16
16
/// Arch-specific maximum size a single access might perform. x86 value is set
17
17
/// 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.
21
18
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
22
19
const ARCH_MAX_ACCESS_SIZE : u64 = 64 ;
23
20
#[ cfg( any( target_arch = "arm" , target_arch = "aarch64" ) ) ]
24
21
const 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 ;
25
31
26
32
/// The address of the page set to be edited, initialised to a sentinel null
27
33
/// pointer.
@@ -37,7 +43,7 @@ static PAGE_COUNT: AtomicU64 = AtomicU64::new(1);
37
43
/// consist of functions with a small number of register-sized integer arguments.
38
44
/// See <https://man7.org/linux/man-pages/man2/syscall.2.html> for sources
39
45
trait ArchIndependentRegs {
40
- /// The instruction pointer.
46
+ /// Gets the address of the instruction pointer.
41
47
fn ip ( & self ) -> usize ;
42
48
/// Set the instruction pointer; remember to also set the stack pointer, or
43
49
/// else the stack might get messed up!
@@ -75,7 +81,14 @@ impl ArchIndependentRegs for libc::user_regs_struct {
75
81
fn set_sp ( & mut self , sp : usize ) { self . sp = sp as _ }
76
82
}
77
83
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
+ }
79
92
80
93
/// A unified event representing something happening on the child process. Wraps
81
94
/// `nix`'s `WaitStatus` and our custom signals so it can all be done with one
@@ -432,8 +445,8 @@ fn handle_segfault(
432
445
} ;
433
446
434
447
for op in arch_detail. operands ( ) {
435
- // TODO: cfg() parts out?
436
448
match op {
449
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
437
450
arch:: ArchOperand :: X86Operand ( x86_operand) => {
438
451
match x86_operand. op_type {
439
452
// We only care about memory accesses
@@ -463,18 +476,39 @@ fn handle_segfault(
463
476
_ => ( ) ,
464
477
}
465
478
}
479
+ #[ cfg( target_arch = "aarch64" ) ]
466
480
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
468
482
match arm64_operand. op_type {
469
483
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) ;
471
509
// FIXME: This now has access type info in the latest
472
510
// git version of capstone because this pissed me off
473
511
// 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?
478
512
acc_events. append (
479
513
& mut append. clone ( ) . into_iter ( ) . map ( AccessEvent :: Read ) . collect ( ) ,
480
514
) ;
@@ -485,10 +519,18 @@ fn handle_segfault(
485
519
_ => ( ) ,
486
520
}
487
521
}
522
+ #[ cfg( target_arch = "arm" ) ]
488
523
arch:: ArchOperand :: ArmOperand ( arm_operand) =>
489
524
match arm_operand. op_type {
490
525
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) ;
492
534
let acc_ty = arm_operand. access . unwrap ( ) ;
493
535
if acc_ty. is_readable ( ) {
494
536
acc_events. append (
@@ -511,7 +553,22 @@ fn handle_segfault(
511
553
}
512
554
_ => ( ) ,
513
555
} ,
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
+ }
515
572
_ => unimplemented ! ( ) ,
516
573
}
517
574
}
0 commit comments