sbpf-coverage 0.2.11

Maps SBPF execution traces to source code for test coverage and trace disassembly of Solana programs
Documentation
diff --git a/src/anchor_cli_lib/mod.rs b/src/anchor_cli_lib/mod.rs
index 13c393d..ce14616 100644
--- a/src/anchor_cli_lib/mod.rs
+++ b/src/anchor_cli_lib/mod.rs
@@ -322,7 +322,7 @@ fn _build_rust_cwd(
     }
 
     // Generate IDL
-    if !no_idl {
+    if false && !no_idl {
         let idl = generate_idl(cfg, skip_lint, no_docs, &cargo_args)?;
 
         // JSON out path.
diff --git a/src/bin/anchor-coverage.rs b/src/bin/anchor-coverage.rs
index a4fe3ca..c0feb20 100644
--- a/src/bin/anchor-coverage.rs
+++ b/src/bin/anchor-coverage.rs
@@ -36,12 +36,12 @@ Usage: {0} [ANCHOR_TEST_ARGS]...
 
     let sbf_trace_dir = current_dir.join("sbf_trace_dir");
 
-    if sbf_trace_dir.try_exists()? {
-        eprintln!("Warning: Removing `{}`", sbf_trace_dir.display());
-        remove_dir_all(&sbf_trace_dir)?;
-    }
+    // if sbf_trace_dir.try_exists()? {
+    //     eprintln!("Warning: Removing `{}`", sbf_trace_dir.display());
+    //     remove_dir_all(&sbf_trace_dir)?;
+    // }
 
-    create_dir_all(&sbf_trace_dir)?;
+    // create_dir_all(&sbf_trace_dir)?;
 
     anchor_test_with_debug(&options.args, &sbf_trace_dir)?;
 
@@ -117,12 +117,12 @@ fn anchor_test_with_debug(args: &[String], sbf_trace_dir: &Path) -> Result<()> {
 }
 
 fn anchor_test_skip_build(args: &[String], sbf_trace_dir: &Path) -> Result<()> {
-    let mut command = Command::new("anchor");
-    command.args(["test", "--skip-build"]);
-    command.args(args);
-    command.env(SBF_TRACE_DIR, sbf_trace_dir);
-    let status = command.status()?;
-    ensure!(status.success(), "command failed: {:?}", command);
+    // let mut command = Command::new("anchor");
+    // command.args(["test", "--skip-build"]);
+    // command.args(args);
+    // command.env(SBF_TRACE_DIR, sbf_trace_dir);
+    // let status = command.status()?;
+    // ensure!(status.success(), "command failed: {:?}", command);
     Ok(())
 }
 
diff --git a/src/branch.rs b/src/branch.rs
index 5d6092a..1b2c4e0 100644
--- a/src/branch.rs
+++ b/src/branch.rs
@@ -175,7 +175,7 @@ pub fn get_branches(
                         );
                 }
 
-                let ins = insns[i].to_be_bytes();
+                let ins = insns[i].to_le_bytes();
                 // eprintln!("{:02x?}", ins);
 
                 let ins_type = ins[0];
@@ -284,32 +284,35 @@ pub fn get_branches(
 }
 
 pub fn write_branch_coverage(branches: &Branches, pcs_path: &Path) -> Result<()> {
-    let path = pcs_path
-        .parent()
-        .and_then(|p| p.parent())
-        .ok_or(anyhow!("Can't get to root of the project"))?
-        .join("programs");
+    // let path = pcs_path
+    //     .parent()
+    //     .and_then(|p| p.parent())
+    //     .ok_or(anyhow!("Can't get to root of the project"))?
+    //     .join("programs");
 
-    let programs: Vec<_> = std::fs::read_dir(&path)?
-        .map(|e| e.map(|e| e.file_name().display().to_string()))
-        .collect::<Result<Vec<_>, _>>()?;
+    // let programs: Vec<_> = std::fs::read_dir(&path)?
+    //     .map(|e| e.map(|e| e.file_name().display().to_string()))
+    //     .collect::<Result<Vec<_>, _>>()?;
 
-    let sbf_trace_dir = std::env::var("SBF_TRACE_DIR").unwrap_or("sbf_trace_dir".into());
+    let branches_lcov_file = pcs_path.with_file_name("branches.lcov");
     let mut lcov_file = OpenOptions::new()
         .create(true)
         .append(true)
-        .open(format!("{}/branches.lcov", sbf_trace_dir))
+        .open(branches_lcov_file)
         .expect("cannot open file");
 
     for (_vaddr, branch) in branches {
         match (&branch.file, branch.line) {
             (Some(file), Some(line)) => {
-                if programs
-                    .iter()
-                    .filter(|e| file.contains(*e))
-                    .nth(0)
-                    .is_none()
-                {
+                // if programs
+                //     .iter()
+                //     .filter(|e| file.contains(*e))
+                //     .nth(0)
+                //     .is_none()
+                // {
+                //     continue;
+                // }
+                if !file.contains("native_app") && !file.contains("solana_onboarding") {
                     continue;
                 }
 
diff --git a/src/lib.rs b/src/lib.rs
index b908ffa..e868556 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -152,6 +152,7 @@ fn debug_paths() -> Result<Vec<PathBuf>> {
 }
 
 fn build_dwarf(debug_path: &Path) -> Result<Dwarf> {
+    eprintln!("debug_path: {}", debug_path.to_string_lossy().to_string());
     let start_address = start_address(debug_path)?;
 
     let loader = Loader::new(debug_path).map_err(|error| {
@@ -181,7 +182,8 @@ fn process_pcs_path(dwarfs: &[Dwarf], pcs_path: &Path) -> Result<Outcome> {
         pcs_path.strip_current_dir().display()
     );
 
-    let (mut vaddrs, insns, regs) = read_vaddrs(pcs_path)?;
+    let (mut vaddrs, regs) = read_vaddrs(pcs_path)?;
+    let insns = read_insns(&pcs_path.with_extension("insns"))?;
     // for va in vaddrs.iter() {
     //     eprintln!(
     //         "\t\t\t {:x} from {}",
@@ -289,13 +291,21 @@ fn dump_vaddr_entry_map(vaddr_entry_map: BTreeMap<u64, Entry<'_>>) {
     }
 }
 
-fn read_vaddrs(pcs_path: &Path) -> Result<(Vaddrs, Insns, Regs)> {
+fn read_insns(insns_path: &Path) -> Result<Insns> {
+    let mut insns = Vec::new();
+    let mut insns_file = File::open(insns_path)?;
+    while let Ok(insn) = insns_file.read_u64::<LittleEndian>() {
+        insns.push(insn);
+    }
+    Ok(insns)
+}
+
+fn read_vaddrs(pcs_path: &Path) -> Result<(Vaddrs, Regs)> {
     let mut regs = Regs::new();
-    let mut insns = Insns::new();
     let mut vaddrs = Vaddrs::new();
     let mut pcs_file = File::open(pcs_path)?;
 
-    let mut data_trace = [0u64; 13];
+    let mut data_trace = [0u64; 12];
     'outer: loop {
         for i in 0..data_trace.len() {
             match pcs_file.read_u64::<LittleEndian>() {
@@ -315,12 +325,11 @@ fn read_vaddrs(pcs_path: &Path) -> Result<(Vaddrs, Insns, Regs)> {
         // data_file.write_all(format!("0x{:08x?} all: {:08x?}\n", vaddr, data_trace).as_bytes())?;
 
         vaddrs.push(vaddr);
-        insns.push(data_trace[12].to_be()); // we've stored the insn in data_trace[12] i.e the 13th element - 0..11 are the vm regs
         let regs_values: [u64; 12] = data_trace[0..12].try_into().unwrap();
         regs.push(regs_values);
     }
 
-    Ok((vaddrs, insns, regs))
+    Ok((vaddrs, regs))
 }
 
 fn find_applicable_dwarf<'a>(