Skip to content

proc,dwarf: support string constant parse #4022

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions pkg/dwarf/godwarf/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down
29 changes: 19 additions & 10 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"errors"
"fmt"
"go/ast"
"go/constant"
"go/token"
"hash/crc32"
"io"
Expand Down Expand Up @@ -792,7 +793,7 @@ type constantType struct {
type constantValue struct {
name string
fullName string
value int64
value constant.Value
singleBit bool
}

Expand Down Expand Up @@ -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()

Expand Down
15 changes: 13 additions & 2 deletions pkg/proc/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
12 changes: 7 additions & 5 deletions pkg/proc/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
}
}
Expand All @@ -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
}
}
Expand All @@ -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 {
Expand Down