gocore: ignore unmapped parts of spans

If part of a span is not backed by physical memory (because it hasn't been
touched yet, or it has been MADV_DONTNEEDed), don't count that part
toward space used.

Change-Id: I35db31f5ea56b6fdb0d6d652dc7f1763f75c28a8
Reviewed-on: https://go-review.googlesource.com/106117
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/gocore/process.go b/gocore/process.go
index d618566..5a88ef6 100644
--- a/gocore/process.go
+++ b/gocore/process.go
@@ -339,7 +339,6 @@
 		panic(fmt.Sprintf("page size not a multiple of %d", heapInfoSize))
 	}
 	allspans := mheap.Field("allspans")
-	var allSpanSize int64
 	var freeSpanSize int64
 	var releasedSpanSize int64
 	var manualSpanSize int64
@@ -357,7 +356,16 @@
 		nPages := int64(s.Field("npages").Uintptr())
 		spanSize := nPages * pageSize
 		max := min.Add(spanSize)
-		allSpanSize += spanSize
+		for a := min; a != max; a = a.Add(pageSize) {
+			if !p.proc.Readable(a) {
+				// Sometimes allocated but not yet touched pages or
+				// MADV_DONTNEEDed pages are not written
+				// to the core file.  Don't count these pages toward
+				// space usage (otherwise it can look like the heap
+				// is larger than the total memory used).
+				spanSize -= pageSize
+			}
+		}
 		switch s.Field("state").Uint8() {
 		case spanInUse:
 			inUseSpanSize += spanSize