in internal/gocore/process.go [644:708]
func (p *Process) readFrame(sp, pc core.Address) (*Frame, error) {
f := p.funcTab.find(pc)
if f == nil {
return nil, fmt.Errorf("cannot find func for pc=%#x", pc)
}
off := pc.Sub(f.entry)
size, err := f.frameSize.find(off)
if err != nil {
return nil, fmt.Errorf("cannot read frame size at pc=%#x: %v", pc, err)
}
size += p.proc.PtrSize() // TODO: on amd64, the pushed return address
frame := &Frame{f: f, pc: pc, min: sp, max: sp.Add(size)}
// Find live ptrs in locals
live := map[core.Address]bool{}
if x := int(p.rtConstants["_FUNCDATA_LocalsPointerMaps"]); x < len(f.funcdata) {
locals := region{p: p, a: f.funcdata[x], typ: p.findType("runtime.stackmap")}
n := locals.Field("n").Int32() // # of bitmaps
nbit := locals.Field("nbit").Int32() // # of bits per bitmap
idx, err := f.stackMap.find(off)
if err != nil {
return nil, fmt.Errorf("cannot read stack map at pc=%#x: %v", pc, err)
}
if idx < 0 {
idx = 0
}
if idx < int64(n) {
bits := locals.Field("bytedata").a.Add(int64(nbit+7) / 8 * idx)
base := frame.max.Add(-16).Add(-int64(nbit) * p.proc.PtrSize())
// TODO: -16 for amd64. Return address and parent's frame pointer
for i := int64(0); i < int64(nbit); i++ {
if p.proc.ReadUint8(bits.Add(i/8))>>uint(i&7)&1 != 0 {
live[base.Add(i*p.proc.PtrSize())] = true
}
}
}
}
// Same for args
if x := int(p.rtConstants["_FUNCDATA_ArgsPointerMaps"]); x < len(f.funcdata) {
args := region{p: p, a: f.funcdata[x], typ: p.findType("runtime.stackmap")}
n := args.Field("n").Int32() // # of bitmaps
nbit := args.Field("nbit").Int32() // # of bits per bitmap
idx, err := f.stackMap.find(off)
if err != nil {
return nil, fmt.Errorf("cannot read stack map at pc=%#x: %v", pc, err)
}
if idx < 0 {
idx = 0
}
if idx < int64(n) {
bits := args.Field("bytedata").a.Add(int64(nbit+7) / 8 * idx)
base := frame.max
// TODO: add to base for LR archs.
for i := int64(0); i < int64(nbit); i++ {
if p.proc.ReadUint8(bits.Add(i/8))>>uint(i&7)&1 != 0 {
live[base.Add(i*p.proc.PtrSize())] = true
}
}
}
}
frame.Live = live
return frame, nil
}