go-delve/delve · error
could not read section .gopclntab
Error message
could not read section .gopclntab
What it means
readPcLnTableElf cannot locate the Go pclntab section (.gopclntab) in an ELF binary, nor its PIE-relocated variant (.data.rel.ro.gopclntab). Delve needs this table for Go-runtime function metadata when DWARF-based lookup falls back to runtime tables.
Source
Thrown at pkg/proc/pclntab.go:22
"debug/elf"
"debug/macho"
"errors"
"fmt"
"github.com/go-delve/delve/pkg/internal/gosym"
)
func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, uint64, error) {
// Default section label is .gopclntab
sectionLabel := ".gopclntab"
section := exe.Section(sectionLabel)
if section == nil {
// binary may be built with -pie
sectionLabel = ".data.rel.ro.gopclntab"
section = exe.Section(sectionLabel)
if section == nil {
return nil, 0, errors.New("could not read section .gopclntab")
}
}
tableData, err := section.Data()
if err != nil {
return nil, 0, errors.New("found section but could not read .gopclntab")
}
addr := exe.Section(".text").Addr
lineTable := gosym.NewLineTable(tableData, addr)
symTable, err := gosym.NewTable([]byte{}, lineTable)
if err != nil {
return nil, 0, fmt.Errorf("could not create symbol table from %s ", path)
}
return symTable, section.Addr, nil
}
func readPcLnTableMacho(exe *macho.File, path string) (*gosym.Table, uint64, error) {
// Default section label is __gopclntabView on GitHub (pinned to a23773e6c3)
Solutions
- Verify the binary was produced by the Go toolchain (go version -m <binary>)
- Do not strip Go binaries with external strippers; keep .gopclntab intact
- Rebuild with a supported Go version and without -ldflags that remove runtime sections
- Confirm the binary architecture/format matches what delve was asked to open
Example fix
// before go build -ldflags="-s -w" -o app . && strip app // after go build -o app . // keep pclntab and symbol metadata
Defensive patterns
Strategy: validation
Validate before calling
out, _ := exec.Command("go", "version", "-m", binaryPath).Output()
if !strings.Contains(string(out), "go") {
return fmt.Errorf("%s is not a Go binary", binaryPath)
} Try / catch
_, _, err := loadBinaryInfo(path)
if err != nil && strings.Contains(err.Error(), "could not read section .gopclntab") {
return fmt.Errorf("not a Go-built ELF binary (or pclntab stripped): %w", err)
} Prevention
- Only open Go-built binaries with the Go-runtime symbolization path
- Never strip Go binaries with external strippers (strip/objcopy)
- Match delve's Go version support with the target's toolchain version
When it happens
Trigger: Loading (attach/exec/core) an ELF binary whose symbolization falls back to loadBinaryInfoGoRuntimeElf but that contains neither .gopclntab nor .data.rel.ro.gopclntab — typically a non-Go binary, a stripped Go binary, or one built/linked with an unusual toolchain.
Common situations: Attaching delve to a C/C++ program that happens to be loaded in a mixed-process scenario; analyzing a Go binary stripped with objcopy that removed the section; very old Go versions or cgo-heavy builds with different section layout.
Related errors
- found section but could not read .gopclntab
- could not create symbol table from %s
- ErrCouldNotDetermineRelocation
- ErrNoDebugInfoFound
- unsupported operating system
AI-assisted analysis of go-delve/delve@a23773e6c3 (2026-08-31).
Data as JSON: /api/errors/10ff3459bb2435d1.
Report an issue: GitHub.