diff --git a/BCC-Examples/hello_fields.py b/BCC-Examples/hello_fields.py new file mode 100644 index 0000000..3a52fc1 --- /dev/null +++ b/BCC-Examples/hello_fields.py @@ -0,0 +1,33 @@ +from pythonbpf import bpf, section, bpfglobal, BPF, trace_fields +from ctypes import c_void_p, c_int64 + + +@bpf +@section("tracepoint/syscalls/sys_enter_clone") +def hello_world(ctx: c_void_p) -> c_int64: + print("Hello, World!") + return c_int64(0) + + +@bpf +@bpfglobal +def LICENSE() -> str: + return "GPL" + + +# compile +b = BPF() +b.load_and_attach() + +# header +print(f"{'TIME(s)':<18} {'COMM':<16} {'PID':<6} {'MESSAGE'}") + +# format output +while True: + try: + (task, pid, cpu, flags, ts, msg) = trace_fields() + except ValueError: + continue + except KeyboardInterrupt: + exit() + print(f"{ts:<18} {task:<16} {pid:<6} {msg}") diff --git a/BCC-Examples/hello_world.py b/BCC-Examples/hello_world.py index a44753c..ff51731 100644 --- a/BCC-Examples/hello_world.py +++ b/BCC-Examples/hello_world.py @@ -15,7 +15,6 @@ def LICENSE() -> str: return "GPL" -# compile() b = BPF() b.load_and_attach() diff --git a/pythonbpf/utils.py b/pythonbpf/utils.py index 8dbc5e5..47e9913 100644 --- a/pythonbpf/utils.py +++ b/pythonbpf/utils.py @@ -1,9 +1,4 @@ import subprocess -import re - -TRACE_PATTERN = re.compile( - rb"^(.{1,16}?)-(\d+)\s+\[(\d+)\]\s+([a-zA-Z.]+)\s+([0-9.]+):\s+.*?:\s+(.*)$" -) def trace_pipe(): @@ -20,12 +15,42 @@ def trace_fields(): while True: line = f.readline().rstrip() - if not line or line.startswith(b"CPU:"): + if not line: continue - match = TRACE_PATTERN.match(line) - if not match: + # Skip lost event lines + if line.startswith(b"CPU:"): + continue + + # Parse BCC-style: first 16 bytes = task + task = line[:16].lstrip().decode("utf-8") + line = line[17:] # Skip past task field and space + + # Find the colon that ends "pid cpu flags timestamp" + ts_end = line.find(b":") + if ts_end == -1: raise ValueError("Cannot parse trace line") - task, pid, cpu, flags, ts, msg = match.groups() - return (task.strip(), int(pid), int(cpu), flags, float(ts), msg) + # Split "pid [cpu] flags timestamp" + try: + parts = line[:ts_end].split() + if len(parts) < 4: + raise ValueError("Not enough fields") + + pid = int(parts[0]) + cpu = parts[1][1:-1] # Remove brackets from [cpu] + cpu = int(cpu) + flags = parts[2] + ts = float(parts[3]) + except (ValueError, IndexError): + raise ValueError("Cannot parse trace line") + + # Get message: skip ": symbol:" part + line = line[ts_end + 1 :] # Skip first ":" + sym_end = line.find(b":") + if sym_end != -1: + msg = line[sym_end + 2 :].decode("utf-8") # Skip ": " after symbol + else: + msg = line.lstrip().decode("utf-8") + + return (task, pid, cpu, flags, ts, msg)