Skip to content

Repository files navigation

usdt - USDT Probe Support for Go and eBPF

A standalone Go library for working with User Statically-Defined Tracepoints (USDTs). Parse USDT probes from ELF binaries, extract argument specifications, and attach eBPF programs to probes at runtime.

Features

  • ELF probe parsing: Read .note.stapsdt sections, apply prelink adjustments, convert virtual addresses to file offsets for uprobe attachment
  • Argument spec parsing: Decode USDT argument specifications (registers, memory dereferences, constants) for x86_64 and ARM64
  • eBPF helpers: BPF-side headers for extracting USDT arguments at runtime (BPF_USDT() macro, bpf_usdt_arg())
  • CLI tool: cmd/usdt for inspecting probes in binaries from the command line

Installation

# Library
go get github.com/parca-dev/usdt

# CLI tool
go install github.com/parca-dev/usdt/cmd/usdt@latest

Library usage

Parse USDT probes from a binary

probes, err := usdt.ParseProbesFromFile("/usr/lib/libc.so.6")
if err != nil {
    log.Fatal(err)
}
for _, p := range probes {
    fmt.Printf("%s:%s at offset 0x%x args=%q\n",
        p.Provider, p.Name, p.Location, p.Arguments)
}

Parse argument specifications

// Parse a USDT argument string like "-4@%esi 8@%rdi"
spec, err := usdt.ParseUSDTArguments("-4@%esi 8@%rdi")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%d arguments\n", spec.Arg_cnt)

Attach BPF programs to probes

// Bring your own BPF objects (e.g. generated by bpf2go from your own .c sources).
probes, _ := usdt.ParseProbesFromFile(exePath)

// Populate the spec map so the BPF side can extract arguments.
specIDs, err := usdt.PopulateSpecMap(myObjs.BpfUsdtSpecs, probes, 1 /*startID*/)

// Optionally merge spec IDs with per-probe user cookies.
cookies := usdt.MergeCookies(specIDs, userCookies)

// Attach one BPF program per probe.
exe, _ := link.OpenExecutable(exePath)
pl, err := usdt.AttachUprobes(exe, myObjs.BpfUsdtSpecs, probes, progs, cookies)
defer pl.Close()

Custom ELF reader

Implement the ELFReader interface to use your own ELF parser:

type ELFReader interface {
    Sections() ([]usdt.ELFSection, error)
    LoadSegments() []usdt.ELFProg
}

probes, err := usdt.ParseProbes(myCustomReader)

eBPF headers

Include in your BPF programs for USDT argument extraction. The headers intentionally pull in nothing — your own prelude (providing u8/u64/ bool/pt_regs/EBPF_INLINE and the BPF helper declarations) must be included first. The bundled ebpf/kernel.h is one such prelude:

#include "kernel.h"     // or your own equivalent
#include "usdt_args.h"

SEC("usdt/myprovider/myprobe")
int BPF_USDT(myprobe, s64 arg0, u64 arg1)
{
    // arg0 and arg1 are automatically extracted
    return 0;
}

usdt_defs.h (struct/enum definitions only) can be included on its own when you just need the userspace-visible layouts without the BPF helpers.

CLI tool

usdt list <binary> [flags]       List USDT probes in an ELF binary
  -provider string               Filter by provider name
  -name     string               Filter by probe name
  -args                          Show raw argument strings

usdt parse-args <arg-string>     Parse a USDT argument specification string

Examples:

# List all probes in a binary
usdt list /usr/bin/python3

# Show probes with their argument strings
usdt list --args /usr/bin/python3

# Filter by provider
usdt list --provider python /usr/bin/python3

# Inspect an argument spec string
usdt parse-args "-4@%esi 8@%rax -4@-24(%rbp)"

Building

# Generate eBPF objects and run tests
make

# Build the CLI tool (output: bin/usdt)
make build

# Regenerate after modifying BPF sources
make generate

# Run tests only
make test

Requirements

  • Go 1.25+
  • clang (for go generate / bpf2go BPF compilation)
  • systemtap-sdt-dev (for test probes, provides sys/sdt.h)
  • Requires Linux 5.15+ for bpf_get_attach_cookie

License

Apache License 2.0. See LICENSE for details.

About

USDT support for Go inspired by libbpf

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages