delve/proc/moduledata.go
Alessandro Arzilli 9bc6ad4f46 Go 1.7 compatibility (#524)
* tests: update to cope with go1.7 SSA compiler

* de-vendored golang.org/x/debug/dwarf

We need our own tweaked version

* dwarf/debug/dwarf: always use the entry's name attribute

Using the name attribute leads to better type names as well as fixes
inconsistencies between 1.5, 1.6 and 1.7.

* proc: Updated loadInterface to work with go1.7

go1.7 changed the internal representation of types, removing the string
field from runtime._type.
Updated loadInterface to use the new str field.
2016-05-29 12:20:09 -07:00

88 lines
1.9 KiB
Go

package proc
import (
"go/constant"
)
// delve counterpart to runtime.moduledata
type moduleData struct {
types, etypes uintptr
}
func (dbp *Process) loadModuleData() (err error) {
dbp.loadModuleDataOnce.Do(func() {
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
var md *Variable
md, err = scope.packageVarAddr("runtime.firstmoduledata")
if err != nil {
return
}
for md.Addr != 0 {
var typesVar, etypesVar, nextVar *Variable
var types, etypes uint64
if typesVar, err = md.structMember("types"); err != nil {
return
}
if etypesVar, err = md.structMember("etypes"); err != nil {
return
}
if nextVar, err = md.structMember("next"); err != nil {
return
}
if types, err = typesVar.asUint(); err != nil {
return
}
if etypes, err = etypesVar.asUint(); err != nil {
return
}
dbp.moduleData = append(dbp.moduleData, moduleData{uintptr(types), uintptr(etypes)})
md = nextVar.maybeDereference()
if md.Unreadable != nil {
err = md.Unreadable
return
}
}
})
return
}
func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (uintptr, error) {
// See runtime.resolveNameOff in $GOROOT/src/runtime/type.go
if err := dbp.loadModuleData(); err != nil {
return 0, err
}
for _, md := range dbp.moduleData {
if typeAddr >= md.types && typeAddr < md.etypes {
return md.types + off, nil
}
}
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs")
if err != nil {
return 0, err
}
reflectOffsm, err := reflectOffs.structMember("m")
if err != nil {
return 0, err
}
v, err := reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread))
if err != nil {
return 0, err
}
resv := v.maybeDereference()
if resv.Unreadable != nil {
return 0, resv.Unreadable
}
return resv.Addr, nil
}