@@ -87,47 +87,52 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
8787 }
8888
8989 /// Get the pointer to the function of the specified name in the shared object file,
90- /// if it exists. The function must be in the shared object file specified: we do *not*
91- /// return pointers to functions in dependencies of the library.
90+ /// if it exists. The function must be in one of the shared object files specified:
91+ /// we do *not* return pointers to functions in dependencies of libraries.
9292 fn get_func_ptr_explicitly_from_lib ( & mut self , link_name : Symbol ) -> Option < CodePtr > {
9393 let this = self . eval_context_mut ( ) ;
94- // Try getting the function from the shared library.
95- let ( lib, lib_path) = this. machine . native_lib . as_ref ( ) . unwrap ( ) ;
96- let func: libloading:: Symbol < ' _ , unsafe extern "C" fn ( ) > =
97- unsafe { lib. get ( link_name. as_str ( ) . as_bytes ( ) ) . ok ( ) ? } ;
98- #[ expect( clippy:: as_conversions) ] // fn-ptr to raw-ptr cast needs `as`.
99- let fn_ptr = * func. deref ( ) as * mut std:: ffi:: c_void ;
94+ // Try getting the function from one of the shared libraries.
95+ for ( lib, lib_path) in & this. machine . native_lib {
96+ let Ok ( func) : Result < libloading:: Symbol < ' _ , unsafe extern "C" fn ( ) > , _ > =
97+ ( unsafe { lib. get ( link_name. as_str ( ) . as_bytes ( ) ) } )
98+ else {
99+ continue ;
100+ } ;
101+ #[ expect( clippy:: as_conversions) ] // fn-ptr to raw-ptr cast needs `as`.
102+ let fn_ptr = * func. deref ( ) as * mut std:: ffi:: c_void ;
100103
101- // FIXME: this is a hack!
102- // The `libloading` crate will automatically load system libraries like `libc`.
103- // On linux `libloading` is based on `dlsym`: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#202
104- // and `dlsym`(https://linux.die.net/man/3/dlsym) looks through the dependency tree of the
105- // library if it can't find the symbol in the library itself.
106- // So, in order to check if the function was actually found in the specified
107- // `machine.external_so_lib` we need to check its `dli_fname` and compare it to
108- // the specified SO file path.
109- // This code is a reimplementation of the mechanism for getting `dli_fname` in `libloading`,
110- // from: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#411
111- // using the `libc` crate where this interface is public.
112- let mut info = std:: mem:: MaybeUninit :: < libc:: Dl_info > :: zeroed ( ) ;
113- unsafe {
114- if libc:: dladdr ( fn_ptr, info. as_mut_ptr ( ) ) != 0 {
115- let info = info. assume_init ( ) ;
116- #[ cfg( target_os = "cygwin" ) ]
117- let fname_ptr = info. dli_fname . as_ptr ( ) ;
118- #[ cfg( not( target_os = "cygwin" ) ) ]
119- let fname_ptr = info. dli_fname ;
120- assert ! ( !fname_ptr. is_null( ) ) ;
121- if std:: ffi:: CStr :: from_ptr ( fname_ptr) . to_str ( ) . unwrap ( )
122- != lib_path. to_str ( ) . unwrap ( )
123- {
124- return None ;
104+ // FIXME: this is a hack!
105+ // The `libloading` crate will automatically load system libraries like `libc`.
106+ // On linux `libloading` is based on `dlsym`: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#202
107+ // and `dlsym`(https://linux.die.net/man/3/dlsym) looks through the dependency tree of the
108+ // library if it can't find the symbol in the library itself.
109+ // So, in order to check if the function was actually found in the specified
110+ // `machine.external_so_lib` we need to check its `dli_fname` and compare it to
111+ // the specified SO file path.
112+ // This code is a reimplementation of the mechanism for getting `dli_fname` in `libloading`,
113+ // from: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#411
114+ // using the `libc` crate where this interface is public.
115+ let mut info = std:: mem:: MaybeUninit :: < libc:: Dl_info > :: zeroed ( ) ;
116+ unsafe {
117+ if libc:: dladdr ( fn_ptr, info. as_mut_ptr ( ) ) != 0 {
118+ let info = info. assume_init ( ) ;
119+ #[ cfg( target_os = "cygwin" ) ]
120+ let fname_ptr = info. dli_fname . as_ptr ( ) ;
121+ #[ cfg( not( target_os = "cygwin" ) ) ]
122+ let fname_ptr = info. dli_fname ;
123+ assert ! ( !fname_ptr. is_null( ) ) ;
124+ if std:: ffi:: CStr :: from_ptr ( fname_ptr) . to_str ( ) . unwrap ( )
125+ != lib_path. to_str ( ) . unwrap ( )
126+ {
127+ return None ;
128+ }
125129 }
126130 }
127- }
128131
129- // Return a pointer to the function.
130- Some ( CodePtr ( fn_ptr) )
132+ // Return a pointer to the function.
133+ return Some ( CodePtr ( fn_ptr) ) ;
134+ }
135+ None
131136 }
132137}
133138
0 commit comments