From 041a348ce4a6101c46d5f185105c8ed3f2fb06dd Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Sun, 2 Oct 2022 23:42:39 +0200
Subject: [PATCH] move to clap 4, wip4, replay almost working

---
 cargo-klee/src/cli.rs  |  2 +-
 cargo-klee/src/main.rs | 75 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/cargo-klee/src/cli.rs b/cargo-klee/src/cli.rs
index e461c6c..b69eced 100644
--- a/cargo-klee/src/cli.rs
+++ b/cargo-klee/src/cli.rs
@@ -45,7 +45,7 @@ pub struct Cli {
 
     /// GDB Replay
     #[arg(long, short)]
-    pub replay: bool,
+    pub gdb: bool,
     // #[command(subcommand)]
     // binary: Option<Commands>,
 }
diff --git a/cargo-klee/src/main.rs b/cargo-klee/src/main.rs
index db6535f..8964e55 100644
--- a/cargo-klee/src/main.rs
+++ b/cargo-klee/src/main.rs
@@ -156,7 +156,7 @@ fn main() -> Result<(), Error> {
             // enable coloring of output
             .arg("--color")
             // ll file to analyse
-            .arg(ll);
+            .arg(ll.clone());
 
         println!("klee {:?}", klee);
 
@@ -174,11 +174,78 @@ fn main() -> Result<(), Error> {
         if !output.success() {
             return Err(anyhow!("`klee` failed, exiting `cargo-klee`"));
         }
+    }
 
-        let output = klee.stdout(Stdio::piped()).output()?;
-        let stderr = String::from_utf8(output.stderr)?;
+    // replay execution in `gdb`
+    if args.gdb {
+        // compile to object code for replay using `llc`
+        let mut llc = Command::new("llc");
+        llc.arg("-filetype=obj")
+            .arg("-relocation-model=pic")
+            .arg(ll.clone());
 
-        eprintln!("{}", stderr);
+        if args.verbose {
+            eprintln!("\n{:?}\n", llc);
+        }
+
+        let output = llc
+            .stdout(Stdio::piped())
+            .status()
+            .expect("failed to invoke `llc`, exiting `cargo-klee`");
+
+        if !output.success() {
+            return Err(anyhow!("`llc` failed, exiting `cargo-klee`"));
+        }
+
+        // compile to executable for replay using `clang`
+        let mut clang = Command::new("clang");
+
+        let obj_name = format!("{}.o", ll);
+        let replay_name = format!("{}.replay", ll);
+
+        clang
+            .arg(obj_name)
+            .arg("--rtlib=compiler-rt")
+            .arg("-lkleeRuntest")
+            .args(&["-o", &replay_name]);
+
+        if args.verbose {
+            eprintln!("\n{:?}\n", clang);
+        }
+
+        let output = llc
+            .stdout(Stdio::piped())
+            .status()
+            .expect("failed to invoke `clang`, exiting `cargo-klee`");
+
+        if !output.success() {
+            return Err(anyhow!("`clang` failed, exiting `cargo-klee`"));
+        }
+
+        let mut gdb = Command::new("gdb");
+        if let Ok(cwd) = env::var("GDB_CWD") {
+            // set gdb current dir to `GDB_CWD`
+            gdb.current_dir(cwd);
+        } else {
+            // set gdb current dir to the target directory
+            gdb.current_dir(out_dir);
+        };
+
+        // set replay name to be loaded by gdb
+        gdb.arg(replay_name);
+
+        if args.verbose {
+            eprintln!("\n{:?}\n", gdb);
+        }
+
+        let output = gdb
+            .stdout(Stdio::piped())
+            .status()
+            .expect("failed to invoke `gdb`, exiting `cargo-klee`");
+
+        if !output.success() {
+            return Err(anyhow!("`gdb` failed, exiting `cargo-klee`"));
+        }
     }
 
     println!("--- done ---");
-- 
GitLab