11//! Implements calling functions from a native library. 
22
3- // FIXME: disabled since it fails to build on many targets. 
4- //#[cfg(target_os = "linux")] 
5- //pub mod trace; 
6- 
73use  std:: ops:: Deref ; 
84
95use  libffi:: high:: call as  ffi; 
@@ -13,14 +9,55 @@ use rustc_middle::mir::interpret::Pointer;
139use  rustc_middle:: ty:: { self  as  ty,  IntTy ,  UintTy } ; 
1410use  rustc_span:: Symbol ; 
1511
16- //#[cfg(target_os = "linux")] 
17- //use self::trace::Supervisor; 
12+ #[ cfg_attr(  
13+     not( all(  
14+         target_os = "linux" ,  
15+         target_env = "gnu" ,  
16+         any( target_arch = "x86" ,  target_arch = "x86_64" )  
17+     ) ) ,  
18+     path = "trace/stub.rs"  
19+ ) ] 
20+ pub  mod  trace; 
21+ 
1822use  crate :: * ; 
1923
20- //#[cfg(target_os = "linux")] 
21- //type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>; 
22- //#[cfg(not(target_os = "linux"))] 
23- type  CallResult < ' tcx >  = InterpResult < ' tcx ,  ( ImmTy < ' tcx > ,  Option < !> ) > ; 
24+ /// The final results of an FFI trace, containing every relevant event detected 
25+ /// by the tracer. 
26+ #[ allow( dead_code) ]  
27+ #[ cfg_attr( target_os = "linux" ,  derive( serde:: Serialize ,  serde:: Deserialize ) ) ]  
28+ #[ derive( Debug ) ]  
29+ pub  struct  MemEvents  { 
30+     /// An list of memory accesses that occurred, in the order they occurred in. 
31+ pub  acc_events :  Vec < AccessEvent > , 
32+ } 
33+ 
34+ /// A single memory access. 
35+ #[ allow( dead_code) ]  
36+ #[ cfg_attr( target_os = "linux" ,  derive( serde:: Serialize ,  serde:: Deserialize ) ) ]  
37+ #[ derive( Debug ) ]  
38+ pub  enum  AccessEvent  { 
39+     /// A read may have occurred on this memory range. 
40+ /// Some instructions *may* read memory without *always* doing that, 
41+ /// so this can be an over-approximation. 
42+ /// The range info, however, is reliable if the access did happen. 
43+ Read ( AccessRange ) , 
44+     /// A read may have occurred on this memory range. 
45+ /// Some instructions *may* write memory without *always* doing that, 
46+ /// so this can be an over-approximation. 
47+ /// The range info, however, is reliable if the access did happen. 
48+ Write ( AccessRange ) , 
49+ } 
50+ 
51+ /// The memory touched by a given access. 
52+ #[ allow( dead_code) ]  
53+ #[ cfg_attr( target_os = "linux" ,  derive( serde:: Serialize ,  serde:: Deserialize ) ) ]  
54+ #[ derive( Clone ,  Debug ) ]  
55+ pub  struct  AccessRange  { 
56+     /// The base address in memory where an access occurred. 
57+ pub  addr :  usize , 
58+     /// The number of bytes affected from the base. 
59+ pub  size :  usize , 
60+ } 
2461
2562impl < ' tcx >  EvalContextExtPriv < ' tcx >  for  crate :: MiriInterpCx < ' tcx >  { } 
2663trait  EvalContextExtPriv < ' tcx > :  crate :: MiriInterpCxExt < ' tcx >  { 
@@ -31,18 +68,17 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
3168        dest :  & MPlaceTy < ' tcx > , 
3269        ptr :  CodePtr , 
3370        libffi_args :  Vec < libffi:: high:: Arg < ' a > > , 
34-     )  -> CallResult < ' tcx >  { 
71+     )  -> InterpResult < ' tcx ,   ( crate :: ImmTy < ' tcx > ,   Option < MemEvents > ) >  { 
3572        let  this = self . eval_context_mut ( ) ; 
36-         //#[cfg(target_os = "linux")] 
37-         //let alloc = this.machine.allocator.as_ref().unwrap(); 
38- 
39-         // SAFETY: We don't touch the machine memory past this point. 
40-         //#[cfg(target_os = "linux")] 
41-         //let (guard, stack_ptr) = unsafe { Supervisor::start_ffi(alloc) }; 
73+         #[ cfg( target_os = "linux" ) ]  
74+         let  alloc = this. machine . allocator . as_ref ( ) . unwrap ( ) ; 
75+         #[ cfg( not( target_os = "linux" ) ) ]  
76+         // Placeholder value. 
77+         let  alloc = ( ) ; 
4278
43-         // Call the function (`ptr`) with arguments `libffi_args`, and obtain the return value 
44-         // as  the specified primitive integer type  
45-         let  res =  ' res :   { 
79+         trace :: Supervisor :: do_ffi ( alloc ,  ||  { 
80+              // Call  the function (`ptr`) with arguments `libffi_args`, and obtain the return value  
81+              // as the specified primitive integer type 
4682            let  scalar = match  dest. layout . ty . kind ( )  { 
4783                // ints 
4884                ty:: Int ( IntTy :: I8 )  => { 
@@ -93,31 +129,22 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
93129                // have the output_type `Tuple([])`. 
94130                ty:: Tuple ( t_list)  if  ( * t_list) . deref ( ) . is_empty ( )  => { 
95131                    unsafe  {  ffi:: call :: < ( ) > ( ptr,  libffi_args. as_slice ( ) )  } ; 
96-                     break   ' res  interp_ok ( ImmTy :: uninit ( dest. layout ) ) ; 
132+                     return  interp_ok ( ImmTy :: uninit ( dest. layout ) ) ; 
97133                } 
98134                ty:: RawPtr ( ..)  => { 
99135                    let  x = unsafe  {  ffi:: call :: < * const  ( ) > ( ptr,  libffi_args. as_slice ( ) )  } ; 
100136                    let  ptr = Pointer :: new ( Provenance :: Wildcard ,  Size :: from_bytes ( x. addr ( ) ) ) ; 
101137                    Scalar :: from_pointer ( ptr,  this) 
102138                } 
103139                _ =>
104-                     break   ' res  Err ( err_unsup_format ! ( 
140+                     return  Err ( err_unsup_format ! ( 
105141                        "unsupported return type for native call: {:?}" , 
106142                        link_name
107143                    ) ) 
108144                    . into ( ) , 
109145            } ; 
110146            interp_ok ( ImmTy :: from_scalar ( scalar,  dest. layout ) ) 
111-         } ; 
112- 
113-         // SAFETY: We got the guard and stack pointer from start_ffi, and 
114-         // the allocator is the same 
115-         //#[cfg(target_os = "linux")] 
116-         //let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) }; 
117-         //#[cfg(not(target_os = "linux"))] 
118-         let  events = None ; 
119- 
120-         interp_ok ( ( res?,  events) ) 
147+         } ) 
121148    } 
122149
123150    /// Get the pointer to the function of the specified name in the shared object file, 
@@ -214,10 +241,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
214241                if  !this. machine . native_call_mem_warned . replace ( true )  { 
215242                    // Newly set, so first time we get here. 
216243                    this. emit_diagnostic ( NonHaltingDiagnostic :: NativeCallSharedMem  { 
217-                         //#[cfg(target_os = "linux")] 
218-                         //tracing: self::trace::Supervisor::is_enabled(), 
219-                         //#[cfg(not(target_os = "linux"))] 
220-                         tracing :  false , 
244+                         tracing :  self :: trace:: Supervisor :: is_enabled ( ) , 
221245                    } ) ; 
222246                } 
223247
0 commit comments