Skip to content

Commit 16bb4be

Browse files
Merge pull request #152 from microsoft/main
Fork Sync: Update from parent repository
2 parents d202399 + 3a5101b commit 16bb4be

File tree

6 files changed

+109
-52
lines changed

6 files changed

+109
-52
lines changed

src/agent/coverage/examples/coverage.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use anyhow::Result;
55
use clap::Parser;
66
use coverage::allowlist::{AllowList, TargetAllowList};
77
use coverage::binary::BinaryCoverage;
8+
use coverage::record::CoverageRecorder;
9+
use debuggable_module::loader::Loader;
810

911
#[derive(Parser, Debug)]
1012
struct Args {
@@ -45,14 +47,19 @@ fn main() -> Result<()> {
4547
allowlist.source_files = AllowList::load(path)?;
4648
}
4749

48-
let coverage = coverage::record::record(cmd, timeout, allowlist)?;
50+
let loader = Loader::new();
51+
let recorded = CoverageRecorder::new(cmd)
52+
.allowlist(allowlist)
53+
.loader(loader)
54+
.timeout(timeout)
55+
.record()?;
4956

50-
dump_modoff(coverage)?;
57+
dump_modoff(&recorded.coverage)?;
5158

5259
Ok(())
5360
}
5461

55-
fn dump_modoff(coverage: BinaryCoverage) -> Result<()> {
62+
fn dump_modoff(coverage: &BinaryCoverage) -> Result<()> {
5663
for (module, coverage) in &coverage.modules {
5764
for (offset, count) in coverage.as_ref() {
5865
if count.reached() {

src/agent/coverage/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ mod timer;
1414
pub use allowlist::{AllowList, TargetAllowList};
1515

1616
#[doc(inline)]
17-
pub use record::record;
17+
pub use record::{CoverageRecorder, Recorded};

src/agent/coverage/src/record.rs

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,100 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4+
use std::process::{Command, Output, Stdio};
5+
use std::sync::Arc;
6+
use std::time::Duration;
7+
8+
use anyhow::Result;
9+
use debuggable_module::loader::Loader;
10+
11+
use crate::allowlist::TargetAllowList;
12+
use crate::binary::BinaryCoverage;
13+
414
#[cfg(target_os = "linux")]
515
pub mod linux;
616

717
#[cfg(target_os = "windows")]
818
pub mod windows;
919

10-
#[cfg(target_os = "linux")]
11-
pub use crate::record::linux::record;
20+
pub struct CoverageRecorder {
21+
allowlist: TargetAllowList,
22+
cmd: Command,
23+
loader: Arc<Loader>,
24+
timeout: Duration,
25+
}
1226

13-
#[cfg(target_os = "windows")]
14-
pub use crate::record::windows::record;
27+
impl CoverageRecorder {
28+
pub fn new(mut cmd: Command) -> Self {
29+
cmd.stdout(Stdio::piped());
30+
cmd.stderr(Stdio::piped());
31+
32+
let allowlist = TargetAllowList::default();
33+
let loader = Arc::new(Loader::new());
34+
let timeout = Duration::from_secs(5);
35+
36+
Self {
37+
allowlist,
38+
cmd,
39+
loader,
40+
timeout,
41+
}
42+
}
43+
44+
pub fn allowlist(mut self, allowlist: TargetAllowList) -> Self {
45+
self.allowlist = allowlist;
46+
self
47+
}
48+
49+
pub fn loader(mut self, loader: impl Into<Arc<Loader>>) -> Self {
50+
self.loader = loader.into();
51+
self
52+
}
53+
54+
pub fn timeout(mut self, timeout: Duration) -> Self {
55+
self.timeout = timeout;
56+
self
57+
}
58+
59+
#[cfg(target_os = "linux")]
60+
pub fn record(self) -> Result<Recorded> {
61+
use linux::debugger::Debugger;
62+
use linux::LinuxRecorder;
63+
64+
let loader = self.loader.clone();
65+
66+
crate::timer::timed(self.timeout, move || {
67+
let mut recorder = LinuxRecorder::new(&loader, self.allowlist);
68+
let dbg = Debugger::new(&mut recorder);
69+
let output = dbg.run(self.cmd)?;
70+
let coverage = recorder.coverage;
71+
72+
Ok(Recorded { coverage, output })
73+
})?
74+
}
75+
76+
#[cfg(target_os = "windows")]
77+
pub fn record(self) -> Result<Recorded> {
78+
use debugger::Debugger;
79+
use windows::WindowsRecorder;
80+
81+
let loader = self.loader.clone();
82+
83+
crate::timer::timed(self.timeout, move || {
84+
let mut recorder = WindowsRecorder::new(&loader, self.allowlist);
85+
let (mut dbg, child) = Debugger::init(self.cmd, &mut recorder)?;
86+
dbg.run(&mut recorder)?;
87+
88+
let output = child.wait_with_output()?;
89+
let coverage = recorder.coverage;
90+
91+
Ok(Recorded { coverage, output })
92+
})?
93+
}
94+
}
95+
96+
#[derive(Clone, Debug)]
97+
pub struct Recorded {
98+
pub coverage: BinaryCoverage,
99+
pub output: Output,
100+
}

src/agent/coverage/src/record/linux.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Licensed under the MIT License.
33

44
use std::collections::BTreeMap;
5-
use std::process::Command;
6-
use std::time::Duration;
75

86
use anyhow::{bail, Result};
97
use debuggable_module::linux::LinuxModule;
@@ -14,31 +12,14 @@ use debuggable_module::Address;
1412
use pete::Tracee;
1513

1614
pub mod debugger;
17-
use debugger::{DebugEventHandler, Debugger, DebuggerContext, ModuleImage};
15+
use debugger::{DebugEventHandler, DebuggerContext, ModuleImage};
1816

1917
use crate::allowlist::TargetAllowList;
2018
use crate::binary::{self, BinaryCoverage};
2119

22-
pub fn record(
23-
cmd: Command,
24-
timeout: Duration,
25-
allowlist: impl Into<Option<TargetAllowList>>,
26-
) -> Result<BinaryCoverage> {
27-
let loader = Loader::new();
28-
let allowlist = allowlist.into().unwrap_or_default();
29-
30-
crate::timer::timed(timeout, move || {
31-
let mut recorder = LinuxRecorder::new(&loader, allowlist);
32-
let dbg = Debugger::new(&mut recorder);
33-
dbg.run(cmd)?;
34-
35-
Ok(recorder.coverage)
36-
})?
37-
}
38-
3920
pub struct LinuxRecorder<'data> {
4021
allowlist: TargetAllowList,
41-
coverage: BinaryCoverage,
22+
pub coverage: BinaryCoverage,
4223
loader: &'data Loader,
4324
modules: BTreeMap<FilePath, LinuxModule<'data>>,
4425
}

src/agent/coverage/src/record/linux/debugger.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
use std::collections::BTreeMap;
5-
use std::process::Command;
5+
use std::process::{Command, Output};
66

77
use anyhow::{bail, format_err, Result};
88
use debuggable_module::path::FilePath;
@@ -36,7 +36,7 @@ impl<'eh> Debugger<'eh> {
3636
}
3737
}
3838

39-
pub fn run(mut self, cmd: Command) -> Result<()> {
39+
pub fn run(mut self, cmd: Command) -> Result<Output> {
4040
let mut child = self.context.tracer.spawn(cmd)?;
4141

4242
if let Err(err) = self.wait_on_stops() {
@@ -46,7 +46,9 @@ impl<'eh> Debugger<'eh> {
4646
return Err(err);
4747
}
4848

49-
Ok(())
49+
let output = child.wait_with_output()?;
50+
51+
Ok(output)
5052
}
5153

5254
fn wait_on_stops(mut self) -> Result<()> {

src/agent/coverage/src/record/windows.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
use std::collections::BTreeMap;
55
use std::path::Path;
6-
use std::process::Command;
7-
use std::time::Duration;
86

97
use anyhow::{anyhow, Result};
108
use debuggable_module::load_module::LoadModule;
@@ -17,27 +15,10 @@ use debugger::{BreakpointId, BreakpointType, DebugEventHandler, Debugger, Module
1715
use crate::allowlist::TargetAllowList;
1816
use crate::binary::{self, BinaryCoverage};
1917

20-
pub fn record(
21-
cmd: Command,
22-
timeout: Duration,
23-
allowlist: impl Into<Option<TargetAllowList>>,
24-
) -> Result<BinaryCoverage> {
25-
let loader = Loader::new();
26-
let allowlist = allowlist.into().unwrap_or_default();
27-
28-
crate::timer::timed(timeout, move || {
29-
let mut recorder = WindowsRecorder::new(&loader, allowlist);
30-
let (mut dbg, _child) = Debugger::init(cmd, &mut recorder)?;
31-
dbg.run(&mut recorder)?;
32-
33-
Ok(recorder.coverage)
34-
})?
35-
}
36-
3718
pub struct WindowsRecorder<'data> {
3819
allowlist: TargetAllowList,
3920
breakpoints: Breakpoints,
40-
coverage: BinaryCoverage,
21+
pub coverage: BinaryCoverage,
4122
loader: &'data Loader,
4223
modules: BTreeMap<FilePath, WindowsModule<'data>>,
4324
}

0 commit comments

Comments
 (0)