valgrind-requests
Idiomatic Rust bindings for Valgrind client requests, with zero-indirection execution and zero-cost fallback.
About
valgrind-requests is a standalone crate providing idiomatic Rust bindings for
Valgrind's Client Request Mechanism. It is a retake and
rewrite from scratch of the abandoned valgrind_request.
This implementation is considered complete and covers all Valgrind tools with
client requests (Memcheck, Callgrind, Cachegrind, Helgrind, DRD, DHAT) on all
platforms which Valgrind supports.
This crate was formerly hardcoded into Gungraun. Gungraun still uses
valgrind-requests but this crate was extracted in the hope to be useful
outside of the Gungraun crate.
valgrind-requests uses inline assembly for zero-indirection execution on
supported platforms - avoiding the function call overhead of a C FFI layer. The
stubs feature compiles all client requests to no-ops with zero runtime cost,
making it safe to ship in production code without conditional compilation.
Core client request APIs are no_std compatible. The std feature, which
implies alloc, is enabled by default.
Features
act(default): Enables actual execution of client requests when running under Valgrind. Impliesstubs.stubs: Enables the same public API surface and build-time code generation, but all client requests compile to no-ops.alloc: Enables allocation-backed convenience APIs, such as formatting macros and owned C string helpers.std(default): Enables standard library support and impliesalloc.
Formatting convenience macros such as valgrind_printf! and
valgrind_println! require the alloc feature because they allocate
owned C strings. Allocation-free alternatives are valgrind_print or
valgrind_print_backtrace.
Installation
[]
= "1.1"
or cargo add valgrind-requests.
To use the zero-cost fallback, for example if you want to use the client requests for tests or benchmarks and need to make annotations in production code:
[]
= { = "1.1", = false, = ["stubs"] }
[]
= { = "1.1" }
The stubs compile down to nothing and your production code is as performant as
without any annotations. If your production code uses the formatting convenience
macros, enable both stubs and alloc with features = ["stubs", "alloc"].
The client requests require the Valgrind header files. These are typically installed by your distribution's package manager alongside Valgrind and discovered automatically.
If the headers cannot be found, set the VALGRIND_REQUESTS_VALGRIND_INCLUDE
environment variable to the include path containing the valgrind/ directory.
For cross-compilation, you can use the target-specific variant:
VALGRIND_REQUESTS_X86_64_UNKNOWN_LINUX_GNU_VALGRIND_INCLUDE=/path/to/include cargo build
Quick start
use ;
use ;
no_std Example
Disable default features and re-enable either stubs or act:
= { = "1.1", = false, = ["act"] }
The core client request functions are no_std compatible and can be used as
usual. In allocation-free environments, you can use allocation-free print
functions, for example:
valgrind_print;
Gungraun example
Measure only a specific code region with Callgrind
// my_lib.rs
use callgrind;
For example, in a Gungraun benchmark this could be used
use *;
use ;
use black_box;
use some_func;
library_benchmark_group!;
main!;
Modules
The client requests are organized into modules representing the source header file:
valgrind- core client requests fromvalgrind.hmemcheck-memcheck.h- (Memcheck: a memory error detector)callgrind-callgrind.h- Callgrind: a call-graph generating cache and branch prediction profilercachegrind-cachegrind.h- (Cachegrind: a high-precision tracing profiler)helgrind-helgrind.h- Helgrind: a thread error detectordrd-drd.h- DRD: a thread error detectordhat-dhat.h- DHAT: a dynamic heap analysis tool
The allocation-free valgrind_print and valgrind_print_backtrace
functions live in the crate root. The alloc-backed valgrind_printf!,
valgrind_printf_unchecked!, valgrind_println!,
valgrind_println_unchecked!, valgrind_printf_backtrace!,
valgrind_printf_backtrace_unchecked!, valgrind_println_backtrace!, and
valgrind_println_backtrace_unchecked! macros also live in the crate root.
Platform support
If possible, client requests execute with zero indirection and the same overhead
as the original Valgrind C macros usable even in high performance
code. On Valgrind-supported platforms for which
zero-indirection isn't implemented by us, a native C FFI binding is used which
introduces at least an additional frame on the stack and the costs for the
function call. That means all targets covered by Valgrind are also covered by
valgrind-requests. Targets not supported by Valgrind produce a compile error.
| Target | Zero-indirection | Notes |
|---|---|---|
x86_64/linux |
yes | except the x32 ABI |
x86_64/android |
yes | except the x32 ABI |
x86_64/freebsd |
yes | - |
x86_64/macos |
yes | the versions supported by Valgrind and LouisBrunner/valgrind-macos |
x86_64/windows+gnu |
yes | - |
x86_64/solaris |
yes | - |
x86/linux |
yes | - |
x86/android |
yes | - |
x86/freebsd |
yes | - |
x86/macos |
yes | the versions supported by Valgrind and LouisBrunner/valgrind-macos |
x86/windows+gnu |
yes | - |
x86/solaris |
yes | - |
arm/linux |
yes | - |
arm/android |
yes | - |
aarch64/linux |
yes | - |
aarch64/android |
yes | - |
aarch64/freebsd |
yes | - |
aarch64/macos |
yes | LouisBrunner/valgrind-macos |
riscv64/linux |
yes | - |
s390x/linux |
yes | - |
powerpc/linux |
yes | rust >= 1.95.0 |
powerpc64/linux |
yes | rust >= 1.95.0 |
powerpc64le/linux |
yes | rust >= 1.95.0 |
mips32/linux |
no | no rust inline assembly available |
mips64/linux |
no | no rust inline assembly available |
nanomips/linux |
no | no zero-indirection planned |
x86/windows+msvc |
no | no zero-indirection planned |
To disable the native C FFI binding as fallback you can set the environment
variable VALGRIND_REQUESTS_STRATEGY=strict (possible values are: strict,
fallback).
License
Licensed under Apache-2.0 or MIT, at your option.