func()

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
}