Skip to content

Commit

Permalink
Merge pull request iovisor#417 from iovisor/funccount_alternate
Browse files Browse the repository at this point in the history
Remove use of update() in funccount
  • Loading branch information
4ast committed Feb 23, 2016
2 parents e58ed9f + 9572883 commit 3ce27b5
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 18 deletions.
41 changes: 28 additions & 13 deletions src/python/bcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
tracefile = None
TRACEFS = "/sys/kernel/debug/tracing"
KALLSYMS = "/proc/kallsyms"
ksym_addrs = []
ksym_names = []
ksyms = []
ksym_names = {}
ksym_loaded = 0
_kprobe_limit = 1000

Expand Down Expand Up @@ -642,7 +642,7 @@ def trace_print(self, fmt=None):

@staticmethod
def _load_kallsyms():
global ksym_loaded, ksym_addrs, ksym_names
global ksym_loaded, ksyms, ksym_names
if ksym_loaded:
return
try:
Expand All @@ -654,19 +654,20 @@ def _load_kallsyms():
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
Expand All @@ -679,12 +680,12 @@ def ksym(addr):
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):
Expand All @@ -694,13 +695,27 @@ def ksymaddr(addr):
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():
Expand Down
4 changes: 4 additions & 0 deletions src/python/bcc/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ def clear(self):
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)

Expand Down
24 changes: 19 additions & 5 deletions tools/funccount.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ def signal_ignore(signal, frame):
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;
}
Expand All @@ -81,6 +85,16 @@ def signal_ignore(signal, frame):
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:
Expand All @@ -106,10 +120,10 @@ def signal_ignore(signal, frame):
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...")
Expand Down

0 comments on commit 3ce27b5

Please sign in to comment.