mirror of
https://github.com/rizsotto/Bear.git
synced 2026-10-07 16:49:04 +02:00
Bear's log output serves two readers, and one format could not serve both. A user running a build wants terse, program-prefixed messages like every other UNIX tool; a developer debugging Bear wants a rich trace that tells apart the driver, wrapper, and preload processes as their lines interleave on one terminal. The old code had three divergent init sites: the driver used env_logger's default format, which tags each line with the Rust module path rather than the process, so a single process spanning many crates was mislabelled; the wrapper and preload each hand-rolled a timestamped format with duplicated epoch math. Replace all three with one shared initializer in the intercept crate (the only dependency common to every binary). It picks a format from the environment: unset RUST_LOG gives the UNIX user view "prog: message" on stderr with warning:/error: qualifiers; a set RUST_LOG gives the developer view tagging every line with a timestamp, level, process identity plus pid, and source module. Process identities are stable: bear, wrapper, preload. Behavior change worth noting for release: the wrapper and preload previously had no explicit default filter (effectively error level); they now default to warn like the driver, so a rare preload warning (non-UTF-8 popen/system command, or a double-init guard) can reach an intercepted compiler's stderr. This is intentional per the new contract. Governed by the new requirement cli-diagnostic-format, verified by unit tests on the format helpers and integration tests on the format switch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dynamic library for Bear interception
This crate provides a dynamic library for Unix systems that can be used with Bear for intercepting system calls via the LD_PRELOAD mechanism (or DYLD_INSERT_LIBRARIES on macOS).
Overview
libexec is designed to work with the Bear compilation database generator. It intercepts system calls like execve to track command execution during builds.
The library is split into a C shim (src/c/shim.c) and Rust implementation (src/implementation.rs). This separation exists because:
- Stable Rust cannot handle C variadic arguments (
execlfamily) - On FreeBSD, libc functions may call each other internally — having all exported symbols in C call into Rust (which uses
dlsym(RTLD_NEXT, ...)) avoids recursive interception issues
Supported Platforms
| Platform | Mechanism | Symbol visibility |
|---|---|---|
| Linux, FreeBSD, OpenBSD, NetBSD, DragonFly BSD | LD_PRELOAD |
ELF version scripts |
| macOS | DYLD_INSERT_LIBRARIES |
-exported_symbols_list |
On unsupported platforms (e.g. Windows), the build displays a warning and skips library generation.
Features
- Intercepts
execfamily calls,posix_spawn,popen, andsystem - Automatically "doctors" child process environments to maintain interception across
execcalls - Reports intercepted executions to a TCP collector
- Platform capability detection at build time (only intercepts functions available on the host)
Building
To build libexec in debug mode:
cargo build -p intercept-preload
For the release version:
cargo build -p intercept-preload --release
The resulting shared library will be in target/debug/libexec.so (or .dylib on macOS) and target/release/libexec.so respectively.