Skip to content

Commit

Permalink
tools: switch to v2/3 independent bytes usage
Browse files Browse the repository at this point in the history
Conform to bytes encoding for some portion of the tools/tests, such that
smoke tests pass on python3. More conversions are surely required.

Signed-off-by: Brenden Blanco <[email protected]>
  • Loading branch information
drzaeus77 committed Feb 8, 2018
1 parent c0ca99a commit 42d6098
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 60 deletions.
26 changes: 14 additions & 12 deletions tests/python/test_debuginfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ def grab_sym(self):
# Grab the first symbol in kallsyms that has type 't' or 'T'.
# Also, find all aliases of this symbol which are identifiable
# by the same address.
with open("/proc/kallsyms") as f:
with open("/proc/kallsyms", "rb") as f:
for line in f:

# Extract the first 3 columns only. The 4th column
# containing the module name may not exist for all
# symbols.
(addr, t, name) = line.strip().split()[:3]
if t == "t" or t == "T":
if t == b"t" or t == b"T":
if not address:
address = addr
if addr == address:
Expand All @@ -32,7 +32,7 @@ def grab_sym(self):
return (address, aliases)

def test_ksymname(self):
sym = BPF.ksymname("__kmalloc")
sym = BPF.ksymname(b"__kmalloc")
self.assertIsNotNone(sym)
self.assertNotEqual(sym, 0)

Expand All @@ -58,21 +58,23 @@ def setUp(self):
def tearDown(self):
self.process.kill()
self.process.wait()
self.process.stdout.close()
self.process = None

def resolve_addr(self):
sym, offset, module = self.syms.resolve(self.addr, False)
self.assertEqual(sym, self.mangled_name)
self.assertEqual(offset, 0)
self.assertTrue(module[-5:] == 'dummy')
self.assertTrue(module[-5:] == b'dummy')
sym, offset, module = self.syms.resolve(self.addr, True)
self.assertEqual(sym, 'some_namespace::some_function(int, int)')
self.assertEqual(sym, b'some_namespace::some_function(int, int)')
self.assertEqual(offset, 0)
self.assertTrue(module[-5:] == 'dummy')
self.assertTrue(module[-5:] == b'dummy')


def resolve_name(self):
script_dir = os.path.dirname(os.path.realpath(__file__))
addr = self.syms.resolve_name(os.path.join(script_dir, 'dummy'),
script_dir = os.path.dirname(os.path.realpath(__file__).encode("utf8"))
addr = self.syms.resolve_name(os.path.join(script_dir, b'dummy'),
self.mangled_name)
self.assertEqual(addr, self.addr)
pass
Expand All @@ -82,8 +84,8 @@ def build_command(self):
subprocess.check_output('g++ -o dummy dummy.cc'.split())
lines = subprocess.check_output('nm dummy'.split()).splitlines()
for line in lines:
if "some_function" in line:
self.mangled_name = line.split(' ')[2]
if b"some_function" in line:
self.mangled_name = line.split(b' ')[2]
break
self.assertTrue(self.mangled_name)

Expand All @@ -108,8 +110,8 @@ def build_command(self):
.split())
lines = subprocess.check_output('nm dummy'.split()).splitlines()
for line in lines:
if "some_function" in line:
self.mangled_name = line.split(' ')[2]
if b"some_function" in line:
self.mangled_name = line.split(b' ')[2]
break
self.assertTrue(self.mangled_name)

Expand Down
6 changes: 3 additions & 3 deletions tests/python/test_probe_count.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) Suchakra Sharma <[email protected]>
# Licensed under the Apache License, Version 2.0 (the "License")

from bcc import BPF, _get_num_open_probes
from bcc import BPF, _get_num_open_probes, TRACEFS
import os
import sys
from unittest import main, TestCase
Expand All @@ -18,9 +18,9 @@ def setUp(self):

def test_attach1(self):
actual_cnt = 0
with open("/sys/kernel/debug/tracing/available_filter_functions") as f:
with open("%s/available_filter_functions" % TRACEFS, "rb") as f:
for line in f:
if str(line).startswith("vfs_"):
if line.startswith(b"vfs_"):
actual_cnt += 1
open_cnt = self.b.num_open_kprobes()
self.assertEqual(actual_cnt, open_cnt)
Expand Down
2 changes: 1 addition & 1 deletion tests/python/test_stackid.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_simple(self):
stackid = stack_entries[k]
self.assertIsNotNone(stackid)
stack = stack_traces[stackid].ip
self.assertEqual(b.ksym(stack[0]), "htab_map_lookup_elem")
self.assertEqual(b.ksym(stack[0]), b"htab_map_lookup_elem")


if __name__ == "__main__":
Expand Down
8 changes: 4 additions & 4 deletions tools/cachestat.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ def usage():
counts = b.get_table("counts")
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):

if re.match('mark_page_accessed', b.ksym(k.ip)) is not None:
if re.match(b'mark_page_accessed', b.ksym(k.ip)) is not None:
mpa = max(0, v.value)

if re.match('mark_buffer_dirty', b.ksym(k.ip)) is not None:
if re.match(b'mark_buffer_dirty', b.ksym(k.ip)) is not None:
mbd = max(0, v.value)

if re.match('add_to_page_cache_lru', b.ksym(k.ip)) is not None:
if re.match(b'add_to_page_cache_lru', b.ksym(k.ip)) is not None:
apcl = max(0, v.value)

if re.match('account_page_dirtied', b.ksym(k.ip)) is not None:
if re.match(b'account_page_dirtied', b.ksym(k.ip)) is not None:
apd = max(0, v.value)

# access = total cache access incl. reads(mpa) and writes(mbd)
Expand Down
16 changes: 10 additions & 6 deletions tools/execsnoop.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

from __future__ import print_function
from bcc import BPF
from bcc.utils import ArgString, printb
import bcc.utils as utils
import argparse
import ctypes as ct
import re
Expand All @@ -41,8 +43,10 @@
parser.add_argument("-x", "--fails", action="store_true",
help="include failed exec()s")
parser.add_argument("-n", "--name",
type=ArgString,
help="only print commands matching this name (regex), any arg")
parser.add_argument("-l", "--line",
type=ArgString,
help="only print commands where arg contains this line (regex)")
parser.add_argument("--max-args", default="20",
help="maximum number of arguments parsed and displayed, defaults to 20")
Expand Down Expand Up @@ -186,19 +190,19 @@ def print_event(cpu, data, size):
elif event.type == EventType.EVENT_RET:
if event.retval != 0 and not args.fails:
skip = True
if args.name and not re.search(args.name, event.comm):
if args.name and not re.search(bytes(args.name), event.comm):
skip = True
if args.line and not re.search(args.line,
b' '.join(argv[event.pid]).decode()):
if args.line and not re.search(bytes(args.line),
b' '.join(argv[event.pid])):
skip = True

if not skip:
if args.timestamp:
print("%-8.3f" % (time.time() - start_ts), end="")
ppid = get_ppid(event.pid)
print("%-16s %-6s %-6s %3s %s" % (event.comm.decode(), event.pid,
ppid if ppid > 0 else "?", event.retval,
b' '.join(argv[event.pid]).decode()))
ppid = b"%d" % ppid if ppid > 0 else b"?"
printb(b"%-16s %-6d %-6s %3d %s" % (event.comm, event.pid,
ppid, event.retval, b' '.join(argv[event.pid])))
try:
del(argv[event.pid])
except Exception:
Expand Down
65 changes: 33 additions & 32 deletions tools/funccount.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# 18-Oct-2016 Sasha Goldshtein Generalized for uprobes, tracepoints, USDT.

from __future__ import print_function
from bcc import BPF, USDT
from bcc import ArgString, BPF, USDT
from time import sleep, strftime
import argparse
import os
Expand Down Expand Up @@ -49,15 +49,15 @@ def __init__(self, pattern, use_regex=False, pid=None):
t:cat:event -- probe a kernel tracepoint
u:lib:probe -- probe a USDT tracepoint
"""
parts = pattern.split(':')
parts = bytes(pattern).split(b':')
if len(parts) == 1:
parts = ["p", "", parts[0]]
parts = [b"p", b"", parts[0]]
elif len(parts) == 2:
parts = ["p", parts[0], parts[1]]
parts = [b"p", parts[0], parts[1]]
elif len(parts) == 3:
if parts[0] == "t":
parts = ["t", "", "%s:%s" % tuple(parts[1:])]
if parts[0] not in ["p", "t", "u"]:
if parts[0] == b"t":
parts = [b"t", b"", b"%s:%s" % tuple(parts[1:])]
if parts[0] not in [b"p", b"t", b"u"]:
raise Exception("Type must be 'p', 't', or 'u', but got %s" %
parts[0])
else:
Expand All @@ -66,10 +66,10 @@ def __init__(self, pattern, use_regex=False, pid=None):

(self.type, self.library, self.pattern) = parts
if not use_regex:
self.pattern = self.pattern.replace('*', '.*')
self.pattern = '^' + self.pattern + '$'
self.pattern = self.pattern.replace(b'*', b'.*')
self.pattern = b'^' + self.pattern + b'$'

if (self.type == "p" and self.library) or self.type == "u":
if (self.type == b"p" and self.library) or self.type == b"u":
libpath = BPF.find_library(self.library)
if libpath is None:
# This might be an executable (e.g. 'bash')
Expand All @@ -83,46 +83,46 @@ def __init__(self, pattern, use_regex=False, pid=None):
self.trace_functions = {} # map location number to function name

def is_kernel_probe(self):
return self.type == "t" or (self.type == "p" and self.library == "")
return self.type == b"t" or (self.type == b"p" and self.library == b"")

def attach(self):
if self.type == "p" and not self.library:
if self.type == b"p" and not self.library:
for index, function in self.trace_functions.items():
self.bpf.attach_kprobe(
event=function,
fn_name="trace_count_%d" % index)
elif self.type == "p" and self.library:
elif self.type == b"p" and self.library:
for index, function in self.trace_functions.items():
self.bpf.attach_uprobe(
name=self.library,
sym=function,
fn_name="trace_count_%d" % index,
pid=self.pid or -1)
elif self.type == "t":
elif self.type == b"t":
for index, function in self.trace_functions.items():
self.bpf.attach_tracepoint(
tp=function,
fn_name="trace_count_%d" % index)
elif self.type == "u":
elif self.type == b"u":
pass # Nothing to do -- attach already happened in `load`

def _add_function(self, template, probe_name):
new_func = "trace_count_%d" % self.matched
text = template.replace("PROBE_FUNCTION", new_func)
text = text.replace("LOCATION", str(self.matched))
new_func = b"trace_count_%d" % self.matched
text = template.replace(b"PROBE_FUNCTION", new_func)
text = text.replace(b"LOCATION", b"%d" % self.matched)
self.trace_functions[self.matched] = probe_name
self.matched += 1
return text

def _generate_functions(self, template):
self.usdt = None
text = ""
if self.type == "p" and not self.library:
text = b""
if self.type == b"p" and not self.library:
functions = BPF.get_kprobe_functions(self.pattern)
verify_limit(len(functions))
for function in functions:
text += self._add_function(template, function)
elif self.type == "p" and self.library:
elif self.type == b"p" and self.library:
# uprobes are tricky because the same function may have multiple
# addresses, and the same address may be mapped to multiple
# functions. We aren't allowed to create more than one uprobe
Expand All @@ -139,12 +139,12 @@ def _generate_functions(self, template):
addresses.add(address)
functions.add(function)
text += self._add_function(template, function)
elif self.type == "t":
elif self.type == b"t":
tracepoints = BPF.get_tracepoints(self.pattern)
verify_limit(len(tracepoints))
for tracepoint in tracepoints:
text += self._add_function(template, tracepoint)
elif self.type == "u":
elif self.type == b"u":
self.usdt = USDT(path=self.library, pid=self.pid)
matches = []
for probe in self.usdt.enumerate_probes():
Expand All @@ -154,15 +154,15 @@ def _generate_functions(self, template):
matches.append(probe.name)
verify_limit(len(matches))
for match in matches:
new_func = "trace_count_%d" % self.matched
new_func = b"trace_count_%d" % self.matched
text += self._add_function(template, match)
self.usdt.enable_probe(match, new_func)
if debug:
print(self.usdt.get_text())
return text

def load(self):
trace_count_text = """
trace_count_text = b"""
int PROBE_FUNCTION(void *ctx) {
FILTER
int loc = LOCATION;
Expand All @@ -174,23 +174,23 @@ def load(self):
return 0;
}
"""
bpf_text = """#include <uapi/linux/ptrace.h>
bpf_text = b"""#include <uapi/linux/ptrace.h>
BPF_ARRAY(counts, u64, NUMLOCATIONS);
"""

# We really mean the tgid from the kernel's perspective, which is in
# the top 32 bits of bpf_get_current_pid_tgid().
if self.pid:
trace_count_text = trace_count_text.replace('FILTER',
"""u32 pid = bpf_get_current_pid_tgid() >> 32;
trace_count_text = trace_count_text.replace(b'FILTER',
b"""u32 pid = bpf_get_current_pid_tgid() >> 32;
if (pid != %d) { return 0; }""" % self.pid)
else:
trace_count_text = trace_count_text.replace('FILTER', '')
trace_count_text = trace_count_text.replace(b'FILTER', b'')

bpf_text += self._generate_functions(trace_count_text)
bpf_text = bpf_text.replace("NUMLOCATIONS",
str(len(self.trace_functions)))
bpf_text = bpf_text.replace(b"NUMLOCATIONS",
b"%d" % len(self.trace_functions))
if debug:
print(bpf_text)

Expand Down Expand Up @@ -242,6 +242,7 @@ def __init__(self):
parser.add_argument("-D", "--debug", action="store_true",
help="print BPF program before starting (for debugging purposes)")
parser.add_argument("pattern",
type=ArgString,
help="search expression for events")
self.args = parser.parse_args()
global debug
Expand All @@ -260,7 +261,7 @@ def run(self):
self.probe.load()
self.probe.attach()
print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." %
(self.probe.matched, self.args.pattern))
(self.probe.matched, bytes(self.args.pattern)))
exiting = 0 if self.args.interval else 1
seconds = 0
while True:
Expand Down
2 changes: 1 addition & 1 deletion tools/memleak.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ def print_outstanding():
key=lambda a: a.size)[-top_stacks:]
for alloc in to_show:
print("\t%d bytes in %d allocations from stack\n\t\t%s" %
(alloc.size, alloc.count, "\n\t\t".join(alloc.stack)))
(alloc.size, alloc.count, b"\n\t\t".join(alloc.stack)))

def print_outstanding_combined():
stack_traces = bpf["stack_traces"]
Expand Down
3 changes: 2 additions & 1 deletion tools/slabratetop.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from __future__ import print_function
from bcc import BPF
from bcc.utils import printb
from time import sleep, strftime
import argparse
import signal
Expand Down Expand Up @@ -124,7 +125,7 @@ def signal_ignore(signal, frame):
line = 0
for k, v in reversed(sorted(counts.items(),
key=lambda counts: counts[1].size)):
print("%-32s %6d %10d" % (k.name.decode(), v.count, v.size))
printb(b"%-32s %6d %10d" % (k.name, v.count, v.size))

line += 1
if line >= maxrows:
Expand Down

0 comments on commit 42d6098

Please sign in to comment.