hello-raw-tracepoint.py (2222B)
1 #!/usr/bin/env python3 2 from bcc import BPF 3 import ctypes as ct 4 5 # https://docs.kernel.org/trace/events.html 6 # Tracepoints can be used without creating custom kernel modules 7 # to register probe functions using the event tracing infrastructure. 8 9 # eCHO Episode 74: eBPF Tail Calls 10 # https://www.youtube.com/watch?v=3qLXw3E0YWg 11 12 bpf_text = r""" 13 #include <linux/sched.h> 14 15 int noop() { 16 return 0; 17 } 18 19 static int ignore_syscall() { 20 return 0; 21 } 22 23 // eBPF tail calls allow for calling a series of functions w/o growing the stack 24 // BPF_PROG_ARRAY is a map to index eBPF functions 25 // https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#10-bpf_prog_array 26 BPF_PROG_ARRAY(syscall, 300); 27 28 // searchable list of syscalls 29 // https://filippo.io/linux-syscall-table 30 31 // https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#7-raw-tracepoints 32 // https://github.com/torvalds/linux/blob/master/include/trace/events/syscalls.h 33 RAW_TRACEPOINT_PROBE(sys_enter) { 34 // printf() to the common trace_pipe (/sys/kernel/debug/tracing/trace_pipe) 35 // https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#1-bpf_trace_printk 36 bpf_trace_printk("syscall"); 37 38 // the syscall opcode id is the second argument 39 // ctx is hidden by the macro RAW_TRACEPOINT_PROBE 40 // https://github.com/torvalds/linux/blob/master/include/trace/events/syscalls.h 41 int opcode = ctx->args[1]; 42 switch (opcode) { 43 case 64: 44 // eBPF stack only 512 bytes, don't repeat that too often 45 ignore_syscall(); 46 break; 47 } 48 49 // perform a "tail call" to another function for each specified opcode 50 // the mapping of tail call to opcode is done in userspace 51 // func invocation on struct is not proper C, will be translated by BCC 52 syscall.call(ctx, opcode); 53 54 // this line will never be evaluated when the tail call succeeds 55 bpf_trace_printk("Another syscall: %d", opcode); 56 57 return 0; 58 } 59 """ 60 61 b = BPF(text=bpf_text) 62 63 # fetch the program map 64 prog_array = b.get_table("syscall") 65 66 # map the 64 syscall to the ignore function in the program map 67 noop_fn = b.load_func("noop", BPF.RAW_TRACEPOINT) 68 prog_array[ct.c_int(64)] = ct.c_int(noop_fn.fd) 69 70 b.trace_print()