@@ -4,24 +4,30 @@ use nix::unistd;
4
4
5
5
use crate :: discrete_alloc;
6
6
7
+ #[ cfg( target_pointer_width = "64" ) ]
8
+ const BITS : u32 = 64 ;
9
+ #[ cfg( target_pointer_width = "32" ) ]
10
+ const BITS : u32 = 32 ;
11
+
12
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
13
+ const BREAKPT_INSTR : i64 = 0xCC ;
14
+ #[ cfg( target_arch = "aarch64" ) ]
15
+ const BREAKPT_INSTR : i64 = 0xD420 ;
16
+
7
17
// We do NOT ever want to block the child from accessing this!!
8
18
static SUPERVISOR : std:: sync:: Mutex < Option < Supervisor > > = std:: sync:: Mutex :: new ( None ) ;
9
19
static mut PAGE_ADDR : * mut libc:: c_void = std:: ptr:: null_mut ( ) ;
10
20
static mut PAGE_SIZE : usize = 4096 ;
11
21
static mut CLICK_HERE_4_FREE_STACK : [ u8 ; 1024 ] = [ 0 ; 1024 ] ;
12
22
13
- #[ cfg( target_pointer_width = "64" ) ]
14
- const BITS : u32 = 64 ;
15
- #[ cfg( target_pointer_width = "32" ) ]
16
- const BITS : u32 = 32 ;
17
-
18
23
trait ArchIndependentRegs {
19
- fn ax ( & self ) -> usize ;
20
- fn di ( & self ) -> usize ;
21
- fn si ( & self ) -> usize ;
24
+ // see https://man7.org/linux/man-pages/man2/syscall.2.html
25
+ fn retval ( & self ) -> usize ;
26
+ fn arg1 ( & self ) -> usize ;
27
+ fn arg2 ( & self ) -> usize ;
28
+ fn syscall_nr ( & self ) -> usize ;
22
29
fn ip ( & self ) -> usize ;
23
30
fn sp ( & self ) -> usize ;
24
- fn orig_ax ( & self ) -> usize ;
25
31
fn set_ip ( & mut self , ip : usize ) ;
26
32
fn set_sp ( & mut self , sp : usize ) ;
27
33
}
@@ -30,12 +36,12 @@ trait ArchIndependentRegs {
30
36
#[ allow( clippy:: cast_possible_truncation) ]
31
37
#[ rustfmt:: skip]
32
38
impl ArchIndependentRegs for libc:: user_regs_struct {
33
- fn ax ( & self ) -> usize { self . rax as _ }
34
- fn di ( & self ) -> usize { self . rdi as _ }
35
- fn si ( & self ) -> usize { self . rsi as _ }
39
+ fn retval ( & self ) -> usize { self . rax as _ }
40
+ fn arg1 ( & self ) -> usize { self . rdi as _ }
41
+ fn arg2 ( & self ) -> usize { self . rsi as _ }
42
+ fn syscall_nr ( & self ) -> usize { self . orig_rax as _ }
36
43
fn ip ( & self ) -> usize { self . rip as _ }
37
44
fn sp ( & self ) -> usize { self . rsp as _ }
38
- fn orig_ax ( & self ) -> usize { self . orig_rax as _ }
39
45
fn set_ip ( & mut self , ip : usize ) { self . rip = ip as _ }
40
46
fn set_sp ( & mut self , sp : usize ) { self . rsp = sp as _ }
41
47
}
@@ -44,16 +50,30 @@ impl ArchIndependentRegs for libc::user_regs_struct {
44
50
#[ allow( clippy:: cast_possible_truncation) ]
45
51
#[ rustfmt:: skip]
46
52
impl ArchIndependentRegs for libc:: user_regs_struct {
47
- fn ax ( & self ) -> usize { self . eax as _ }
48
- fn di ( & self ) -> usize { self . edi as _ }
49
- fn si ( & self ) -> usize { self . esi as _ }
53
+ fn retval ( & self ) -> usize { self . eax as _ }
54
+ fn arg1 ( & self ) -> usize { self . edi as _ }
55
+ fn arg2 ( & self ) -> usize { self . esi as _ }
56
+ fn syscall_nr ( & self ) -> usize { self . orig_eax as _ }
50
57
fn ip ( & self ) -> usize { self . eip as _ }
51
58
fn sp ( & self ) -> usize { self . esp as _ }
52
- fn orig_ax ( & self ) -> usize { self . orig_eax as _ }
53
59
fn set_ip ( & mut self , ip : usize ) { self . eip = ip as _ }
54
60
fn set_sp ( & mut self , sp : usize ) { self . esp = sp as _ }
55
61
}
56
62
63
+ #[ cfg( target_arch = "aarch64" ) ]
64
+ #[ allow( clippy:: cast_possible_truncation) ]
65
+ #[ rustfmt:: skip]
66
+ impl ArchIndependentRegs for libc:: user_regs_struct {
67
+ fn retval ( & self ) -> usize { self . regs [ 0 ] as _ }
68
+ fn arg1 ( & self ) -> usize { self . regs [ 0 ] as _ }
69
+ fn arg2 ( & self ) -> usize { self . regs [ 1 ] as _ }
70
+ fn syscall_nr ( & self ) -> usize { self . regs [ 8 ] as _ }
71
+ fn ip ( & self ) -> usize { self . pc as _ }
72
+ fn sp ( & self ) -> usize { self . sp as _ }
73
+ fn set_ip ( & mut self , ip : usize ) { self . pc = ip as _ }
74
+ fn set_sp ( & mut self , sp : usize ) { self . sp = sp as _ }
75
+ }
76
+
57
77
pub struct Supervisor {
58
78
t_message : ipc:: IpcSender < TraceRequest > ,
59
79
r_event : ipc:: IpcReceiver < MemEvents > ,
@@ -295,16 +315,16 @@ fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
295
315
}
296
316
wait:: WaitStatus :: PtraceSyscall ( pid) => {
297
317
let regs = ptrace:: getregs ( pid) . unwrap ( ) ;
298
- let syscall_nr = regs. orig_ax ( ) ;
318
+ let syscall_nr = regs. syscall_nr ( ) ;
299
319
if enter {
300
320
if syscall_nr as i64 == libc:: SYS_mmap {
301
- let len = regs. si ( ) ;
321
+ let len = regs. arg2 ( ) ;
302
322
flush_mapped = Some ( len) ;
303
323
} else if syscall_nr as i64 == libc:: SYS_munmap {
304
324
// The unmap call might hit multiple mappings we've saved,
305
325
// or overlap with them partially (or both)
306
- let um_start = regs. di ( ) ;
307
- let um_len = regs. si ( ) ;
326
+ let um_start = regs. arg1 ( ) ;
327
+ let um_len = regs. arg2 ( ) ;
308
328
let um_end = um_start + um_len;
309
329
let mut idxes = vec ! [ ] ;
310
330
for ( idx, & ( mp_start, len) ) in mappings. iter ( ) . enumerate ( ) {
@@ -326,9 +346,9 @@ fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
326
346
} // TODO: handle brk/sbrk
327
347
} else {
328
348
if syscall_nr as i64 == libc:: SYS_mmap {
329
- if regs. ax ( ) as isize > 0 {
349
+ if regs. retval ( ) as isize > 0 {
330
350
if let Some ( len) = flush_mapped. take ( ) {
331
- let addr = regs. ax ( ) ;
351
+ let addr = regs. retval ( ) ;
332
352
mappings. push ( ( addr, len as _ ) ) ;
333
353
} else {
334
354
eprintln ! (
@@ -338,7 +358,7 @@ fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
338
358
}
339
359
} else if syscall_nr as i64 == libc:: SYS_munmap {
340
360
if let Some ( ( idxes, um_start, um_len) ) = munmap_args. take ( ) {
341
- if regs. ax ( ) as isize > 0 {
361
+ if regs. retval ( ) as isize > 0 {
342
362
// Unmap succeeded, so take out the mapping(s) from our list
343
363
// but it may be only partial so we may readd some sections
344
364
for idx in idxes {
@@ -373,9 +393,9 @@ fn sv_loop(listener: ChildListener, t_event: ipc::IpcSender<MemEvents>) -> ! {
373
393
ptrace:: seize ( main_pid, ptrace:: Options :: PTRACE_O_TRACESYSGOOD ) . unwrap ( ) ;
374
394
let _ = wait:: waitpid ( main_pid, None ) . unwrap ( ) ;
375
395
376
- ptrace:: write ( main_pid, malloc_addr as _ , 0xcc ) . unwrap ( ) ;
377
- ptrace:: write ( main_pid, realloc_addr as _ , 0xcc ) . unwrap ( ) ;
378
- ptrace:: write ( main_pid, free_addr as _ , 0xcc ) . unwrap ( ) ;
396
+ ptrace:: write ( main_pid, malloc_addr as _ , BREAKPT_INSTR ) . unwrap ( ) ;
397
+ ptrace:: write ( main_pid, realloc_addr as _ , BREAKPT_INSTR ) . unwrap ( ) ;
398
+ ptrace:: write ( main_pid, free_addr as _ , BREAKPT_INSTR ) . unwrap ( ) ;
379
399
380
400
ptrace:: syscall ( main_pid, None ) . unwrap ( ) ;
381
401
}
@@ -515,13 +535,13 @@ fn handle_sigtrap(
515
535
let regs = ptrace:: getregs ( pid) . unwrap ( ) ;
516
536
match regs. ip ( ) - 1 {
517
537
a if a == malloc_addr => {
518
- let size = regs. di ( ) ; // !
538
+ let size = regs. arg1 ( ) ; // !
519
539
let ptr = intercept_retptr ( pid, regs, malloc_addr, malloc_bytes) ;
520
540
mappings. push ( ( ptr as _ , size) ) ;
521
541
}
522
542
a if a == realloc_addr => {
523
- let old_ptr = regs. di ( ) ;
524
- let size = regs. si ( ) ;
543
+ let old_ptr = regs. arg1 ( ) ;
544
+ let size = regs. arg2 ( ) ;
525
545
let pos = mappings
526
546
. iter ( )
527
547
. position ( |& ( ptr, size) | ptr <= old_ptr as _ && ( old_ptr as usize ) < ptr + size) ;
@@ -532,7 +552,7 @@ fn handle_sigtrap(
532
552
mappings. push ( ( ptr as _ , size as _ ) ) ;
533
553
}
534
554
a if a == free_addr => {
535
- let old_ptr = regs. di ( ) ;
555
+ let old_ptr = regs. arg1 ( ) ;
536
556
//let size = regs.rdi;
537
557
let pos =
538
558
mappings. iter ( ) . position ( |& ( ptr, size) | ptr <= old_ptr && old_ptr < ptr + size) ;
@@ -565,7 +585,7 @@ fn intercept_retptr(
565
585
regs. set_ip ( regs. ip ( ) - 1 ) ;
566
586
let ret_addr = ptrace:: read ( pid, regs. sp ( ) as _ ) . unwrap ( ) ;
567
587
let ret_bytes = ptrace:: read ( pid, ret_addr as _ ) . unwrap ( ) ;
568
- ptrace:: write ( pid, ret_addr as _ , 0xcc ) . unwrap ( ) ;
588
+ ptrace:: write ( pid, ret_addr as _ , BREAKPT_INSTR ) . unwrap ( ) ;
569
589
ptrace:: write ( pid, fn_addr as _ , fn_bytes) . unwrap ( ) ;
570
590
ptrace:: setregs ( pid, regs) . unwrap ( ) ;
571
591
@@ -574,9 +594,9 @@ fn intercept_retptr(
574
594
575
595
// now we're getting the return hopefully
576
596
let mut regs = ptrace:: getregs ( pid) . unwrap ( ) ;
577
- let ptr = regs. ax ( ) ; // !
597
+ let ptr = regs. retval ( ) ; // !
578
598
regs. set_ip ( regs. ip ( ) - 1 ) ;
579
- ptrace:: write ( pid, fn_addr as _ , 0xcc ) . unwrap ( ) ;
599
+ ptrace:: write ( pid, fn_addr as _ , BREAKPT_INSTR ) . unwrap ( ) ;
580
600
ptrace:: write ( pid, ret_addr as _ , ret_bytes) . unwrap ( ) ;
581
601
ptrace:: setregs ( pid, regs) . unwrap ( ) ;
582
602
0 commit comments