From 5a4e5b0a9315131ff1014effcf59d1eb0794969d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 30 Jun 2021 21:20:24 +0200 Subject: [PATCH] MacOS Build (#197) * macos build * more fix * fixed clang pass build * fixes for libfuzzer link * more explanation links --- libafl_cc/build.rs | 22 ++++++++++++++++++-- libafl_cc/src/clang.rs | 14 ++++++++++++- libafl_targets/src/common.h | 17 +++++++++++---- libafl_targets/src/libfuzzer_compatibility.c | 12 +++++------ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/libafl_cc/build.rs b/libafl_cc/build.rs index 311865885b..d26c080bfb 100644 --- a/libafl_cc/build.rs +++ b/libafl_cc/build.rs @@ -1,5 +1,13 @@ use std::{env, fs::File, io::Write, path::Path, process::Command, str}; +fn dll_extension<'a>() -> &'a str { + match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { + "windwos" => "dll", + "macos" | "ios" => "dylib", + _ => "so", + } +} + fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); @@ -43,14 +51,24 @@ pub const CLANGXX_PATH: &str = {:?}; let ldflags = str::from_utf8(&output.stdout).expect("Invalid llvm-config output"); let cxxflags: Vec<&str> = cxxflags.trim().split_whitespace().collect(); - let ldflags: Vec<&str> = ldflags.trim().split_whitespace().collect(); + let mut ldflags: Vec<&str> = ldflags.trim().split_whitespace().collect(); + + match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { + // Needed on macos. + // Explanation at https://github.com/banach-space/llvm-tutor/blob/787b09ed31ff7f0e7bdd42ae20547d27e2991512/lib/CMakeLists.txt#L59 + "macos" | "ios" => { + ldflags.push("-undefined"); + ldflags.push("dynamic_lookup"); + } + _ => (), + }; let _ = Command::new(llvm_bindir.join("clang++")) .args(&cxxflags) .arg(src_dir.join("cmplog-routines-pass.cc")) .args(&ldflags) .args(&["-fPIC", "-shared", "-o"]) - .arg(out_dir.join("cmplog-routines-pass.so")) + .arg(out_dir.join(format!("cmplog-routines-pass.{}", dll_extension()))) .status() .expect("Failed to compile cmplog-routines-pass.cc"); } else { diff --git a/libafl_cc/src/clang.rs b/libafl_cc/src/clang.rs index ab69698c16..eb65e73b7d 100644 --- a/libafl_cc/src/clang.rs +++ b/libafl_cc/src/clang.rs @@ -2,6 +2,7 @@ use std::{ convert::Into, + env, path::{Path, PathBuf}, string::String, vec::Vec, @@ -9,6 +10,16 @@ use std::{ use crate::{CompilerWrapper, Error, LIB_EXT, LIB_PREFIX}; +fn dll_extension<'a>() -> &'a str { + if cfg!(target_os = "windows") { + "dll" + } else if cfg!(any(target_os = "ios", target_os = "macos")) { + "dylib" + } else { + "so" + } +} + include!(concat!(env!("OUT_DIR"), "/clang_constants.rs")); #[allow(clippy::upper_case_acronyms)] @@ -21,7 +32,8 @@ impl LLVMPasses { #[must_use] pub fn path(&self) -> PathBuf { match self { - LLVMPasses::CmpLogRtn => PathBuf::from(env!("OUT_DIR")).join("cmplog-routines-pass.so"), + LLVMPasses::CmpLogRtn => PathBuf::from(env!("OUT_DIR")) + .join(format!("cmplog-routines-pass.{}", dll_extension())), } } } diff --git a/libafl_targets/src/common.h b/libafl_targets/src/common.h index 90d56e930e..2fefa05ee9 100644 --- a/libafl_targets/src/common.h +++ b/libafl_targets/src/common.h @@ -75,6 +75,8 @@ #define EXT_FUNC_DEF(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) +#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ RETURN_TYPE (*NAME##Def) FUNC_SIG = NULL; \ @@ -83,14 +85,21 @@ #if defined(__APPLE__) // TODO: Find a proper way to deal with weak fns on Apple! + // On Apple, weak_import and weak attrs behave differently to linux. #define EXT_FUNC_DEF(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) { return 0; } + EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) { return (RETURN_TYPE) 0; } + + #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG { \ + return (RETURN_TYPE) 0; \ + } + + #define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG - #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - RETURN_TYPE NAME FUNC_SIG __attribute__((weak_import)) #else -#define EXT_FUNC_DEF(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ +#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) // Declare these symbols as weak to allow them to be optionally defined. diff --git a/libafl_targets/src/libfuzzer_compatibility.c b/libafl_targets/src/libfuzzer_compatibility.c index 7cf68d2955..d7e80a03fe 100644 --- a/libafl_targets/src/libfuzzer_compatibility.c +++ b/libafl_targets/src/libfuzzer_compatibility.c @@ -3,19 +3,19 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -EXT_FUNC_DEF(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); -EXT_FUNC_DEF(LLVMFuzzerCustomMutator, size_t, +EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); +EXT_FUNC(LLVMFuzzerCustomMutator, size_t, (uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed), false); -EXT_FUNC_DEF(LLVMFuzzerCustomCrossOver, size_t, +EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, (const uint8_t *Data1, size_t Size1, const uint8_t *Data2, size_t Size2, uint8_t *Out, size_t MaxOutSize, unsigned int Seed), false); -EXT_FUNC_DEF(LLVMFuzzerTestOneInput, int, (uint8_t *Data, size_t Size), false); +EXT_FUNC(LLVMFuzzerTestOneInput, int, (uint8_t *Data, size_t Size), false); -void libafl_main(); -EXT_FUNC(main, int, (int argc, char** argv), false) { +void libafl_main(void); +EXT_FUNC_IMPL(main, int, (int argc, char** argv), false) { libafl_main(); return 0; }