Commit 3ce27b5d authored by 4ast's avatar 4ast

Merge pull request #417 from iovisor/funccount_alternate

Remove use of update() in funccount
parents e58ed9f1 95728834
......@@ -33,8 +33,8 @@ open_uprobes = {}
tracefile = None
TRACEFS = "/sys/kernel/debug/tracing"
KALLSYMS = "/proc/kallsyms"
ksym_addrs = []
ksym_names = []
ksyms = []
ksym_names = {}
ksym_loaded = 0
_kprobe_limit = 1000
......@@ -642,7 +642,7 @@ class BPF(object):
@staticmethod
def _load_kallsyms():
global ksym_loaded, ksym_addrs, ksym_names
global ksym_loaded, ksyms, ksym_names
if ksym_loaded:
return
try:
......@@ -654,19 +654,20 @@ class BPF(object):
cols = line.split()
name = cols[2]
addr = int(cols[0], 16)
ksym_addrs.append(addr)
ksym_names.append(name)
# keep a mapping of names to ksyms index
ksym_names[name] = len(ksyms)
ksyms.append((name, addr))
syms.close()
ksym_loaded = 1
@staticmethod
def _ksym_addr2index(addr):
global ksym_addrs
global ksyms
start = -1
end = len(ksym_addrs)
end = len(ksyms)
while end != start + 1:
mid = int((start + end) / 2)
if addr < ksym_addrs[mid]:
if addr < ksyms[mid][1]:
end = mid
else:
start = mid
......@@ -679,12 +680,12 @@ class BPF(object):
Translate a kernel memory address into a kernel function name, which is
returned. This is a simple translator that uses /proc/kallsyms.
"""
global ksym_names
global ksyms
BPF._load_kallsyms()
idx = BPF._ksym_addr2index(addr)
if idx == -1:
return "[unknown]"
return ksym_names[idx]
return ksyms[idx][0]
@staticmethod
def ksymaddr(addr):
......@@ -694,13 +695,27 @@ class BPF(object):
instruction offset as a hexidecimal number, which is returned as a
string. This is a simple translator that uses /proc/kallsyms.
"""
global ksym_addrs, ksym_names
global ksyms
BPF._load_kallsyms()
idx = BPF._ksym_addr2index(addr)
if idx == -1:
return "[unknown]"
offset = int(addr - ksym_addrs[idx])
return ksym_names[idx] + hex(offset)
offset = int(addr - ksyms[idx][1])
return ksyms[idx][0] + hex(offset)
@staticmethod
def ksymname(name):
"""ksymname(name)
Translate a kernel name into an address. This is the reverse of
ksymaddr. Returns -1 when the function name is unknown."""
global ksyms, ksym_names
BPF._load_kallsyms()
idx = ksym_names.get(name, -1)
if idx == -1:
return 0
return ksyms[idx][1]
@staticmethod
def num_open_kprobes():
......
......@@ -186,6 +186,10 @@ class TableBase(MutableMapping):
for k in self.keys():
self.__delitem__(k)
def zero(self):
for k in self.keys():
self[k] = self.Leaf()
def __iter__(self):
return TableBase.Iter(self, self.Key)
......
......@@ -65,9 +65,13 @@ BPF_HASH(counts, struct key_t);
int trace_count(struct pt_regs *ctx) {
FILTER
struct key_t key = {};
u64 zero = 0, *val;
key.ip = ctx->ip;
val = counts.lookup_or_init(&key, &zero);
u64 *val;
// the kprobe pc is slightly after the function starting address, align
// 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)++;
return 0;
}
......@@ -81,6 +85,16 @@ else:
if debug:
print(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")
matched = b.num_open_kprobes()
if matched == 0:
......@@ -106,10 +120,10 @@ while (1):
print("%-8s\n" % strftime("%H:%M:%S"), end="")
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):
if v.value == 0: continue
print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value))
counts.clear()
counts.zero()
if exiting:
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