{"record":{"id":"3372de8ae3f0deb1","repo":"golang/go","slug":"subprogram-die-has-no-low-pc-attr","errorCode":null,"errorMessage":"subprogram DIE has no low_pc attr","messagePattern":"subprogram DIE has no low_pc attr","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/link/internal/dwtest/dwtest.go","lineNumber":211,"sourceCode":"\tfor i, k := range sl {\n\t\tret[i] = ex.entryFromIdx(k)\n\t}\n\treturn ret\n}\n\n// SubprogLoAndHighPc returns the values of the lo_pc and high_pc\n// attrs of the DWARF DIE subprogdie.  For DWARF versions 2-3, both of\n// these attributes had to be of class address; with DWARF 4 the rules\n// were changed, allowing compilers to emit a high PC attr of class\n// constant, where the high PC could be computed by starting with the\n// low PC address and then adding in the high_pc attr offset.  This\n// function accepts both styles of specifying a hi/lo pair, returning\n// the values or an error if the attributes are malformed in some way.\nfunc SubprogLoAndHighPc(subprogdie *dwarf.Entry) (lo uint64, hi uint64, err error) {\n\t// The low_pc attr for a subprogram DIE has to be of class address.\n\tlofield := subprogdie.AttrField(dwarf.AttrLowpc)\n\tif lofield == nil {\n\t\terr = fmt.Errorf(\"subprogram DIE has no low_pc attr\")\n\t\treturn\n\t}\n\tif lofield.Class != dwarf.ClassAddress {\n\t\terr = fmt.Errorf(\"subprogram DIE low_pc attr is not of class address\")\n\t\treturn\n\t}\n\tif lopc, ok := lofield.Val.(uint64); ok {\n\t\tlo = lopc\n\t} else {\n\t\terr = fmt.Errorf(\"subprogram DIE low_pc not convertible to uint64\")\n\t\treturn\n\t}\n\n\t// For the high_pc value, we'll accept either an address or a constant\n\t// offset from lo pc.\n\thifield := subprogdie.AttrField(dwarf.AttrHighpc)\n\tif hifield == nil {\n\t\terr = fmt.Errorf(\"subprogram DIE has no high_pc attr\")","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/link/internal/dwtest/dwtest.go#L193-L229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Filter subprogram DIEs before calling SubprogLoAndHighPc: skip those with DW_AT_declaration=true or an abstract_origin reference.","Check subprogdie.AttrField(dwarf.AttrLowpc) != nil before calling the helper.","If the function is expected to have a body, investigate why the linker emitted a declaration-only DIE."],"exampleFix":"// before\nfor _, d := range subprograms {\n    lo, hi, err := dwtest.SubprogLoAndHighPc(d)\n}\n// after\nfor _, d := range subprograms {\n    if d.AttrField(dwarf.AttrLowpc) == nil {\n        continue // skip declarations / abstract origins\n    }\n    lo, hi, err := dwtest.SubprogLoAndHighPc(d)\n}","handlingStrategy":"validation","validationCode":"if subprogdie.AttrField(dwarf.AttrLowpc) == nil {\n    // declaration or abstract origin — no code address; skip\n    return 0, 0, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter out DW_AT_declaration and abstract-origin subprograms before calling SubprogLoAndHighPc.","Pre-check AttrLowpc presence to avoid the error on declaration-only DIEs."],"tags":["dwarf","go-linker","dwtest","debug-info"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}