proc: refactor parseg
Instead of doing a bunch of manual DWARF / memory parsing we instead can just dogfood the internal Variable API to retrieve the G struct.
This commit is contained in:
parent
d9a31dd598
commit
afe77160b0
@ -366,117 +366,54 @@ func (gvar *Variable) parseG() (*G, error) {
|
|||||||
return nil, NoGError{tid: id}
|
return nil, NoGError{tid: id}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if gaddr == 0 {
|
||||||
rdr := dbp.DwarfReader()
|
return nil, NoGError{}
|
||||||
rdr.Seek(0)
|
|
||||||
entry, err := rdr.SeekToTypeNamed("runtime.g")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
gvar.loadValue()
|
||||||
if gtype, err := dbp.dwarf.Type(entry.Offset); err == nil {
|
if gvar.Unreadable != nil {
|
||||||
mem = cacheMemory(mem, uintptr(gaddr), int(gtype.Size()))
|
return nil, gvar.Unreadable
|
||||||
}
|
}
|
||||||
|
schedVar := gvar.toFieldNamed("sched")
|
||||||
// Parse defer
|
pc, _ := constant.Int64Val(schedVar.toFieldNamed("pc").Value)
|
||||||
deferAddr, err := rdr.AddrForMember("_defer", initialInstructions)
|
sp, _ := constant.Int64Val(schedVar.toFieldNamed("sp").Value)
|
||||||
if err != nil {
|
id, _ := constant.Int64Val(gvar.toFieldNamed("goid").Value)
|
||||||
return nil, err
|
gopc, _ := constant.Int64Val(gvar.toFieldNamed("gopc").Value)
|
||||||
|
waitReason := constant.StringVal(gvar.toFieldNamed("waitreason").Value)
|
||||||
|
d := gvar.toFieldNamed("_defer")
|
||||||
|
deferPC := int64(0)
|
||||||
|
fnvar := d.toFieldNamed("fn")
|
||||||
|
if fnvar != nil {
|
||||||
|
fnvalvar := fnvar.toFieldNamed("fn")
|
||||||
|
deferPC, _ = constant.Int64Val(fnvalvar.Value)
|
||||||
}
|
}
|
||||||
var deferPC uint64
|
status, _ := constant.Int64Val(gvar.toFieldNamed("atomicstatus").Value)
|
||||||
// Dereference *defer pointer
|
f, l, fn := gvar.dbp.goSymTable.PCToLine(uint64(pc))
|
||||||
deferAddrBytes, err := mem.readMemory(uintptr(deferAddr), dbp.arch.PtrSize())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error derefing defer %s", err)
|
|
||||||
}
|
|
||||||
if binary.LittleEndian.Uint64(deferAddrBytes) != 0 {
|
|
||||||
initialDeferInstructions := append([]byte{op.DW_OP_addr}, deferAddrBytes...)
|
|
||||||
_, err = rdr.SeekToTypeNamed("runtime._defer")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
deferPCAddr, err := rdr.AddrForMember("fn", initialDeferInstructions)
|
|
||||||
deferPC, err = readUintRaw(mem, uintptr(deferPCAddr), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
deferPC, err = readUintRaw(mem, uintptr(deferPC), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let's parse all of the members we care about in order so that
|
|
||||||
// we don't have to spend any extra time seeking.
|
|
||||||
|
|
||||||
err = rdr.SeekToEntry(entry)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse sched
|
|
||||||
schedAddr, err := rdr.AddrForMember("sched", initialInstructions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// From sched, let's parse PC and SP.
|
|
||||||
sp, err := readUintRaw(mem, uintptr(schedAddr), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pc, err := readUintRaw(mem, uintptr(schedAddr+uint64(dbp.arch.PtrSize())), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Parse atomicstatus
|
|
||||||
atomicStatusAddr, err := rdr.AddrForMember("atomicstatus", initialInstructions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
atomicStatus, err := readUintRaw(mem, uintptr(atomicStatusAddr), 4)
|
|
||||||
// Parse goid
|
|
||||||
goidAddr, err := rdr.AddrForMember("goid", initialInstructions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
goid, err := readIntRaw(mem, uintptr(goidAddr), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Parse waitreason
|
|
||||||
waitReasonAddr, err := rdr.AddrForMember("waitreason", initialInstructions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
waitreason, _, err := readString(mem, dbp.arch, uintptr(waitReasonAddr))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Parse gopc
|
|
||||||
gopcAddr, err := rdr.AddrForMember("gopc", initialInstructions)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gopc, err := readUintRaw(mem, uintptr(gopcAddr), 8)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, l, fn := dbp.goSymTable.PCToLine(pc)
|
|
||||||
g := &G{
|
g := &G{
|
||||||
ID: int(goid),
|
ID: int(id),
|
||||||
GoPC: gopc,
|
GoPC: uint64(gopc),
|
||||||
PC: pc,
|
PC: uint64(pc),
|
||||||
SP: sp,
|
SP: uint64(sp),
|
||||||
CurrentLoc: Location{PC: pc, File: f, Line: l, Fn: fn},
|
WaitReason: waitReason,
|
||||||
WaitReason: waitreason,
|
DeferPC: uint64(deferPC),
|
||||||
DeferPC: deferPC,
|
Status: uint64(status),
|
||||||
Status: atomicStatus,
|
CurrentLoc: Location{PC: uint64(pc), File: f, Line: l, Fn: fn},
|
||||||
dbp: dbp,
|
dbp: gvar.dbp,
|
||||||
}
|
}
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Variable) toFieldNamed(name string) *Variable {
|
||||||
|
v, err := v.structMember(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v.loadValue()
|
||||||
|
if v.Unreadable != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// From $GOROOT/src/runtime/traceback.go:597
|
// From $GOROOT/src/runtime/traceback.go:597
|
||||||
// isExportedRuntime reports whether name is an exported runtime function.
|
// isExportedRuntime reports whether name is an exported runtime function.
|
||||||
// It is only for runtime functions, so ASCII A-Z is fine.
|
// It is only for runtime functions, so ASCII A-Z is fine.
|
||||||
|
Loading…
Reference in New Issue
Block a user