2 Commits

2 changed files with 32 additions and 14 deletions

View File

@ -1,7 +1,6 @@
from pythonbpf import bpf, map, struct, section, bpfglobal, BPF, trace_pipe from pythonbpf import bpf, map, struct, section, bpfglobal, BPF
from pythonbpf.helper import ktime, pid, comm from pythonbpf.helper import ktime, pid, comm
from pythonbpf.maps import PerfEventArray from pythonbpf.maps import PerfEventArray
from ctypes import c_void_p, c_int64, c_uint64 from ctypes import c_void_p, c_int64, c_uint64
@ -25,7 +24,6 @@ def hello(ctx: c_void_p) -> c_int64:
dataobj = data_t() dataobj = data_t()
dataobj.pid, dataobj.ts = pid(), ktime() dataobj.pid, dataobj.ts = pid(), ktime()
comm(dataobj.comm) comm(dataobj.comm)
print(f"clone called at {dataobj.ts} by pid {dataobj.pid}, comm {dataobj.comm}")
events.output(dataobj) events.output(dataobj)
return 0 # type: ignore [return-value] return 0 # type: ignore [return-value]
@ -36,8 +34,28 @@ def LICENSE() -> str:
return "GPL" return "GPL"
# compile # Compile and load
BPF().load_and_attach() b = BPF()
b.load()
attached = b.attach_all()
print("Tracing clone()... Ctrl-C to end") start = 0
trace_pipe()
def callback(cpu, event):
global start
if start == 0:
start = event.ts
ts = (event.ts - start) / 1e9
print(f"[CPU {cpu}] PID: {event.pid}, TS: {ts}, COMM: {event.comm.decode()}")
perf = b["events"].open_perf_buffer(callback, struct_name="data_t")
print("Starting to poll... (Ctrl+C to stop)")
print("Try running: fork() or clone() system calls to trigger events")
try:
while True:
b["events"].poll(1000)
except KeyboardInterrupt:
print("Stopping...")

View File

@ -15,7 +15,7 @@ import os
import subprocess import subprocess
import inspect import inspect
from pathlib import Path from pathlib import Path
from pylibbpf import BpfProgram from pylibbpf import BpfObject
import tempfile import tempfile
from logging import Logger from logging import Logger
import logging import logging
@ -158,7 +158,7 @@ def _run_llc(ll_file, obj_file):
return False return False
def compile(loglevel=logging.INFO) -> bool: def compile(loglevel=logging.WARNING) -> bool:
# Look one level up the stack to the caller of this function # Look one level up the stack to the caller of this function
caller_frame = inspect.stack()[1] caller_frame = inspect.stack()[1]
caller_file = Path(caller_frame.filename).resolve() caller_file = Path(caller_frame.filename).resolve()
@ -166,7 +166,9 @@ def compile(loglevel=logging.INFO) -> bool:
ll_file = Path("/tmp") / caller_file.with_suffix(".ll").name ll_file = Path("/tmp") / caller_file.with_suffix(".ll").name
o_file = caller_file.with_suffix(".o") o_file = caller_file.with_suffix(".o")
compile_to_ir(str(caller_file), str(ll_file), loglevel=loglevel) _, structs_sym_tab, maps_sym_tab = compile_to_ir(
str(caller_file), str(ll_file), loglevel=loglevel
)
if not _run_llc(ll_file, o_file): if not _run_llc(ll_file, o_file):
logger.error("Compilation to object file failed.") logger.error("Compilation to object file failed.")
@ -176,7 +178,7 @@ def compile(loglevel=logging.INFO) -> bool:
return True return True
def BPF(loglevel=logging.INFO) -> BpfProgram: def BPF(loglevel=logging.WARNING) -> BpfObject:
caller_frame = inspect.stack()[1] caller_frame = inspect.stack()[1]
src = inspect.getsource(caller_frame.frame) src = inspect.getsource(caller_frame.frame)
with tempfile.NamedTemporaryFile( with tempfile.NamedTemporaryFile(
@ -194,6 +196,4 @@ def BPF(loglevel=logging.INFO) -> BpfProgram:
) )
_run_llc(str(inter.name), str(obj_file.name)) _run_llc(str(inter.name), str(obj_file.name))
return BpfProgram( return BpfObject(str(obj_file.name), structs=structs_sym_tab)
str(obj_file.name), structs=structs_sym_tab, maps=maps_sym_tab
)