addrspace

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: 10 Imported by: 0

Documentation

Overview

Package addrspace reads bytes at runtime virtual addresses for the heap-native pprof label decoder. It recovers ordinary runtime/pprof label string bytes that are not stored in heap dump object contents (typical for pprof.Labels("job", "42") where the string headers point into the executable's read-only data segment).

A Reader abstracts "give me size bytes starting at this virtual address". Concrete implementations:

*ProcessReader   — reads the running process address space:
                     Linux: /proc/self/mem (read-only mappings only).
                     FreeBSD: /proc/self/mem when procfs is mounted;
                       otherwise the on-disk ELF executable, which is
                       correct only for non-PIE binaries (PIE shifts
                       the runtime load bias and the ELF fallback does
                       not correct for it).
                     macOS: ASLR-corrected Mach-O executable sections.
                     Windows: ASLR-corrected PE executable sections.
                   Used by /debug/memusage.
*ELFReader       — reads PT_LOAD segments from an ELF executable
                   on disk (offline fallback; non-PIE only).
Composite        — tries readers in order, returning the first hit.

Readers never panic on malformed addresses, never silently truncate, and reject overflowing reads. They return a fresh slice on success so callers may keep the bytes after the reader is closed.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupported = errors.New("addrspace: unsupported on this platform")

ErrUnsupported is returned by constructors that have no implementation for the current platform. Callers should treat it as a soft failure and continue without the reader.

Functions

func AddUint64

func AddUint64(a, b uint64) (uint64, bool)

AddUint64 returns a+b and reports false on uint64 wrap-around.

func ReadString

func ReadString(r Reader, addr uint64, length uint64, max uint64) (string, bool)

ReadString reads a (possibly non-UTF-8) Go string of length bytes starting at addr. length==0 always succeeds with the empty string. length>max fails to bound runaway reads.

func ReadUintptr

func ReadUintptr(r Reader, addr uint64, ptrSize int, order binary.ByteOrder) (uint64, bool)

ReadUintptr reads a ptrSize-wide little-/big-endian unsigned integer at addr. ptrSize must be 4 or 8.

Types

type Composite

type Composite struct {
	Readers []NamedReader
}

Composite tries Readers in order and returns the first successful read. The intended use for heap-label decoding is:

Composite{Readers: []NamedReader{heapRangeReader, processReader}}

so heap dump bytes are preferred when present and the process address space is only consulted to fill in string literals.

func (Composite) Name

func (c Composite) Name() string

Name returns a diagnostic name like "composite[heap,process]".

func (Composite) ReadAtAddr

func (c Composite) ReadAtAddr(addr uint64, size uint64) ([]byte, bool)

ReadAtAddr implements Reader.

func (Composite) SourceFor

func (c Composite) SourceFor(addr uint64, size uint64) (string, bool)

SourceFor returns the Name() of the first reader that satisfies a read of [addr, addr+size). Useful in tests and diagnostics; not required for normal decoding.

type ELFReader

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

ELFReader reads bytes from an ELF executable's PT_LOAD segments at the segment's virtual addresses (Vaddr). It recovers label string literals from the executable's read-only data when no live process memory source is available — including offline analysis and FreeBSD hosts without procfs mounted, where ProcessReader uses it internally as its primary address-space source.

CAVEAT: Position-independent / ASLR-loaded executables run at a base different from their on-disk Vaddrs. Without a load-bias correction, ELF reading is only reliable for non-PIE binaries. On platforms where ProcessReader has a live-memory source (Linux /proc/self/mem, Darwin Mach VM, Windows ReadProcessMemory, or FreeBSD with procfs mounted), that source is preferred because it handles PIE correctly.

func OpenELFReader

func OpenELFReader(path string) (*ELFReader, error)

OpenELFReader opens path, indexes its readable file-backed PT_LOAD segments, and returns a reader. Callers must Close it.

func (*ELFReader) Close

func (r *ELFReader) Close() error

Close releases the underlying executable file.

func (*ELFReader) Name

func (r *ELFReader) Name() string

Name implements NamedReader. It returns "elf:<path>".

func (*ELFReader) ReadAtAddr

func (r *ELFReader) ReadAtAddr(addr uint64, size uint64) ([]byte, bool)

ReadAtAddr implements Reader. It reads only from the file-backed part [Vaddr, Vaddr+Filesz) of each segment; addresses inside the BSS-only tail [Vaddr+Filesz, Vaddr+Memsz) return false.

func (*ELFReader) Segments

func (r *ELFReader) Segments() []ELFSegment

Segments returns a copy of the indexed PT_LOAD segments.

type ELFSegment

type ELFSegment struct {
	Vaddr  uint64
	Memsz  uint64
	Filesz uint64
	Off    uint64
	Flags  elf.ProgFlag
}

ELFSegment is the file-backed portion of a PT_LOAD segment that ELFReader can satisfy reads from.

type Mapping

type Mapping struct {
	Start uint64
	End   uint64
	Read  bool
	Write bool
	Exec  bool
	Path  string
}

Mapping describes a contiguous virtual address range with its permission flags and optional backing path. On Linux this maps directly to a /proc/<pid>/maps entry; on other platforms it is used as a generic segment descriptor where applicable.

type NamedReader

type NamedReader interface {
	Reader
	Name() string
}

NamedReader is a Reader that knows what to call itself in diagnostics (e.g. "heap", "process", "elf:./server"). Composite.SourceFor reports the first reader that satisfies a given read.

type ProcessReader

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

ProcessReader reads bytes from the current process's address space via /proc/self/mem, gated by the readable mappings reported in /proc/self/maps. It is intended for the in-process /debug/memusage handler so the heap-label decoder can recover ordinary runtime/pprof string literals that live in read-only program data.

func OpenSelfProcessReader

func OpenSelfProcessReader() (*ProcessReader, error)

OpenSelfProcessReader opens /proc/self/mem and parses /proc/self/maps. Callers must Close the returned reader.

func (*ProcessReader) Close

func (r *ProcessReader) Close() error

Close releases the underlying /proc/self/mem file.

func (*ProcessReader) EligibleStringRanges added in v0.2.0

func (r *ProcessReader) EligibleStringRanges() []Mapping

EligibleStringRanges returns the runtime virtual-address ranges this reader would serve ReadAtAddr from (the read-only mappings eligible for string literal bytes). Used to snapshot those ranges into an external-analyser bundle. The slice is safe to mutate.

func (*ProcessReader) Mappings

func (r *ProcessReader) Mappings() []Mapping

Mappings returns a copy of the readable mappings the reader is aware of. Useful in diagnostics; the slice is safe to mutate.

func (*ProcessReader) Name

func (r *ProcessReader) Name() string

Name implements NamedReader.

func (*ProcessReader) ReadAtAddr

func (r *ProcessReader) ReadAtAddr(addr uint64, size uint64) ([]byte, bool)

ReadAtAddr implements Reader. It only succeeds when the requested [addr, addr+size) range lies entirely inside a single eligible mapping; cross-mapping reads return false.

func (*ProcessReader) Source

func (r *ProcessReader) Source() string

Source returns a human-readable description of which backing source the reader is using. Used for diagnostics (e.g. by cmd/labeloffsetprobe).

type Reader

type Reader interface {
	ReadAtAddr(addr uint64, size uint64) ([]byte, bool)
}

Reader reads bytes at a runtime virtual address.

Implementations MUST:

  • Return ok=true and an empty slice when size == 0.
  • Return ok=false when addr == 0 and size > 0.
  • Return ok=false when addr + size overflows uint64.
  • Never panic; return ok=false for any unreadable range.
  • Return a fresh copy or a read-only view; callers MUST NOT modify the returned bytes, and may retain them after the call.

Jump to

Keyboard shortcuts

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