in internal/gocore/process.go [185:273]
func (p *Process) readHeap() {
ptrSize := p.proc.PtrSize()
logPtrSize := p.proc.LogPtrSize()
p.pageTable = map[core.Address]*pageTableEntry{}
mheap := p.rtGlobals["mheap_"]
var arenas []arena
if mheap.HasField("spans") {
// go 1.9 or 1.10. There is a single arena.
arenaStart := core.Address(mheap.Field("arena_start").Uintptr())
arenaUsed := core.Address(mheap.Field("arena_used").Uintptr())
arenaEnd := core.Address(mheap.Field("arena_end").Uintptr())
bitmapEnd := core.Address(mheap.Field("bitmap").Uintptr())
bitmapStart := bitmapEnd.Add(-int64(mheap.Field("bitmap_mapped").Uintptr()))
spanTableStart := mheap.Field("spans").SlicePtr().Address()
spanTableEnd := spanTableStart.Add(mheap.Field("spans").SliceCap() * ptrSize)
arenas = append(arenas, arena{
heapMin: arenaStart,
heapMax: arenaEnd,
bitmapMin: bitmapStart,
bitmapMax: bitmapEnd,
spanTableMin: spanTableStart,
spanTableMax: spanTableEnd,
})
// Copy pointer bits to heap info.
// Note that the pointer bits are stored backwards.
for a := arenaStart; a < arenaUsed; a = a.Add(ptrSize) {
off := a.Sub(arenaStart) >> logPtrSize
if p.proc.ReadUint8(bitmapEnd.Add(-(off>>2)-1))>>uint(off&3)&1 != 0 {
p.setHeapPtr(a)
}
}
} else {
// go 1.11+. Has multiple arenas.
arenaSize := p.rtConstants["heapArenaBytes"]
if arenaSize%heapInfoSize != 0 {
panic("arenaSize not a multiple of heapInfoSize")
}
arenaBaseOffset := p.getArenaBaseOffset()
if ptrSize == 4 && arenaBaseOffset != 0 {
panic("arenaBaseOffset must be 0 for 32-bit inferior")
}
level1Table := mheap.Field("arenas")
level1size := level1Table.ArrayLen()
for level1 := int64(0); level1 < level1size; level1++ {
ptr := level1Table.ArrayIndex(level1)
if ptr.Address() == 0 {
continue
}
level2table := ptr.Deref()
level2size := level2table.ArrayLen()
for level2 := int64(0); level2 < level2size; level2++ {
ptr = level2table.ArrayIndex(level2)
if ptr.Address() == 0 {
continue
}
a := ptr.Deref()
min := core.Address(arenaSize*(level2+level1*level2size) - arenaBaseOffset)
max := min.Add(arenaSize)
bitmap := a.Field("bitmap")
spans := a.Field("spans")
arenas = append(arenas, arena{
heapMin: min,
heapMax: max,
bitmapMin: bitmap.a,
bitmapMax: bitmap.a.Add(bitmap.ArrayLen()),
spanTableMin: spans.a,
spanTableMax: spans.a.Add(spans.ArrayLen() * ptrSize),
})
// Copy out ptr/nonptr bits
n := bitmap.ArrayLen()
for i := int64(0); i < n; i++ {
m := bitmap.ArrayIndex(i).Uint8()
for j := int64(0); j < 8; j++ {
if m>>uint(j)&1 != 0 {
p.setHeapPtr(min.Add((i*8 + j) * ptrSize))
}
}
}
}
}
}
p.readSpans(mheap, arenas)
}