Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.

Commit

Permalink
Separate trace collection from trace decoding.
Browse files Browse the repository at this point in the history
We are about to add our own trace decoder (as an alternative to libipt)
to hwtracer. In order to do this we need the ability to have separate
notions of trace collection and trace decoding.

In other words, instead of having a `PerfPT backend`, we now have a
`PerfTraceCollector` and a `LibIPTTraceDecoder`.

(There was also something called a `Dummy` backend, which I saw no
utility to, and have thus removed)

This is a large change, that will be hard to review I'm afraid.

In doing this work I've realised how crusty and unidiomatic some of the
hwtracer code is. Regardless I've tried hard to resist the urge to
uncrustify unrelated parts of code. I will fix some of this stuff in
follow up PRs.
  • Loading branch information
vext01 committed Oct 20, 2022
1 parent 5d98a99 commit 6f4c702
Show file tree
Hide file tree
Showing 21 changed files with 1,486 additions and 1,541 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ libc = "0.2.80"
lazy_static = "1.4.0"
tempfile = "3.1.0"
phdrs = { git = "https://github.com/softdevteam/phdrs" }
strum = { version = "0.24.1", features = ["derive", "strum_macros"] }
strum_macros = "0.24.3"

[build-dependencies]
cc = "1.0.62"
Expand Down
20 changes: 13 additions & 7 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,19 @@ fn main() {

let c_deps_dir = make_c_deps_dir();
let c_deps_dir_s = c_deps_dir.display();
c_build.file("src/util.c");

// Check if we should build the perf_pt backend.
// Check if we should build the perf collector.
if cfg!(all(target_os = "linux", target_arch = "x86_64"))
&& feature_check("check_perf_pt.c", "check_perf_pt")
&& feature_check("check_perf.c", "check_perf")
{
c_build.file("src/backends/perf_pt/collect.c");
c_build.file("src/backends/perf_pt/decode.c");
c_build.file("src/backends/perf_pt/util.c");
c_build.file("src/collect/perf/collect.c");
println!("cargo:rustc-cfg=collector_perf");
}

// FIXME: libipt support is unconditionally built-in for now.
if cfg!(all(target_os = "linux", target_arch = "x86_64")) {
c_build.file("src/decode/libipt/decode.c");

// Decide whether to build our own libipt.
if let Ok(val) = env::var("IPT_PATH") {
Expand Down Expand Up @@ -133,13 +138,14 @@ fn main() {
c_deps_dir_s
));

println!("cargo:rustc-cfg=perf_pt");
println!("cargo:rustc-cfg=decoder_libipt");
if cpu_supports_pt() {
println!("cargo:rustc-cfg=perf_pt_test");
println!("cargo:rustc-cfg=decoder_libipt_test");
}
println!("cargo:rustc-link-lib=static=ipt");
}
c_build.include("src/util");
c_build.include("src"); // to find `hwtracer_private.h`.
c_build.compile("hwtracer_c");

// Additional circumstances under which to re-run this build.rs.
Expand Down
3 changes: 2 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ unlicensed = "deny"
confidence-threshold = 1.0
allow = [
"Apache-2.0",
"ISC",
"MIT",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
]
24 changes: 12 additions & 12 deletions examples/simple_example.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use hwtracer::backends::TracerBuilder;
use hwtracer::Trace;
use hwtracer::{collect::TraceCollectorBuilder, decode::TraceDecoderBuilder};
use std::time::SystemTime;

/// Prints the addresses of the first `qty` blocks in a trace along with it's name and
/// computation result.
fn print_trace(trace: &Box<dyn Trace>, name: &str, result: u32, qty: usize) {
let count = trace.iter_blocks().count();
fn print_trace(trace: Box<dyn Trace>, name: &str, result: u32, qty: usize) {
let dec = TraceDecoderBuilder::new().build().unwrap();
let count = dec.iter_blocks(&*trace).count();
println!("{}: num_blocks={}, result={}", name, count, result);

for (i, blk) in trace.iter_blocks().take(qty).enumerate() {
for (i, blk) in dec.iter_blocks(&*trace).take(qty).enumerate() {
println!(" block {}: 0x{:x}", i, blk.unwrap().first_instr());
}
if count > qty {
Expand All @@ -29,21 +30,20 @@ fn work() -> u32 {
res
}

/// Trace a simple computation loop.
/// Collect and decode a trace for a simple computation loop.
///
/// The results are printed to discourage the compiler from optimising the computation out.
fn main() {
let mut bldr = TracerBuilder::new();
println!("Backend configuration: {:?}", bldr.config());
let mut thr_tracer = bldr.build().unwrap().thread_tracer();
let bldr = TraceCollectorBuilder::new();
let mut thr_col = bldr.build().unwrap().thread_collector();

for i in 1..4 {
thr_tracer.start_tracing().unwrap_or_else(|e| {
panic!("Failed to start tracer: {}", e);
thr_col.start_collector().unwrap_or_else(|e| {
panic!("Failed to start collector: {}", e);
});
let res = work();
let trace = thr_tracer.stop_tracing().unwrap();
let trace = thr_col.stop_collector().unwrap();
let name = format!("trace{}", i);
print_trace(&trace, &name, res, 10);
print_trace(trace, &name, res, 10);
}
}
8 changes: 8 additions & 0 deletions feature_checks/check_perf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <linux/perf_event.h>

int
check(void)
{
// The perf configuration struct version that first supported Intel PT.
return PERF_ATTR_SIZE_VER5;
}
121 changes: 0 additions & 121 deletions src/backends/dummy.rs

This file was deleted.

Loading

0 comments on commit 6f4c702

Please sign in to comment.