sbpf-coverage 0.2.7

Maps SBPF execution traces to source code for test coverage and trace disassembly of Solana programs
Documentation
diff --git a/src/lib.rs b/src/lib.rs
index 57f88ab..66d3081 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,7 @@ use anyhow::{Result, anyhow, bail};
 use byteorder::{LittleEndian, ReadBytesExt};
 use object::{Object, ObjectSection};
 use std::{
-    collections::{BTreeMap, HashSet},
+    collections::{BTreeMap, HashMap, HashSet},
     fs::{File, OpenOptions, metadata},
     io::Write,
     path::{Path, PathBuf},
@@ -259,6 +259,7 @@ fn build_vaddr_entry_map<'a>(
     src_paths: &HashSet<PathBuf>,
 ) -> Result<VaddrEntryMap<'a>> {
     let mut vaddr_entry_map = VaddrEntryMap::new();
+    let mut resolved_paths: HashMap<&str, Option<&'a str>> = HashMap::new();
     let metadata = metadata(debug_path)?;
     for vaddr in (0..metadata.len()).step_by(size_of::<u64>()) {
         let location = loader.find_location(vaddr).map_err(|error| {
@@ -270,11 +271,26 @@ fn build_vaddr_entry_map<'a>(
         let Some(file) = location.file else {
             continue;
         };
-        // smoelius: Ignore files that do not exist.
-        if !Path::new(file).try_exists()? {
-            continue;
-        }
+        // Resolve relative paths to absolute and cache the result.
+        // canonicalize also verifies the file exists, replacing the old try_exists check.
+        let file: &str = match resolved_paths.get(file) {
+            Some(Some(resolved)) => resolved,
+            Some(None) => continue,
+            None => match Path::new(file).canonicalize() {
+                Ok(abs) => {
+                    let leaked: &'static str =
+                        Box::leak(abs.to_string_lossy().into_owned().into_boxed_str());
+                    resolved_paths.insert(file, Some(leaked));
+                    leaked
+                }
+                Err(_) => {
+                    resolved_paths.insert(file, None);
+                    continue;
+                }
+            },
+        };
         // procdump: ignore files other than what user has provided.
+        eprintln!("vaddr: 0x{:x}, file: {}, location: {:?}", vaddr, file.to_string(), location.line);
         if !src_paths
             .iter()
             .any(|src_path| file.starts_with(&src_path.to_string_lossy().to_string()))
@@ -284,6 +300,9 @@ fn build_vaddr_entry_map<'a>(
         let Some(line) = location.line else {
             continue;
         };
+        if line > 134 {
+            continue;
+        }
         // smoelius: Even though we ignore columns, fetch them should we ever want to act on them.
         let Some(_column) = location.column else {
             continue;