libafl_libfuzzer: macOS build support (#1711)
* libafl_libfuzzer: macOS support * make clippy happy --------- Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
parent
a4f753b0f0
commit
13dd1cc4ec
@ -1,7 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufRead, BufReader, BufWriter, Write},
|
io::{BufRead, BufReader, BufWriter, Write},
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,9 +17,9 @@ fn main() {
|
|||||||
return; // skip when clippy or docs is running
|
return; // skip when clippy or docs is running
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(not(any(target_os = "linux", target_os = "macos"))) {
|
||||||
println!(
|
println!(
|
||||||
"cargo:warning=The libafl_libfuzzer runtime may only be built for linux; failing fast."
|
"cargo:warning=The libafl_libfuzzer runtime may only be built for linux or macos; failing fast."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -29,12 +29,12 @@ fn main() {
|
|||||||
println!("cargo:rerun-if-changed=libafl_libfuzzer_runtime/build.rs");
|
println!("cargo:rerun-if-changed=libafl_libfuzzer_runtime/build.rs");
|
||||||
|
|
||||||
let custom_lib_dir =
|
let custom_lib_dir =
|
||||||
PathBuf::from(std::env::var_os("OUT_DIR").unwrap()).join("libafl_libfuzzer");
|
AsRef::<Path>::as_ref(&std::env::var_os("OUT_DIR").unwrap()).join("libafl_libfuzzer");
|
||||||
std::fs::create_dir_all(&custom_lib_dir)
|
std::fs::create_dir_all(&custom_lib_dir)
|
||||||
.expect("Couldn't create the output directory for the fuzzer runtime build");
|
.expect("Couldn't create the output directory for the fuzzer runtime build");
|
||||||
|
|
||||||
let mut lib_src = PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
let lib_src: PathBuf = AsRef::<Path>::as_ref(&std::env::var_os("CARGO_MANIFEST_DIR").unwrap())
|
||||||
lib_src.push("libafl_libfuzzer_runtime");
|
.join("libafl_libfuzzer_runtime");
|
||||||
|
|
||||||
let mut command = Command::new(std::env::var_os("CARGO").unwrap());
|
let mut command = Command::new(std::env::var_os("CARGO").unwrap());
|
||||||
command
|
command
|
||||||
@ -77,17 +77,15 @@ fn main() {
|
|||||||
.arg(std::env::var_os("TARGET").unwrap());
|
.arg(std::env::var_os("TARGET").unwrap());
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!command.status().map(|s| !s.success()).unwrap_or(true),
|
command.status().map_or(false, |s| s.success()),
|
||||||
"Couldn't build runtime crate! Did you remember to use nightly? (`rustup default nightly` to install) Or, did you remember to install ucd-generate? (`cargo install ucd-generate` to install)"
|
"Couldn't build runtime crate! Did you remember to use nightly? (`rustup default nightly` to install) Or, did you remember to install ucd-generate? (`cargo install ucd-generate` to install)"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut lib_path = custom_lib_dir.join(std::env::var_os("TARGET").unwrap());
|
let mut archive_path = custom_lib_dir.join(std::env::var_os("TARGET").unwrap());
|
||||||
lib_path.push("release");
|
archive_path.push("release");
|
||||||
|
|
||||||
if cfg!(target_family = "unix") {
|
if cfg!(unix) {
|
||||||
use std::path::Path;
|
archive_path.push("libafl_libfuzzer_runtime.a");
|
||||||
|
|
||||||
lib_path.push("libafl_libfuzzer_runtime.a");
|
|
||||||
let target_libdir = Command::new("rustc")
|
let target_libdir = Command::new("rustc")
|
||||||
.args(["--print", "target-libdir"])
|
.args(["--print", "target-libdir"])
|
||||||
.output()
|
.output()
|
||||||
@ -95,50 +93,52 @@ fn main() {
|
|||||||
let target_libdir = String::from_utf8(target_libdir.stdout).unwrap();
|
let target_libdir = String::from_utf8(target_libdir.stdout).unwrap();
|
||||||
let target_libdir = Path::new(target_libdir.trim());
|
let target_libdir = Path::new(target_libdir.trim());
|
||||||
|
|
||||||
let rust_lld = target_libdir.join("../bin/rust-lld");
|
|
||||||
let rust_ar = target_libdir.join("../bin/llvm-ar"); // NOTE: depends on llvm-tools
|
|
||||||
let rust_objcopy = target_libdir.join("../bin/llvm-objcopy"); // NOTE: depends on llvm-tools
|
let rust_objcopy = target_libdir.join("../bin/llvm-objcopy"); // NOTE: depends on llvm-tools
|
||||||
let nm = "nm"; // NOTE: we use system nm here because llvm-nm doesn't respect the encoding?
|
let nm = if cfg!(target_os = "macos") {
|
||||||
|
// NOTE: depends on llvm-tools
|
||||||
|
target_libdir.join("../bin/llvm-nm")
|
||||||
|
} else {
|
||||||
|
// NOTE: we use system nm on linux because llvm-nm doesn't respect the encoding?
|
||||||
|
PathBuf::from("nm")
|
||||||
|
};
|
||||||
|
|
||||||
|
let redefined_archive_path = custom_lib_dir.join("libFuzzer.a");
|
||||||
let redefined_symbols = custom_lib_dir.join("redefs.txt");
|
let redefined_symbols = custom_lib_dir.join("redefs.txt");
|
||||||
|
|
||||||
let objfile_orig = custom_lib_dir.join("libFuzzer.o");
|
let mut nm_child = Command::new(nm)
|
||||||
let objfile_dest = custom_lib_dir.join("libFuzzer-mimalloc.o");
|
.arg(&archive_path)
|
||||||
|
|
||||||
let mut command = Command::new(rust_lld);
|
|
||||||
command
|
|
||||||
.args(["-flavor", "gnu"])
|
|
||||||
.arg("-r")
|
|
||||||
.arg("--whole-archive")
|
|
||||||
.arg(lib_path)
|
|
||||||
.args(["-o", objfile_orig.to_str().expect("Invalid path characters present in your current directory prevent us from linking to the runtime")]);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
!command.status().map(|s| !s.success()).unwrap_or(true),
|
|
||||||
"Couldn't link runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)"
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut child = Command::new(nm)
|
|
||||||
.arg(&objfile_orig)
|
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut redefinitions_file = BufWriter::new(File::create(&redefined_symbols).unwrap());
|
let mut redefinitions_file = BufWriter::new(File::create(&redefined_symbols).unwrap());
|
||||||
|
|
||||||
let replacement = format!("_ZN{NAMESPACE_LEN}{NAMESPACE}");
|
let zn_prefix = if cfg!(target_os = "macos") {
|
||||||
|
// macOS symbols have an extra `_`
|
||||||
|
"__ZN"
|
||||||
|
} else {
|
||||||
|
"_ZN"
|
||||||
|
};
|
||||||
|
|
||||||
|
let replacement = format!("{zn_prefix}{NAMESPACE_LEN}{NAMESPACE}");
|
||||||
|
|
||||||
// redefine all the rust-mangled symbols we can
|
// redefine all the rust-mangled symbols we can
|
||||||
// TODO this will break when v0 mangling is stabilised
|
// TODO this will break when v0 mangling is stabilised
|
||||||
for line in BufReader::new(child.stdout.take().unwrap()).lines() {
|
for line in BufReader::new(nm_child.stdout.take().unwrap()).lines() {
|
||||||
let line = line.unwrap();
|
let line = line.unwrap();
|
||||||
|
|
||||||
|
// Skip headers
|
||||||
|
if line.ends_with(':') || line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let (_, symbol) = line.rsplit_once(' ').unwrap();
|
let (_, symbol) = line.rsplit_once(' ').unwrap();
|
||||||
if symbol.starts_with("_ZN") {
|
|
||||||
|
if symbol.starts_with(zn_prefix) {
|
||||||
writeln!(
|
writeln!(
|
||||||
redefinitions_file,
|
redefinitions_file,
|
||||||
"{} {}",
|
"{} {}",
|
||||||
symbol,
|
symbol,
|
||||||
symbol.replacen("_ZN", &replacement, 1)
|
symbol.replacen(zn_prefix, &replacement, 1)
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -147,11 +147,11 @@ fn main() {
|
|||||||
drop(redefinitions_file);
|
drop(redefinitions_file);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!child.wait().map(|s| !s.success()).unwrap_or(true),
|
nm_child.wait().map_or(false, |s| s.success()),
|
||||||
"Couldn't link runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)"
|
"Couldn't link runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut command = Command::new(rust_objcopy);
|
let mut objcopy_command = Command::new(rust_objcopy);
|
||||||
|
|
||||||
for symbol in [
|
for symbol in [
|
||||||
"__rust_drop_panic",
|
"__rust_drop_panic",
|
||||||
@ -173,39 +173,34 @@ fn main() {
|
|||||||
"__rust_no_alloc_shim_is_unstable",
|
"__rust_no_alloc_shim_is_unstable",
|
||||||
"__rust_alloc_error_handler_should_panic",
|
"__rust_alloc_error_handler_should_panic",
|
||||||
] {
|
] {
|
||||||
command
|
let mut symbol = symbol.to_string();
|
||||||
|
// macOS symbols have an extra `_`
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
symbol.insert(0, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
objcopy_command
|
||||||
.arg("--redefine-sym")
|
.arg("--redefine-sym")
|
||||||
.arg(format!("{symbol}={symbol}_libafl_libfuzzer_runtime"));
|
.arg(format!("{symbol}={symbol}_libafl_libfuzzer_runtime"));
|
||||||
}
|
}
|
||||||
|
|
||||||
command
|
objcopy_command
|
||||||
.arg("--redefine-syms")
|
.arg("--redefine-syms")
|
||||||
.arg(redefined_symbols)
|
.arg(redefined_symbols)
|
||||||
.args([&objfile_orig, &objfile_dest]);
|
.args([&archive_path, &redefined_archive_path]);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!command.status().map(|s| !s.success()).unwrap_or(true),
|
objcopy_command.status().map_or(false, |s| s.success()),
|
||||||
"Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)"
|
"Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed? (`rustup component add llvm-tools-preview` to install)"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut command = Command::new(rust_ar);
|
|
||||||
command
|
|
||||||
.arg("cr")
|
|
||||||
.arg(custom_lib_dir.join("libFuzzer.a"))
|
|
||||||
.arg(objfile_dest);
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
!command.status().map(|s| !s.success()).unwrap_or(true),
|
|
||||||
"Couldn't create runtime archive!"
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "embed-runtime")]
|
#[cfg(feature = "embed-runtime")]
|
||||||
{
|
{
|
||||||
// NOTE: lib, .a are added always on unix-like systems as described in:
|
// NOTE: lib, .a are added always on unix-like systems as described in:
|
||||||
// https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b
|
// https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b
|
||||||
println!(
|
println!(
|
||||||
"cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}",
|
"cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}",
|
||||||
custom_lib_dir.join("libFuzzer.a").display()
|
redefined_archive_path.display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,13 +209,11 @@ fn main() {
|
|||||||
custom_lib_dir.to_str().unwrap()
|
custom_lib_dir.to_str().unwrap()
|
||||||
);
|
);
|
||||||
println!("cargo:rustc-link-lib=static=Fuzzer");
|
println!("cargo:rustc-link-lib=static=Fuzzer");
|
||||||
} else {
|
|
||||||
println!(
|
|
||||||
"cargo:rustc-link-search=native={}",
|
|
||||||
lib_path.to_str().unwrap()
|
|
||||||
);
|
|
||||||
println!("cargo:rustc-link-lib=static=afl_fuzzer_runtime");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
println!("cargo:rustc-link-lib=c++");
|
||||||
|
} else {
|
||||||
println!("cargo:rustc-link-lib=stdc++");
|
println!("cargo:rustc-link-lib=stdc++");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user