@@ -33,16 +33,16 @@ use x86_64_target::HyperlightSandboxTarget;
3333
3434use super :: InterruptHandle ;
3535use super :: regs:: CommonRegisters ;
36+ use crate :: HyperlightError ;
3637use crate :: hypervisor:: regs:: CommonFpu ;
37- use crate :: hypervisor:: virtual_machine:: VirtualMachine ;
38+ use crate :: hypervisor:: virtual_machine:: { HypervisorError , RegisterError , VirtualMachine } ;
3839use crate :: mem:: layout:: SandboxMemoryLayout ;
3940use crate :: mem:: memory_region:: MemoryRegion ;
4041use crate :: mem:: mgr:: SandboxMemoryManager ;
4142use crate :: mem:: shared_mem:: HostSharedMemory ;
42- use crate :: { HyperlightError , new_error} ;
4343
4444#[ derive( Debug , Error ) ]
45- pub ( crate ) enum GdbTargetError {
45+ pub enum GdbTargetError {
4646 #[ error( "Error encountered while binding to address and port" ) ]
4747 CannotBind ,
4848 #[ error( "Error encountered while listening for connections" ) ]
@@ -86,6 +86,17 @@ pub(crate) struct DebugMemoryAccess {
8686 pub ( crate ) guest_mmap_regions : Vec < MemoryRegion > ,
8787}
8888
89+ /// Errors that can occur during debug memory access operations
90+ #[ derive( Debug , thiserror:: Error ) ]
91+ pub enum DebugMemoryAccessError {
92+ #[ error( "Failed to copy memory: {0}" ) ]
93+ CopyFailed ( Box < HyperlightError > ) ,
94+ #[ error( "Failed to acquire lock at {0}:{1} - {2}" ) ]
95+ LockFailed ( & ' static str , u32 , String ) ,
96+ #[ error( "Failed to translate guest address {0:#x}" ) ]
97+ TranslateGuestAddress ( u64 ) ,
98+ }
99+
89100impl DebugMemoryAccess {
90101 /// Reads memory from the guest's address space with a maximum length of a PAGE_SIZE
91102 ///
@@ -94,8 +105,12 @@ impl DebugMemoryAccess {
94105 /// * `gpa` - Guest physical address to read from.
95106 /// This address is shall be translated before calling this function
96107 /// # Returns
97- /// * `Result<(), HyperlightError>` - Ok if successful, Err otherwise
98- pub ( crate ) fn read ( & self , data : & mut [ u8 ] , gpa : u64 ) -> crate :: Result < ( ) > {
108+ /// * `Result<(), DebugMemoryAccessError>` - Ok if successful, Err otherwise
109+ pub ( crate ) fn read (
110+ & self ,
111+ data : & mut [ u8 ] ,
112+ gpa : u64 ,
113+ ) -> std:: result:: Result < ( ) , DebugMemoryAccessError > {
99114 let read_len = data. len ( ) ;
100115
101116 let mem_offset = ( gpa as usize )
@@ -107,7 +122,7 @@ impl DebugMemoryAccess {
107122 gpa,
108123 SandboxMemoryLayout :: BASE_ADDRESS
109124 ) ;
110- HyperlightError :: TranslateGuestAddress ( gpa)
125+ DebugMemoryAccessError :: TranslateGuestAddress ( gpa)
111126 } ) ?;
112127
113128 // First check the mapped memory regions to see if the address is within any of them
@@ -123,7 +138,7 @@ impl DebugMemoryAccess {
123138 mem_offset,
124139 reg. guest_region. start,
125140 ) ;
126- HyperlightError :: TranslateGuestAddress ( mem_offset as u64 )
141+ DebugMemoryAccessError :: TranslateGuestAddress ( mem_offset as u64 )
127142 } ) ?;
128143
129144 let bytes: & [ u8 ] = unsafe {
@@ -144,9 +159,10 @@ impl DebugMemoryAccess {
144159
145160 self . dbg_mem_access_fn
146161 . try_lock ( )
147- . map_err ( |e| new_error ! ( "Error locking at {}:{}: {}" , file!( ) , line!( ) , e) ) ?
162+ . map_err ( |e| DebugMemoryAccessError :: LockFailed ( file ! ( ) , line ! ( ) , e. to_string ( ) ) ) ?
148163 . get_shared_mem_mut ( )
149- . copy_to_slice ( & mut data[ ..read_len] , mem_offset) ?;
164+ . copy_to_slice ( & mut data[ ..read_len] , mem_offset)
165+ . map_err ( |e| DebugMemoryAccessError :: CopyFailed ( Box :: new ( e) ) ) ?;
150166 }
151167
152168 Ok ( ( ) )
@@ -159,8 +175,12 @@ impl DebugMemoryAccess {
159175 /// * `gpa` - Guest physical address to write to.
160176 /// This address is shall be translated before calling this function
161177 /// # Returns
162- /// * `Result<(), HyperlightError>` - Ok if successful, Err otherwise
163- pub ( crate ) fn write ( & self , data : & [ u8 ] , gpa : u64 ) -> crate :: Result < ( ) > {
178+ /// * `Result<(), DebugMemoryAccessError>` - Ok if successful, Err otherwise
179+ pub ( crate ) fn write (
180+ & self ,
181+ data : & [ u8 ] ,
182+ gpa : u64 ,
183+ ) -> std:: result:: Result < ( ) , DebugMemoryAccessError > {
164184 let write_len = data. len ( ) ;
165185
166186 let mem_offset = ( gpa as usize )
@@ -172,7 +192,7 @@ impl DebugMemoryAccess {
172192 gpa,
173193 SandboxMemoryLayout :: BASE_ADDRESS
174194 ) ;
175- HyperlightError :: TranslateGuestAddress ( gpa)
195+ DebugMemoryAccessError :: TranslateGuestAddress ( gpa)
176196 } ) ?;
177197
178198 // First check the mapped memory regions to see if the address is within any of them
@@ -188,7 +208,7 @@ impl DebugMemoryAccess {
188208 mem_offset,
189209 reg. guest_region. start,
190210 ) ;
191- HyperlightError :: TranslateGuestAddress ( mem_offset as u64 )
211+ DebugMemoryAccessError :: TranslateGuestAddress ( mem_offset as u64 )
192212 } ) ?;
193213
194214 let bytes: & mut [ u8 ] = unsafe {
@@ -213,9 +233,10 @@ impl DebugMemoryAccess {
213233
214234 self . dbg_mem_access_fn
215235 . try_lock ( )
216- . map_err ( |e| new_error ! ( "Error locking at {}:{}: {}" , file!( ) , line!( ) , e) ) ?
236+ . map_err ( |e| DebugMemoryAccessError :: LockFailed ( file ! ( ) , line ! ( ) , e. to_string ( ) ) ) ?
217237 . get_shared_mem_mut ( )
218- . copy_from_slice ( & data[ ..write_len] , mem_offset) ?;
238+ . copy_from_slice ( & data[ ..write_len] , mem_offset)
239+ . map_err ( |e| DebugMemoryAccessError :: CopyFailed ( Box :: new ( e) ) ) ?;
219240 }
220241
221242 Ok ( ( ) )
@@ -275,24 +296,42 @@ pub(crate) enum DebugResponse {
275296 WriteRegisters ,
276297}
277298
299+ /// Errors that can occur during debug operations
300+ #[ derive( Debug , Clone , thiserror:: Error ) ]
301+ pub enum DebugError {
302+ #[ error( "Hardware breakpoint not found at address {0:#x}" ) ]
303+ HwBreakpointNotFound ( u64 ) ,
304+ #[ error( "Failed to enable/disable intercept: {enable}, {inner}" ) ]
305+ Intercept {
306+ enable : bool ,
307+ inner : HypervisorError ,
308+ } ,
309+ #[ error( "Register operation failed: {0}" ) ]
310+ Register ( #[ from] RegisterError ) ,
311+ #[ error( "Maximum hardware breakpoints ({0}) exceeded" ) ]
312+ TooManyHwBreakpoints ( usize ) ,
313+ #[ error( "Translation of guest virtual address failed: {0}" ) ]
314+ TranslateGva ( u64 ) ,
315+ }
316+
278317/// Trait for VMs that support debugging capabilities.
279318/// This extends the base VirtualMachine trait with GDB-specific functionality.
280319pub ( crate ) trait DebuggableVm : VirtualMachine {
281320 /// Translates a guest virtual address to a guest physical address
282- fn translate_gva ( & self , gva : u64 ) -> crate :: Result < u64 > ;
321+ fn translate_gva ( & self , gva : u64 ) -> std :: result :: Result < u64 , DebugError > ;
283322
284323 /// Enable/disable debugging
285- fn set_debug ( & mut self , enable : bool ) -> crate :: Result < ( ) > ;
324+ fn set_debug ( & mut self , enable : bool ) -> std :: result :: Result < ( ) , DebugError > ;
286325
287326 /// Enable/disable single stepping
288- fn set_single_step ( & mut self , enable : bool ) -> crate :: Result < ( ) > ;
327+ fn set_single_step ( & mut self , enable : bool ) -> std :: result :: Result < ( ) , DebugError > ;
289328
290329 /// Add a hardware breakpoint at the given address.
291330 /// Must be idempotent.
292- fn add_hw_breakpoint ( & mut self , addr : u64 ) -> crate :: Result < ( ) > ;
331+ fn add_hw_breakpoint ( & mut self , addr : u64 ) -> std :: result :: Result < ( ) , DebugError > ;
293332
294333 /// Remove a hardware breakpoint at the given address
295- fn remove_hw_breakpoint ( & mut self , addr : u64 ) -> crate :: Result < ( ) > ;
334+ fn remove_hw_breakpoint ( & mut self , addr : u64 ) -> std :: result :: Result < ( ) , DebugError > ;
296335}
297336
298337/// Debug communication channel that is used for sending a request type and
@@ -513,7 +552,9 @@ mod tests {
513552 }
514553
515554 let mut read_data = [ 0u8 ; 1 ] ;
516- mem_access. read ( & mut read_data, ( BASE_VIRT + offset) as u64 ) ?;
555+ mem_access
556+ . read ( & mut read_data, ( BASE_VIRT + offset) as u64 )
557+ . unwrap ( ) ;
517558
518559 assert_eq ! ( read_data[ 0 ] , 0xAA ) ;
519560
@@ -536,7 +577,9 @@ mod tests {
536577 }
537578
538579 let mut read_data = [ 0u8 ; 16 ] ;
539- mem_access. read ( & mut read_data, ( BASE_VIRT + offset) as u64 ) ?;
580+ mem_access
581+ . read ( & mut read_data, ( BASE_VIRT + offset) as u64 )
582+ . unwrap ( ) ;
540583
541584 assert_eq ! (
542585 read_data,
@@ -556,7 +599,9 @@ mod tests {
556599 }
557600
558601 let write_data = [ 0xCCu8 ; 1 ] ;
559- mem_access. write ( & write_data, ( BASE_VIRT + offset) as u64 ) ?;
602+ mem_access
603+ . write ( & write_data, ( BASE_VIRT + offset) as u64 )
604+ . unwrap ( ) ;
560605
561606 let slice = unsafe { get_mmap_slice ( & mut mem_access) } ;
562607 assert_eq ! ( slice[ offset] , write_data[ 0 ] ) ;
@@ -577,7 +622,9 @@ mod tests {
577622 }
578623
579624 let write_data = [ 0xAAu8 ; 16 ] ;
580- mem_access. write ( & write_data, ( BASE_VIRT + offset) as u64 ) ?;
625+ mem_access
626+ . write ( & write_data, ( BASE_VIRT + offset) as u64 )
627+ . unwrap ( ) ;
581628
582629 let slice = unsafe { get_mmap_slice ( & mut mem_access) } ;
583630 assert_eq ! ( slice[ offset..offset + 16 ] , write_data) ;
0 commit comments