From 436fed8ec49a19f2f0cfd84dbbd54464588f4969 Mon Sep 17 00:00:00 2001 From: Frederic Branczyk Date: Tue, 31 Jan 2023 17:40:19 +0100 Subject: [PATCH] godwarf: Allow extracting a DWARF entry's field (#3258) Previously it was only possible to extract a value of type `any` using an attribute name. This poses challenges when fields are allowed to have different classes, and it is ambiguous how to handle them. --- pkg/dwarf/godwarf/tree.go | 12 ++++++++++-- pkg/proc/fncall.go | 20 ++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/pkg/dwarf/godwarf/tree.go b/pkg/dwarf/godwarf/tree.go index 379da1a9..b9be92ba 100644 --- a/pkg/dwarf/godwarf/tree.go +++ b/pkg/dwarf/godwarf/tree.go @@ -11,14 +11,22 @@ import ( // entry specified by DW_AT_abstract_origin will be searched recursively. type Entry interface { Val(dwarf.Attr) interface{} + AttrField(dwarf.Attr) *dwarf.Field } type compositeEntry []*dwarf.Entry func (ce compositeEntry) Val(attr dwarf.Attr) interface{} { + if f := ce.AttrField(attr); f != nil { + return f.Val + } + return nil +} + +func (ce compositeEntry) AttrField(a dwarf.Attr) *dwarf.Field { for _, e := range ce { - if r := e.Val(attr); r != nil { - return r + if f := e.AttrField(a); f != nil { + return f } } return nil diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go index 5f378a00..31a0332b 100644 --- a/pkg/proc/fncall.go +++ b/pkg/proc/fncall.go @@ -1248,9 +1248,17 @@ func debugCallProtocolReg(archName string, version int) (uint64, bool) { } } -type fakeEntry map[dwarf.Attr]interface{} +type fakeEntry map[dwarf.Attr]*dwarf.Field func (e fakeEntry) Val(attr dwarf.Attr) interface{} { + if e[attr] == nil { + return nil + } + + return e[attr].Val +} + +func (e fakeEntry) AttrField(attr dwarf.Attr) *dwarf.Field { return e[attr] } @@ -1273,11 +1281,11 @@ func regabiMallocgcWorkaround(bi *BinaryInfo) ([]*godwarf.Tree, error) { if err1 != nil { return nil } - var e fakeEntry = map[dwarf.Attr]interface{}{ - dwarf.AttrName: name, - dwarf.AttrType: typ.Common().Offset, - dwarf.AttrLocation: []byte{byte(op.DW_OP_reg0) + byte(reg)}, - dwarf.AttrVarParam: isret, + var e fakeEntry = map[dwarf.Attr]*dwarf.Field{ + dwarf.AttrName: &dwarf.Field{Attr: dwarf.AttrName, Val: name, Class: dwarf.ClassString}, + dwarf.AttrType: &dwarf.Field{Attr: dwarf.AttrType, Val: typ.Common().Offset, Class: dwarf.ClassReference}, + dwarf.AttrLocation: &dwarf.Field{Attr: dwarf.AttrLocation, Val: []byte{byte(op.DW_OP_reg0) + byte(reg)}, Class: dwarf.ClassBlock}, + dwarf.AttrVarParam: &dwarf.Field{Attr: dwarf.AttrVarParam, Val: isret, Class: dwarf.ClassFlag}, } return &godwarf.Tree{