Documentation
¶
Overview ¶
Package symbol resolves runtime stack addresses captured by ptop's eBPF tracers into human-readable frames (function + file:line). It is the userspace half of issue #54.
The ELF Module core (elf.go) is OS-agnostic: it parses any ELF image with debug/elf and debug/gosym, so it works — and is unit-tested — on every platform. The Symbolizer (proc_linux.go) ties a per-module cache to a live process via /proc/<pid>/maps and is Linux-only (proc_other.go stubs it).
Per-module resolution order: the Go line table (.gopclntab) yields func + file:line for Go binaries and survives symbol stripping; the ELF symbol table (.symtab/.dynsym) yields function names for C/C++; a stripped module degrades gracefully to "module+0xoffset". Modules are parsed once and cached.
Deferred (see #54): C/C++ file:line (DWARF), C++ demangling, and kernel-stack resolution via /proc/kallsyms.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Frame ¶
Frame is a symbolized stack frame.
- Func is "" when the address couldn't be resolved to a function (a stripped non-Go module); Module + Offset still locate it as "lib+0xNN".
- File/Line are populated only for Go modules (via .gopclntab) in this cut. C/C++ file:line needs DWARF, which is deferred (#54 follow-up).
- Offset is module-relative (file vaddr − the module's load base), so it is comparable across runs/ASLR.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module wraps a parsed ELF image and resolves file virtual addresses to Frames. It retains no open file handle (all needed data is read at open time), so it is cheap to cache and safe for concurrent Resolve calls.
func OpenModule ¶
OpenModule parses the ELF image in r. name is used for Frame.Module (its basename) and error messages. r is fully consumed before returning; the caller may close it immediately.
type Symbolizer ¶
type Symbolizer struct {
// contains filtered or unexported fields
}
Symbolizer resolves runtime addresses of a live process to Frames. It parses the process's executable mappings once at construction and lazily opens + caches each backing ELF module on first use.
func NewSymbolizer ¶
func NewSymbolizer(pid int) (*Symbolizer, error)
NewSymbolizer snapshots pid's executable mappings. The set of mapped modules is assumed stable for the lifetime of the symbolizer (true for the steady state ptop observes); dlopen after construction won't be picked up.
func (*Symbolizer) Close ¶
func (s *Symbolizer) Close() error
func (*Symbolizer) ProcessBuildID ¶
func (s *Symbolizer) ProcessBuildID() string
ProcessBuildID returns the GNU build-id (hex) of the target's main executable, or "" if it has none / can't be read. It is a stable per-process key for the stack ids this symbolizer's process hands out: the same stack id denotes a different stack once the binary changes. Computed once, lazily.
func (*Symbolizer) Symbolize ¶
func (s *Symbolizer) Symbolize(addr uint64) Frame
Symbolize resolves a runtime address. It never errors: an address in an unmapped / anonymous / unreadable region degrades to a bare Frame{Offset}.