From 9c449548604bee779e11baae4593e55d6290288f Mon Sep 17 00:00:00 2001 From: Frederic Branczyk Date: Thu, 5 Jan 2023 18:45:55 +0100 Subject: [PATCH] godwarf: Attempt to load `DW_AT_specification` if present (#3247) --- pkg/dwarf/godwarf/tree.go | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/pkg/dwarf/godwarf/tree.go b/pkg/dwarf/godwarf/tree.go index 12008d9e..379da1a9 100644 --- a/pkg/dwarf/godwarf/tree.go +++ b/pkg/dwarf/godwarf/tree.go @@ -24,11 +24,13 @@ func (ce compositeEntry) Val(attr dwarf.Attr) interface{} { return nil } -// LoadAbstractOrigin loads the entry corresponding to the -// DW_AT_abstract_origin of entry and returns a combination of entry and its -// abstract origin. -func LoadAbstractOrigin(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.Offset) { - ao, ok := entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset) +// LoadAbstractOriginAndSpecification loads the entry corresponding to the +// DW_AT_abstract_origin and/or DW_AT_specification of entry and returns a +// combination of entry and its abstract origin. If a DIE has both a +// specification and an abstract origin the specification will be ignored, the +// DWARF standard is unclear on how this should be handled +func LoadAbstractOriginAndSpecification(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.Offset) { + ao, ok := getAbstractOriginOrSpecification(entry) if !ok { return entry, entry.Offset } @@ -43,7 +45,7 @@ func LoadAbstractOrigin(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.O } r = append(r, e) - ao, ok = e.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset) + ao, ok = getAbstractOriginOrSpecification(e) if !ok { break } @@ -52,6 +54,18 @@ func LoadAbstractOrigin(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.O return compositeEntry(r), entry.Offset } +func getAbstractOriginOrSpecification(e *dwarf.Entry) (dwarf.Offset, bool) { + ao, ok := e.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset) + if ok { + return ao, true + } + sp, ok := e.Val(dwarf.AttrSpecification).(dwarf.Offset) + if ok { + return sp, true + } + return dwarf.Offset(0), false +} + // Tree represents a tree of dwarf objects. type Tree struct { Entry @@ -85,7 +99,7 @@ func LoadTree(off dwarf.Offset, dw *dwarf.Data, staticBase uint64) (*Tree, error if err != nil { return nil, err } - r.resolveAbstractEntries(rdr) + r.resolveAbstractAndSpecificationEntries(rdr) return r, nil } @@ -228,10 +242,10 @@ func rangeContains(a, b [2]uint64) bool { return a[0] <= b[0] && a[1] >= b[1] } -func (n *Tree) resolveAbstractEntries(rdr *dwarf.Reader) { - n.Entry, n.Offset = LoadAbstractOrigin(n.Entry.(*dwarf.Entry), rdr) +func (n *Tree) resolveAbstractAndSpecificationEntries(rdr *dwarf.Reader) { + n.Entry, n.Offset = LoadAbstractOriginAndSpecification(n.Entry.(*dwarf.Entry), rdr) for _, child := range n.Children { - child.resolveAbstractEntries(rdr) + child.resolveAbstractAndSpecificationEntries(rdr) } }