From 273719c6fb427779eeb8db36eade5609274483a5 Mon Sep 17 00:00:00 2001 From: Zxilly Date: Tue, 3 Jun 2025 01:03:42 +0800 Subject: [PATCH] proc,dwarf: support string constant parse --- pkg/dwarf/godwarf/type.go | 18 ++++++++++++++++++ pkg/proc/bininfo.go | 29 +++++++++++++++++++---------- pkg/proc/eval.go | 15 +++++++++++++-- pkg/proc/variables.go | 12 +++++++----- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/pkg/dwarf/godwarf/type.go b/pkg/dwarf/godwarf/type.go index 6cc1d85b48..50cc950a56 100644 --- a/pkg/dwarf/godwarf/type.go +++ b/pkg/dwarf/godwarf/type.go @@ -151,6 +151,12 @@ type BoolType struct { BasicType } +// A ConstStringType represents a const string type. +type ConstStringType struct { + BasicType + Value string +} + // An AddrType represents a machine address type. type AddrType struct { BasicType @@ -1042,6 +1048,18 @@ func readType(d *dwarf.Data, name string, r *dwarf.Reader, off dwarf.Offset, typ typeCache[off] = t t.Name, _ = e.Val(dwarf.AttrName).(string) + case dwarf.TagStringType: + // String type (DWARF v3 ยง5.10) + // Attributes: + // AttrName: name + // AttrType: type of string [used by gdb to determine the size] + // AttrConstValue: value of string + t := new(ConstStringType) + typ = t + typeCache[off] = t + t.Name, _ = e.Val(dwarf.AttrName).(string) + t.Value, _ = e.Val(dwarf.AttrConstValue).(string) + default: // This is some other type DIE that we're currently not // equipped to handle. Return an abstract "unsupported type" diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go index 722f61b03d..9ba60b768d 100644 --- a/pkg/proc/bininfo.go +++ b/pkg/proc/bininfo.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "go/ast" + "go/constant" "go/token" "hash/crc32" "io" @@ -792,7 +793,7 @@ type constantType struct { type constantValue struct { name string fullName string - value int64 + value constant.Value singleBit bool } @@ -2708,17 +2709,25 @@ func (bi *BinaryInfo) loadDebugInfoMapsCompileUnit(ctxt *loadDebugInfoMapsContex case dwarf.TagConstant: name, okName := entry.Val(dwarf.AttrName).(string) typ, okType := entry.Val(dwarf.AttrType).(dwarf.Offset) - val, okVal := entry.Val(dwarf.AttrConstValue).(int64) - if okName && okType && okVal { - if !cu.isgo { - name = "C." + name + if okName && okType { + var cval constant.Value + switch v := entry.Val(dwarf.AttrConstValue).(type) { + case int64: + cval = constant.MakeInt64(v) + case []byte: + cval = constant.MakeString(string(v)) } - ct := bi.consts[dwarfRef{image.index, typ}] - if ct == nil { - ct = &constantType{} - bi.consts[dwarfRef{image.index, typ}] = ct + if cval != nil { + if !cu.isgo { + name = "C." + name + } + ct := bi.consts[dwarfRef{image.index, typ}] + if ct == nil { + ct = &constantType{} + bi.consts[dwarfRef{image.index, typ}] = ct + } + ct.values = append(ct.values, constantValue{name: name, fullName: name, value: cval}) } - ct.values = append(ct.values, constantValue{name: name, fullName: name, value: val}) } reader.SkipChildren() diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index de0c1cc4bc..6cdbb7f877 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -803,9 +803,20 @@ func (scope *EvalScope) findGlobalInternal(name string) (*Variable, error) { v := newVariable(name, 0x0, t, scope.BinInfo, scope.Mem) switch v.Kind { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v.Value = constant.MakeInt64(cval.value) + if n, ok := constant.Int64Val(cval.value); ok { + v.Value = constant.MakeInt64(n) + } else { + return nil, fmt.Errorf("invalid integer constant %s", name) + } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - v.Value = constant.MakeUint64(uint64(cval.value)) + if n, ok := constant.Uint64Val(cval.value); ok { + v.Value = constant.MakeUint64(n) + } else { + return nil, fmt.Errorf("invalid unsigned constant %s", name) + } + case reflect.String: + v.Value = cval.value + v.Len = int64(len(constant.StringVal(cval.value))) default: return nil, fmt.Errorf("unsupported constant kind %v", v.Kind) } diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index d457b3fe5b..385a549221 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -767,6 +767,8 @@ func newVariable(name string, addr uint64, dwarfType godwarf.Type, bi *BinaryInf v.Kind = reflect.Invalid case *godwarf.UnspecifiedType: v.Kind = reflect.Invalid + case *godwarf.ConstStringType: + v.Kind = reflect.String default: v.Unreadable = fmt.Errorf("unknown type: %T", t) } @@ -2307,11 +2309,11 @@ func (cm constantsMap) Get(typ godwarf.Type) *constantType { if !ctyp.initialized { ctyp.initialized = true slices.SortFunc(ctyp.values, func(a, b constantValue) int { - return cmp.Compare(a.value, b.value) + return cmp.Compare(a.value.ExactString(), b.value.ExactString()) }) for i := range ctyp.values { ctyp.values[i].name = strings.TrimPrefix(ctyp.values[i].name, typepkg) - if bits.OnesCount64(uint64(ctyp.values[i].value)) == 1 { + if v, ok := constant.Int64Val(ctyp.values[i].value); ok && bits.OnesCount64(uint64(v)) == 1 { ctyp.values[i].singleBit = true } } @@ -2321,7 +2323,7 @@ func (cm constantsMap) Get(typ godwarf.Type) *constantType { func (ctyp *constantType) describe(n int64) string { for _, val := range ctyp.values { - if val.value == n { + if v, ok := constant.Int64Val(val.value); ok && v == n { return val.name } } @@ -2338,9 +2340,9 @@ func (ctyp *constantType) describe(n int64) string { if !val.singleBit { continue } - if n&val.value != 0 { + if v, ok := constant.Int64Val(val.value); ok && n&v != 0 { fields = append(fields, val.name) - n = n & ^val.value + n = n & ^v } } if n == 0 {