Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make dylib_flag cross-platform #31

Merged
merged 2 commits into from
Sep 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ anyhow = "1.0.65"
clap = { version = "4.0.29", features = ["derive"] }
ctrlc = "3.2.5"
genemichaels = "0.1.21"
libloading = "0.8.0"
owo-colors = "3.5.0"
proc-macro2 = { version = "1.0.48", features = ["span-locations"] }
quote = "1.0.23"
Expand All @@ -33,6 +34,3 @@ tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
tracing-tree = "0.2.2"
walkdir = "2.3.2"

[target."cfg(unix)".dependencies]
libc = "0.2.138"
47 changes: 15 additions & 32 deletions src/dylib_flag.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Handles the --verify-fn flag.
//! It takes in a Rust closure like `|str| true` that takes in a `&str` and returns a bool.

use std::{fmt::Debug, str::FromStr};
use std::{fmt::Debug, mem::ManuallyDrop, str::FromStr};

use anyhow::{Context, Result};
use libloading::Symbol;

#[repr(C)]
pub struct RawOutput {
Expand All @@ -24,7 +25,7 @@ impl FromStr for RustFunction {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::compile(s)
Self::compile(s).context("compiling and loading rust function")
}
}

Expand Down Expand Up @@ -83,17 +84,9 @@ fn wrap_func_body(func: &str) -> Result<String> {
}

impl RustFunction {
#[cfg(not(target_os = "linux"))]
pub fn compile(body: &str) -> Result<Self> {
Err(anyhow::anyhow!("--verify-fn only works on unix"))
}

#[cfg(target_os = "linux")]
pub fn compile(body: &str) -> Result<Self> {
use anyhow::bail;
use std::io;
use std::process::Command;
use std::{ffi::CString, os::unix::prelude::OsStringExt};

let file = tempfile::tempdir()?;

Expand All @@ -114,29 +107,20 @@ impl RustFunction {
bail!("Failed to compile code: {stderr}");
}

let dylib_path = file.path().join("libhelper.so");

let os_str = dylib_path.into_os_string();
let vec = os_str.into_vec();
let cstr = CString::new(vec)?;

let dylib = unsafe { libc::dlopen(cstr.as_ptr(), libc::RTLD_LAZY) };

if dylib.is_null() {
bail!("failed to open dylib: {}", io::Error::last_os_error());
}

let symbol = b"cargo_minimize_ffi_function\0";

let func = unsafe { libc::dlsym(dylib, symbol.as_ptr().cast()) };

if func.is_null() {
bail!("didn't find entrypoint symbol");
}
// SAFETY: We are loading a simple rust cdylib, which does not do weird things. But we cannot unload Rust dylibs, so we use MD below.
let dylib = unsafe {
libloading::Library::new(file.path().join(libloading::library_filename("helper")))
.context("loading helper shared library")?
};
let dylib = ManuallyDrop::new(dylib);

let func = unsafe { std::mem::transmute::<*mut _, CheckerCFn>(func) };
let func: Symbol<CheckerCFn> = unsafe {
dylib
.get(b"cargo_minimize_ffi_function\0")
.context("failed to find entrypoint symbol")?
};

Ok(Self { func })
Ok(Self { func: *func })
}

pub fn call(&self, output: &str, code: Option<i32>) -> bool {
Expand Down Expand Up @@ -169,7 +153,6 @@ mod tests {
use super::RustFunction;

#[test]
#[cfg_attr(not(target_os = "linux"), ignore)]
fn basic_contains_work() {
let code = r#"|output| output.out.contains("test")"#;

Expand Down
3 changes: 2 additions & 1 deletion src/processor/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ impl PassController {
fn next_in_worklist(&mut self) {
let PassControllerState::Bisecting {
current, worklist, ..
} = &mut self.state else {
} = &mut self.state
else {
unreachable!("next_in_worklist called on non-bisecting state");
};
match worklist.pop() {
Expand Down
11 changes: 5 additions & 6 deletions src/processor/reaper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,11 @@ impl Minimizer {
suggestions: &HashMap<&Path, Vec<&Suggestion>>,
) -> Result<()> {
for (sugg_file, suggestions) in suggestions {
let Some(file) = self
.files
.iter()
.find(|source| source.path.ends_with(sugg_file) || sugg_file.ends_with(&source.path)) else {
continue;
};
let Some(file) = self.files.iter().find(|source| {
source.path.ends_with(sugg_file) || sugg_file.ends_with(&source.path)
}) else {
continue;
};

let changes = &mut Changes::default();

Expand Down