Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cargo-auditable/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ auditable-serde = {version = "0.8.0", path = "../auditable-serde"}
miniz_oxide = {version = "0.8.0"}
serde_json = "1.0.57"
cargo_metadata = "0.18"
pico-args = "0.5"
pico-args = { version = "0.5", features = ["eq-separator"] }
serde = "1.0.147"
wasm-gen = "0.1.4"

Expand Down
104 changes: 92 additions & 12 deletions cargo-auditable/src/rustc_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ use std::{ffi::OsString, path::PathBuf};
// https://github.com/rust-lang/rust/blob/26ecd44160f54395b3bd5558cc5352f49cb0a0ba/compiler/rustc_session/src/config.rs

/// Includes only the rustc arguments we care about
#[derive(Debug)]
pub struct RustcArgs {
pub crate_name: String,
pub crate_types: Vec<String>,
pub cfg: Vec<String>,
pub emit: Vec<String>,
pub out_dir: PathBuf,
pub target: Option<String>,
pub print: Vec<String>,
Expand All @@ -35,18 +37,96 @@ impl RustcArgs {
}
}

impl RustcArgs {
// Split into its own function for unit testing
fn from_vec(raw_args: Vec<OsString>) -> Result<RustcArgs, pico_args::Error> {
let mut parser = pico_args::Arguments::from_vec(raw_args);

// --emit requires slightly more complex parsing
let raw_emit_args: Vec<String> = parser.values_from_str("--emit")?;
let mut emit: Vec<String> = Vec::new();
for raw_arg in raw_emit_args {
for item in raw_arg.split(',') {
emit.push(item.to_owned());
}
}

Ok(RustcArgs {
crate_name: parser.value_from_str("--crate-name")?,
crate_types: parser.values_from_str("--crate-type")?,
cfg: parser.values_from_str("--cfg")?,
emit,
out_dir: parser
.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
Ok(PathBuf::from(s))
})?,
target: parser.opt_value_from_str("--target")?,
print: parser.values_from_str("--print")?,
})
}
}

pub fn parse_args() -> Result<RustcArgs, pico_args::Error> {
let raw_args: Vec<OsString> = std::env::args_os().skip(2).collect();
let mut parser = pico_args::Arguments::from_vec(raw_args);

Ok(RustcArgs {
crate_name: parser.value_from_str("--crate-name")?,
crate_types: parser.values_from_str("--crate-type")?,
cfg: parser.values_from_str("--cfg")?,
out_dir: parser.value_from_os_str::<&str, PathBuf, pico_args::Error>("--out-dir", |s| {
Ok(PathBuf::from(s))
})?,
target: parser.opt_value_from_str("--target")?,
print: parser.values_from_str("--print")?,
})
RustcArgs::from_vec(raw_args)
}

pub fn should_embed_audit_data(args: &RustcArgs) -> bool {
// Only inject audit data into crate types 'bin' and 'cdylib',
// it doesn't make sense for static libs and weird other types.
if !(args.crate_types.contains(&"bin".to_owned())
|| args.crate_types.contains(&"cdylib".to_owned()))
{
return false;
}

// when --emit is specified explicitly, only inject audit data for --emit=link
// because it doesn't make sense for all other types such as llvm-ir, asm, etc.
if !args.emit.is_empty() && !args.emit.contains(&"link".to_owned()) {
return false;
}

// --print disables compilation UNLESS --emit is also specified
if !args.print.is_empty() && args.emit.is_empty() {
return false;
}

true
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn cargo_c_compatibility() {
let raw_rustc_args = vec!["--crate-name", "rustls", "--edition=2021", "src/lib.rs", "--error-format=json", "--json=diagnostic-rendered-ansi,artifacts,future-incompat", "--crate-type", "staticlib", "--crate-type", "cdylib", "--emit=dep-info,link", "-C", "embed-bitcode=no", "-C", "debuginfo=2", "-C", "link-arg=-Wl,-soname,librustls.so.0.14.0", "-Cmetadata=rustls-ffi", "--cfg", "cargo_c", "--print", "native-static-libs", "--cfg", "feature=\"aws-lc-rs\"", "--cfg", "feature=\"capi\"", "--cfg", "feature=\"default\"", "--check-cfg", "cfg(docsrs)", "--check-cfg", "cfg(feature, values(\"aws-lc-rs\", \"capi\", \"cert_compression\", \"default\", \"no_log_capture\", \"read_buf\", \"ring\"))", "-C", "metadata=b6a43041f637feb8", "--out-dir", "/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps", "--target", "x86_64-unknown-linux-gnu", "-C", "linker=clang", "-C", "incremental=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/incremental", "-L", "dependency=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps", "-L", "dependency=/home/user/Code/rustls-ffi/target/debug/deps", "--extern", "libc=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/liblibc-4fc7c9f82dda33ee.rlib", "--extern", "log=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/liblog-6f7c8f4d1d5ec422.rlib", "--extern", "rustls=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls-a93cda0ba0380929.rlib", "--extern", "pki_types=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls_pki_types-27749859644f0979.rlib", "--extern", "rustls_platform_verifier=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/librustls_platform_verifier-bceca5cf09f3d7ba.rlib", "--extern", "webpki=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/deps/libwebpki-bc4a16dd84e0b062.rlib", "-C", "link-arg=-fuse-ld=/home/user/mold-2.32.0-x86_64-linux/bin/mold", "-L", "native=/home/user/Code/rustls-ffi/target/x86_64-unknown-linux-gnu/debug/build/aws-lc-sys-d52f8990d9ede41d/out"];
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
let args = RustcArgs::from_vec(raw_rustc_args).unwrap();
assert!(should_embed_audit_data(&args));
}

#[test]
fn multiple_emit_values() {
let raw_rustc_args = vec![
"--emit=dep-info,link",
"--emit",
"llvm-bc",
// end of interesting args, start of boilerplate
"--crate-name",
"foobar",
"--out-dir",
"/foo/bar",
];
let raw_rustc_args: Vec<OsString> = raw_rustc_args.into_iter().map(|s| s.into()).collect();
let mut args = RustcArgs::from_vec(raw_rustc_args).unwrap();

let expected = vec!["dep-info", "link", "llvm-bc"];
let mut expected: Vec<String> = expected.into_iter().map(|s| s.into()).collect();

args.emit.sort();
expected.sort();

assert_eq!(args.emit, expected)
}
}
10 changes: 3 additions & 7 deletions cargo-auditable/src/rustc_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use std::{
use crate::{
binary_file, collect_audit_data,
platform_detection::{is_apple, is_msvc, is_wasm},
rustc_arguments, target_info,
rustc_arguments::{self, should_embed_audit_data},
target_info,
};

use std::io::BufRead;
Expand All @@ -20,12 +21,7 @@ pub fn main(rustc_path: &OsStr) {
if env::var_os("CARGO_PRIMARY_PACKAGE").is_some() {
let arg_parsing_result = rustc_arguments::parse_args();
if let Ok(args) = rustc_arguments::parse_args() {
// Only inject audit data into crate types 'bin' and 'cdylib',
// and only if --print is not specified (which disables compilation)
if args.print.is_empty()
&& (args.crate_types.contains(&"bin".to_owned())
|| args.crate_types.contains(&"cdylib".to_owned()))
{
if should_embed_audit_data(&args) {
// Get the audit data to embed
let target_triple = args
.target
Expand Down