golang/go · error

pcln not available in go object file

Error message

pcln not available in go object file

What it means

Go object files (`.o` files produced by the compiler, not linked executables) store line-table data in a format that is read through the `Liner` interface (`PCToLine`, `LineToPC`), not through the `pcln()` method. This stub is implemented solely to satisfy the `rawFile` interface contract and should never be reached by callers. If it is, it indicates a bug in the calling code.

Source

Thrown at src/cmd/internal/objfile/goobj.go:227

	n := ndef + uint32(r.NNonpkgref())
	for i := ndef; i < n; i++ {
		osym := r.Sym(i)
		sym := Sym{Name: osym.Name(r), Code: 'U'}
		syms = append(syms, sym)
	}
	for i := 0; i < nrefName; i++ {
		rn := r.RefName(i)
		sym := Sym{Name: rn.Name(r), Code: 'U'}
		syms = append(syms, sym)
	}

	return syms, nil
}

func (f *goobjFile) pcln() (textStart uint64, pclntab []byte, err error) {
	// Should never be called. We implement Liner below, callers
	// should use that instead.
	return 0, nil, fmt.Errorf("pcln not available in go object file")
}

// PCToLine returns the file name, line, and function data for the given pc.
// Returns "",0,nil if unknown.
// This function implements the Liner interface in preference to pcln() above.
func (f *goobjFile) PCToLine(pc uint64) (string, int, *gosym.Func) {
	r := f.r
	if f.arch == nil {
		return "", 0, nil
	}
	getSymData := func(s goobj.SymRef) []byte {
		if s.PkgIdx != goobj.PkgIdxHashed {
			// We don't need the data for non-hashed symbols, yet.
			panic("not supported")
		}
		i := s.SymIdx + uint32(r.NSym()+r.NHashed64def())
		return r.BytesAt(r.DataOff(i), r.DataSize(i))
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Ensure callers use `File.PCLineTable()` (which returns a `Liner`) instead of directly calling `pcln()` on a `goobjFile`.
  2. If you are modifying `objfile`, check that `goobjFile` implements `Liner` via `PCToLine` and `LineToPC`.
  3. Report this as a Go bug if encountered with an unmodified toolchain.

Example fix

// before — wrong code path reaches pcln()
liner, _ := f.PCLineTable()  // on .o files, this should return Liner
// If internal code mistakenly calls pcln() on goobjFile, fix the dispatch:

// after — use Liner interface
liner, err := f.PCLineTable()
file, line, fn := liner.PCToLine(pc)  // correct path for .o files
Defensive patterns

Strategy: validation

Validate before calling

// Use PCLineTable() which returns Liner, never pcln() directly
func safeGetLiner(f *objfile.File) (objfile.Liner, error) {
    return f.PCLineTable()  // routes correctly for all file types
}

Prevention

When it happens

Trigger: A code path in `objfile` that calls `pcln()` on a `goobjFile` instead of routing through the `Liner` interface. This is an internal invariant violation, not a user-facing configuration problem.

Common situations: Modifying the `objfile` package without respecting the `Liner` interface convention. A regression in the toolchain's internal binary analysis code. Using a forked or patched Go toolchain that broke the caller routing logic.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/2bf0d9694abcc5d9. Report an issue: GitHub.