From 03dba6f1636d24b6726acdfdb3ed37ec3f8862c9 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 14 Dec 2021 08:33:41 -0800 Subject: [PATCH] Implement collection of source line coverage (#1518) Implement source line coverage recording for both Linux and Windows. --- src/agent/Cargo.lock | 288 ++++++++++++++++++++++++- src/agent/coverage/Cargo.toml | 1 + src/agent/coverage/examples/src-cov.rs | 145 +++++++++++++ src/agent/coverage/src/block.rs | 66 ++++++ src/agent/coverage/src/debuginfo.rs | 118 ++++++++++ src/agent/coverage/src/lib.rs | 1 + src/ci/agent.sh | 3 +- 7 files changed, 620 insertions(+), 2 deletions(-) create mode 100644 src/agent/coverage/examples/src-cov.rs create mode 100644 src/agent/coverage/src/debuginfo.rs diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 98b6d5083..6a359037d 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -71,6 +71,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "async-channel" version = "1.6.1" @@ -213,6 +219,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "brownstone" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ea61398f34f1395ccbeb046fb68c87b631d1f34567fed0f0f11fa35d18d8d" +dependencies = [ + "arrayvec 0.7.2", +] + [[package]] name = "bumpalo" version = "3.7.1" @@ -240,6 +255,27 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cache-padded" version = "1.1.1" @@ -368,6 +404,7 @@ dependencies = [ "serde", "serde_json", "structopt", + "symbolic", "uuid", "win-util", "winapi 0.3.9", @@ -563,6 +600,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "debugid" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91cf5a8c2f2097e2a32627123508635d47ce10563d999ec1a95addf08b502ba" +dependencies = [ + "uuid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -591,6 +637,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dmsort" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4699f5cb7678f099b747ffdc1e6ce6cdc42579e29d28315aa715b9fd10324fc" + [[package]] name = "doc-comment" version = "0.3.3" @@ -615,6 +667,16 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elementtree" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c5d32d0ab83734d2d7452047ef901c105991044b7b07da30fe82371a149a25" +dependencies = [ + "string_cache", + "xml-rs", +] + [[package]] name = "encoding_rs" version = "0.8.28" @@ -974,6 +1036,10 @@ name = "gimli" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +dependencies = [ + "fallible-iterator", + "stable_deref_trait", +] [[package]] name = "glob" @@ -1160,6 +1226,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "idna" version = "0.2.3" @@ -1171,6 +1243,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indent_write" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" + [[package]] name = "indexmap" version = "1.7.0" @@ -1255,6 +1333,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + [[package]] name = "js-sys" version = "0.3.55" @@ -1286,13 +1370,19 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "lexical-core" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ - "arrayvec", + "arrayvec 0.5.2", "bitflags", "cfg-if 1.0.0", "ryu", @@ -1379,6 +1469,16 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "memmap2" version = "0.5.0" @@ -1513,6 +1613,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + [[package]] name = "nix" version = "0.23.0" @@ -1560,6 +1666,19 @@ dependencies = [ "version_check", ] +[[package]] +name = "nom-supreme" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aadc66631948f6b65da03be4c4cd8bd104d481697ecbb9bbd65719b1ec60bc9f" +dependencies = [ + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom 7.1.0", +] + [[package]] name = "notify" version = "4.0.17" @@ -1871,6 +1990,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.0.8" @@ -1921,6 +2049,12 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "pretty_assertions" version = "1.0.0" @@ -2472,6 +2606,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "slab" version = "0.4.4" @@ -2565,6 +2705,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stacktrace-parser" version = "0.1.0" @@ -2609,6 +2755,20 @@ dependencies = [ "uuid", ] +[[package]] +name = "string_cache" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923f0f39b6267d37d23ce71ae7235602134b250ace715dd2c90421998ddac0c6" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", + "serde", +] + [[package]] name = "strsim" version = "0.8.0" @@ -2658,6 +2818,86 @@ dependencies = [ "syn 1.0.76", ] +[[package]] +name = "symbolic" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0b3be4c272aaef995fca595a89355caf49993b84a964013e4a94447f13c779" +dependencies = [ + "symbolic-common", + "symbolic-debuginfo", + "symbolic-demangle", + "symbolic-symcache", +] + +[[package]] +name = "symbolic-common" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfc8618f0f31ed048f8e66aa2caecedfbdbbca962ff9ad87107ba4171de0742b" +dependencies = [ + "debugid", + "memmap", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-debuginfo" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac34b5f005e9c87aa9c60a712102f80dca51cd9edf1fa04d5c7392b936c45d06" +dependencies = [ + "dmsort", + "elementtree", + "fallible-iterator", + "flate2", + "gimli", + "goblin", + "lazy_static", + "lazycell", + "nom 7.1.0", + "nom-supreme", + "parking_lot", + "pdb", + "regex", + "scroll", + "serde", + "serde_json", + "smallvec", + "symbolic-common", + "thiserror", + "walrus", + "wasmparser", + "zip", +] + +[[package]] +name = "symbolic-demangle" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be790f170c892899802aa1d382b7b5b65baf692b1357864c74e92bbbbdabfbe" +dependencies = [ + "cc", + "cpp_demangle", + "msvc-demangler", + "rustc-demangle", + "symbolic-common", +] + +[[package]] +name = "symbolic-symcache" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35cdeb276d2476e76b3ce365d3e812a0df5ab04ef4c2781b6f4a962e22337c6" +dependencies = [ + "dmsort", + "fnv", + "symbolic-common", + "symbolic-debuginfo", + "thiserror", +] + [[package]] name = "syn" version = "0.15.44" @@ -3034,6 +3274,32 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "walrus" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8" +dependencies = [ + "anyhow", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasmparser", +] + +[[package]] +name = "walrus-macro" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e5bd22c71e77d60140b0bd5be56155a37e5bd14e24f5f87298040d0cc40d7" +dependencies = [ + "heck", + "proc-macro2 1.0.29", + "quote 1.0.9", + "syn 1.0.76", +] + [[package]] name = "want" version = "0.3.0" @@ -3122,6 +3388,12 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +[[package]] +name = "wasmparser" +version = "0.77.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6" + [[package]] name = "web-sys" version = "0.3.55" @@ -3290,3 +3562,17 @@ name = "z3-sys" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa18ba5fbd4933e41ffb440c3fd91f91fe9cdb7310cce3ddfb6648563811de0" + +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "flate2", + "thiserror", + "time", +] diff --git a/src/agent/coverage/Cargo.toml b/src/agent/coverage/Cargo.toml index e8fee6cd1..382e88ca9 100644 --- a/src/agent/coverage/Cargo.toml +++ b/src/agent/coverage/Cargo.toml @@ -24,6 +24,7 @@ msvc-demangler = "0.9" regex = "1.4" rustc-demangle = "0.1" serde = { version = "1.0", features = ["derive"] } +symbolic = { version = "8.5", features = ["debuginfo", "demangle", "symcache"] } uuid = { version = "0.8", features = ["guid"] } win-util = { path = "../win-util" } diff --git a/src/agent/coverage/examples/src-cov.rs b/src/agent/coverage/examples/src-cov.rs new file mode 100644 index 000000000..2ca347271 --- /dev/null +++ b/src/agent/coverage/examples/src-cov.rs @@ -0,0 +1,145 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use std::path::{Path, PathBuf}; +use std::time::{Duration, Instant}; +use std::{process::Command, process::Stdio}; + +use anyhow::Result; +use coverage::block::CommandBlockCov as Coverage; +use coverage::cache::ModuleCache; +use coverage::code::CmdFilter; +use structopt::StructOpt; + +#[derive(Debug, PartialEq, StructOpt)] +struct Opt { + #[structopt(short, long, min_values = 1)] + inputs: Vec, + + #[structopt(short, long)] + dir: Option, + + #[structopt(min_values = 2)] + cmd: Vec, + + #[structopt(short, long, long_help = "Timeout in ms", default_value = "5000")] + timeout: u64, +} + +fn main() -> Result<()> { + let opt = Opt::from_args(); + let filter = CmdFilter::default(); + + let mut cache = ModuleCache::default(); + let mut total = Coverage::default(); + let timeout = Duration::from_millis(opt.timeout); + + if let Some(dir) = &opt.dir { + for entry in std::fs::read_dir(dir)? { + let input = entry?.path(); + + println!("testing input: {}", input.display()); + + let cmd = input_command(&opt.cmd, &input); + let coverage = record(&mut cache, filter.clone(), cmd, timeout)?; + + total.merge_max(&coverage); + } + } + + for input in &opt.inputs { + println!("testing input: {}", input.display()); + + let cmd = input_command(&opt.cmd, input); + let coverage = record(&mut cache, filter.clone(), cmd, timeout)?; + + total.merge_max(&coverage); + } + + let mut debug_info = coverage::debuginfo::DebugInfo::default(); + let src_coverage = total.source_coverage(&mut debug_info)?; + + for file_coverage in src_coverage.files { + for location in &file_coverage.locations { + println!( + "{} {}:{}", + location.count, file_coverage.file, location.line + ); + } + } + + Ok(()) +} + +fn input_command(argv: &[String], input: &Path) -> Command { + let mut cmd = Command::new(&argv[0]); + cmd.stdin(Stdio::null()); + cmd.stderr(Stdio::null()); + cmd.stdout(Stdio::null()); + + let args: Vec<_> = argv[1..] + .iter() + .map(|a| { + if &*a == "@@" { + input.display().to_string() + } else { + a.to_string() + } + }) + .collect(); + + cmd.args(&args); + + cmd +} + +#[cfg(target_os = "macos")] +fn record( + _cache: &mut ModuleCache, + _filter: CmdFilter, + _cmd: Command, + _timeout: Duration, +) -> Result { + unimplemented!("coverage recording is not supported on macOS"); +} + +#[cfg(target_os = "linux")] +fn record( + cache: &mut ModuleCache, + filter: CmdFilter, + cmd: Command, + timeout: Duration, +) -> Result { + use coverage::block::linux::Recorder; + + let now = Instant::now(); + + let coverage = Recorder::record(cmd, timeout, cache, filter.clone())?; + + let elapsed = now.elapsed(); + log::info!("recorded in {:?}", elapsed); + + Ok(coverage) +} + +#[cfg(target_os = "windows")] +fn record( + cache: &mut ModuleCache, + filter: CmdFilter, + cmd: Command, + timeout: Duration, +) -> Result { + use coverage::block::windows::{Recorder, RecorderEventHandler}; + + let mut recorder = Recorder::new(cache, filter); + let mut handler = RecorderEventHandler::new(&mut recorder, timeout); + + let now = Instant::now(); + + handler.run(cmd)?; + + let elapsed = now.elapsed(); + log::info!("recorded in {:?}", elapsed); + + Ok(recorder.into_coverage()) +} diff --git a/src/agent/coverage/src/block.rs b/src/agent/coverage/src/block.rs index f01c89c05..ddba3ed6d 100644 --- a/src/agent/coverage/src/block.rs +++ b/src/agent/coverage/src/block.rs @@ -17,7 +17,9 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; use crate::code::ModulePath; +use crate::debuginfo::DebugInfo; use crate::report::{CoverageReport, CoverageReportEntry}; +use crate::source::SourceCoverage; /// Block coverage for a command invocation. /// @@ -104,6 +106,70 @@ impl CommandBlockCov { pub fn try_from_report(report: BlockCoverageReport) -> Result { Self::try_from(report) } + + /// Translate binary block coverage to source line coverage, using a caching + /// debug info provider. + pub fn source_coverage(&self, debuginfo: &mut DebugInfo) -> Result { + use crate::source::{SourceCoverageLocation as Location, *}; + use std::collections::HashMap; + + // Temporary map to collect line coverage results without duplication. + // Will be converted after processing block coverage. + // + // Maps: source_file_path -> (line -> count) + let mut files: HashMap> = HashMap::default(); + + for (module, coverage) in &self.modules { + let loaded = debuginfo.load_module(module.path().to_owned())?; + + if !loaded { + continue; + } + + let mod_info = debuginfo.get(&module.path()); + + if let Some(mod_info) = mod_info { + for (offset, block) in &coverage.blocks { + let lines = mod_info.source.lookup(u64::from(*offset))?; + + for line_info in lines { + let line_info = line_info?; + let file = line_info.path().to_owned(); + let line = line_info.line(); + + let file_entry = files.entry(file).or_default(); + let line_entry = file_entry.entry(line).or_insert(0); + + // Will always be 0 or 1. + *line_entry = u32::max(*line_entry, block.count); + } + } + } + } + + let mut src = SourceCoverage::default(); + + for (file, lines) in files { + let mut locations = vec![]; + + for (line, count) in lines { + // Valid lines are always 1-indexed. + if line > 0 { + let location = Location::new(line, None, count)?; + locations.push(location) + } + } + + locations.sort_unstable_by_key(|l| l.line); + + let file_coverage = SourceFileCoverage { file, locations }; + src.files.push(file_coverage); + } + + src.files.sort_unstable_by_key(|f| f.file.clone()); + + Ok(src) + } } impl From for BlockCoverageReport { diff --git a/src/agent/coverage/src/debuginfo.rs b/src/agent/coverage/src/debuginfo.rs new file mode 100644 index 000000000..b995baeba --- /dev/null +++ b/src/agent/coverage/src/debuginfo.rs @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +use anyhow::Result; +use symbolic::{ + debuginfo::{pe, Object, ObjectDebugSession}, + symcache::{SymCache, SymCacheWriter}, +}; + +/// Caching provider of debug info for executable code modules. +#[derive(Default)] +pub struct DebugInfo { + // Cached debug info, keyed by module path. + modules: HashMap, + + // Set of module paths known to lack debug info. + no_debug_info: HashSet, +} + +impl DebugInfo { + /// Try to load debug info for a module. + /// + /// If debug info was founded and loaded (now or previously), returns + /// `true`. If the module does not have debug info, returns `false`. + pub fn load_module(&mut self, module: PathBuf) -> Result { + if self.no_debug_info.contains(&module) { + return Ok(false); + } + + if self.modules.get(&module).is_some() { + return Ok(true); + } + + let info = match ModuleDebugInfo::load(&module)? { + Some(info) => info, + None => { + self.no_debug_info.insert(module); + return Ok(false); + } + }; + + self.modules.insert(module, info); + + Ok(true) + } + + /// Fetch debug info for `module`, if loaded. + /// + /// Does not attempt to load debug info for the module. + pub fn get(&self, module: impl AsRef) -> Option<&ModuleDebugInfo> { + self.modules.get(module.as_ref()) + } +} + +/// Debug info for a single executable module. +pub struct ModuleDebugInfo { + /// Backing debug info file data for the module. + /// + /// May not include the actual executable code. + pub object: Object<'static>, + + /// Interface and caching structures for general debug info querying. + pub session: ObjectDebugSession<'static>, + + /// Cache which allows efficient source line lookups. + pub source: SymCache<'static>, +} + +impl ModuleDebugInfo { + /// Load debug info for a module. + /// + /// Returns `None` when the module was found and loadable, but no matching + /// debug info could be found. + /// + /// Leaks module and symbol data. + fn load(module: &Path) -> Result> { + let mut data = fs::read(&module)?.into_boxed_slice(); + + // If our module is a PE file, the debug info will be in the PDB. + // + // We will need a similar check to support split DWARF. + let is_pe = pe::PeObject::test(&data); + if is_pe { + // Assume a sibling PDB. + // + // TODO: Find PDB using `dbghelp::`SymGetSymbolFile()`. + let pdb = module.with_extension("pdb"); + data = fs::read(&pdb)?.into_boxed_slice(); + } + + // Now we're sure we want this data, so leak it. + let data = Box::leak(data); + + let object = Object::parse(data)?; + + if !object.has_debug_info() { + return Ok(None); + } + + let session = object.debug_session()?; + + let cursor = io::Cursor::new(vec![]); + let cursor = SymCacheWriter::write_object(&object, cursor)?; + let cache_data = Box::leak(cursor.into_inner().into_boxed_slice()); + let source = SymCache::parse(cache_data)?; + + Ok(Some(Self { + object, + session, + source, + })) + } +} diff --git a/src/agent/coverage/src/lib.rs b/src/agent/coverage/src/lib.rs index 1644bae5d..dbbce3494 100644 --- a/src/agent/coverage/src/lib.rs +++ b/src/agent/coverage/src/lib.rs @@ -18,6 +18,7 @@ pub mod elf; pub mod block; pub mod cache; pub mod code; +pub mod debuginfo; pub mod demangle; pub mod report; pub mod sancov; diff --git a/src/ci/agent.sh b/src/ci/agent.sh index 926269f84..3c3f9b7df 100755 --- a/src/ci/agent.sh +++ b/src/ci/agent.sh @@ -39,9 +39,10 @@ cargo fmt -- --check # RUSTSEC-2020-0036: a dependency `failure` (pulled from proc-maps) is deprecated # RUSTSEC-2019-0036: a dependency `failure` (pulled from proc-maps) has type confusion vulnerability # RUSTSEC-2021-0065: a dependency `anymap` is no longer maintained +# RUSTSEC-2020-0077: `memmap` dependency unmaintained, via `symbolic` (see: `getsentry/symbolic#304`) # RUSTSEC-2020-0159: potential segfault in `time`, not yet patched (#1366) # RUSTSEC-2020-0071: potential segfault in `chrono`, not yet patched (#1366) -cargo audit --deny warnings --deny unmaintained --deny unsound --deny yanked --ignore RUSTSEC-2020-0016 --ignore RUSTSEC-2020-0036 --ignore RUSTSEC-2019-0036 --ignore RUSTSEC-2021-0065 --ignore RUSTSEC-2020-0159 --ignore RUSTSEC-2020-0071 +cargo audit --deny warnings --deny unmaintained --deny unsound --deny yanked --ignore RUSTSEC-2020-0016 --ignore RUSTSEC-2020-0036 --ignore RUSTSEC-2019-0036 --ignore RUSTSEC-2021-0065 --ignore RUSTSEC-2020-0159 --ignore RUSTSEC-2020-0071 --ignore RUSTSEC-2020-0077 cargo-license -j > data/licenses.json cargo build --release --locked cargo clippy --release -- -D warnings