@@ -65,6 +65,7 @@ pub(crate) fn is_hypervisor_present() -> bool {
65
65
66
66
#[ cfg( gdb) ]
67
67
mod debug {
68
+ use std:: collections:: HashMap ;
68
69
use std:: sync:: { Arc , Mutex } ;
69
70
70
71
use hyperlight_common:: mem:: PAGE_SIZE ;
@@ -80,6 +81,13 @@ mod debug {
80
81
use crate :: mem:: layout:: SandboxMemoryLayout ;
81
82
use crate :: { new_error, Result } ;
82
83
84
+ /// Software Breakpoint size in memory
85
+ pub const SW_BP_SIZE : usize = 1 ;
86
+ /// Software Breakpoinnt opcode
87
+ const SW_BP_OP : u8 = 0xCC ;
88
+ /// Software Breakpoint written to memory
89
+ pub const SW_BP : [ u8 ; SW_BP_SIZE ] = [ SW_BP_OP ] ;
90
+
83
91
/// KVM Debug struct
84
92
/// This struct is used to abstract the internal details of the kvm
85
93
/// guest debugging settings
@@ -90,6 +98,8 @@ mod debug {
90
98
91
99
/// Array of addresses for HW breakpoints
92
100
hw_breakpoints : Vec < u64 > ,
101
+ /// Saves the bytes modified to enable sw breakpoints
102
+ sw_breakpoints : HashMap < u64 , [ u8 ; SW_BP_SIZE ] > ,
93
103
94
104
/// Sent to KVM for enabling guest debug
95
105
pub dbg_cfg : kvm_guest_debug ,
@@ -107,6 +117,7 @@ mod debug {
107
117
Self {
108
118
single_step : false ,
109
119
hw_breakpoints : vec ! [ ] ,
120
+ sw_breakpoints : HashMap :: new ( ) ,
110
121
dbg_cfg : dbg,
111
122
}
112
123
}
@@ -380,6 +391,69 @@ mod debug {
380
391
}
381
392
}
382
393
394
+ pub fn add_sw_breakpoint (
395
+ & mut self ,
396
+ addr : u64 ,
397
+ dbg_mem_access_fn : Arc < Mutex < dyn DbgMemAccessHandlerCaller > > ,
398
+ ) -> Result < bool > {
399
+ let addr = {
400
+ let debug = self
401
+ . debug
402
+ . as_ref ( )
403
+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
404
+ let addr = self . translate_gva ( addr) ?;
405
+ if debug. sw_breakpoints . contains_key ( & addr) {
406
+ return Ok ( true ) ;
407
+ }
408
+
409
+ addr
410
+ } ;
411
+
412
+ let mut save_data = [ 0 ; SW_BP_SIZE ] ;
413
+ self . read_addrs ( addr, & mut save_data[ ..] , dbg_mem_access_fn. clone ( ) ) ?;
414
+ self . write_addrs ( addr, & SW_BP , dbg_mem_access_fn. clone ( ) ) ?;
415
+
416
+ {
417
+ let debug = self
418
+ . debug
419
+ . as_mut ( )
420
+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
421
+ debug. sw_breakpoints . insert ( addr, save_data) ;
422
+ }
423
+
424
+ Ok ( true )
425
+ }
426
+
427
+ pub fn remove_sw_breakpoint (
428
+ & mut self ,
429
+ addr : u64 ,
430
+ dbg_mem_access_fn : Arc < Mutex < dyn DbgMemAccessHandlerCaller > > ,
431
+ ) -> Result < bool > {
432
+ let ( ret, data) = {
433
+ let addr = self . translate_gva ( addr) ?;
434
+ let debug = self
435
+ . debug
436
+ . as_mut ( )
437
+ . ok_or_else ( || new_error ! ( "Debug is not enabled" ) ) ?;
438
+
439
+ if debug. sw_breakpoints . contains_key ( & addr) {
440
+ let save_data = debug
441
+ . sw_breakpoints
442
+ . remove ( & addr)
443
+ . expect ( "Expected the hashmap to contain the address" ) ;
444
+
445
+ ( true , Some ( save_data) )
446
+ } else {
447
+ ( false , None )
448
+ }
449
+ } ;
450
+
451
+ if ret {
452
+ self . write_addrs ( addr, & data. unwrap ( ) , dbg_mem_access_fn. clone ( ) ) ?;
453
+ }
454
+
455
+ Ok ( ret)
456
+ }
383
457
384
458
/// Get the reason the vCPU has stopped
385
459
pub fn get_stop_reason ( & self ) -> Result < VcpuStopReason > {
@@ -394,6 +468,9 @@ mod debug {
394
468
395
469
let ip = self . get_instruction_pointer ( ) ?;
396
470
let gpa = self . translate_gva ( ip) ?;
471
+ if debug. sw_breakpoints . contains_key ( & gpa) {
472
+ return Ok ( VcpuStopReason :: SwBp ) ;
473
+ }
397
474
398
475
if debug. hw_breakpoints . contains ( & gpa) {
399
476
return Ok ( VcpuStopReason :: HwBp ) ;
@@ -418,6 +495,13 @@ mod debug {
418
495
. expect ( "Add hw breakpoint error" ) ;
419
496
Ok ( DebugResponse :: AddHwBreakpoint ( res) )
420
497
}
498
+ DebugMsg :: AddSwBreakpoint ( addr) => {
499
+ let res = self
500
+ . add_sw_breakpoint ( addr, dbg_mem_access_fn. clone ( ) )
501
+ . expect ( "Add sw breakpoint error" ) ;
502
+
503
+ Ok ( DebugResponse :: AddSwBreakpoint ( res) )
504
+ }
421
505
DebugMsg :: Continue => {
422
506
self . set_single_step ( false ) ?;
423
507
Ok ( DebugResponse :: Continue )
@@ -454,6 +538,12 @@ mod debug {
454
538
. expect ( "Remove hw breakpoint error" ) ;
455
539
Ok ( DebugResponse :: RemoveHwBreakpoint ( res) )
456
540
}
541
+ DebugMsg :: RemoveSwBreakpoint ( addr) => {
542
+ let res = self
543
+ . remove_sw_breakpoint ( addr, dbg_mem_access_fn. clone ( ) )
544
+ . expect ( "Remove sw breakpoint error" ) ;
545
+ Ok ( DebugResponse :: RemoveSwBreakpoint ( res) )
546
+ }
457
547
DebugMsg :: Step => {
458
548
self . set_single_step ( true ) ?;
459
549
Ok ( DebugResponse :: Step )
0 commit comments