Skip to content

Commit 0b58790

Browse files
author
Ellen Arteca
committed
update README; moving libloading load and hack into its own function
1 parent 7f85148 commit 0b58790

File tree

2 files changed

+43
-25
lines changed

2 files changed

+43
-25
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,11 @@ environment variable. We first document the most relevant and most commonly used
287287
`-Zmiri-disable-isolation` is also set.
288288
* `-Zmiri-extern-so-file=<path to a shared object file>` is an experimental flag for providing support
289289
for FFI calls.
290-
**WARNING**: If an invalid/incorrect SO file is specified, this can cause undefined behaviour in Miri itself!
291-
This is [work in progress](https://github.com/rust-lang/miri/pull/2363);
292-
current support is for functions with integer arguments/returns.
290+
**WARNING**: If an invalid/incorrect `.so` file is specified, this can cause undefined behaviour in Miri itself!
291+
And of course, Miri cannot do any checks on the actions taken by the external code.
292+
This is **work in progress**; currently, only integer arguments and return values are
293+
supported (and no, pointer/integer casts to work around this limitation will not work;
294+
they will fail horribly).
293295
Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365).
294296
* `-Zmiri-env-forward=<var>` forwards the `var` environment variable to the interpreted program. Can
295297
be used multiple times to forward several variables. This takes precedence over

src/shims/ffi_support.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -150,36 +150,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
150150
}
151151
}
152152

153-
/// Call specified external C function, with supplied arguments.
154-
/// Need to convert all the arguments from their hir representations to
155-
/// a form compatible with C (through `libffi` call).
156-
/// Then, convert return from the C call into a corresponding form that
157-
/// can be stored in Miri internal memory.
158-
fn call_and_add_external_c_fct_to_context(
159-
&mut self,
160-
link_name: Symbol,
161-
dest: &PlaceTy<'tcx, Tag>,
162-
args: &[OpTy<'tcx, Tag>],
163-
) -> InterpResult<'tcx, bool> {
153+
/// Get the pointer to the function of the specified name in the shared object file,
154+
/// if it exists. The function must be in the shared object file specified: we do *not*
155+
/// return pointers to functions in dependencies of the library.
156+
fn get_func_ptr_explicitly_from_lib(&mut self, link_name: Symbol) -> Option<CodePtr> {
164157
let this = self.eval_context_mut();
158+
// Try getting the function from the shared library.
165159
let (lib, lib_path) = this.machine.external_so_lib.as_ref().unwrap();
166-
167-
// Load the C function from the library.
168-
// Because this is getting the C function from the shared object file
169-
// it is not necessarily a sound operation, but there is no way around
170-
// this and we've checked as much as we can.
171160
let func: libloading::Symbol<'_, unsafe extern "C" fn()> = unsafe {
172161
match lib.get(link_name.as_str().as_bytes()) {
173162
Ok(x) => x,
174163
Err(_) => {
175-
// Shared object file does not export this function -- try the shims next.
176-
return Ok(false);
164+
return None;
177165
}
178166
}
179167
};
180168

181169
// FIXME: this is a hack!
182170
// The `libloading` crate will automatically load system libraries like `libc`.
171+
// On linux `libloading` is based on `dlsym`: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#202
172+
// and `dlsym`(https://linux.die.net/man/3/dlsym) looks through the dependency tree of the
173+
// library if it can't find the symbol in the library itself.
183174
// So, in order to check if the function was actually found in the specified
184175
// `machine.external_so_lib` we need to check its `dli_fname` and compare it to
185176
// the specified SO file path.
@@ -192,10 +183,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
192183
if std::ffi::CStr::from_ptr(info.assume_init().dli_fname).to_str().unwrap()
193184
!= lib_path.to_str().unwrap()
194185
{
195-
return Ok(false);
186+
return None;
196187
}
197188
}
198189
}
190+
// Return a pointer to the function.
191+
Some(CodePtr(*func.deref() as *mut _))
192+
}
193+
194+
/// Call specified external C function, with supplied arguments.
195+
/// Need to convert all the arguments from their hir representations to
196+
/// a form compatible with C (through `libffi` call).
197+
/// Then, convert return from the C call into a corresponding form that
198+
/// can be stored in Miri internal memory.
199+
fn call_and_add_external_c_fct_to_context(
200+
&mut self,
201+
link_name: Symbol,
202+
dest: &PlaceTy<'tcx, Tag>,
203+
args: &[OpTy<'tcx, Tag>],
204+
) -> InterpResult<'tcx, bool> {
205+
// Get the pointer to the function in the shared object file if it exists.
206+
let code_ptr = match self.get_func_ptr_explicitly_from_lib(link_name) {
207+
Some(ptr) => ptr,
208+
None => {
209+
// Shared object file does not export this function -- try the shims next.
210+
return Ok(false);
211+
}
212+
};
213+
214+
let this = self.eval_context_mut();
199215

200216
// Get the function arguments, and convert them to `libffi`-compatible form.
201217
let mut libffi_args = Vec::<CArg>::with_capacity(args.len());
@@ -214,9 +230,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
214230
.collect::<Vec<libffi::high::Arg<'_>>>();
215231

216232
// Code pointer to C function.
217-
let ptr = CodePtr(*func.deref() as *mut _);
218-
// Call the functio and store output, depending on return type in the function signature.
219-
self.call_external_c_and_store_return(link_name, dest, ptr, libffi_args)?;
233+
// let ptr = CodePtr(*func.deref() as *mut _);
234+
// Call the function and store output, depending on return type in the function signature.
235+
self.call_external_c_and_store_return(link_name, dest, code_ptr, libffi_args)?;
220236
Ok(true)
221237
}
222238
}

0 commit comments

Comments
 (0)