heaplabels

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

Documentation

Overview

Package heaplabels prototypes recovery of runtime/pprof goroutine labels directly from the heap dump's runtime.g objects.

This package intentionally depends on runtime-internal layouts. It is an experiment: callers must provide or discover the runtime.g.labels offset, and every failure is reported explicitly rather than silently falling back.

Index

Constants

View Source
const (
	DefaultMaxLabels    = 1024
	DefaultMaxStringLen = 1 << 20
)

Variables

This section is empty.

Functions

func DecodeLabelMap

func DecodeLabelMap(structuralReader addrspace.Reader, bodyReader addrspace.Reader, layout runtimelayout.Layout, opts Options, addr uint64) (map[string]string, error)

DecodeLabelMap walks a labelMap pointed to by addr and returns its flattened key/value map.

structuralReader covers heap dump object contents and is used for all structural reads (labelMap, slice header, label array, string headers). bodyReader is used only for string body bytes and may fall through to process/ELF memory. Pass structuralReader as bodyReader when no fallback is needed.

func DecodeString

func DecodeString(structuralReader addrspace.Reader, bodyReader addrspace.Reader, layout runtimelayout.Layout, opts Options, headerAddr uint64) (string, error)

DecodeString reads a Go string header at headerAddr and returns the referenced bytes.

structuralReader (heap-only) is used for the string header itself (data pointer and length fields). bodyReader is used for the actual string bytes and may fall through to process/ELF memory where literal label strings reside. Pass structuralReader as bodyReader when no fallback is needed.

func FormatLabels

func FormatLabels(labels map[string]string) []string

func LookupInputFromSnapshot

func LookupInputFromSnapshot(snap *heapsnapshot.HeapSnapshot) runtimelayout.LookupInput

LookupInputFromSnapshot extracts the runtime-layout lookup key from a parsed heap snapshot. Callers pass the result to runtimelayout.Lookup (or runtimelayout.Manual for debug CLIs).

Types

type DecodeStatus

type DecodeStatus string
const (
	StatusDecoded             DecodeStatus = "decoded"
	StatusNoLabels            DecodeStatus = "no_labels"
	StatusUnsupportedRuntime  DecodeStatus = "unsupported_runtime"
	StatusGObjectMissing      DecodeStatus = "g_object_missing"
	StatusLabelsObjectMissing DecodeStatus = "labels_object_missing"
	StatusLabelArrayMissing   DecodeStatus = "label_array_missing"
	StatusStringMissing       DecodeStatus = "string_missing"
	StatusMalformed           DecodeStatus = "malformed"
)

type GoroutineResult

type GoroutineResult struct {
	GID       uint64
	GAddr     uint64
	LabelsPtr uint64

	Labels map[string]string

	Status DecodeStatus
	Error  string
}

func DecodeLabelsForGoroutine

func DecodeLabelsForGoroutine(structuralReader addrspace.Reader, bodyReader addrspace.Reader, layout runtimelayout.Layout, opts Options, g heapsnapshot.Goroutine) GoroutineResult

DecodeLabelsForGoroutine decodes a single goroutine's labels.

structuralReader must cover heap dump object contents and is used for all structural reads (runtime.g pointer, labelMap, slice headers, string headers). bodyReader is used only for string body bytes and may be a composite that falls through to process/ELF memory for literal label strings. Pass structuralReader as bodyReader when no fallback is needed.

type Memory

type Memory struct {
	// contains filtered or unexported fields
}

Memory exposes a heap snapshot's per-object contents as an address-indexed byte source. It implements addrspace.Reader (and addrspace.NamedReader). Structural label reads (runtime.g, labelMap, slice headers, string headers) use a Memory directly; string body reads may use a composite that falls through to ExtraStringMemory.

Memory has two source modes. The eager mode (NewMemory) indexes snap.Objects[i].Contents directly; the lazy mode (NewMemoryFromReader) delegates every address-keyed read to an external addrspace.Reader — in practice, the *heapdump.ContentResolver produced by heapdump.ParseLazyContents, which fetches object bytes from the dump file on demand instead of holding them all in the Go heap.

func NewMemory

func NewMemory(snap *heapsnapshot.HeapSnapshot) *Memory

NewMemory builds a Memory from a parsed heap snapshot. Objects without retained contents are skipped; ranges whose addr+size overflows uint64 are skipped defensively.

func NewMemoryFromReader

func NewMemoryFromReader(r addrspace.Reader) *Memory

NewMemoryFromReader builds a Memory whose address-keyed reads are satisfied by r. This is the lazy path: r is expected to be a *heapdump.ContentResolver that fetches heap object bytes from the dump file on demand. Compared with NewMemory, this avoids retaining every object's content bytes in the Go heap.

A nil reader produces a Memory whose Read always returns ok=false.

func (*Memory) Name

func (m *Memory) Name() string

Name implements addrspace.NamedReader. The diagnostic name "heap" distinguishes this source from process/elf memory when a Composite reports SourceFor.

func (*Memory) Read

func (m *Memory) Read(addr uint64, size uint64) ([]byte, bool)

Read returns the byte slice at [addr, addr+size). It returns ok=true with an empty slice on size==0, and ok=false on addr==0 (size>0), overflow, or a range that crosses a heap object boundary.

func (*Memory) ReadAtAddr

func (m *Memory) ReadAtAddr(addr uint64, size uint64) ([]byte, bool)

ReadAtAddr implements addrspace.Reader.

func (*Memory) ReadString

func (m *Memory) ReadString(addr uint64, length uint64) (string, bool)

ReadString reads length bytes at addr as a Go string. length==0 is always ok; otherwise the bytes must lie inside a single heap object.

func (*Memory) ReadUintptr

func (m *Memory) ReadUintptr(addr uint64, ptrSize int, order binary.ByteOrder) (uint64, bool)

ReadUintptr decodes a ptrSize-wide unsigned integer at addr.

type OffsetCandidate

type OffsetCandidate struct {
	Offset       uint64
	Matches      int
	GoroutineIDs []uint64
}

func FindOffsetCandidates

func FindOffsetCandidates(snap *heapsnapshot.HeapSnapshot, mem *Memory, want map[string]string, opts Options) []OffsetCandidate

FindOffsetCandidates is a debug/diagnostic helper used by the labeloffsetprobe binary and offline offset probes. It scans each goroutine's runtime.g object contents for a pointer that, when interpreted as a labelMap address, yields a label map containing the requested label key/value pairs.

The scan works on little-endian targets (both 32-bit and 64-bit); on big-endian it returns an empty slice. Callers must treat candidates as candidates, never as verified offsets.

type Options

type Options struct {
	MaxLabels    uint64
	MaxStringLen uint64

	// ExtraStringMemory is an optional secondary address-space reader
	// consulted only when reading string body bytes (key or value
	// characters) that live outside heap dump object contents. The
	// decoder uses the heap-only reader for all structural reads
	// (runtime.g, labelMap, slice headers, string headers);
	// ExtraStringMemory is consulted solely for the raw bytes that
	// follow a located string header.
	//
	// Typical use: set to addrspace.ProcessReader for the in-process
	// /debug/memusage handler so ordinary pprof.Labels("job","42")
	// string literals (which live in executable read-only data) are
	// recovered. Nil disables the fallback.
	ExtraStringMemory addrspace.Reader

	// HeapMemory, when non-nil, replaces the Memory that DecodeAll would
	// otherwise build internally from snap.Objects. Use this with the
	// lazy parse path (heapdump.ParseLazyContents) so structural reads
	// hit a ContentResolver-backed Memory instead of materialized object
	// content bytes.
	HeapMemory *Memory
}

Options tunes decoding limits applied to every goroutine. Runtime layout (offsets / pointer width) is supplied separately as a runtimelayout.Layout argument.

type Range

type Range struct {
	Start uint64
	End   uint64
	Data  []byte
	Kind  string
}

Range is a contiguous mapping of bytes at virtual addresses [Start, End). End is exclusive: Start+len(Data) == End.

type Result

type Result struct {
	LabelsByGID map[uint64]map[string]string
	Goroutines  []GoroutineResult
	Stats       Stats
	Warnings    []string
}

func DecodeAll

func DecodeAll(snap *heapsnapshot.HeapSnapshot, layout runtimelayout.Layout, opts Options) Result

DecodeAll decodes pprof labels for every goroutine in snap using the supplied runtime layout. The layout must come from runtimelayout.Lookup (verified) or runtimelayout.Manual (debug CLI / test); the decoder itself never guesses offsets.

Use DecodeAllAuto for the common case where the caller wants the verified-table lookup applied implicitly.

func UnsupportedResult

func UnsupportedResult(snap *heapsnapshot.HeapSnapshot, message string) Result

UnsupportedResult builds a Result that reports every goroutine as unsupported_runtime with the supplied diagnostic. /debug/memusage uses this so the unsupported message is consistent across callers.

func (Result) PrintSummary

func (r Result) PrintSummary(w io.Writer)

type Stats

type Stats struct {
	GoroutinesTotal       int
	GoroutinesDecoded     int
	GoroutinesNoLabels    int
	GoroutinesUnsupported int
	GoroutinesFailed      int

	LabelsTotal    int
	StringsMissing int
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL