golang/go · error

subprogram DIE has no low_pc attr

Error message

subprogram DIE has no low_pc attr

What it means

Thrown by SubprogLoAndHighPc (dwtest.go:209-213) when a subprogram DIE has no DW_AT_low_pc attribute (AttrField returns nil). The low_pc address is mandatory for a subprogram with a concrete code range, so its absence means the DIE is malformed or describes an abstract/declaration entity without an address.

Source

Thrown at src/cmd/link/internal/dwtest/dwtest.go:211

	for i, k := range sl {
		ret[i] = ex.entryFromIdx(k)
	}
	return ret
}

// SubprogLoAndHighPc returns the values of the lo_pc and high_pc
// attrs of the DWARF DIE subprogdie.  For DWARF versions 2-3, both of
// these attributes had to be of class address; with DWARF 4 the rules
// were changed, allowing compilers to emit a high PC attr of class
// constant, where the high PC could be computed by starting with the
// low PC address and then adding in the high_pc attr offset.  This
// function accepts both styles of specifying a hi/lo pair, returning
// the values or an error if the attributes are malformed in some way.
func SubprogLoAndHighPc(subprogdie *dwarf.Entry) (lo uint64, hi uint64, err error) {
	// The low_pc attr for a subprogram DIE has to be of class address.
	lofield := subprogdie.AttrField(dwarf.AttrLowpc)
	if lofield == nil {
		err = fmt.Errorf("subprogram DIE has no low_pc attr")
		return
	}
	if lofield.Class != dwarf.ClassAddress {
		err = fmt.Errorf("subprogram DIE low_pc attr is not of class address")
		return
	}
	if lopc, ok := lofield.Val.(uint64); ok {
		lo = lopc
	} else {
		err = fmt.Errorf("subprogram DIE low_pc not convertible to uint64")
		return
	}

	// For the high_pc value, we'll accept either an address or a constant
	// offset from lo pc.
	hifield := subprogdie.AttrField(dwarf.AttrHighpc)
	if hifield == nil {
		err = fmt.Errorf("subprogram DIE has no high_pc attr")

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Filter subprogram DIEs before calling SubprogLoAndHighPc: skip those with DW_AT_declaration=true or an abstract_origin reference.
  2. Check subprogdie.AttrField(dwarf.AttrLowpc) != nil before calling the helper.
  3. If the function is expected to have a body, investigate why the linker emitted a declaration-only DIE.

Example fix

// before
for _, d := range subprograms {
    lo, hi, err := dwtest.SubprogLoAndHighPc(d)
}
// after
for _, d := range subprograms {
    if d.AttrField(dwarf.AttrLowpc) == nil {
        continue // skip declarations / abstract origins
    }
    lo, hi, err := dwtest.SubprogLoAndHighPc(d)
}
Defensive patterns

Strategy: validation

Validate before calling

if subprogdie.AttrField(dwarf.AttrLowpc) == nil {
    // declaration or abstract origin — no code address; skip
    return 0, 0, nil
}

Prevention

When it happens

Trigger: Calling SubprogLoAndHighPc on a DW_AT_subprogram DIE that is an abstract declaration (DW_AT_inline present, no code address) or on an external/imported declaration; DIE produced by a compiler that omits low_pc for functions without a body.

Common situations: Iterating over all subprogram DIEs without filtering out declarations/abstracts; reading a binary with split DWARF where the address lives in a different .o; linker dropped the low_pc during dead-code elimination.

Related errors


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