Commit 95728834 authored by Brenden Blanco's avatar Brenden Blanco

Use pre-calculated function addresses in funccount

Hash map updates are not safe in recursive context. Change the
implementation of funccount to be read-only by converting
lookup_or_init() to lookup(). When run in interval mode, zero the counts
table instead of clearing it.
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 2e2b26d8
...@@ -65,9 +65,13 @@ BPF_HASH(counts, struct key_t); ...@@ -65,9 +65,13 @@ BPF_HASH(counts, struct key_t);
int trace_count(struct pt_regs *ctx) { int trace_count(struct pt_regs *ctx) {
FILTER FILTER
struct key_t key = {}; struct key_t key = {};
u64 zero = 0, *val; u64 *val;
key.ip = ctx->ip; // the kprobe pc is slightly after the function starting address, align
val = counts.lookup_or_init(&key, &zero); // back to the start (4 byte alignment) in order to match /proc/kallsyms
key.ip = ctx->ip & ~3ull;
val = counts.lookup(&key);
if (!val)
return 0;
(*val)++; (*val)++;
return 0; return 0;
} }
...@@ -81,6 +85,16 @@ else: ...@@ -81,6 +85,16 @@ else:
if debug: if debug:
print(bpf_text) print(bpf_text)
b = BPF(text=bpf_text) b = BPF(text=bpf_text)
counts = b.get_table("counts")
# pre-insert the function addresses into the counts table
fns = b._get_kprobe_functions(pattern)
for fn in fns:
addr = b.ksymname(fn)
if addr == -1:
raise Exception("Unknown symbol name %s" % fn)
counts[counts.Key(addr)] = counts.Leaf()
b.attach_kprobe(event_re=pattern, fn_name="trace_count") b.attach_kprobe(event_re=pattern, fn_name="trace_count")
matched = b.num_open_kprobes() matched = b.num_open_kprobes()
if matched == 0: if matched == 0:
...@@ -106,10 +120,10 @@ while (1): ...@@ -106,10 +120,10 @@ while (1):
print("%-8s\n" % strftime("%H:%M:%S"), end="") print("%-8s\n" % strftime("%H:%M:%S"), end="")
print("%-16s %-26s %8s" % ("ADDR", "FUNC", "COUNT")) print("%-16s %-26s %8s" % ("ADDR", "FUNC", "COUNT"))
counts = b.get_table("counts")
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
if v.value == 0: continue
print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value)) print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value))
counts.clear() counts.zero()
if exiting: if exiting:
print("Detaching...") print("Detaching...")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment