Added -z and -Z switches for filtering by size, added copyright notices
diff --git a/tools/memleak.c b/tools/memleak.c
index 5c1ce42..48de6af 100644
--- a/tools/memleak.c
+++ b/tools/memleak.c
@@ -1,3 +1,10 @@
+/*
+ * memleak.c Trace and display outstanding allocations to detect
+ * memory leaks in user-mode processes and the kernel.
+ *
+ * Copyright (C) 2016 Sasha Goldshtein.
+ */
+
#include <uapi/linux/ptrace.h>
struct alloc_info_t {
@@ -33,9 +40,7 @@
int alloc_enter(struct pt_regs *ctx, size_t size)
{
- // Ideally, this should use a random number source, such as
- // BPF_FUNC_get_prandom_u32, but that's currently not supported
- // by the bcc front-end.
+ SIZE_FILTER
if (SAMPLE_EVERY_N > 1) {
u64 ts = bpf_ktime_get_ns();
if (ts % SAMPLE_EVERY_N != 0)
diff --git a/tools/memleak.py b/tools/memleak.py
index 41063c7..7ab6b7c 100755
--- a/tools/memleak.py
+++ b/tools/memleak.py
@@ -1,4 +1,14 @@
#!/usr/bin/env python
+#
+# memleak.py Trace and display outstanding allocations to detect
+# memory leaks in user-mode processes and the kernel.
+#
+# USAGE: memleak.py [-h] [-p PID] [-t] [-a] [-o OLDER] [-c COMMAND]
+# [-s SAMPLE_RATE] [-d STACK_DEPTH] [-T TOP] [-z MIN_SIZE]
+# [-Z MAX_SIZE]
+# [interval] [count]
+#
+# Copyright (C) 2016 Sasha Goldshtein.
from bcc import BPF
from time import sleep
@@ -195,6 +205,10 @@
help="maximum stack depth to capture")
parser.add_argument("-T", "--top", type=int, default=10,
help="display only this many top allocating stacks (by size)")
+parser.add_argument("-z", "--min-size", type=int,
+ help="capture only allocations larger than this size")
+parser.add_argument("-Z", "--max-size", type=int,
+ help="capture only allocations smaller than this size")
args = parser.parse_args()
@@ -208,6 +222,12 @@
num_prints = args.count
max_stack_size = args.stack_depth + 2
top_stacks = args.top
+min_size = args.min_size
+max_size = args.max_size
+
+if min_size is not None and max_size is not None and min_size > max_size:
+ print("min_size (-z) can't be greater than max_size (-Z)")
+ exit(1)
if command is not None:
print("Executing '%s' and tracing the resulting process." % command)
@@ -219,6 +239,17 @@
bpf_source = bpf_source.replace("GRAB_ONE_FRAME", max_stack_size *
"\tif (!(info->callstack[depth++] = get_frame(&bp))) return depth;\n")
bpf_source = bpf_source.replace("MAX_STACK_SIZE", str(max_stack_size))
+
+size_filter = ""
+if min_size is not None and max_size is not None:
+ size_filter = "if (size < %d || size > %d) return 0;" % \
+ (min_size, max_size)
+elif min_size is not None:
+ size_filter = "if (size < %d) return 0;" % min_size
+elif max_size is not None:
+ size_filter = "if (size > %d) return 0;" % max_size
+bpf_source = bpf_source.replace("SIZE_FILTER", size_filter)
+
bpf_program = BPF(text=bpf_source)
if not kernel_trace:
diff --git a/tools/memleak_examples.txt b/tools/memleak_examples.txt
index 2f7dd74..82a01b0 100644
--- a/tools/memleak_examples.txt
+++ b/tools/memleak_examples.txt
@@ -178,6 +178,10 @@
-d STACK_DEPTH, --stack_depth STACK_DEPTH
maximum stack depth to capture
-T TOP, --top TOP display only this many top allocating stacks (by size)
+ -z MIN_SIZE, --min-size MIN_SIZE
+ capture only allocations larger than this size
+ -Z MAX_SIZE, --max-size MAX_SIZE
+ capture only allocations smaller than this size
EXAMPLES: