blob: c3f862f8346f7b465b45208b02232d207c7b7f0b [file] [log] [blame] [view] [edit]
<div align="center">
<h1>crabgrind</h1>
<p><a href="https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq">Valgrind Client Request</a> interface for Rust programs</p>
[crates.io]: https://crates.io/crates/crabgrind
[libs.rs]: https://lib.rs/crates/crabgrind
[documentation]: https://docs.rs/crabgrind
[license]: https://github.com/2dav/crabgrind/blob/main/LICENSE
[![crates.io](https://img.shields.io/crates/v/crabgrind)][crates.io]
[![libs.rs](https://img.shields.io/badge/libs.rs-crabgrind-orange)][libs.rs]
[![documentation](https://img.shields.io/docsrs/crabgrind)][documentation]
[![license](https://img.shields.io/crates/l/crabgrind)][license]
</div>
`crabgrind` allows Rust programs running under Valgrind to interact with the tools and virtualized
environment.
[Valgrind's "client request interface"](https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq)
is primarily accessible through a set of `C` macros in Valgrind's header files. However, these macros
cannot be utilized in languages that lack support for C-preprocessor, such as Rust.
To address this, `crabgrind` wraps "client request interface" macros with `C` functions and expose
this API to Rust programs.
This library is essentially a wrapper. It only adds type conversions and some structure, while all
the real things happens inside Valgrind.
## Table of Contents
- [Table of Contents](#table-of-contents)
- [Valgrind 3 API Coverage](#valgind-3-api-coverage)
- [Quickstart](#quickstart)
- [Examples](#examples)
- [Overhead](#overhead)
- [Safety](#safety)
- [Development](#development)
- [License](#license)
### Valgrind 3 API coverage
- Supported tool-specific client request interface:
[valgrind](https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq),
[callgrind](https://valgrind.org/docs/manual/cl-manual.html),
[memcheck](https://valgrind.org/docs/manual/mc-manual.html),
[helgrind](https://valgrind.org/docs/manual/hg-manual.html),
[massif](https://valgrind.org/docs/manual/ms-manual.html),
[cachegrind](https://valgrind.org/docs/manual/cg-manual.html#cg-manual.clientrequests)
- [Monitor commands](https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver-commandhandling) interface
### Quickstart
`crabgrind` does not link against Valgrind but instead reads its header files, which must be accessible during build.
If you have installed Vallgrind using OS-specific package manager, the paths to the headers are likely
to be resolved automatically by [`cc`](https://docs.rs/cc/latest/cc/index.html).
In case of manual installation or any `missing file` error, you can set the path to the Valgrind headers location
through the `DEP_VALGRIND` environment variable. For example:
```bash
DEP_VALGRIND=/usr/include cargo build
```
add dependency `Cargo.toml`
```toml
[dependencies]
crabgrind = "0.1"
```
use some of the [Valgrind's API](https://docs.rs/crabgrind/latest/crabgrind/#modules)
```rust
use crabgrind as cg;
fn main() {
if matches!(cg::run_mode(), cg::RunMode::Native) {
println!("run me under Valgrind");
} else {
cg::println!("Hey, Valgrind!");
}
}
```
and run under Valgrind,
*using [cargo-valgrind](https://github.com/jfrimmel/cargo-valgrind):*
> cargo valgrind run
*manually:*
> cargo build
> valgrind ./target/debug/appname
### Examples
- [Print current function stack-trace to the Valgrind log](https://docs.rs/crabgrind/latest/crabgrind/#print-current-function-stack-trace-to-the-valgrind-log)
- [Exclude expensive initialization code from the measurements](https://docs.rs/crabgrind/latest/crabgrind/#exclude-expensive-initialization-code-from-the-measurements)
- [Run a closure on the real CPU while running under Valgrind](https://docs.rs/crabgrind/latest/crabgrind/#run-a-closure-on-the-real-cpu-while-running-under-valgrind)
- [Save current memory usage snapshot to a file](https://docs.rs/crabgrind/latest/crabgrind/#save-current-memory-usage-snapshot-to-a-file)
- [Dump Callgrind counters on a function basis](https://docs.rs/crabgrind/latest/crabgrind/#dump-callgrind-counters-on-a-function-basis)
### Overhead
from [Valgrind docs](https://valgrind.org/docs/manual/manual-core-adv.html)
> The code added to your binary has negligible performance impact: on x86, amd64, ppc32, ppc64 and ARM,
the overhead is 6 simple integer instructions and is probably undetectable except in tight loops.
> ... the code does nothing when not run on Valgrind, so you are not forced to run your program
under Valgrind just because you use the macros in this file.
Although your loops should be very tight (like a well-executed dance move) to notice any impact,
keep in mind that:
- Wrapping each macros in a function implies function call overhead regardless of the run mode. This can potentially impact the performance of your Rust program.
- Functions that return `std::result::Result` involve branching, which can also have an impact on performance.
- Functions that take strings as parameters internally convert them to `std::ffi::CString`, which can introduce additional overhead.
### Safety
No
### License
`crabgrind` is distributed under `MIT` license.
`Valgrind` itself is a GPL2, however `valgrind/*.h` headers are distributed under a BSD-style license,
so we can use them without worrying about license conflicts.