diff --git a/libafl_targets/Cargo.toml b/libafl_targets/Cargo.toml index 9205f25ca3..5c041686f2 100644 --- a/libafl_targets/Cargo.toml +++ b/libafl_targets/Cargo.toml @@ -9,31 +9,49 @@ readme = "../README.md" license = "MIT OR Apache-2.0" keywords = ["fuzzing", "testing"] edition = "2021" -categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"] - +categories = [ + "development-tools::testing", + "emulators", + "embedded", + "os", + "no-std", +] [package.metadata.docs.rs] all-features = true [features] -default = ["std", "sanitizers_flags"] +default = [ + "std", + "sanitizers_flags", + "windows_asan", + "forkserver", + "cmplog", + "coverage", + "common", +] std = ["libafl/std"] -libfuzzer = ["std", "sanitizer_interfaces"] +libfuzzer = ["std", "common", "sanitizer_interfaces"] libfuzzer_no_link_main = ["libfuzzer"] libfuzzer_define_run_driver = ["libfuzzer"] libfuzzer_interceptors = ["libfuzzer", "sancov_cmplog"] libfuzzer_oom = ["libfuzzer"] sanitizers_flags = [] pointer_maps = [] -sancov_pcguard_edges = [] -sancov_pcguard_hitcounts = [] -sancov_value_profile = [] +sancov_pcguard_edges = ["coverage"] +sancov_pcguard_hitcounts = ["coverage"] +sancov_value_profile = ["common"] sancov_8bit = [] -sancov_cmplog = [] # Defines cmp and __sanitizer_weak_hook functions. Use libfuzzer_interceptors to define interceptors (only compatible with Linux) +sancov_cmplog = ["common"] # Defines cmp and __sanitizer_weak_hook functions. Use libfuzzer_interceptors to define interceptors (only compatible with Linux) sancov_pcguard = ["sancov_pcguard_hitcounts"] sanitizer_interfaces = [] clippy = [] # Ignore compiler warnings during clippy observers = ["meminterval", "ahash"] +common = [] # Compile common C code defining sanitizer options and cross-platform intrinsics +coverage = ["common"] # Compile C code definining coverage maps +cmplog = ["common"] # Compile C code defining cmp log maps +forkserver = ["common"] # Compile C code for forkserver support +windows_asan = ["common"] # Compile C code for ASAN on Windows whole_archive = [] # use +whole-archive to ensure the presence of weak symbols [build-dependencies] @@ -49,6 +67,6 @@ log = "0.4.20" rangemap = "1.3" serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib -meminterval = {version = "0.4", features = ["serde"], optional = true } +meminterval = { version = "0.4", features = ["serde"], optional = true } ahash = { version = "0.8.3", default-features = false, optional = true } # serde-big-array = "0.3.2" diff --git a/libafl_targets/build.rs b/libafl_targets/build.rs index e0cfc44824..86e3cd32b4 100644 --- a/libafl_targets/build.rs +++ b/libafl_targets/build.rs @@ -2,10 +2,6 @@ use std::{env, fs::File, io::Write, path::Path}; -#[cfg(feature = "whole_archive")] -#[rustversion::not(nightly)] -compile_error!("Must use a nightly release with whole_archive!"); - #[allow(clippy::too_many_lines)] fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); @@ -68,6 +64,21 @@ fn main() { println!("cargo:rerun-if-env-changed=LIBAFL_CMPLOG_MAP_H"); println!("cargo:rerun-if-env-changed=LIBAFL_ACCOUNTING_MAP_SIZE"); + #[cfg(feature = "common")] + { + println!("cargo:rerun-if-changed=src/common.h"); + println!("cargo:rerun-if-changed=src/common.c"); + + let mut common = cc::Build::new(); + + #[cfg(feature = "sanitizers_flags")] + { + common.define("DEFAULT_SANITIZERS_OPTIONS", "1"); + } + + common.file(src_dir.join("common.c")).compile("common"); + } + #[cfg(any(feature = "sancov_value_profile", feature = "sancov_cmplog"))] { println!("cargo:rerun-if-changed=src/sancov_cmp.c"); @@ -76,10 +87,6 @@ fn main() { #[cfg(unix)] sancov_cmp.flag("-Wno-sign-compare"); - #[cfg(feature = "whole_archive")] - { - sancov_cmp.link_lib_modifier("+whole-archive"); - } #[cfg(feature = "sancov_value_profile")] { @@ -133,37 +140,91 @@ fn main() { let mut libfuzzer = cc::Build::new(); libfuzzer.file(src_dir.join("libfuzzer.c")); - #[cfg(feature = "whole_archive")] - { - libfuzzer.link_lib_modifier("+whole-archive"); - } - #[cfg(feature = "libfuzzer_no_link_main")] libfuzzer.define("FUZZER_NO_LINK_MAIN", "1"); #[cfg(feature = "libfuzzer_define_run_driver")] libfuzzer.define("FUZZER_DEFINE_RUN_DRIVER", "1"); libfuzzer.compile("libfuzzer"); + } - #[cfg(feature = "libfuzzer_interceptors")] + #[cfg(feature = "coverage")] + { + println!("cargo:rerun-if-changed=src/coverage.c"); + + cc::Build::new() + .file(src_dir.join("coverage.c")) + .define("EDGES_MAP_SIZE", Some(&*format!("{edges_map_size}"))) + .define("ACCOUNTING_MAP_SIZE", Some(&*format!("{acc_map_size}"))) + .compile("coverage"); + } + + #[cfg(feature = "cmplog")] + { + println!("cargo:rerun-if-changed=src/cmplog.h"); + println!("cargo:rerun-if-changed=src/cmplog.c"); + + #[cfg(unix)] { - println!("cargo:rerun-if-changed=src/libfuzzer/FuzzerInterceptors.cpp"); + cc::Build::new() + .flag("-Wno-pointer-sign") // UNIX ONLY FLAGS + .flag("-Wno-sign-compare") + .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) + .define( + "AFLPP_CMPLOG_MAP_W", + Some(&*format!("{aflpp_cmplog_map_w}")), + ) + .define( + "AFLPP_CMPLOG_MAP_H", + Some(&*format!("{aflpp_cmplog_map_h}")), + ) + .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) + .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) + .file(src_dir.join("cmplog.c")) + .compile("cmplog"); + } - let mut interceptors = cc::Build::new(); - interceptors.file(src_dir.join("libfuzzer/FuzzerInterceptors.cpp")); - - #[cfg(feature = "whole_archive")] - { - interceptors.link_lib_modifier("+whole-archive"); - } - - interceptors.cpp(true).compile("interceptors"); + #[cfg(not(unix))] + { + cc::Build::new() + .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) + .define( + "AFLPP_CMPLOG_MAP_W", + Some(&*format!("{aflpp_cmplog_map_w}")), + ) + .define( + "AFLPP_CMPLOG_MAP_H", + Some(&*format!("{aflpp_cmplog_map_h}")), + ) + .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) + .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) + .file(src_dir.join("cmplog.c")) + .compile("cmplog"); } } - println!("cargo:rerun-if-changed=src/common.h"); - println!("cargo:rerun-if-changed=src/common.c"); + #[cfg(feature = "forkserver")] + { + #[cfg(unix)] + { + println!("cargo:rerun-if-changed=src/forkserver.c"); + cc::Build::new() + .file(src_dir.join("forkserver.c")) + .compile("forkserver"); + } + } + + #[cfg(all(feature = "windows_asan", windows))] + { + println!("cargo:rerun-if-changed=src/windows_asan.c"); + + cc::Build::new() + .file(src_dir.join("windows_asan.c")) + .compile("windows_asan"); + } + + // NOTE: Sanitizer interfaces doesn't require common #[cfg(feature = "sanitizer_interfaces")] if env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "64" { println!("cargo:rerun-if-changed=src/sanitizer_interfaces.h"); @@ -185,99 +246,6 @@ fn main() { write!(file, "").unwrap(); } - let mut common = cc::Build::new(); - - #[cfg(feature = "whole_archive")] - { - common.link_lib_modifier("+whole-archive"); - } - - #[cfg(feature = "sanitizers_flags")] - { - common.define("DEFAULT_SANITIZERS_OPTIONS", "1"); - } - - common.file(src_dir.join("common.c")).compile("common"); - - println!("cargo:rerun-if-changed=src/coverage.c"); - - let mut coverage = cc::Build::new(); - - #[cfg(feature = "whole_archive")] - { - coverage.link_lib_modifier("+whole-archive"); - } - - coverage - .file(src_dir.join("coverage.c")) - .define("EDGES_MAP_SIZE", Some(&*format!("{edges_map_size}"))) - .define("ACCOUNTING_MAP_SIZE", Some(&*format!("{acc_map_size}"))) - .compile("coverage"); - - println!("cargo:rerun-if-changed=src/cmplog.h"); - println!("cargo:rerun-if-changed=src/cmplog.c"); - - let mut cmplog = cc::Build::new(); - - #[cfg(feature = "whole_archive")] - { - cmplog.link_lib_modifier("+whole-archive"); - } - - #[cfg(unix)] - { - cmplog - .flag("-Wno-pointer-sign") // UNIX ONLY FLAGS - .flag("-Wno-sign-compare"); - } - - cmplog - .define("CMP_MAP_SIZE", Some(&*format!("{cmp_map_size}"))) - .define( - "AFLPP_CMPLOG_MAP_W", - Some(&*format!("{aflpp_cmplog_map_w}")), - ) - .define( - "AFLPP_CMPLOG_MAP_H", - Some(&*format!("{aflpp_cmplog_map_h}")), - ) - .define("CMPLOG_MAP_W", Some(&*format!("{cmplog_map_w}"))) - .define("CMPLOG_MAP_H", Some(&*format!("{cmplog_map_h}"))) - .file(src_dir.join("cmplog.c")) - .compile("cmplog"); - - #[cfg(unix)] - { - println!("cargo:rerun-if-changed=src/forkserver.c"); - - let mut forkserver = cc::Build::new(); - - #[cfg(feature = "whole_archive")] - { - forkserver.link_lib_modifier("+whole-archive"); - } - - forkserver - .file(src_dir.join("forkserver.c")) - .compile("forkserver"); - } - - #[cfg(windows)] - { - println!("cargo:rerun-if-changed=src/windows_asan.c"); - - let mut winasan = cc::Build::new(); - - #[cfg(feature = "whole_archive")] - { - winasan.link_lib_modifier("+whole-archive"); - } - - winasan - .file(src_dir.join("windows_asan.c")) - .compile("windows_asan"); - } - println!("cargo:rustc-link-search=native={}", &out_dir); println!("cargo:rerun-if-changed=build.rs"); diff --git a/libafl_targets/src/cmps/mod.rs b/libafl_targets/src/cmps/mod.rs index 29ba3d9bc0..5cdf0d7067 100644 --- a/libafl_targets/src/cmps/mod.rs +++ b/libafl_targets/src/cmps/mod.rs @@ -46,6 +46,7 @@ pub const AFL_CMP_TYPE_RTN: u32 = 2; // EXTERNS, GLOBALS +#[cfg(feature = "cmplog")] // void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2) extern "C" { /// Logs an instruction for feedback during fuzzing @@ -58,6 +59,7 @@ extern "C" { pub static mut libafl_cmplog_map_ptr: *mut CmpLogMap; } +#[cfg(feature = "cmplog")] pub use libafl_cmplog_map_ptr as CMPLOG_MAP_PTR; /// Value indicating if cmplog is enabled. diff --git a/libafl_targets/src/cmps/observers/cmplog.rs b/libafl_targets/src/cmps/observers/cmplog.rs index 82b8f686fc..f66cb074f8 100644 --- a/libafl_targets/src/cmps/observers/cmplog.rs +++ b/libafl_targets/src/cmps/observers/cmplog.rs @@ -14,8 +14,9 @@ use libafl::{ }; use libafl_bolts::{ownedref::OwnedMutPtr, Named}; -use crate::cmps::{libafl_cmplog_map_ptr, CmpLogMap, CMPLOG_ENABLED}; - +#[cfg(feature = "cmplog")] +use crate::cmps::libafl_cmplog_map_ptr; +use crate::cmps::{CmpLogMap, CMPLOG_ENABLED}; /// A [`CmpObserver`] observer for `CmpLog` #[derive(Debug)] pub struct CmpLogObserver { @@ -98,6 +99,7 @@ impl CmpLogObserver { } } + #[cfg(feature = "cmplog")] /// Creates a new [`CmpLogObserver`] with the given name from the default cmplog map #[must_use] pub fn new(name: &'static str, add_meta: bool) -> Self { diff --git a/libafl_targets/src/lib.rs b/libafl_targets/src/lib.rs index 2c08f15cbd..3ab0edb53c 100644 --- a/libafl_targets/src/lib.rs +++ b/libafl_targets/src/lib.rs @@ -100,7 +100,9 @@ pub mod sancov_8bit; #[cfg(feature = "sancov_8bit")] pub use sancov_8bit::*; +#[cfg(feature = "coverage")] pub mod coverage; +#[cfg(feature = "coverage")] pub use coverage::*; pub mod value_profile; @@ -113,12 +115,12 @@ pub use cmps::*; #[cfg(feature = "std")] pub mod drcov; -#[cfg(all(windows, feature = "std"))] +#[cfg(all(windows, feature = "std", feture = "windows_asan"))] pub mod windows_asan; -#[cfg(all(windows, feature = "std"))] +#[cfg(all(windows, feature = "std", feture = "windows_asan"))] pub use windows_asan::*; -#[cfg(unix)] +#[cfg(all(unix, feature = "forkserver"))] pub mod forkserver; -#[cfg(unix)] +#[cfg(all(unix, feature = "forkserver"))] pub use forkserver::*;