1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Compiler Wrapper from `LibAFL`

use std::{convert::Into, path::Path, process::Command, string::String, vec::Vec};

pub mod clang;
pub use clang::{ClangWrapper, LLVMPasses};

/// `LibAFL` CC Error Type
#[derive(Debug)]
pub enum Error {
    /// CC Wrapper called with invalid arguments
    InvalidArguments(String),
    /// Io error occurred
    Io(std::io::Error),
    /// Something else happened
    Unknown(String),
}

// TODO macOS
/// extension for static libraries
#[cfg(windows)]
pub const LIB_EXT: &str = "lib";
/// extension for static libraries
#[cfg(not(windows))]
pub const LIB_EXT: &str = "a";

/// prefix for static libraries
#[cfg(windows)]
pub const LIB_PREFIX: &str = "";
/// prefix for static libraries
#[cfg(not(windows))]
pub const LIB_PREFIX: &str = "lib";

/// Wrap a compiler hijacking its arguments
pub trait CompilerWrapper {
    /// Set the wrapper arguments parsing a command line set of arguments
    fn from_args<S>(&mut self, args: &[S]) -> Result<&'_ mut Self, Error>
    where
        S: AsRef<str>;

    /// Add a compiler argument
    fn add_arg<S>(&mut self, arg: S) -> &'_ mut Self
    where
        S: AsRef<str>;

    /// Add a compiler argument only when compiling
    fn add_cc_arg<S>(&mut self, arg: S) -> &'_ mut Self
    where
        S: AsRef<str>;

    /// Add a compiler argument only when linking
    fn add_link_arg<S>(&mut self, arg: S) -> &'_ mut Self
    where
        S: AsRef<str>;

    /// Add compiler arguments
    fn add_args<S>(&mut self, args: &[S]) -> &'_ mut Self
    where
        S: AsRef<str>,
    {
        for arg in args {
            self.add_arg(arg);
        }
        self
    }

    /// Add compiler arguments only when compiling
    fn add_cc_args<S>(&mut self, args: &[S]) -> &'_ mut Self
    where
        S: AsRef<str>,
    {
        for arg in args {
            self.add_cc_arg(arg);
        }
        self
    }

    /// Add compiler arguments only when linking
    fn add_link_args<S>(&mut self, args: &[S]) -> &'_ mut Self
    where
        S: AsRef<str>,
    {
        for arg in args {
            self.add_link_arg(arg);
        }
        self
    }

    /// Link static C lib
    fn link_staticlib<S>(&mut self, dir: &Path, name: S) -> &'_ mut Self
    where
        S: AsRef<str>;

    /// Command to run the compiler
    fn command(&mut self) -> Result<Vec<String>, Error>;

    /// Get if in linking mode
    fn is_linking(&self) -> bool;

    /// Silences `libafl_cc` output
    fn silence(&mut self, value: bool) -> &'_ mut Self;

    /// Returns `true` if `silence` was called with `true`
    fn is_silent(&self) -> bool;

    /// Run the compiler
    fn run(&mut self) -> Result<Option<i32>, Error> {
        let args = self.command()?;

        if !self.is_silent() {
            dbg!(&args);
        }
        if args.is_empty() {
            return Err(Error::InvalidArguments(
                "The number of arguments cannot be 0".into(),
            ));
        }
        let status = match Command::new(&args[0]).args(&args[1..]).status() {
            Ok(s) => s,
            Err(e) => return Err(Error::Io(e)),
        };
        if !self.is_silent() {
            dbg!(status);
        }
        Ok(status.code())
    }
}