diff --git a/cargo-klee/src/main.rs b/cargo-klee/src/main.rs index 7a518baa2b48b69b3c6d773d743354c2688a91e1..d0dba132ba3d165c36ab72af85dbc4f7a2ffc24e 100644 --- a/cargo-klee/src/main.rs +++ b/cargo-klee/src/main.rs @@ -2,7 +2,7 @@ extern crate libc; use std::{ env, fs, - path::PathBuf, + path::{Path, PathBuf}, process::{self, Command}, time::SystemTime, }; @@ -90,6 +90,12 @@ fn run() -> Result<i32, failure::Error> { .short("r") .help("Generate replay binary in target directory [default: <NAME>.replay]"), ) + .arg( + Arg::with_name("gdb") + .long("gdb") + .short("g") + .help("Run the generated replay binary in gdb"), + ) .get_matches(); let is_example = matches.is_present("example"); @@ -98,10 +104,11 @@ fn run() -> Result<i32, failure::Error> { let is_release = matches.is_present("release"); let is_replay = matches.is_present("replay"); let is_ktest = matches.is_present("ktest"); + let is_gdb = matches.is_present("gdb"); // let target_flag = matches.value_of("target"); // not supported - let file = if is_binary { + let file = if is_example { matches.value_of("example").unwrap() } else { matches.value_of("bin").unwrap() @@ -220,6 +227,8 @@ fn run() -> Result<i32, failure::Error> { } } + let mut obj = ll.clone().unwrap(); + let replay_name = obj.with_file_name(file).with_extension("replay"); if is_replay { // compile to object code for replay using llc // llc -filetype=obj -relocation-model=pic target/<debug|release>/examples/foo-<hash>.ll @@ -240,10 +249,9 @@ fn run() -> Result<i32, failure::Error> { // compile to executable for replay using clang // clang target/<debug|release>/examples/foo-<hash>.o -lkleeRuntest let mut clang = Command::new("clang"); - let mut obj = ll.clone().unwrap(); + obj = obj.with_extension("o"); - let replay_name = obj.with_file_name(file).with_extension("replay"); println!("file {:?}", replay_name); clang .arg(obj) @@ -275,6 +283,37 @@ fn run() -> Result<i32, failure::Error> { return Ok(status.code().unwrap_or(1)); } } + + // gdb + println!("{:?}", env::var_os("GDB_CWD")); + if is_gdb { + let mut gdb = Command::new("gdb"); + // run gdb in the target/target/<debug|release>/examples/ directory + if let Ok(cwd) = env::var("GDB_CWD") { + // set gdb current dir to GDB_CWD + gdb.current_dir(cwd); + // set replay name to be loaded by gdb + gdb.arg(replay_name); + } else { + // set gdb current dir to the target directory + gdb.current_dir(replay_name.parent().unwrap()); + // set replay name to be loaded by gdb + gdb.arg(replay_name.file_name().unwrap()); + }; + + //gdb.current_dir(cwd); + //gdb.arg(); + + if verbose { + eprintln!("\n{:?}\n", gdb); + } + + // TODO: better error handling, e.g., if gdb is not installed/in path + let status = gdb.status()?; + if !status.success() { + println!("gdb failed: {:?}", status.code().unwrap_or(1)); + } + } // return to shell without error Ok(0) }