summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-08-28 15:21:06 -0700
committerOri Bernstein <ori@eigenstate.org>2016-08-28 15:21:06 -0700
commit2216e4b75b74784ba691af9492db3d449b41c361 (patch)
tree9bdd9ffd8e93199c77237d544745aadfe17b96f7 /support
parentb2ca8481f37bccdd0488cf7de05ea79cd17ae5ed (diff)
downloadmc-2216e4b75b74784ba691af9492db3d449b41c361.tar.gz
Add support for leak tracing.
Diffstat (limited to 'support')
-rw-r--r--support/dumpleak.myr103
1 files changed, 103 insertions, 0 deletions
diff --git a/support/dumpleak.myr b/support/dumpleak.myr
new file mode 100644
index 0000000..06a4953
--- /dev/null
+++ b/support/dumpleak.myr
@@ -0,0 +1,103 @@
+use std
+use bio
+
+var stackaggr = 10
+
+const main = {args
+ var tab : std.htab(int64, (int64, int64[:]))#
+ var cmd
+
+ cmd = std.optparse(args, &[
+ .argdesc="dumps...",
+ .opts=[
+ [.opt='d', .arg="depth", .desc="aggregate by at most `depth` stack elements"],
+ ][:]
+ ])
+
+ for opt in cmd.opts
+ match opt
+ | ('d', depth):
+ match std.intparse(depth)
+ | `std.Some d: stackaggr = d
+ | `std.None: std.fatal("could not parse stack depth {}\n", depth)
+ ;;
+ | _: std.die("unreachable")
+ ;;
+ ;;
+
+ tab = std.mkht(std.inthash, std.inteq)
+ for d in cmd.args
+ match bio.open(d, bio.Rd)
+ | `std.Ok f: dump(d, f, tab)
+ | `std.Err e: std.fatal("could not open {}: {}\n", d, e)
+ ;;
+ ;;
+}
+
+const dump = {path, f, tab
+ while true
+ match bio.getle64(f)
+ | `bio.Ok 0: tracealloc(path, f, tab)
+ | `bio.Ok 1: tracefree(path, f, tab)
+ | `bio.Eof: break
+ | `bio.Ok wat: std.fatal("unknown action type {x}\n", wat)
+ | `bio.Err e: std.fatal("failed to read {}: {}\n", path, e)
+ ;;
+ ;;
+ dumptrace(tab)
+}
+
+const tracealloc = {path, f, tab
+ var ptr, sz, stk
+
+ ptr = get64(path, f)
+ sz = get64(path, f)
+ stk = [][:]
+ for var i = 0; i < 10; i++
+ std.slpush(&stk, get64(path, f))
+ ;;
+ std.htput(tab, ptr, (sz, stk))
+}
+
+const tracefree = {path, f, tab
+ var ptr, sz
+
+ ptr = get64(path, f)
+ sz = get64(path, f)
+ std.htdel(tab, ptr)
+}
+
+const dumptrace = {tab
+ var aggr
+
+ aggr = std.mkht(hashintsl, std.sleq)
+ for (k, (sz, stk)) in std.htbykeyvals(tab)
+ match std.htget(aggr, stk[:stackaggr])
+ | `std.Some (count, total):
+ std.htput(aggr, stk[:stackaggr], (count + 1, sz + total))
+ | `std.None:
+ std.htput(aggr, stk[:stackaggr], (1, sz))
+ ;;
+ ;;
+
+ for (stk, (n, sz)) in std.htbykeyvals(aggr)
+ std.put("unfreed: {} (size: {}): {}\n", n, sz, stk)
+ ;;
+}
+
+const get64 = {path, f
+ match bio.getle64(f)
+ | `bio.Ok v: -> v
+ | res: std.fatal("failed to read {}: {}\n", path, res)
+ ;;
+}
+
+const hashintsl = {sl
+ var h
+
+ h = 0
+ for i in sl
+ h ^= std.inthash(i)
+ ;;
+ -> h
+}