From 19133f5827288a56ec23bed3e3f074aa8a5bdd0b Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Tue, 23 Mar 2021 12:17:28 +0100 Subject: [PATCH] clang wrapper skeleton --- libafl_cc/src/lib.rs | 130 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 3 deletions(-) diff --git a/libafl_cc/src/lib.rs b/libafl_cc/src/lib.rs index 005323f7bb..7c92da60ee 100644 --- a/libafl_cc/src/lib.rs +++ b/libafl_cc/src/lib.rs @@ -1,9 +1,133 @@ -pub mod runtime; +use std::{string::String, vec::Vec}; + +#[derive(Debug)] +pub enum Error { + InvalidArguments(String), + Unknown(String), +} + +/// Wrap a compiler hijacking its arguments +pub trait CompilerWrapper { + /// Set the wrapper arguments parsing a command line set of arguments + fn from_args<'a>(&'a mut self, args: Vec) -> Result<&'a mut Self, Error>; + + /// Add a compiler argument + fn add_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error>; + + /// Run the compiler + fn compile(&mut self) -> Result<(), Error>; +} + +/// Wrap Clang +pub struct ClangWrapper { + optimize: bool, + wrapped_cc: String, + wrapped_cxx: String, + + name: String, + is_cpp: bool, + linking: bool, + x_set: bool, + bit_mode: u32, + + args: Vec, +} + +impl CompilerWrapper for ClangWrapper { + fn from_args<'a>(&'a mut self, args: Vec) -> Result<&'a mut Self, Error> { + let mut new_args = vec![]; + if args.len() < 1 { + return Err(Error::InvalidArguments( + "The number of arguments cannot be 0".into(), + )); + } + + self.name = args[0].clone(); + // Detect C++ compiler looking at the wrapper name + self.is_cpp = self.name.ends_with("++"); + if self.is_cpp { + new_args.push(self.wrapped_cxx.clone()); + } else { + new_args.push(self.wrapped_cc.clone()); + } + + // Sancov flag + // new_args.push("-fsanitize-coverage=trace-pc-guard".into()); + + let mut linking = true; + // Detect stray -v calls from ./configure scripts. + if args.len() == 1 && args[1] == "-v" { + linking = false; + } + + for arg in &args[1..] { + match arg.as_str() { + "-x" => self.x_set = true, + "-m32" => self.bit_mode = 32, + "-m64" => self.bit_mode = 64, + "-c" | "-S" | "-E" => linking = false, + "-shared" => linking = false, // TODO dynamic list? + "-Wl,-z,defs" | "-Wl,--no-undefined" => continue, + _ => (), + }; + new_args.push(arg.clone()); + } + self.linking = linking; + + if self.optimize { + new_args.push("-g".into()); + new_args.push("-O3".into()); + new_args.push("-funroll-loops".into()); + } + + // Fuzzing define common among tools + new_args.push("-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1".into()); + + self.args = new_args; + Ok(self) + } + + fn add_arg<'a>(&'a mut self, arg: String) -> Result<&'a mut Self, Error> { + self.args.push(arg); + Ok(self) + } + + fn compile(&mut self) -> Result<(), Error> { + if self.linking { + if self.x_set { + self.args.push("-x".into()); + self.args.push("none".into()); + } + } + + Ok(()) + } +} + +impl ClangWrapper { + pub fn new(wrapped_cc: &str, wrapped_cxx: &str) -> Self { + Self { + optimize: true, + wrapped_cc: wrapped_cc.into(), + wrapped_cxx: wrapped_cxx.into(), + name: "".into(), + is_cpp: false, + linking: false, + x_set: false, + bit_mode: 0, + args: vec![], + } + } +} #[cfg(test)] mod tests { #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + fn test_clang_version() { + ClangWrapper::new("clang", "clang++") + .from_args(vec!["my-clang", "-v"]) + .unwrap() + .compile() + .unwrap(); } }