func (rt *RuntimeLibrary) foreachGCPointer(v Value, fn func(ptrValue uint64)) {
	ptrSize := uint64(rt.Arch.PointerSize)
	endAddr := v.Addr + v.Size()
	startAddr := roundUp(v.Addr, ptrSize)
	if startAddr >= endAddr {
		return
	}
	if heapObj, ok := rt.FindHeapObject(v.Addr); ok {
		bv := rt.gcHeapBitvectorForObject(heapObj)
		bv.foreachPointer(startAddr, endAddr-startAddr, fn)
		return
	}
	for _, md := range rt.moduledatas {
		if md.data.contains(startAddr) {
			md.gcdatabv.foreachPointer(startAddr, endAddr-startAddr, fn)
			return
		}
		if md.bss.contains(startAddr) {
			md.gcbssbv.foreachPointer(startAddr, endAddr-startAddr, fn)
			return
		}
		if md.noptrdata.contains(startAddr) || md.noptrbss.contains(startAddr) {
			return
		}
	}
	findStack := func(gs []*Goroutine) *gcBitvector {
		for _, g := range gs {
			for sf := g.Stack; sf != nil; sf = sf.Callee {
				if sf.argsBV.contains(startAddr) {
					return sf.argsBV
				}
				if sf.localsBV.contains(startAddr) {
					return sf.localsBV
				}
			}
		}
		return nil
	}
	bv := findStack(rt.Program.Goroutines)
	if bv == nil {
		bv = findStack(rt.Goroutines)
	}
	if bv != nil {
		bv.foreachPointer(startAddr, endAddr-startAddr, fn)
	}
}
foreachGCPointer calls fn with each GC-visible pointer in Value.
The Value is assumed to be derived from a single program value
(i.e., a single Var or heap object).
package corefile
import (
	"errors"
	"fmt"
	"golang.org/x/debug/arch"
)
type OSThread struct {
	PID    uint64             
	GPRegs map[string]uint64  
	M       Value       
	CurG    *Goroutine  
	G0      *Goroutine  
	GSignal *Goroutine  
}
type RuntimeLibrary struct {
	Arch    arch.Architecture  
	Version string             
	GOARCH  string             
	GOOS    string             
	Program    *Program      
	Goroutines []*Goroutine  
	Threads    []*OSThread   
	Vars       *VarSet       
	Finalizers runtimeFinalizers
	GCRoots runtimeGCRoots
	HeapObjects runtimeHeapObjects
	moduledatas []*runtimeModuleData  
	mheapArena  dataSegment           
	mheapBitmap dataSegment           
	mheapSpans  Value                 
	mspantypeType       Type         
	mspanStartAddrField StructField  
	mspanNpagesField    StructField  
	mspanFreeindexField StructField  
	mspanNelemsField    StructField  
	mspanAllocBitsField StructField  
	mspanStateField     StructField  
	mspanElemsizeField  StructField  
	mspanLimitField     StructField  
	itabTypeField              StructField  
	typeType                   Type         
	typeSizeField              StructField  
	typeKindField              StructField  
	typeTflagField             StructField  
	typeStrField               StructField  
	arraytypeType              Type         
	arraytypeLenField          StructField  
	arraytypeElemField         StructField  
	ptrtypeType                Type         
	ptrtypeElemField           StructField  
	structtypeType             Type         
	structtypeFieldsField      StructField  
	structfieldType            Type         
	structfieldNameField       StructField  
	structfieldTypeField       StructField  
	structfieldOffsetAnonField StructField  
	interfacetypeType          Type         
	slicetypeType              Type         
	slicetypeElemField         StructField  
	chantypeType               Type         
	chantypeDirField           StructField  
	chantypeElemField          StructField  
	maptypeType                Type         
	maptypeKeyField            StructField  
	maptypeElemField           StructField  
	uncommontypeType           Type         
	uncommontypePkgPathField   StructField  
	sliceRepType               *StructType  
	chanRepType                *PtrType     
	mapRepType                 *PtrType     
	funcType           *StructType  
	findfuncbucketType *StructType  
	ptrToStackmapType  *PtrType     
}
type runtimeFinalizers struct{ p *Program }
type runtimeGCRoots struct{ p *Program }
type runtimeHeapObjects struct{ p *Program }
type RegisteredFinalizer struct {
	Obj Value  
	Fn  Value  
}
type runtimeMSpan struct {
	base      uint64
	npages    uint64
	freeindex uint64
	nelems    uint64
	allocBits dataSegment
	state     uint64
	elemsize  uint64
	limit     uint64
}
func (rt *RuntimeLibrary) readMSpan(idx uint64) (*runtimeMSpan, error) {
	spanPtr, err := rt.mheapSpans.Index(idx)
	if err != nil {
		logf("unexpected error in mheap.spans[%d]: %v", idx, err)
		return nil, err
	}
	if spanPtr.IsZero() {
		return nil, ErrNil
	}
	span, err := spanPtr.Deref()
	if err != nil {
		logf("unexpected error in *mheap.spans[%d] (0x%x): %v", idx, spanPtr.ReadUint(), err)
		return nil, err
	}
	s := &runtimeMSpan{}
	var allocBitsAddr uint64
	fields := []struct {
		x *uint64
		f StructField
	}{
		{&s.base, rt.mspanStartAddrField},
		{&s.npages, rt.mspanNpagesField},
		{&s.freeindex, rt.mspanFreeindexField},
		{&s.nelems, rt.mspanNelemsField},
		{&allocBitsAddr, rt.mspanAllocBitsField},
		{&s.state, rt.mspanStateField},
		{&s.elemsize, rt.mspanElemsizeField},
		{&s.limit, rt.mspanLimitField},
	}
	for _, f := range fields {
		*f.x, err = span.ReadUintField(f.f)
		if err != nil {
			return nil, err
		}
	}
	var ok bool
	s.allocBits, ok = rt.Program.dataSegments.slice(allocBitsAddr, (s.nelems+7)/8)
	if !ok {
		err := fmt.Errorf("could not load mheap.spans[%d].allocBits from mspan 0x%x, allocBits 0x%x, nelem %d",
			idx, spanPtr.ReadUint(), allocBitsAddr, s.nelems)
		logf("unexpected error: %v", err)
		return nil, err
	}
	return s, nil
}
func (rt *RuntimeLibrary) FindHeapObject(targetAddr uint64) (Value, bool) {
	if !rt.mheapArena.contains(targetAddr) {
		return Value{}, false
	}
	const _PageShift = 13  
	const _MSpanInUse = 1  
	spanIdx := (targetAddr - rt.mheapArena.addr) >> _PageShift
	span, err := rt.readMSpan(spanIdx)
	if err != nil || targetAddr < span.base || targetAddr >= span.limit || span.state != _MSpanInUse {
		return Value{}, false
	}
	objIdx := (targetAddr - span.base) / span.elemsize
	if objIdx >= span.freeindex {
		return Value{}, false
	}
	mask := uint8(1) << (objIdx % 8)
	if isFree := (span.allocBits.data[objIdx/8] & mask) == 0; isFree {
		return Value{}, false
	}
	baseAddr := span.base + objIdx*span.elemsize
	obj, err := rt.Program.Value(baseAddr, rt.Program.MakeGCObjectType(span.elemsize))
	if err != nil {
		logf("unexpected error loading value from 0x%x, size 0x%x: %v", baseAddr, span.elemsize, err)
		return Value{}, false
	}
	return obj, true
}
func (rt *RuntimeLibrary) gcHeapBitvectorForObject(v Value) gcHeapBitvector {
	ptrSize := uint64(rt.Arch.PointerSize)
	return makeGCHeapBitvector(rt.mheapArena.addr, v.Addr, v.Size(), ptrSize, rt.mheapBitmap.data)
}