debug

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package debug wraps a Delve debugger so forge can drive a debugging session from the CLI / MCP layers.

The package exposes two complementary surfaces:

  • DelveDebugger — the rich per-session control surface (breakpoints, execution control, inspection, lifecycle). One implementation today (Delve via rpc2), so callers hold the concrete *DelveDebugger rather than a single-impl interface. Constructed via NewDelveDebugger; callers hold the handle for the duration of a session.

  • Service — the package's behavioral seam: load, save, and clear the persisted SessionInfo on disk. Tests intercept the on-disk session file by injecting a mock Service.

The data carriers (SessionInfo, StopState, Variable, BreakpointInfo, StackFrame, GoroutineInfo) remain plain types — they are not behavior to mock.

Code generated by forge. DO NOT EDIT. forge:hash=5215c89baa6fc4776dbe8dc62d9ba7bbfb26f238611507058bf6ddb71e26332a forge-owned: regenerated every run — do not edit (forge disown to take ownership) Source: contract.go in this package.

To customize: edit contract.go (the interface IS the public surface) and re-run "forge generate". This file is regenerated unconditionally.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BreakpointInfo

type BreakpointInfo struct {
	ID           int    `json:"id"`
	File         string `json:"file"`
	Line         int    `json:"line"`
	FunctionName string `json:"function_name,omitempty"`
	Condition    string `json:"condition,omitempty"`
	HitCount     uint64 `json:"hit_count"`
}

BreakpointInfo describes a breakpoint.

type DelveDebugger

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

DelveDebugger drives a running Delve server via its rpc2 client. It is the package's concrete debugger control surface (breakpoints, execution control, inspection, lifecycle); one implementation today, so callers hold the concrete *DelveDebugger rather than a single-impl interface.

func NewDelveDebugger

func NewDelveDebugger() *DelveDebugger

NewDelveDebugger returns a new, unconnected DelveDebugger.

func (*DelveDebugger) Addr

func (d *DelveDebugger) Addr() string

Addr returns the listen address of the Delve server.

func (*DelveDebugger) Args

func (d *DelveDebugger) Args() ([]Variable, error)

Args returns the function arguments of the current stack frame.

func (*DelveDebugger) ClearBreakpoint

func (d *DelveDebugger) ClearBreakpoint(id int) error

ClearBreakpoint removes the breakpoint with the given ID.

func (*DelveDebugger) Connect

func (d *DelveDebugger) Connect(addr string) error

Connect connects to an already-running Delve instance at addr. It applies a timeout so the caller isn't blocked indefinitely when Delve's RPC handler is stuck (e.g. due to stale CLOSE_WAIT connections).

func (*DelveDebugger) Continue

func (d *DelveDebugger) Continue() (*StopState, error)

Continue resumes execution until the next breakpoint or program exit.

func (*DelveDebugger) Disconnect

func (d *DelveDebugger) Disconnect()

Disconnect closes the RPC connection without killing the debugee.

func (*DelveDebugger) DlvPID

func (d *DelveDebugger) DlvPID() int

DlvPID returns the PID of the dlv server process forge spawned, or 0 when this debugger merely connected to an existing dlv. Tracked so `stop` can reap the dlv server even after the session has been reconnected from disk.

func (*DelveDebugger) Eval

func (d *DelveDebugger) Eval(expr string) (*Variable, error)

Eval evaluates an expression in the current goroutine's scope.

func (*DelveDebugger) Goroutines

func (d *DelveDebugger) Goroutines() ([]GoroutineInfo, error)

Goroutines lists every goroutine known to the debugger.

func (*DelveDebugger) ListBreakpoints

func (d *DelveDebugger) ListBreakpoints() ([]BreakpointInfo, error)

ListBreakpoints returns every breakpoint currently set in the debugger.

func (*DelveDebugger) Locals

func (d *DelveDebugger) Locals() ([]Variable, error)

Locals returns the local variables of the current stack frame.

func (*DelveDebugger) PID

func (d *DelveDebugger) PID() int

PID returns the PID of the debugged (target) process.

func (*DelveDebugger) SetBreakpoint

func (d *DelveDebugger) SetBreakpoint(file string, line int, condition string) (*BreakpointInfo, error)

SetBreakpoint sets a source-line breakpoint with an optional condition.

func (*DelveDebugger) SetFunctionBreakpoint

func (d *DelveDebugger) SetFunctionBreakpoint(funcName string, condition string) (*BreakpointInfo, error)

SetFunctionBreakpoint sets a breakpoint on a function entry by name.

func (*DelveDebugger) Stacktrace

func (d *DelveDebugger) Stacktrace(depth int) ([]StackFrame, error)

Stacktrace returns up to depth stack frames for the current goroutine.

func (*DelveDebugger) Start

func (d *DelveDebugger) Start(ctx context.Context, binary string, args []string, listenPort int) error

Start launches dlv exec in headless mode for the given binary and connects. If listenPort > 0, it is used as the debugger listen port; otherwise a free port is chosen.

func (*DelveDebugger) StartAttach

func (d *DelveDebugger) StartAttach(ctx context.Context, pid int) error

StartAttach launches dlv attach in headless mode for the given PID.

func (*DelveDebugger) StartWithEnv

func (d *DelveDebugger) StartWithEnv(ctx context.Context, binary string, args []string, extraEnv []string, listenPort int) error

StartWithEnv is Start with extra environment variables layered onto the debugged process's environment (os.Environ() + extraEnv, extraEnv wins). Used to inject the SERVICE_NAME / PORT a forge service binary needs to actually serve.

func (*DelveDebugger) StepInto

func (d *DelveDebugger) StepInto() (*StopState, error)

StepInto steps into the call on the current line.

func (*DelveDebugger) StepOut

func (d *DelveDebugger) StepOut() (*StopState, error)

StepOut runs until the current function returns.

func (*DelveDebugger) StepOver

func (d *DelveDebugger) StepOver() (*StopState, error)

StepOver advances to the next source line in the current function.

func (*DelveDebugger) Stop

func (d *DelveDebugger) Stop() error

Stop detaches and kills the debugger process.

type Deps

type Deps struct{}

Deps is the dependency set for the debug Service. Empty today — Delve is invoked via process exec / rpc2 and needs no injected collaborators.

type GoroutineInfo

type GoroutineInfo struct {
	ID          int64  `json:"id"`
	Status      string `json:"status"`
	Function    string `json:"function"`
	CurrentFile string `json:"current_file"`
	CurrentLine int    `json:"current_line"`
}

GoroutineInfo describes a goroutine.

type MockService

type MockService struct {
	contractkit.Recorder
	LoadSessionFunc  func(string) (*SessionInfo, error)
	SaveSessionFunc  func(string, *SessionInfo) error
	ClearSessionFunc func(string) error
}

MockService is a test mock for the Service interface.

The embedded contractkit.Recorder records every call so tests can assert call counts and captured arguments. Set XxxFunc fields to override per-method behaviour; unset methods return the canonical "MockService.<Method>Func not set" error.

func (*MockService) ClearSession

func (m *MockService) ClearSession(dir string) error

func (*MockService) LoadSession

func (m *MockService) LoadSession(dir string) (*SessionInfo, error)

func (*MockService) SaveSession

func (m *MockService) SaveSession(dir string, session *SessionInfo) error

type Service

type Service interface {
	// LoadSession reads .forge/debug-session.json from dir. Returns
	// (nil, nil) when no session file exists.
	LoadSession(dir string) (*SessionInfo, error)

	// SaveSession writes session to dir/.forge/debug-session.json.
	SaveSession(dir string, session *SessionInfo) error

	// ClearSession removes the session file from dir.
	ClearSession(dir string) error
}

Service is the behavioral surface of the debug package.

Session helpers (Load/Save/Clear) hang off this interface so tests can intercept the on-disk session file without touching the filesystem.

func New

func New(_ Deps) Service

New constructs a debug.Service.

type SessionInfo

type SessionInfo struct {
	Type   string `json:"type"`    // "delve"
	Addr   string `json:"addr"`    // e.g. "127.0.0.1:2345"
	PID    int    `json:"pid"`     // debugged (target) process PID
	DlvPID int    `json:"dlv_pid"` // the dlv server process PID forge spawned (0 if unknown)
	Binary string `json:"binary"`  // binary path or service name
	TmpDir string `json:"tmp_dir"` // temp build directory for cleanup
	Docker bool   `json:"docker"`  // true if session is running in a Docker container
	// Owned reports whether forge launched the target process itself
	// (`forge debug start <service>` / `--docker`). When false the session
	// is an ATTACH (`forge debug --attach <pid>`) onto a process forge does
	// not own: `stop` MUST detach the debugger and leave the target alive.
	// Killing an attached target is a data-loss-class bug — it terminated a
	// live admin-server in the field.
	Owned   bool      `json:"owned"`
	Started time.Time `json:"started"`
}

SessionInfo is persisted to .forge/debug-session.json so subsequent debug commands can reconnect to the same debugger.

type StackFrame

type StackFrame struct {
	Function string     `json:"function"`
	File     string     `json:"file"`
	Line     int        `json:"line"`
	Args     []Variable `json:"args,omitempty"`
	Locals   []Variable `json:"locals,omitempty"`
}

StackFrame describes one frame in a stack trace.

type StopState

type StopState struct {
	File        string     `json:"file"`
	Line        int        `json:"line"`
	Function    string     `json:"function"`
	Reason      string     `json:"reason"` // "breakpoint", "step", "next", etc.
	GoroutineID int64      `json:"goroutine_id"`
	Args        []Variable `json:"args,omitempty"`
	Locals      []Variable `json:"locals,omitempty"`
}

StopState describes where the debugger stopped after a continue/step.

type Variable

type Variable struct {
	Name     string     `json:"name"`
	Type     string     `json:"type"`
	Value    string     `json:"value"`
	Children []Variable `json:"children,omitempty"`
}

Variable represents an inspectable variable with optional children.

Jump to

Keyboard shortcuts

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