blazesym

repository·main·Indexed 42 days ago

https://github.com/libbpf/blazesym

A high-performance symbolization library used to map memory addresses to human-readable function names and vice versa. Designed for tracing and profiling contexts, it supports DWARF, ELF, Breakpad, and Gsym formats. Written in Rust, it provides first-class C APIs via blazesym-c and Go bindings via blazsym-go, as well as a command-line interface called blazecli. Version 0.2.6.

Tokens
27.5K
Snippets
103
Records
137
Agent score
54%

What's inside blazesym

  1. Overview of blazesym

    main

    blazesym is a library designed for address symbolization, a process used to convert raw memory addresses (e.g., from stacktraces) into human-readable function names. It also supports the reverse operation: looking up addresses from symbol names, which is useful for configuring breakpoints or tracepoints.

    Key characteristics:

    • Batteries-included: Provides sensible defaults for ease of use, with advanced APIs available for performance-critical runtime configuration.
    • Multi-format support: Supports DWARF, ELF, Breakpad, and Gsym formats.
    • Multi-language: Written in Rust with first-class C APIs and Go language bindings.
    • Production-ready: Used at Meta for continuous profiling (Strobelight) and crash dump symbolization.
  2. OS Support for blazesym

    main

    The library's primary target is Linux (supporting most recent kernel versions and distributions).

    MacOS and Windows support is limited to file-based symbolization using Breakpad, Elf, or Gsym sources. Standalone address normalization, as well as process or kernel symbolization, are not supported on these operating systems.

  3. Run benchmarks and enable instruction counting

    main

    Blazesym uses a mix of Criterion and libtest benchmarks.

    Setup: Benchmarks require a one-time setup of large test files via the blazesym-dev package.

    Instruction Counting: On Linux, you can report instruction counts for Criterion benchmarks by enabling the bench-instrs feature.

    Kernel Requirements: Some benchmarks require the PROCMAP_QUERY ioctl. If your kernel supports it, enable these benchmarks by setting the RUSTFLAGS environment variable.

    # 1. One-time setup of required data
    $ cargo check --package blazesym-dev --features=generate-large-test-files
    
    # 2. Run standard benchmarks
    $ cargo bench --features=nightly
    
    # 3. Run benchmarks with instruction counting (Linux)
    $ cargo bench features=nightly,blazesym-dev/bench-instrs
    
    # 4. Enable benchmarks requiring PROCMAP_QUERY ioctl
    $ RUSTFLAGS="--cfg has_procmap_query_ioctl" cargo bench --features=nightly
  4. Generate shell completion for blazecli

    main

    You can generate context-sensitive tab completion scripts for various shells using the shell-complete utility. Once generated, the script can be sourced in your current session or installed system-wide by adding it to initialization files like ~/.bashrc.

    To generate a Bash completion script using cargo:

    1. Run the shell-complete binary with the clap_complete feature enabled.
    2. Redirect the output to a file.
    3. Source that file.
    $ cargo run -p blazecli --bin=shell-complete --features="clap_complete" -- bash > blazecli.bash
    $ source blazecli.bash
  5. Perform allocation profiling

    main

    The crate includes built-in infrastructure for gathering memory allocation statistics and printing backtraces via the allocs test. This is intended for performance-sensitive paths to understand or assert allocation behavior. It is recommended to run a single test rather than the whole suite to avoid multi-threading noise.

    # Run a specific allocation test and print statistics
    $ cargo test --test=allocs -- normalize_process --nocapture
    
    # Run with backtraces enabled
    $ RUST_LIB_BACKTRACE=1 cargo test --test=allocs -- normalize_process --nocapture
  6. Run the blazesym test suite

    main

    Most tests are managed via cargo. Note that tests require sudo privileges because some functionality relies on privileged operations.

    If you are only running tests for the C API bindings (blazesym-c), you must first generate the necessary test artifacts using the blazesym-dev package.

    # Run the full workspace test suite (requires sudo)
    $ cargo test --workspace
    
    # If testing ONLY blazesym-c, run this first to generate artifacts:
    $ cargo check --package blazesym-dev --features=generate-unit-test-files
  7. Use blazecli to symbolize addresses

    main

    The blazecli command-line interface mirrors the blazesym library's API structure. You can use it to resolve addresses to symbols from different sources, such as ELF files or running processes.

    Symbolize an address in an ELF file

    Use the symbolize elf sub-command with the --path flag to specify the target ELF file and provide the address as a positional argument.

    Symbolize an address in a process

    Use the symbolize process sub-command to resolve addresses within a running process. Refer to the program's --help text for specific process-related flags.

    # Example: Symbolize an address in an ELF file
    $ blazecli symbolize elf --path /lib64/libc.so.6 00000000000caee0
    > 0xcaee0: readdir_r@0xcaee0+0 :0
    
    # Example: Running from a cargo checkout without installation
    $ cargo run -p blazecli -- symbolize elf --path /lib64/libc.so.6 00000000000caee0
  8. Build and use the blazesym-c library

    main

    To use the C bindings for blazesym, you must first build the library using the Rust toolchain and Cargo. The build process generates libblazesym_c.a (static) and libblazesym_c.so (shared) in your target directory (e.g., <project-root>/target/debug/).

    To integrate it into your C program:

    1. Include blazesym.h (provided with the crate) in your source code.
    2. Link against the generated library.

    If you are linking statically against libblazesym_c.a, you must also link the following system libraries:

    • -lrt
    • -ldl
    • -lpthread
    • -lm
    # Build the library
    cargo build
    
    # Example linking command for static builds (conceptual)
    gcc my_program.c -L./target/debug -lblazesym_c -lrt -ldl -lpthread -lm
  9. Run Miri for undefined behavior detection

    main

    Miri is used to test the crate for undefined behavior. It is restricted to non-FFI and non-I/O functionality. To avoid conflicts with custom test runners, you should remove the local .cargo/config.toml before running Miri.

    $ rm .cargo/config.toml
    $ MIRIFLAGS='-Zmiri-disable-stacked-borrows' cargo miri test --workspace -- ":miri:"
  10. Generate documentation for docs.rs

    main

    To generate documentation that matches the format and configuration used on docs.rs, use the docsrs configuration flag and enable the required features.

    RUSTDOCFLAGS='--cfg docsrs' cargo doc --open --features="apk,backtrace,breakpad,demangle,dwarf,gsym"
  11. Profile CPU usage with flamegraphs

    main

    You can generate CPU flamegraphs using cargo-flamegraph. You must set RUSTFLAGS="-C force-frame-pointers=yes" to ensure accurate profiling.

    # Profile a specific unit benchmark
    $ RUSTFLAGS="-C force-frame-pointers=yes" cargo flamegraph -o /tmp/flamegraph.svg --cmd 'record -F 997 --call-graph dwarf,64000 -g -o /tmp/perf.dat' --package=blazesym --unit-bench --root --features=nightly -- bench_function_parsing_blazesym
    
    # Profile a Criterion benchmark
    $ RUSTFLAGS="-C force-frame-pointers=yes" cargo flamegraph -o /tmp/flamegraph.svg --cmd 'record -F 997 --call-graph dwarf,64000 -g -o /tmp/perf.dat' --bench=main --root --features=nightly -- symbolize_gsym_multi_no_setup --bench
  12. Configure static linking for blazsym-go

    main

    To avoid requiring blazesym_c.so to be installed on the target system, you can link against blazesym-c statically.

    1. Add -Wl,-Bstatic -lblazesym_c -Wl,-Bdynamic to your CGO_LDFLAGS.
    2. For a fully static build, pass -ldflags='-extldflags "-static"' to the go build or go install command.
    # Static linking via CGO_LDFLAGS
    CGO_LDFLAGS="-Wl,-Bstatic -lblazesym_c -Wl,-Bdynamic" go build
    
    # Fully static build
    go build -ldflags='-extldflags "-static"'