Commit 022f3d77 authored by Brenden Blanco's avatar Brenden Blanco

Add field support to trace_print and friends

Add trace_readline_fields helper to parse the output of trace_pipe
Add field parsing support to trace_print. Addresses #149.
Fix typo in trace_open s/trace/tracefile/
Make nonblocking=False the default in trace_readline
Use IOError vs BlockingIOError for greater compatibility (untested)

Fixes: #149
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent ee286326
...@@ -6,14 +6,13 @@ ...@@ -6,14 +6,13 @@
# sudo ./hello_world.py" # sudo ./hello_world.py"
from bpf import BPF from bpf import BPF
from subprocess import call
prog = """ prog = """
int hello(void *ctx) { int hello(void *ctx) {
bpf_trace_printk("Hello, World!\\n"); bpf_trace_printk("Hello, World!\\n");
return 0; return 0;
}; }
""" """
b = BPF(text=prog) b = BPF(text=prog)
b.attach_kprobe(event="sys_clone", fn_name="hello") b.attach_kprobe(event="sys_clone", fn_name="hello")
b.trace_print() b.trace_print(fmt="{1} {5}")
...@@ -389,7 +389,7 @@ class BPF(object): ...@@ -389,7 +389,7 @@ class BPF(object):
if res < 0: if res < 0:
raise Exception("Failed to attach BPF to kprobe") raise Exception("Failed to attach BPF to kprobe")
open_kprobes[ev_name] = res open_kprobes[ev_name] = res
return res return self
@staticmethod @staticmethod
def detach_kprobe(event): def detach_kprobe(event):
...@@ -412,7 +412,7 @@ class BPF(object): ...@@ -412,7 +412,7 @@ class BPF(object):
if res < 0: if res < 0:
raise Exception("Failed to attach BPF to kprobe") raise Exception("Failed to attach BPF to kprobe")
open_kprobes[ev_name] = res open_kprobes[ev_name] = res
return res return self
@staticmethod @staticmethod
def detach_kretprobe(event): def detach_kretprobe(event):
...@@ -437,14 +437,33 @@ class BPF(object): ...@@ -437,14 +437,33 @@ class BPF(object):
if not tracefile: if not tracefile:
tracefile = open("%s/trace_pipe" % TRACEFS) tracefile = open("%s/trace_pipe" % TRACEFS)
if nonblocking: if nonblocking:
fd = trace.fileno() fd = tracefile.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL) fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
return tracefile return tracefile
@staticmethod @staticmethod
def trace_readline(nonblocking=True): def trace_readline_fields(nonblocking=False):
"""trace_readline(nonblocking=True) """trace_readline_fields(nonblocking=False)
Read from the kernel debug trace pipe and return a tuple of the
fields (task, pid, cpu, flags, timestamp, msg) or None if no
line was read (nonblocking=True)
"""
line = BPF.trace_readline(nonblocking)
if line:
task = line[:16].lstrip()
line = line[17:]
ts_end = line.find(":")
pid, cpu, flags, ts = line[:ts_end].split()
cpu = cpu[1:-1]
msg = line[ts_end + 4:]
return (task, int(pid), int(cpu), flags, float(ts), msg)
return
@staticmethod
def trace_readline(nonblocking=False):
"""trace_readline(nonblocking=False)
Read from the kernel debug trace pipe and return one line Read from the kernel debug trace pipe and return one line
If nonblocking is False, this will block until ctrl-C is pressed. If nonblocking is False, this will block until ctrl-C is pressed.
...@@ -454,17 +473,28 @@ class BPF(object): ...@@ -454,17 +473,28 @@ class BPF(object):
line = None line = None
try: try:
line = trace.readline(128).rstrip() line = trace.readline(1024).rstrip()
except BlockingIOError: except IOError:
pass pass
except KeyboardInterrupt:
exit()
return line return line
@staticmethod @staticmethod
def trace_print(): def trace_print(fmt=None):
try: """trace_print(fmt=None)
while True:
Read from the kernel debug trace pipe and print on stdout.
If fmt is specified, apply as a format string to the output. See
trace_readline_fields for the members of the tuple
example: trace_print(fmt="pid {1}, msg = {5}")
"""
while True:
if fmt:
fields = BPF.trace_readline_fields(nonblocking=False)
line = fmt.format(*fields)
else:
line = BPF.trace_readline(nonblocking=False) line = BPF.trace_readline(nonblocking=False)
print(line) print(line)
sys.stdout.flush() sys.stdout.flush()
except KeyboardInterrupt:
exit()
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