Skip to content
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())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numbers shouldn't be sorted as string (nor should we do a conversion to string to sort numbers). I think that storing everything as a constant.Value is probably a mistake, strings and ints should stay in different fields.

})
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should be changed to also handle string constants.

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