@@ -154,7 +154,7 @@ pub struct MemAccessInfo {
154
154
#[ derive( Debug , Clone , Copy ) ]
155
155
#[ repr( transparent) ]
156
156
pub struct CPU {
157
- ptr : CPUStatePtr ,
157
+ cpu_ptr : CPUStatePtr ,
158
158
}
159
159
160
160
#[ derive( Debug , Clone , PartialEq ) ]
@@ -305,20 +305,20 @@ impl CPU {
305
305
#[ must_use]
306
306
#[ expect( clippy:: cast_sign_loss) ]
307
307
pub fn index ( & self ) -> usize {
308
- unsafe { libafl_qemu_cpu_index ( self . ptr ) as usize }
308
+ unsafe { libafl_qemu_cpu_index ( self . cpu_ptr ) as usize }
309
309
}
310
310
311
311
pub fn trigger_breakpoint ( & self ) {
312
312
unsafe {
313
- libafl_qemu_trigger_breakpoint ( self . ptr ) ;
313
+ libafl_qemu_trigger_breakpoint ( self . cpu_ptr ) ;
314
314
}
315
315
}
316
316
317
317
// TODO expose tlb_set_dirty and tlb_reset_dirty
318
318
319
319
#[ must_use]
320
320
pub fn num_regs ( & self ) -> i32 {
321
- unsafe { libafl_qemu_num_regs ( self . ptr ) }
321
+ unsafe { libafl_qemu_num_regs ( self . cpu_ptr ) }
322
322
}
323
323
324
324
pub fn read_reg < R > ( & self , reg : R ) -> Result < GuestReg , QemuRWError >
@@ -328,12 +328,12 @@ impl CPU {
328
328
unsafe {
329
329
let reg_id = reg. clone ( ) . into ( ) ;
330
330
let mut val = MaybeUninit :: uninit ( ) ;
331
- let success = libafl_qemu_read_reg ( self . ptr , reg_id, val. as_mut_ptr ( ) as * mut u8 ) ;
331
+ let success = libafl_qemu_read_reg ( self . cpu_ptr , reg_id, val. as_mut_ptr ( ) as * mut u8 ) ;
332
332
if success == 0 {
333
333
Err ( QemuRWError :: wrong_reg (
334
334
QemuRWErrorKind :: Write ,
335
335
reg,
336
- Some ( self . ptr ) ,
336
+ Some ( self . cpu_ptr ) ,
337
337
) )
338
338
} else {
339
339
#[ cfg( feature = "be" ) ]
@@ -357,12 +357,13 @@ impl CPU {
357
357
#[ cfg( not( feature = "be" ) ) ]
358
358
let val = GuestReg :: to_le ( val. into ( ) ) ;
359
359
360
- let success = unsafe { libafl_qemu_write_reg ( self . ptr , reg_id, & raw const val as * mut u8 ) } ;
360
+ let success =
361
+ unsafe { libafl_qemu_write_reg ( self . cpu_ptr , reg_id, & raw const val as * mut u8 ) } ;
361
362
if success == 0 {
362
363
Err ( QemuRWError :: wrong_reg (
363
364
QemuRWErrorKind :: Write ,
364
365
reg,
365
- Some ( self . ptr ) ,
366
+ Some ( self . cpu_ptr ) ,
366
367
) )
367
368
} else {
368
369
Ok ( ( ) )
@@ -374,7 +375,7 @@ impl CPU {
374
375
// TODO use gdbstub's target_cpu_memory_rw_debug
375
376
let ret = unsafe {
376
377
libafl_qemu_sys:: cpu_memory_rw_debug (
377
- self . ptr ,
378
+ self . cpu_ptr ,
378
379
addr as GuestVirtAddr ,
379
380
buf. as_mut_ptr ( ) as * mut _ ,
380
381
buf. len ( ) ,
@@ -385,7 +386,7 @@ impl CPU {
385
386
if ret != 0 {
386
387
Err ( QemuRWError :: wrong_mem_location (
387
388
QemuRWErrorKind :: Read ,
388
- self . ptr ,
389
+ self . cpu_ptr ,
389
390
addr,
390
391
buf. len ( ) ,
391
392
) )
@@ -411,7 +412,7 @@ impl CPU {
411
412
// TODO use gdbstub's target_cpu_memory_rw_debug
412
413
let ret = unsafe {
413
414
libafl_qemu_sys:: cpu_memory_rw_debug (
414
- self . ptr ,
415
+ self . cpu_ptr ,
415
416
addr as GuestVirtAddr ,
416
417
buf. as_ptr ( ) as * mut _ ,
417
418
buf. len ( ) ,
@@ -422,7 +423,7 @@ impl CPU {
422
423
if ret != 0 {
423
424
Err ( QemuRWError :: wrong_mem_location (
424
425
QemuRWErrorKind :: Write ,
425
- self . ptr ,
426
+ self . cpu_ptr ,
426
427
addr,
427
428
buf. len ( ) ,
428
429
) )
@@ -432,15 +433,15 @@ impl CPU {
432
433
}
433
434
434
435
pub fn reset ( & self ) {
435
- unsafe { libafl_qemu_sys:: cpu_reset ( self . ptr ) } ;
436
+ unsafe { libafl_qemu_sys:: cpu_reset ( self . cpu_ptr ) } ;
436
437
}
437
438
438
439
#[ must_use]
439
440
pub fn save_state ( & self ) -> CPUArchState {
440
441
unsafe {
441
442
let mut saved = MaybeUninit :: < CPUArchState > :: uninit ( ) ;
442
443
copy_nonoverlapping (
443
- libafl_qemu_sys:: cpu_env ( self . ptr . as_mut ( ) . unwrap ( ) ) ,
444
+ libafl_qemu_sys:: cpu_env ( self . cpu_ptr . as_mut ( ) . unwrap ( ) ) ,
444
445
saved. as_mut_ptr ( ) ,
445
446
1 ,
446
447
) ;
@@ -452,15 +453,15 @@ impl CPU {
452
453
unsafe {
453
454
copy_nonoverlapping (
454
455
saved,
455
- libafl_qemu_sys:: cpu_env ( self . ptr . as_mut ( ) . unwrap ( ) ) ,
456
+ libafl_qemu_sys:: cpu_env ( self . cpu_ptr . as_mut ( ) . unwrap ( ) ) ,
456
457
1 ,
457
458
) ;
458
459
}
459
460
}
460
461
461
462
#[ must_use]
462
463
pub fn raw_ptr ( & self ) -> CPUStatePtr {
463
- self . ptr
464
+ self . cpu_ptr
464
465
}
465
466
466
467
#[ must_use]
@@ -737,43 +738,62 @@ impl Qemu {
737
738
if ptr. is_null ( ) {
738
739
None
739
740
} else {
740
- Some ( CPU { ptr } )
741
+ Some ( CPU { cpu_ptr : ptr } )
741
742
}
742
743
}
743
744
744
745
#[ must_use]
745
746
#[ expect( clippy:: cast_possible_wrap) ]
746
- pub fn cpu_from_index ( & self , index : usize ) -> CPU {
747
- unsafe {
748
- CPU {
749
- ptr : libafl_qemu_get_cpu ( index as i32 ) ,
750
- }
747
+ pub fn cpu_from_index ( & self , index : usize ) -> Option < CPU > {
748
+ let cpu_ptr = unsafe { libafl_qemu_get_cpu ( index as i32 ) } ;
749
+
750
+ if cpu_ptr. is_null ( ) {
751
+ None
752
+ } else {
753
+ Some ( CPU { cpu_ptr } )
751
754
}
752
755
}
753
756
757
+ /// # Safety
758
+ ///
759
+ /// CPU will be incorrect if CPU index does not exist
760
+ #[ must_use]
761
+ #[ expect( clippy:: cast_possible_wrap) ]
762
+ pub unsafe fn cpu_from_index_unchecked ( & self , index : usize ) -> CPU {
763
+ let cpu_ptr = unsafe { libafl_qemu_get_cpu ( index as i32 ) } ;
764
+
765
+ CPU { cpu_ptr }
766
+ }
767
+
754
768
#[ must_use]
755
769
pub fn page_from_addr ( & self , addr : GuestAddr ) -> GuestAddr {
756
770
unsafe { libafl_page_from_addr ( addr) }
757
771
}
758
772
759
773
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
774
+ /// Uses the 0th CPU if no CPU is currently running.
760
775
pub fn read_mem ( & self , addr : GuestAddr , buf : & mut [ u8 ] ) -> Result < ( ) , QemuRWError > {
761
776
self . current_cpu ( )
762
- . unwrap_or_else ( || self . cpu_from_index ( 0 ) )
777
+ . or_else ( || self . cpu_from_index ( 0 ) )
778
+ . ok_or ( QemuRWError :: current_cpu_not_found ( QemuRWErrorKind :: Read ) ) ?
763
779
. read_mem ( addr, buf)
764
780
}
765
781
766
782
/// Read a value from a guest address, taking into account the potential indirections with the current CPU.
783
+ /// Uses the 0th CPU if no CPU is currently running.
767
784
pub fn read_mem_vec ( & self , addr : GuestAddr , len : usize ) -> Result < Vec < u8 > , QemuRWError > {
768
785
self . current_cpu ( )
769
- . unwrap_or_else ( || self . cpu_from_index ( 0 ) )
786
+ . or_else ( || self . cpu_from_index ( 0 ) )
787
+ . ok_or ( QemuRWError :: current_cpu_not_found ( QemuRWErrorKind :: Read ) ) ?
770
788
. read_mem_vec ( addr, len)
771
789
}
772
790
773
791
/// Write a value to a guest address, taking into account the potential indirections with the current CPU.
792
+ /// Uses the 0th CPU if no CPU is currently running.
774
793
pub fn write_mem ( & self , addr : GuestAddr , buf : & [ u8 ] ) -> Result < ( ) , QemuRWError > {
775
794
self . current_cpu ( )
776
- . unwrap_or_else ( || self . cpu_from_index ( 0 ) )
795
+ . or_else ( || self . cpu_from_index ( 0 ) )
796
+ . ok_or ( QemuRWError :: current_cpu_not_found ( QemuRWErrorKind :: Write ) ) ?
777
797
. write_mem ( addr, buf)
778
798
}
779
799
@@ -816,12 +836,12 @@ impl Qemu {
816
836
/// This may only be safely used for valid guest addresses.
817
837
///
818
838
/// In any case, no check will be performed on the correctness of the operation.
819
- ///
839
+ /// Also, the there must be a current CPU (or a CPU at index 0).
820
840
/// Please refer to [`CPU::read_mem`] for more details.
821
841
pub unsafe fn read_mem_unchecked ( & self , addr : GuestAddr , buf : & mut [ u8 ] ) {
822
842
unsafe {
823
843
self . current_cpu ( )
824
- . unwrap_or_else ( || self . cpu_from_index ( 0 ) )
844
+ . unwrap_or_else ( || self . cpu_from_index_unchecked ( 0 ) )
825
845
. read_mem_unchecked ( addr, buf) ;
826
846
}
827
847
}
@@ -834,11 +854,12 @@ impl Qemu {
834
854
/// In any case, no check will be performed on the correctness of the operation.
835
855
///
836
856
/// This may only be safely used for valid guest addresses.
857
+ /// Also, the there must be a current CPU (or a CPU at index 0).
837
858
/// Please refer to [`CPU::write_mem`] for more details.
838
859
pub unsafe fn write_mem_unchecked ( & self , addr : GuestAddr , buf : & [ u8 ] ) {
839
860
unsafe {
840
861
self . current_cpu ( )
841
- . unwrap_or_else ( || self . cpu_from_index ( 0 ) )
862
+ . unwrap_or_else ( || self . cpu_from_index_unchecked ( 0 ) )
842
863
. write_mem_unchecked ( addr, buf) ;
843
864
}
844
865
}
0 commit comments