Skip to content

Instantly share code, notes, and snippets.

@andreyvit
Created December 5, 2018 13:08
Show Gist options
  • Save andreyvit/76a943202cc09f9aa2bf091e8aed8e52 to your computer and use it in GitHub Desktop.
Save andreyvit/76a943202cc09f9aa2bf091e8aed8e52 to your computer and use it in GitHub Desktop.
A script to filter and summarise the memory map produced by `!address` command in WinDbg (requires Go 1.11)
package main
import (
"bytes"
"flag"
"io/ioutil"
"log"
"strconv"
"strings"
"github.com/dustin/go-humanize"
)
type stats struct {
size uint64
count int
}
func (s *stats) add(size uint64) {
s.count++
s.size += size
}
func main() {
log.SetFlags(0)
flag.Parse()
fn := flag.Arg(0)
data, err := ioutil.ReadFile(fn)
if err != nil {
log.Fatal(err)
}
var total stats
var byUsage = make(map[string]stats)
for _, line := range bytes.Split(data, []byte("\n")) {
if len(bytes.TrimSpace(line)) == 0 {
continue
}
linestr := string(line)
if len(linestr) < 90 {
continue
}
startstr := strings.TrimSpace(linestr[1:10])
endstr := strings.TrimSpace(linestr[11:19])
sizestr := strings.TrimSpace(linestr[20:28])
if sizestr == "RgnSize" || sizestr == "--------" {
continue
}
typestr := strings.TrimSpace(linestr[29:40])
if typestr != "MEM_PRIVATE" {
continue
}
statestr := strings.TrimSpace(linestr[41:52])
if statestr != "MEM_COMMIT" {
continue
}
usagestr := strings.TrimSpace(linestr[88:99])
size, err := strconv.ParseUint(sizestr, 16, 64)
if err != nil {
log.Fatalf("cannot parse %q: %v", sizestr, err)
}
total.add(size)
s := byUsage[usagestr]
s.add(size)
byUsage[usagestr] = s
log.Printf("%d %s %s", size, startstr, endstr)
}
log.Printf("%-12s %5s %11s %7s", "Usage", "Count", "Size", "Size")
log.Print(strings.Repeat("-", 60))
for u, s := range byUsage {
log.Printf("%-12s %5d %11d %7s", u, s.count, s.size, humanize.Bytes(s.size))
}
log.Printf("%-12s %5d %11d %7s", "TOTAL", total.count, total.size, humanize.Bytes(total.size))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment