1# Copyright 2015 PLUMgrid 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from __future__ import print_function 16import atexit 17import ctypes as ct 18import fcntl 19import json 20import os 21import re 22import errno 23import sys 24import platform 25 26from .libbcc import lib, bcc_symbol, bcc_symbol_option, bcc_stacktrace_build_id, _SYM_CB_TYPE 27from .table import Table, PerfEventArray, RingBuf, BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK 28from .perf import Perf 29from .utils import get_online_cpus, printb, _assert_is_bytes, ArgString, StrcmpRewrite 30from .version import __version__ 31from .disassembler import disassemble_prog, decode_map 32from .usdt import USDT, USDTException 33 34try: 35 basestring 36except NameError: # Python 3 37 basestring = str 38 39_default_probe_limit = 1000 40_num_open_probes = 0 41 42# for tests 43def _get_num_open_probes(): 44 global _num_open_probes 45 return _num_open_probes 46 47DEBUGFS = "/sys/kernel/debug" 48TRACEFS = os.path.join(DEBUGFS, "tracing") 49if not os.path.exists(TRACEFS): 50 TRACEFS = "/sys/kernel/tracing" 51 52# Debug flags 53 54# Debug output compiled LLVM IR. 55DEBUG_LLVM_IR = 0x1 56# Debug output loaded BPF bytecode and register state on branches. 57DEBUG_BPF = 0x2 58# Debug output pre-processor result. 59DEBUG_PREPROCESSOR = 0x4 60# Debug output ASM instructions embedded with source. 61DEBUG_SOURCE = 0x8 62# Debug output register state on all instructions in addition to DEBUG_BPF. 63DEBUG_BPF_REGISTER_STATE = 0x10 64# Debug BTF. 65DEBUG_BTF = 0x20 66 67class SymbolCache(object): 68 def __init__(self, pid): 69 self.cache = lib.bcc_symcache_new( 70 pid, ct.cast(None, ct.POINTER(bcc_symbol_option))) 71 72 def resolve(self, addr, demangle): 73 """ 74 Return a tuple of the symbol (function), its offset from the beginning 75 of the function, and the module in which it lies. For example: 76 ("start_thread", 0x202, "/usr/lib/.../libpthread-2.24.so") 77 If the symbol cannot be found but we know which module it is in, 78 return the module name and the offset from the beginning of the 79 module. If we don't even know the module, return the absolute 80 address as the offset. 81 """ 82 83 sym = bcc_symbol() 84 if demangle: 85 res = lib.bcc_symcache_resolve(self.cache, addr, ct.byref(sym)) 86 else: 87 res = lib.bcc_symcache_resolve_no_demangle(self.cache, addr, 88 ct.byref(sym)) 89 if res < 0: 90 if sym.module and sym.offset: 91 return (None, sym.offset, 92 ct.cast(sym.module, ct.c_char_p).value) 93 return (None, addr, None) 94 if demangle: 95 name_res = sym.demangle_name 96 lib.bcc_symbol_free_demangle_name(ct.byref(sym)) 97 else: 98 name_res = sym.name 99 return (name_res, sym.offset, ct.cast(sym.module, ct.c_char_p).value) 100 101 def resolve_name(self, module, name): 102 module = _assert_is_bytes(module) 103 name = _assert_is_bytes(name) 104 addr = ct.c_ulonglong() 105 if lib.bcc_symcache_resolve_name(self.cache, module, name, 106 ct.byref(addr)) < 0: 107 return -1 108 return addr.value 109 110class PerfType: 111 # From perf_type_id in uapi/linux/perf_event.h 112 HARDWARE = 0 113 SOFTWARE = 1 114 TRACEPOINT = 2 115 HW_CACHE = 3 116 RAW = 4 117 BREAKPOINT = 5 118 119class PerfHWConfig: 120 # From perf_hw_id in uapi/linux/perf_event.h 121 CPU_CYCLES = 0 122 INSTRUCTIONS = 1 123 CACHE_REFERENCES = 2 124 CACHE_MISSES = 3 125 BRANCH_INSTRUCTIONS = 4 126 BRANCH_MISSES = 5 127 BUS_CYCLES = 6 128 STALLED_CYCLES_FRONTEND = 7 129 STALLED_CYCLES_BACKEND = 8 130 REF_CPU_CYCLES = 9 131 132class PerfSWConfig: 133 # From perf_sw_id in uapi/linux/perf_event.h 134 CPU_CLOCK = 0 135 TASK_CLOCK = 1 136 PAGE_FAULTS = 2 137 CONTEXT_SWITCHES = 3 138 CPU_MIGRATIONS = 4 139 PAGE_FAULTS_MIN = 5 140 PAGE_FAULTS_MAJ = 6 141 ALIGNMENT_FAULTS = 7 142 EMULATION_FAULTS = 8 143 DUMMY = 9 144 BPF_OUTPUT = 10 145 146class PerfEventSampleFormat: 147 # from perf_event_sample_format in uapi/linux/bpf.h 148 IP = (1 << 0) 149 TID = (1 << 1) 150 TIME = (1 << 2) 151 ADDR = (1 << 3) 152 READ = (1 << 4) 153 CALLCHAIN = (1 << 5) 154 ID = (1 << 6) 155 CPU = (1 << 7) 156 PERIOD = (1 << 8) 157 STREAM_ID = (1 << 9) 158 RAW = (1 << 10) 159 BRANCH_STACK = (1 << 11) 160 REGS_USER = (1 << 12) 161 STACK_USER = (1 << 13) 162 WEIGHT = (1 << 14) 163 DATA_SRC = (1 << 15) 164 IDENTIFIER = (1 << 16) 165 TRANSACTION = (1 << 17) 166 REGS_INTR = (1 << 18) 167 PHYS_ADDR = (1 << 19) 168 AUX = (1 << 20) 169 CGROUP = (1 << 21) 170 DATA_PAGE_SIZE = (1 << 22) 171 CODE_PAGE_SIZE = (1 << 23) 172 WEIGHT_STRUCT = (1 << 24) 173 174class BPFProgType: 175 # From bpf_prog_type in uapi/linux/bpf.h 176 SOCKET_FILTER = 1 177 KPROBE = 2 178 SCHED_CLS = 3 179 SCHED_ACT = 4 180 TRACEPOINT = 5 181 XDP = 6 182 PERF_EVENT = 7 183 CGROUP_SKB = 8 184 CGROUP_SOCK = 9 185 LWT_IN = 10 186 LWT_OUT = 11 187 LWT_XMIT = 12 188 SOCK_OPS = 13 189 SK_SKB = 14 190 CGROUP_DEVICE = 15 191 SK_MSG = 16 192 RAW_TRACEPOINT = 17 193 CGROUP_SOCK_ADDR = 18 194 CGROUP_SOCKOPT = 25 195 TRACING = 26 196 LSM = 29 197 198class BPFAttachType: 199 # from bpf_attach_type uapi/linux/bpf.h 200 CGROUP_INET_INGRESS = 0 201 CGROUP_INET_EGRESS = 1 202 CGROUP_INET_SOCK_CREATE = 2 203 CGROUP_SOCK_OPS = 3 204 SK_SKB_STREAM_PARSER = 4 205 SK_SKB_STREAM_VERDICT = 5 206 CGROUP_DEVICE = 6 207 SK_MSG_VERDICT = 7 208 CGROUP_INET4_BIND = 8 209 CGROUP_INET6_BIND = 9 210 CGROUP_INET4_CONNECT = 10 211 CGROUP_INET6_CONNECT = 11 212 CGROUP_INET4_POST_BIND = 12 213 CGROUP_INET6_POST_BIND = 13 214 CGROUP_UDP4_SENDMSG = 14 215 CGROUP_UDP6_SENDMSG = 15 216 LIRC_MODE2 = 16 217 FLOW_DISSECTOR = 17 218 CGROUP_SYSCTL = 18 219 CGROUP_UDP4_RECVMSG = 19 220 CGROUP_UDP6_RECVMSG = 20 221 CGROUP_GETSOCKOPT = 21 222 CGROUP_SETSOCKOPT = 22 223 TRACE_RAW_TP = 23 224 TRACE_FENTRY = 24 225 TRACE_FEXIT = 25 226 MODIFY_RETURN = 26 227 LSM_MAC = 27 228 TRACE_ITER = 28 229 CGROUP_INET4_GETPEERNAME = 29 230 CGROUP_INET6_GETPEERNAME = 30 231 CGROUP_INET4_GETSOCKNAME = 31 232 CGROUP_INET6_GETSOCKNAME = 32 233 XDP_DEVMAP = 33 234 CGROUP_INET_SOCK_RELEASE = 34 235 XDP_CPUMAP = 35 236 SK_LOOKUP = 36 237 XDP = 37 238 SK_SKB_VERDICT = 38 239 240class XDPAction: 241 # from xdp_action uapi/linux/bpf.h 242 XDP_ABORTED = 0 243 XDP_DROP = 1 244 XDP_PASS = 2 245 XDP_TX = 3 246 XDP_REDIRECT = 4 247 248class XDPFlags: 249 # from xdp_flags uapi/linux/if_link.h 250 # unlike similar enum-type holder classes in this file, source for these 251 # is #define XDP_FLAGS_UPDATE_IF_NOEXIST, #define XDP_FLAGS_SKB_MODE, ... 252 UPDATE_IF_NOEXIST = (1 << 0) 253 SKB_MODE = (1 << 1) 254 DRV_MODE = (1 << 2) 255 HW_MODE = (1 << 3) 256 REPLACE = (1 << 4) 257 258class BPF(object): 259 # Here for backwards compatibility only, add new enum members and types 260 # the appropriate wrapper class elsewhere in this file to avoid namespace 261 # collision issues 262 SOCKET_FILTER = BPFProgType.SOCKET_FILTER 263 KPROBE = BPFProgType.KPROBE 264 SCHED_CLS = BPFProgType.SCHED_CLS 265 SCHED_ACT = BPFProgType.SCHED_ACT 266 TRACEPOINT = BPFProgType.TRACEPOINT 267 XDP = BPFProgType.XDP 268 PERF_EVENT = BPFProgType.PERF_EVENT 269 CGROUP_SKB = BPFProgType.CGROUP_SKB 270 CGROUP_SOCK = BPFProgType.CGROUP_SOCK 271 LWT_IN = BPFProgType.LWT_IN 272 LWT_OUT = BPFProgType.LWT_OUT 273 LWT_XMIT = BPFProgType.LWT_XMIT 274 SOCK_OPS = BPFProgType.SOCK_OPS 275 SK_SKB = BPFProgType.SK_SKB 276 CGROUP_DEVICE = BPFProgType.CGROUP_DEVICE 277 SK_MSG = BPFProgType.SK_MSG 278 RAW_TRACEPOINT = BPFProgType.RAW_TRACEPOINT 279 CGROUP_SOCK_ADDR = BPFProgType.CGROUP_SOCK_ADDR 280 TRACING = BPFProgType.TRACING 281 LSM = BPFProgType.LSM 282 283 XDP_ABORTED = XDPAction.XDP_ABORTED 284 XDP_DROP = XDPAction.XDP_DROP 285 XDP_PASS = XDPAction.XDP_PASS 286 XDP_TX = XDPAction.XDP_TX 287 XDP_REDIRECT = XDPAction.XDP_REDIRECT 288 289 XDP_FLAGS_UPDATE_IF_NOEXIST = XDPFlags.UPDATE_IF_NOEXIST 290 XDP_FLAGS_SKB_MODE = XDPFlags.SKB_MODE 291 XDP_FLAGS_DRV_MODE = XDPFlags.DRV_MODE 292 XDP_FLAGS_HW_MODE = XDPFlags.HW_MODE 293 XDP_FLAGS_REPLACE = XDPFlags.REPLACE 294 # END enum backwards compat 295 296 _probe_repl = re.compile(b"[^a-zA-Z0-9_]") 297 _sym_caches = {} 298 _bsymcache = lib.bcc_buildsymcache_new() 299 300 _auto_includes = { 301 "linux/time.h": ["time"], 302 "linux/fs.h": ["fs", "file"], 303 "linux/blkdev.h": ["bio", "request"], 304 "linux/slab.h": ["alloc"], 305 "linux/netdevice.h": ["sk_buff", "net_device"] 306 } 307 308 _syscall_prefixes = [ 309 b"sys_", 310 b"__x64_sys_", 311 b"__x32_compat_sys_", 312 b"__ia32_compat_sys_", 313 b"__arm64_sys_", 314 b"__s390x_sys_", 315 b"__s390_sys_", 316 ] 317 318 # BPF timestamps come from the monotonic clock. To be able to filter 319 # and compare them from Python, we need to invoke clock_gettime. 320 # Adapted from http://stackoverflow.com/a/1205762 321 CLOCK_MONOTONIC = 1 # see <linux/time.h> 322 323 class timespec(ct.Structure): 324 _fields_ = [('tv_sec', ct.c_long), ('tv_nsec', ct.c_long)] 325 326 _librt = ct.CDLL('librt.so.1', use_errno=True) 327 _clock_gettime = _librt.clock_gettime 328 _clock_gettime.argtypes = [ct.c_int, ct.POINTER(timespec)] 329 330 @classmethod 331 def monotonic_time(cls): 332 """monotonic_time() 333 Returns the system monotonic time from clock_gettime, using the 334 CLOCK_MONOTONIC constant. The time returned is in nanoseconds. 335 """ 336 t = cls.timespec() 337 if cls._clock_gettime(cls.CLOCK_MONOTONIC, ct.byref(t)) != 0: 338 errno = ct.get_errno() 339 raise OSError(errno, os.strerror(errno)) 340 return t.tv_sec * 1e9 + t.tv_nsec 341 342 @classmethod 343 def generate_auto_includes(cls, program_words): 344 """ 345 Generates #include statements automatically based on a set of 346 recognized types such as sk_buff and bio. The input is all the words 347 that appear in the BPF program, and the output is a (possibly empty) 348 string of #include statements, such as "#include <linux/fs.h>". 349 """ 350 headers = "" 351 for header, keywords in cls._auto_includes.items(): 352 for keyword in keywords: 353 for word in program_words: 354 if keyword in word and header not in headers: 355 headers += "#include <%s>\n" % header 356 return headers 357 358 # defined for compatibility reasons, to be removed 359 Table = Table 360 361 class Function(object): 362 def __init__(self, bpf, name, fd): 363 self.bpf = bpf 364 self.name = name 365 self.fd = fd 366 367 @staticmethod 368 def _find_file(filename): 369 """ If filename is invalid, search in ./ of argv[0] """ 370 if filename: 371 if not os.path.isfile(filename): 372 argv0 = ArgString(sys.argv[0]) 373 t = b"/".join([os.path.abspath(os.path.dirname(argv0.__bytes__())), filename]) 374 if os.path.isfile(t): 375 filename = t 376 else: 377 raise Exception("Could not find file %s" % filename) 378 return filename 379 380 @staticmethod 381 def find_exe(bin_path): 382 """ 383 find_exe(bin_path) 384 385 Traverses the PATH environment variable, looking for the first 386 directory that contains an executable file named bin_path, and 387 returns the full path to that file, or None if no such file 388 can be found. This is meant to replace invocations of the 389 "which" shell utility, which doesn't have portable semantics 390 for skipping aliases. 391 """ 392 # Source: http://stackoverflow.com/a/377028 393 def is_exe(fpath): 394 return os.path.isfile(fpath) and \ 395 os.access(fpath, os.X_OK) 396 397 fpath, fname = os.path.split(bin_path) 398 if fpath: 399 if is_exe(bin_path): 400 return bin_path 401 else: 402 for path in os.environ["PATH"].split(os.pathsep): 403 path = path.strip('"') 404 exe_file = os.path.join(path.encode(), bin_path) 405 if is_exe(exe_file): 406 return exe_file 407 return None 408 409 def __init__(self, src_file=b"", hdr_file=b"", text=None, debug=0, 410 cflags=[], usdt_contexts=[], allow_rlimit=True, device=None, 411 attach_usdt_ignore_pid=False): 412 """Create a new BPF module with the given source code. 413 414 Note: 415 All fields are marked as optional, but either `src_file` or `text` 416 must be supplied, and not both. 417 418 Args: 419 src_file (Optional[str]): Path to a source file for the module 420 hdr_file (Optional[str]): Path to a helper header file for the `src_file` 421 text (Optional[str]): Contents of a source file for the module 422 debug (Optional[int]): Flags used for debug prints, can be |'d together 423 See "Debug flags" for explanation 424 """ 425 426 src_file = _assert_is_bytes(src_file) 427 hdr_file = _assert_is_bytes(hdr_file) 428 text = _assert_is_bytes(text) 429 430 assert not (text and src_file) 431 432 self.kprobe_fds = {} 433 self.uprobe_fds = {} 434 self.tracepoint_fds = {} 435 self.raw_tracepoint_fds = {} 436 self.kfunc_entry_fds = {} 437 self.kfunc_exit_fds = {} 438 self.lsm_fds = {} 439 self.perf_buffers = {} 440 self.open_perf_events = {} 441 self._ringbuf_manager = None 442 self.tracefile = None 443 atexit.register(self.cleanup) 444 445 self.debug = debug 446 self.funcs = {} 447 self.tables = {} 448 self.module = None 449 cflags_array = (ct.c_char_p * len(cflags))() 450 for i, s in enumerate(cflags): cflags_array[i] = bytes(ArgString(s)) 451 452 if src_file: 453 src_file = BPF._find_file(src_file) 454 hdr_file = BPF._find_file(hdr_file) 455 456 if src_file: 457 # Read the BPF C source file into the text variable. This ensures, 458 # that files and inline text are treated equally. 459 with open(src_file, mode="rb") as file: 460 text = file.read() 461 462 ctx_array = (ct.c_void_p * len(usdt_contexts))() 463 for i, usdt in enumerate(usdt_contexts): 464 ctx_array[i] = ct.c_void_p(usdt.get_context()) 465 usdt_text = lib.bcc_usdt_genargs(ctx_array, len(usdt_contexts)) 466 if usdt_text is None: 467 raise Exception("can't generate USDT probe arguments; " + 468 "possible cause is missing pid when a " + 469 "probe in a shared object has multiple " + 470 "locations") 471 text = usdt_text + text 472 473 474 self.module = lib.bpf_module_create_c_from_string(text, 475 self.debug, 476 cflags_array, len(cflags_array), 477 allow_rlimit, device) 478 if not self.module: 479 raise Exception("Failed to compile BPF module %s" % (src_file or "<text>")) 480 481 for usdt_context in usdt_contexts: 482 usdt_context.attach_uprobes(self, attach_usdt_ignore_pid) 483 484 # If any "kprobe__" or "tracepoint__" or "raw_tracepoint__" 485 # prefixed functions were defined, 486 # they will be loaded and attached here. 487 self._trace_autoload() 488 489 def load_funcs(self, prog_type=KPROBE): 490 """load_funcs(prog_type=KPROBE) 491 492 Load all functions in this BPF module with the given type. 493 Returns a list of the function handles.""" 494 495 fns = [] 496 for i in range(0, lib.bpf_num_functions(self.module)): 497 func_name = lib.bpf_function_name(self.module, i) 498 fns.append(self.load_func(func_name, prog_type)) 499 500 return fns 501 502 def load_func(self, func_name, prog_type, device = None, attach_type = -1): 503 func_name = _assert_is_bytes(func_name) 504 if func_name in self.funcs: 505 return self.funcs[func_name] 506 if not lib.bpf_function_start(self.module, func_name): 507 raise Exception("Unknown program %s" % func_name) 508 log_level = 0 509 if (self.debug & DEBUG_BPF_REGISTER_STATE): 510 log_level = 2 511 elif (self.debug & DEBUG_BPF): 512 log_level = 1 513 fd = lib.bcc_func_load(self.module, prog_type, func_name, 514 lib.bpf_function_start(self.module, func_name), 515 lib.bpf_function_size(self.module, func_name), 516 lib.bpf_module_license(self.module), 517 lib.bpf_module_kern_version(self.module), 518 log_level, None, 0, device, attach_type) 519 520 if fd < 0: 521 atexit.register(self.donothing) 522 if ct.get_errno() == errno.EPERM: 523 raise Exception("Need super-user privileges to run") 524 525 errstr = os.strerror(ct.get_errno()) 526 raise Exception("Failed to load BPF program %s: %s" % 527 (func_name, errstr)) 528 529 fn = BPF.Function(self, func_name, fd) 530 self.funcs[func_name] = fn 531 532 return fn 533 534 def dump_func(self, func_name): 535 """ 536 Return the eBPF bytecodes for the specified function as a string 537 """ 538 func_name = _assert_is_bytes(func_name) 539 if not lib.bpf_function_start(self.module, func_name): 540 raise Exception("Unknown program %s" % func_name) 541 542 start, = lib.bpf_function_start(self.module, func_name), 543 size, = lib.bpf_function_size(self.module, func_name), 544 return ct.string_at(start, size) 545 546 def disassemble_func(self, func_name): 547 bpfstr = self.dump_func(func_name) 548 return disassemble_prog(func_name, bpfstr) 549 550 def decode_table(self, table_name, sizeinfo=False): 551 table_obj = self[table_name] 552 table_type = lib.bpf_table_type_id(self.module, table_obj.map_id) 553 return decode_map(table_name, table_obj, table_type, sizeinfo=sizeinfo) 554 555 str2ctype = { 556 u"_Bool": ct.c_bool, 557 u"char": ct.c_char, 558 u"wchar_t": ct.c_wchar, 559 u"unsigned char": ct.c_ubyte, 560 u"short": ct.c_short, 561 u"unsigned short": ct.c_ushort, 562 u"int": ct.c_int, 563 u"unsigned int": ct.c_uint, 564 u"long": ct.c_long, 565 u"unsigned long": ct.c_ulong, 566 u"long long": ct.c_longlong, 567 u"unsigned long long": ct.c_ulonglong, 568 u"float": ct.c_float, 569 u"double": ct.c_double, 570 u"long double": ct.c_longdouble, 571 u"__int128": ct.c_int64 * 2, 572 u"unsigned __int128": ct.c_uint64 * 2, 573 } 574 @staticmethod 575 def _decode_table_type(desc): 576 if isinstance(desc, basestring): 577 return BPF.str2ctype[desc] 578 anon = [] 579 fields = [] 580 for t in desc[1]: 581 if len(t) == 2: 582 fields.append((t[0], BPF._decode_table_type(t[1]))) 583 elif len(t) == 3: 584 if isinstance(t[2], list): 585 fields.append((t[0], BPF._decode_table_type(t[1]) * t[2][0])) 586 elif isinstance(t[2], int): 587 fields.append((t[0], BPF._decode_table_type(t[1]), t[2])) 588 elif isinstance(t[2], basestring) and ( 589 t[2] == u"union" or t[2] == u"struct" or 590 t[2] == u"struct_packed"): 591 name = t[0] 592 if name == "": 593 name = "__anon%d" % len(anon) 594 anon.append(name) 595 fields.append((name, BPF._decode_table_type(t))) 596 else: 597 raise Exception("Failed to decode type %s" % str(t)) 598 else: 599 raise Exception("Failed to decode type %s" % str(t)) 600 base = ct.Structure 601 is_packed = False 602 if len(desc) > 2: 603 if desc[2] == u"union": 604 base = ct.Union 605 elif desc[2] == u"struct": 606 base = ct.Structure 607 elif desc[2] == u"struct_packed": 608 base = ct.Structure 609 is_packed = True 610 if is_packed: 611 cls = type(str(desc[0]), (base,), dict(_anonymous_=anon, _pack_=1, 612 _fields_=fields)) 613 else: 614 cls = type(str(desc[0]), (base,), dict(_anonymous_=anon, 615 _fields_=fields)) 616 return cls 617 618 def get_table(self, name, keytype=None, leaftype=None, reducer=None): 619 name = _assert_is_bytes(name) 620 map_id = lib.bpf_table_id(self.module, name) 621 map_fd = lib.bpf_table_fd(self.module, name) 622 is_queuestack = lib.bpf_table_type_id(self.module, map_id) in [BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK] 623 if map_fd < 0: 624 raise KeyError 625 if not keytype and not is_queuestack: 626 key_desc = lib.bpf_table_key_desc(self.module, name).decode("utf-8") 627 if not key_desc: 628 raise Exception("Failed to load BPF Table %s key desc" % name) 629 keytype = BPF._decode_table_type(json.loads(key_desc)) 630 if not leaftype: 631 leaf_desc = lib.bpf_table_leaf_desc(self.module, name).decode("utf-8") 632 if not leaf_desc: 633 raise Exception("Failed to load BPF Table %s leaf desc" % name) 634 leaftype = BPF._decode_table_type(json.loads(leaf_desc)) 635 return Table(self, map_id, map_fd, keytype, leaftype, name, reducer=reducer) 636 637 def __getitem__(self, key): 638 if key not in self.tables: 639 self.tables[key] = self.get_table(key) 640 return self.tables[key] 641 642 def __setitem__(self, key, leaf): 643 self.tables[key] = leaf 644 645 def __len__(self): 646 return len(self.tables) 647 648 def __delitem__(self, key): 649 del self.tables[key] 650 651 def __iter__(self): 652 return self.tables.__iter__() 653 654 @staticmethod 655 def attach_func(fn, attachable_fd, attach_type, flags=0): 656 if not isinstance(fn, BPF.Function): 657 raise Exception("arg 1 must be of type BPF.Function") 658 659 res = lib.bpf_prog_attach(fn.fd, attachable_fd, attach_type, flags) 660 if res < 0: 661 raise Exception("Failed to attach BPF function with attach_type "\ 662 "{0}: {1}".format(attach_type, os.strerror(-res))) 663 664 @staticmethod 665 def detach_func(fn, attachable_fd, attach_type): 666 if not isinstance(fn, BPF.Function): 667 raise Exception("arg 1 must be of type BPF.Function") 668 669 res = lib.bpf_prog_detach2(fn.fd, attachable_fd, attach_type) 670 if res < 0: 671 raise Exception("Failed to detach BPF function with attach_type "\ 672 "{0}: {1}".format(attach_type, os.strerror(-res))) 673 674 @staticmethod 675 def attach_raw_socket(fn, dev): 676 dev = _assert_is_bytes(dev) 677 if not isinstance(fn, BPF.Function): 678 raise Exception("arg 1 must be of type BPF.Function") 679 sock = lib.bpf_open_raw_sock(dev) 680 if sock < 0: 681 errstr = os.strerror(ct.get_errno()) 682 raise Exception("Failed to open raw device %s: %s" % (dev, errstr)) 683 res = lib.bpf_attach_socket(sock, fn.fd) 684 if res < 0: 685 errstr = os.strerror(ct.get_errno()) 686 raise Exception("Failed to attach BPF to device %s: %s" 687 % (dev, errstr)) 688 fn.sock = sock 689 690 @staticmethod 691 def get_kprobe_functions(event_re): 692 blacklist_file = "%s/kprobes/blacklist" % DEBUGFS 693 try: 694 with open(blacklist_file, "rb") as blacklist_f: 695 blacklist = set([line.rstrip().split()[1] for line in blacklist_f]) 696 except IOError as e: 697 if e.errno != errno.EPERM: 698 raise e 699 blacklist = set([]) 700 701 avail_filter_file = "%s/tracing/available_filter_functions" % DEBUGFS 702 try: 703 with open(avail_filter_file, "rb") as avail_filter_f: 704 avail_filter = set([line.rstrip().split()[0] for line in avail_filter_f]) 705 except IOError as e: 706 if e.errno != errno.EPERM: 707 raise e 708 avail_filter = set([]) 709 710 fns = [] 711 712 in_init_section = 0 713 in_irq_section = 0 714 with open("/proc/kallsyms", "rb") as avail_file: 715 for line in avail_file: 716 (t, fn) = line.rstrip().split()[1:3] 717 # Skip all functions defined between __init_begin and 718 # __init_end 719 if in_init_section == 0: 720 if fn == b'__init_begin': 721 in_init_section = 1 722 continue 723 elif in_init_section == 1: 724 if fn == b'__init_end': 725 in_init_section = 2 726 continue 727 # Skip all functions defined between __irqentry_text_start and 728 # __irqentry_text_end 729 if in_irq_section == 0: 730 if fn == b'__irqentry_text_start': 731 in_irq_section = 1 732 continue 733 # __irqentry_text_end is not always after 734 # __irqentry_text_start. But only happens when 735 # no functions between two irqentry_text 736 elif fn == b'__irqentry_text_end': 737 in_irq_section = 2 738 continue 739 elif in_irq_section == 1: 740 if fn == b'__irqentry_text_end': 741 in_irq_section = 2 742 continue 743 # All functions defined as NOKPROBE_SYMBOL() start with the 744 # prefix _kbl_addr_*, blacklisting them by looking at the name 745 # allows to catch also those symbols that are defined in kernel 746 # modules. 747 if fn.startswith(b'_kbl_addr_'): 748 continue 749 # Explicitly blacklist perf-related functions, they are all 750 # non-attachable. 751 elif fn.startswith(b'__perf') or fn.startswith(b'perf_'): 752 continue 753 # Exclude all static functions with prefix __SCT__, they are 754 # all non-attachable 755 elif fn.startswith(b'__SCT__'): 756 continue 757 # Exclude all gcc 8's extra .cold functions 758 elif re.match(b'^.*\.cold(\.\d+)?$', fn): 759 continue 760 if (t.lower() in [b't', b'w']) and re.fullmatch(event_re, fn) \ 761 and fn not in blacklist \ 762 and fn in avail_filter: 763 fns.append(fn) 764 return set(fns) # Some functions may appear more than once 765 766 def _check_probe_quota(self, num_new_probes): 767 global _num_open_probes 768 if _num_open_probes + num_new_probes > BPF.get_probe_limit(): 769 raise Exception("Number of open probes would exceed global quota") 770 771 @staticmethod 772 def get_probe_limit(): 773 env_probe_limit = os.environ.get('BCC_PROBE_LIMIT') 774 if env_probe_limit and env_probe_limit.isdigit(): 775 return int(env_probe_limit) 776 else: 777 return _default_probe_limit 778 779 def _add_kprobe_fd(self, ev_name, fn_name, fd): 780 global _num_open_probes 781 if ev_name not in self.kprobe_fds: 782 self.kprobe_fds[ev_name] = {} 783 self.kprobe_fds[ev_name][fn_name] = fd 784 _num_open_probes += 1 785 786 def _del_kprobe_fd(self, ev_name, fn_name): 787 global _num_open_probes 788 del self.kprobe_fds[ev_name][fn_name] 789 _num_open_probes -= 1 790 791 def _add_uprobe_fd(self, name, fd): 792 global _num_open_probes 793 self.uprobe_fds[name] = fd 794 _num_open_probes += 1 795 796 def _del_uprobe_fd(self, name): 797 global _num_open_probes 798 del self.uprobe_fds[name] 799 _num_open_probes -= 1 800 801 # Find current system's syscall prefix by testing on the BPF syscall. 802 # If no valid value found, will return the first possible value which 803 # would probably lead to error in later API calls. 804 def get_syscall_prefix(self): 805 for prefix in self._syscall_prefixes: 806 if self.ksymname(b"%sbpf" % prefix) != -1: 807 return prefix 808 return self._syscall_prefixes[0] 809 810 # Given a syscall's name, return the full Kernel function name with current 811 # system's syscall prefix. For example, given "clone" the helper would 812 # return "sys_clone" or "__x64_sys_clone". 813 def get_syscall_fnname(self, name): 814 name = _assert_is_bytes(name) 815 return self.get_syscall_prefix() + name 816 817 # Given a Kernel function name that represents a syscall but already has a 818 # prefix included, transform it to current system's prefix. For example, 819 # if "sys_clone" provided, the helper may translate it to "__x64_sys_clone". 820 def fix_syscall_fnname(self, name): 821 name = _assert_is_bytes(name) 822 for prefix in self._syscall_prefixes: 823 if name.startswith(prefix): 824 return self.get_syscall_fnname(name[len(prefix):]) 825 return name 826 827 def attach_kprobe(self, event=b"", event_off=0, fn_name=b"", event_re=b""): 828 event = _assert_is_bytes(event) 829 fn_name = _assert_is_bytes(fn_name) 830 event_re = _assert_is_bytes(event_re) 831 832 # allow the caller to glob multiple functions together 833 if event_re: 834 matches = BPF.get_kprobe_functions(event_re) 835 self._check_probe_quota(len(matches)) 836 failed = 0 837 probes = [] 838 for line in matches: 839 try: 840 self.attach_kprobe(event=line, fn_name=fn_name) 841 except: 842 failed += 1 843 probes.append(line) 844 if failed == len(matches): 845 raise Exception("Failed to attach BPF program %s to kprobe %s" 846 ", it's not traceable (either non-existing, inlined, or marked as \"notrace\")" % 847 (fn_name, '/'.join(probes))) 848 return 849 850 self._check_probe_quota(1) 851 fn = self.load_func(fn_name, BPF.KPROBE) 852 ev_name = b"p_" + event.replace(b"+", b"_").replace(b".", b"_") 853 fd = lib.bpf_attach_kprobe(fn.fd, 0, ev_name, event, event_off, 0) 854 if fd < 0: 855 raise Exception("Failed to attach BPF program %s to kprobe %s" 856 ", it's not traceable (either non-existing, inlined, or marked as \"notrace\")" % 857 (fn_name, event)) 858 self._add_kprobe_fd(ev_name, fn_name, fd) 859 return self 860 861 def attach_kretprobe(self, event=b"", fn_name=b"", event_re=b"", maxactive=0): 862 event = _assert_is_bytes(event) 863 fn_name = _assert_is_bytes(fn_name) 864 event_re = _assert_is_bytes(event_re) 865 866 # allow the caller to glob multiple functions together 867 if event_re: 868 matches = BPF.get_kprobe_functions(event_re) 869 failed = 0 870 probes = [] 871 for line in matches: 872 try: 873 self.attach_kretprobe(event=line, fn_name=fn_name, 874 maxactive=maxactive) 875 except: 876 failed += 1 877 probes.append(line) 878 if failed == len(matches): 879 raise Exception("Failed to attach BPF program %s to kretprobe %s" 880 ", it's not traceable (either non-existing, inlined, or marked as \"notrace\")" % 881 (fn_name, '/'.join(probes))) 882 return 883 884 self._check_probe_quota(1) 885 fn = self.load_func(fn_name, BPF.KPROBE) 886 ev_name = b"r_" + event.replace(b"+", b"_").replace(b".", b"_") 887 fd = lib.bpf_attach_kprobe(fn.fd, 1, ev_name, event, 0, maxactive) 888 if fd < 0: 889 raise Exception("Failed to attach BPF program %s to kretprobe %s" 890 ", it's not traceable (either non-existing, inlined, or marked as \"notrace\")" % 891 (fn_name, event)) 892 self._add_kprobe_fd(ev_name, fn_name, fd) 893 return self 894 895 def detach_kprobe_event(self, ev_name): 896 ev_name = _assert_is_bytes(ev_name) 897 fn_names = list(self.kprobe_fds[ev_name].keys()) 898 for fn_name in fn_names: 899 self.detach_kprobe_event_by_fn(ev_name, fn_name) 900 901 def detach_kprobe_event_by_fn(self, ev_name, fn_name): 902 ev_name = _assert_is_bytes(ev_name) 903 fn_name = _assert_is_bytes(fn_name) 904 if ev_name not in self.kprobe_fds: 905 raise Exception("Kprobe %s is not attached" % ev_name) 906 res = lib.bpf_close_perf_event_fd(self.kprobe_fds[ev_name][fn_name]) 907 if res < 0: 908 raise Exception("Failed to close kprobe FD") 909 self._del_kprobe_fd(ev_name, fn_name) 910 if len(self.kprobe_fds[ev_name]) == 0: 911 res = lib.bpf_detach_kprobe(ev_name) 912 if res < 0: 913 raise Exception("Failed to detach BPF from kprobe") 914 915 def detach_kprobe(self, event, fn_name=None): 916 event = _assert_is_bytes(event) 917 ev_name = b"p_" + event.replace(b"+", b"_").replace(b".", b"_") 918 if fn_name: 919 fn_name = _assert_is_bytes(fn_name) 920 self.detach_kprobe_event_by_fn(ev_name, fn_name) 921 else: 922 self.detach_kprobe_event(ev_name) 923 924 def detach_kretprobe(self, event, fn_name=None): 925 event = _assert_is_bytes(event) 926 ev_name = b"r_" + event.replace(b"+", b"_").replace(b".", b"_") 927 if fn_name: 928 fn_name = _assert_is_bytes(fn_name) 929 self.detach_kprobe_event_by_fn(ev_name, fn_name) 930 else: 931 self.detach_kprobe_event(ev_name) 932 933 @staticmethod 934 def attach_xdp(dev, fn, flags=0): 935 ''' 936 This function attaches a BPF function to a device on the device 937 driver level (XDP) 938 ''' 939 dev = _assert_is_bytes(dev) 940 if not isinstance(fn, BPF.Function): 941 raise Exception("arg 1 must be of type BPF.Function") 942 res = lib.bpf_attach_xdp(dev, fn.fd, flags) 943 if res < 0: 944 err_no = ct.get_errno() 945 if err_no == errno.EBADMSG: 946 raise Exception("Internal error while attaching BPF to device,"+ 947 " try increasing the debug level!") 948 else: 949 errstr = os.strerror(err_no) 950 raise Exception("Failed to attach BPF to device %s: %s" 951 % (dev, errstr)) 952 953 @staticmethod 954 def remove_xdp(dev, flags=0): 955 ''' 956 This function removes any BPF function from a device on the 957 device driver level (XDP) 958 ''' 959 dev = _assert_is_bytes(dev) 960 res = lib.bpf_attach_xdp(dev, -1, flags) 961 if res < 0: 962 errstr = os.strerror(ct.get_errno()) 963 raise Exception("Failed to detach BPF from device %s: %s" 964 % (dev, errstr)) 965 966 @classmethod 967 def _check_path_symbol(cls, module, symname, addr, pid, sym_off=0): 968 module = _assert_is_bytes(module) 969 symname = _assert_is_bytes(symname) 970 sym = bcc_symbol() 971 c_pid = 0 if pid == -1 else pid 972 if lib.bcc_resolve_symname( 973 module, symname, 974 addr or 0x0, c_pid, 975 ct.cast(None, ct.POINTER(bcc_symbol_option)), 976 ct.byref(sym), 977 ) < 0: 978 raise Exception("could not determine address of symbol %s in %s" 979 % (symname.decode(), module.decode())) 980 new_addr = sym.offset + sym_off 981 module_path = ct.cast(sym.module, ct.c_char_p).value 982 lib.bcc_procutils_free(sym.module) 983 return module_path, new_addr 984 985 @staticmethod 986 def find_library(libname): 987 libname = _assert_is_bytes(libname) 988 res = lib.bcc_procutils_which_so(libname, 0) 989 if not res: 990 return None 991 libpath = ct.cast(res, ct.c_char_p).value 992 lib.bcc_procutils_free(res) 993 return libpath 994 995 @staticmethod 996 def get_tracepoints(tp_re): 997 results = [] 998 events_dir = os.path.join(TRACEFS, "events") 999 for category in os.listdir(events_dir): 1000 cat_dir = os.path.join(events_dir, category) 1001 if not os.path.isdir(cat_dir): 1002 continue 1003 for event in os.listdir(cat_dir): 1004 evt_dir = os.path.join(cat_dir, event) 1005 if os.path.isdir(evt_dir): 1006 tp = ("%s:%s" % (category, event)) 1007 if re.match(tp_re.decode(), tp): 1008 results.append(tp.encode()) 1009 return results 1010 1011 @staticmethod 1012 def tracepoint_exists(category, event): 1013 evt_dir = os.path.join(TRACEFS, "events", category, event) 1014 return os.path.isdir(evt_dir) 1015 1016 def attach_tracepoint(self, tp=b"", tp_re=b"", fn_name=b""): 1017 """attach_tracepoint(tp="", tp_re="", fn_name="") 1018 1019 Run the bpf function denoted by fn_name every time the kernel tracepoint 1020 specified by 'tp' is hit. The optional parameters pid, cpu, and group_fd 1021 can be used to filter the probe. The tracepoint specification is simply 1022 the tracepoint category and the tracepoint name, separated by a colon. 1023 For example: sched:sched_switch, syscalls:sys_enter_bind, etc. 1024 1025 Instead of a tracepoint name, a regular expression can be provided in 1026 tp_re. The program will then attach to tracepoints that match the 1027 provided regular expression. 1028 1029 To obtain a list of kernel tracepoints, use the tplist tool or cat the 1030 file /sys/kernel/debug/tracing/available_events. 1031 1032 Examples: 1033 BPF(text).attach_tracepoint(tp="sched:sched_switch", fn_name="on_switch") 1034 BPF(text).attach_tracepoint(tp_re="sched:.*", fn_name="on_switch") 1035 """ 1036 1037 tp = _assert_is_bytes(tp) 1038 tp_re = _assert_is_bytes(tp_re) 1039 fn_name = _assert_is_bytes(fn_name) 1040 if tp_re: 1041 for tp in BPF.get_tracepoints(tp_re): 1042 self.attach_tracepoint(tp=tp, fn_name=fn_name) 1043 return 1044 1045 fn = self.load_func(fn_name, BPF.TRACEPOINT) 1046 (tp_category, tp_name) = tp.split(b':') 1047 fd = lib.bpf_attach_tracepoint(fn.fd, tp_category, tp_name) 1048 if fd < 0: 1049 raise Exception("Failed to attach BPF program %s to tracepoint %s" % 1050 (fn_name, tp)) 1051 self.tracepoint_fds[tp] = fd 1052 return self 1053 1054 def attach_raw_tracepoint(self, tp=b"", fn_name=b""): 1055 """attach_raw_tracepoint(self, tp=b"", fn_name=b"") 1056 1057 Run the bpf function denoted by fn_name every time the kernel tracepoint 1058 specified by 'tp' is hit. The bpf function should be loaded as a 1059 RAW_TRACEPOINT type. The fn_name is the kernel tracepoint name, 1060 e.g., sched_switch, sys_enter_bind, etc. 1061 1062 Examples: 1063 BPF(text).attach_raw_tracepoint(tp="sched_switch", fn_name="on_switch") 1064 """ 1065 1066 tp = _assert_is_bytes(tp) 1067 if tp in self.raw_tracepoint_fds: 1068 raise Exception("Raw tracepoint %s has been attached" % tp) 1069 1070 fn_name = _assert_is_bytes(fn_name) 1071 fn = self.load_func(fn_name, BPF.RAW_TRACEPOINT) 1072 fd = lib.bpf_attach_raw_tracepoint(fn.fd, tp) 1073 if fd < 0: 1074 raise Exception("Failed to attach BPF to raw tracepoint") 1075 self.raw_tracepoint_fds[tp] = fd 1076 return self 1077 1078 def detach_raw_tracepoint(self, tp=b""): 1079 """detach_raw_tracepoint(tp="") 1080 1081 Stop running the bpf function that is attached to the kernel tracepoint 1082 specified by 'tp'. 1083 1084 Example: bpf.detach_raw_tracepoint("sched_switch") 1085 """ 1086 1087 tp = _assert_is_bytes(tp) 1088 if tp not in self.raw_tracepoint_fds: 1089 raise Exception("Raw tracepoint %s is not attached" % tp) 1090 os.close(self.raw_tracepoint_fds[tp]) 1091 del self.raw_tracepoint_fds[tp] 1092 1093 @staticmethod 1094 def add_prefix(prefix, name): 1095 if not name.startswith(prefix): 1096 name = prefix + name 1097 return name 1098 1099 @staticmethod 1100 def support_kfunc(): 1101 # there's no trampoline support for other than x86_64 arch 1102 if platform.machine() != 'x86_64': 1103 return False 1104 if not lib.bpf_has_kernel_btf(): 1105 return False 1106 # kernel symbol "bpf_trampoline_link_prog" indicates kfunc support 1107 if BPF.ksymname("bpf_trampoline_link_prog") != -1: 1108 return True 1109 return False 1110 1111 @staticmethod 1112 def support_lsm(): 1113 if not lib.bpf_has_kernel_btf(): 1114 return False 1115 # kernel symbol "bpf_lsm_bpf" indicates BPF LSM support 1116 if BPF.ksymname(b"bpf_lsm_bpf") != -1: 1117 return True 1118 return False 1119 1120 def detach_kfunc(self, fn_name=b""): 1121 fn_name = _assert_is_bytes(fn_name) 1122 fn_name = BPF.add_prefix(b"kfunc__", fn_name) 1123 1124 if fn_name not in self.kfunc_entry_fds: 1125 raise Exception("Kernel entry func %s is not attached" % fn_name) 1126 os.close(self.kfunc_entry_fds[fn_name]) 1127 del self.kfunc_entry_fds[fn_name] 1128 1129 def detach_kretfunc(self, fn_name=b""): 1130 fn_name = _assert_is_bytes(fn_name) 1131 fn_name = BPF.add_prefix(b"kretfunc__", fn_name) 1132 1133 if fn_name not in self.kfunc_exit_fds: 1134 raise Exception("Kernel exit func %s is not attached" % fn_name) 1135 os.close(self.kfunc_exit_fds[fn_name]) 1136 del self.kfunc_exit_fds[fn_name] 1137 1138 def attach_kfunc(self, fn_name=b""): 1139 fn_name = _assert_is_bytes(fn_name) 1140 fn_name = BPF.add_prefix(b"kfunc__", fn_name) 1141 1142 if fn_name in self.kfunc_entry_fds: 1143 raise Exception("Kernel entry func %s has been attached" % fn_name) 1144 1145 fn = self.load_func(fn_name, BPF.TRACING) 1146 fd = lib.bpf_attach_kfunc(fn.fd) 1147 if fd < 0: 1148 raise Exception("Failed to attach BPF to entry kernel func") 1149 self.kfunc_entry_fds[fn_name] = fd 1150 return self 1151 1152 def attach_kretfunc(self, fn_name=b""): 1153 fn_name = _assert_is_bytes(fn_name) 1154 fn_name = BPF.add_prefix(b"kretfunc__", fn_name) 1155 1156 if fn_name in self.kfunc_exit_fds: 1157 raise Exception("Kernel exit func %s has been attached" % fn_name) 1158 1159 fn = self.load_func(fn_name, BPF.TRACING) 1160 fd = lib.bpf_attach_kfunc(fn.fd) 1161 if fd < 0: 1162 raise Exception("Failed to attach BPF to exit kernel func") 1163 self.kfunc_exit_fds[fn_name] = fd 1164 return self 1165 1166 def detach_lsm(self, fn_name=b""): 1167 fn_name = _assert_is_bytes(fn_name) 1168 fn_name = BPF.add_prefix(b"lsm__", fn_name) 1169 1170 if fn_name not in self.lsm_fds: 1171 raise Exception("LSM %s is not attached" % fn_name) 1172 os.close(self.lsm_fds[fn_name]) 1173 del self.lsm_fds[fn_name] 1174 1175 def attach_lsm(self, fn_name=b""): 1176 fn_name = _assert_is_bytes(fn_name) 1177 fn_name = BPF.add_prefix(b"lsm__", fn_name) 1178 1179 if fn_name in self.lsm_fds: 1180 raise Exception("LSM %s has been attached" % fn_name) 1181 1182 fn = self.load_func(fn_name, BPF.LSM) 1183 fd = lib.bpf_attach_lsm(fn.fd) 1184 if fd < 0: 1185 raise Exception("Failed to attach LSM") 1186 self.lsm_fds[fn_name] = fd 1187 return self 1188 1189 @staticmethod 1190 def support_raw_tracepoint(): 1191 # kernel symbol "bpf_find_raw_tracepoint" indicates raw_tracepoint support 1192 if BPF.ksymname("bpf_find_raw_tracepoint") != -1 or \ 1193 BPF.ksymname("bpf_get_raw_tracepoint") != -1: 1194 return True 1195 return False 1196 1197 @staticmethod 1198 def support_raw_tracepoint_in_module(): 1199 # kernel symbol "bpf_trace_modules" indicates raw tp support in modules, ref: kernel commit a38d1107 1200 kallsyms = "/proc/kallsyms" 1201 with open(kallsyms) as syms: 1202 for line in syms: 1203 (_, _, name) = line.rstrip().split(" ", 2) 1204 name = name.split("\t")[0] 1205 if name == "bpf_trace_modules": 1206 return True 1207 return False 1208 1209 @staticmethod 1210 def kernel_struct_has_field(struct_name, field_name): 1211 struct_name = _assert_is_bytes(struct_name) 1212 field_name = _assert_is_bytes(field_name) 1213 return lib.kernel_struct_has_field(struct_name, field_name) 1214 1215 def detach_tracepoint(self, tp=b""): 1216 """detach_tracepoint(tp="") 1217 1218 Stop running a bpf function that is attached to the kernel tracepoint 1219 specified by 'tp'. 1220 1221 Example: bpf.detach_tracepoint("sched:sched_switch") 1222 """ 1223 1224 tp = _assert_is_bytes(tp) 1225 if tp not in self.tracepoint_fds: 1226 raise Exception("Tracepoint %s is not attached" % tp) 1227 res = lib.bpf_close_perf_event_fd(self.tracepoint_fds[tp]) 1228 if res < 0: 1229 raise Exception("Failed to detach BPF from tracepoint") 1230 (tp_category, tp_name) = tp.split(b':') 1231 res = lib.bpf_detach_tracepoint(tp_category, tp_name) 1232 if res < 0: 1233 raise Exception("Failed to detach BPF from tracepoint") 1234 del self.tracepoint_fds[tp] 1235 1236 def _attach_perf_event(self, progfd, ev_type, ev_config, 1237 sample_period, sample_freq, pid, cpu, group_fd): 1238 res = lib.bpf_attach_perf_event(progfd, ev_type, ev_config, 1239 sample_period, sample_freq, pid, cpu, group_fd) 1240 if res < 0: 1241 raise Exception("Failed to attach BPF to perf event") 1242 return res 1243 1244 def attach_perf_event(self, ev_type=-1, ev_config=-1, fn_name=b"", 1245 sample_period=0, sample_freq=0, pid=-1, cpu=-1, group_fd=-1): 1246 fn_name = _assert_is_bytes(fn_name) 1247 fn = self.load_func(fn_name, BPF.PERF_EVENT) 1248 res = {} 1249 if cpu >= 0: 1250 res[cpu] = self._attach_perf_event(fn.fd, ev_type, ev_config, 1251 sample_period, sample_freq, pid, cpu, group_fd) 1252 else: 1253 for i in get_online_cpus(): 1254 res[i] = self._attach_perf_event(fn.fd, ev_type, ev_config, 1255 sample_period, sample_freq, pid, i, group_fd) 1256 self.open_perf_events[(ev_type, ev_config)] = res 1257 1258 def _attach_perf_event_raw(self, progfd, attr, pid, cpu, group_fd): 1259 res = lib.bpf_attach_perf_event_raw(progfd, ct.byref(attr), pid, 1260 cpu, group_fd, 0) 1261 if res < 0: 1262 raise Exception("Failed to attach BPF to perf raw event") 1263 return res 1264 1265 def attach_perf_event_raw(self, attr=-1, fn_name=b"", pid=-1, cpu=-1, group_fd=-1): 1266 fn_name = _assert_is_bytes(fn_name) 1267 fn = self.load_func(fn_name, BPF.PERF_EVENT) 1268 res = {} 1269 if cpu >= 0: 1270 res[cpu] = self._attach_perf_event_raw(fn.fd, attr, 1271 pid, cpu, group_fd) 1272 else: 1273 for i in get_online_cpus(): 1274 res[i] = self._attach_perf_event_raw(fn.fd, attr, 1275 pid, i, group_fd) 1276 self.open_perf_events[(attr.type, attr.config)] = res 1277 1278 def detach_perf_event(self, ev_type=-1, ev_config=-1): 1279 try: 1280 fds = self.open_perf_events[(ev_type, ev_config)] 1281 except KeyError: 1282 raise Exception("Perf event type {} config {} not attached".format( 1283 ev_type, ev_config)) 1284 1285 res = 0 1286 for fd in fds.values(): 1287 res = lib.bpf_close_perf_event_fd(fd) or res 1288 if res != 0: 1289 raise Exception("Failed to detach BPF from perf event") 1290 del self.open_perf_events[(ev_type, ev_config)] 1291 1292 @staticmethod 1293 def get_user_functions(name, sym_re): 1294 return set([name for (name, _) in 1295 BPF.get_user_functions_and_addresses(name, sym_re)]) 1296 1297 @staticmethod 1298 def get_user_addresses(name, sym_re): 1299 """ 1300 We are returning addresses here instead of symbol names because it 1301 turns out that the same name may appear multiple times with different 1302 addresses, and the same address may appear multiple times with the same 1303 name. We can't attach a uprobe to the same address more than once, so 1304 it makes sense to return the unique set of addresses that are mapped to 1305 a symbol that matches the provided regular expression. 1306 """ 1307 return set([address for (_, address) in 1308 BPF.get_user_functions_and_addresses(name, sym_re)]) 1309 1310 @staticmethod 1311 def get_user_functions_and_addresses(name, sym_re): 1312 name = _assert_is_bytes(name) 1313 sym_re = _assert_is_bytes(sym_re) 1314 addresses = [] 1315 def sym_cb(sym_name, addr): 1316 dname = sym_name 1317 if re.match(sym_re, dname): 1318 addresses.append((dname, addr)) 1319 return 0 1320 1321 res = lib.bcc_foreach_function_symbol(name, _SYM_CB_TYPE(sym_cb)) 1322 if res < 0: 1323 raise Exception("Error %d enumerating symbols in %s" % (res, name)) 1324 return addresses 1325 1326 def _get_uprobe_evname(self, prefix, path, addr, pid): 1327 if pid == -1: 1328 return b"%s_%s_0x%x" % (prefix, self._probe_repl.sub(b"_", path), addr) 1329 else: 1330 # if pid is valid, put pid in the name, so different pid 1331 # can have different event names 1332 return b"%s_%s_0x%x_%d" % (prefix, self._probe_repl.sub(b"_", path), addr, pid) 1333 1334 def attach_uprobe(self, name=b"", sym=b"", sym_re=b"", addr=None, 1335 fn_name=b"", pid=-1, sym_off=0): 1336 """attach_uprobe(name="", sym="", sym_re="", addr=None, fn_name="" 1337 pid=-1, sym_off=0) 1338 1339 Run the bpf function denoted by fn_name every time the symbol sym in 1340 the library or binary 'name' is encountered. Optional parameters pid, 1341 cpu, and group_fd can be used to filter the probe. 1342 1343 If sym_off is given, attach uprobe to offset within the symbol. 1344 1345 The real address addr may be supplied in place of sym, in which case sym 1346 must be set to its default value. If the file is a non-PIE executable, 1347 addr must be a virtual address, otherwise it must be an offset relative 1348 to the file load address. 1349 1350 Instead of a symbol name, a regular expression can be provided in 1351 sym_re. The uprobe will then attach to symbols that match the provided 1352 regular expression. 1353 1354 Libraries can be given in the name argument without the lib prefix, or 1355 with the full path (/usr/lib/...). Binaries can be given only with the 1356 full path (/bin/sh). If a PID is given, the uprobe will attach to the 1357 version of the library used by the process. 1358 1359 Example: BPF(text).attach_uprobe("c", "malloc") 1360 BPF(text).attach_uprobe("/usr/bin/python", "main") 1361 """ 1362 1363 assert sym_off >= 0 1364 if addr is not None: 1365 assert sym_off == 0, "offset with addr is not supported" 1366 1367 name = _assert_is_bytes(name) 1368 sym = _assert_is_bytes(sym) 1369 sym_re = _assert_is_bytes(sym_re) 1370 fn_name = _assert_is_bytes(fn_name) 1371 1372 if sym_re: 1373 addresses = BPF.get_user_addresses(name, sym_re) 1374 self._check_probe_quota(len(addresses)) 1375 for sym_addr in addresses: 1376 self.attach_uprobe(name=name, addr=sym_addr, 1377 fn_name=fn_name, pid=pid) 1378 return 1379 1380 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid, sym_off) 1381 1382 self._check_probe_quota(1) 1383 fn = self.load_func(fn_name, BPF.KPROBE) 1384 ev_name = self._get_uprobe_evname(b"p", path, addr, pid) 1385 fd = lib.bpf_attach_uprobe(fn.fd, 0, ev_name, path, addr, pid) 1386 if fd < 0: 1387 raise Exception("Failed to attach BPF to uprobe") 1388 self._add_uprobe_fd(ev_name, fd) 1389 return self 1390 1391 def attach_uretprobe(self, name=b"", sym=b"", sym_re=b"", addr=None, 1392 fn_name=b"", pid=-1): 1393 """attach_uretprobe(name="", sym="", sym_re="", addr=None, fn_name="" 1394 pid=-1) 1395 1396 Run the bpf function denoted by fn_name every time the symbol sym in 1397 the library or binary 'name' finishes execution. See attach_uprobe for 1398 meaning of additional parameters. 1399 """ 1400 1401 name = _assert_is_bytes(name) 1402 sym = _assert_is_bytes(sym) 1403 sym_re = _assert_is_bytes(sym_re) 1404 fn_name = _assert_is_bytes(fn_name) 1405 1406 if sym_re: 1407 for sym_addr in BPF.get_user_addresses(name, sym_re): 1408 self.attach_uretprobe(name=name, addr=sym_addr, 1409 fn_name=fn_name, pid=pid) 1410 return 1411 1412 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid) 1413 1414 self._check_probe_quota(1) 1415 fn = self.load_func(fn_name, BPF.KPROBE) 1416 ev_name = self._get_uprobe_evname(b"r", path, addr, pid) 1417 fd = lib.bpf_attach_uprobe(fn.fd, 1, ev_name, path, addr, pid) 1418 if fd < 0: 1419 raise Exception("Failed to attach BPF to uretprobe") 1420 self._add_uprobe_fd(ev_name, fd) 1421 return self 1422 1423 def detach_uprobe_event(self, ev_name): 1424 if ev_name not in self.uprobe_fds: 1425 raise Exception("Uprobe %s is not attached" % ev_name) 1426 res = lib.bpf_close_perf_event_fd(self.uprobe_fds[ev_name]) 1427 if res < 0: 1428 raise Exception("Failed to detach BPF from uprobe") 1429 res = lib.bpf_detach_uprobe(ev_name) 1430 if res < 0: 1431 raise Exception("Failed to detach BPF from uprobe") 1432 self._del_uprobe_fd(ev_name) 1433 1434 def detach_uprobe(self, name=b"", sym=b"", addr=None, pid=-1, sym_off=0): 1435 """detach_uprobe(name="", sym="", addr=None, pid=-1) 1436 1437 Stop running a bpf function that is attached to symbol 'sym' in library 1438 or binary 'name'. 1439 """ 1440 1441 name = _assert_is_bytes(name) 1442 sym = _assert_is_bytes(sym) 1443 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid, sym_off) 1444 ev_name = self._get_uprobe_evname(b"p", path, addr, pid) 1445 self.detach_uprobe_event(ev_name) 1446 1447 def detach_uretprobe(self, name=b"", sym=b"", addr=None, pid=-1): 1448 """detach_uretprobe(name="", sym="", addr=None, pid=-1) 1449 1450 Stop running a bpf function that is attached to symbol 'sym' in library 1451 or binary 'name'. 1452 """ 1453 1454 name = _assert_is_bytes(name) 1455 sym = _assert_is_bytes(sym) 1456 1457 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid) 1458 ev_name = self._get_uprobe_evname(b"r", path, addr, pid) 1459 self.detach_uprobe_event(ev_name) 1460 1461 def _trace_autoload(self): 1462 for i in range(0, lib.bpf_num_functions(self.module)): 1463 func_name = lib.bpf_function_name(self.module, i) 1464 if func_name.startswith(b"kprobe__"): 1465 fn = self.load_func(func_name, BPF.KPROBE) 1466 self.attach_kprobe( 1467 event=self.fix_syscall_fnname(func_name[8:]), 1468 fn_name=fn.name) 1469 elif func_name.startswith(b"kretprobe__"): 1470 fn = self.load_func(func_name, BPF.KPROBE) 1471 self.attach_kretprobe( 1472 event=self.fix_syscall_fnname(func_name[11:]), 1473 fn_name=fn.name) 1474 elif func_name.startswith(b"tracepoint__"): 1475 fn = self.load_func(func_name, BPF.TRACEPOINT) 1476 tp = fn.name[len(b"tracepoint__"):].replace(b"__", b":") 1477 self.attach_tracepoint(tp=tp, fn_name=fn.name) 1478 elif func_name.startswith(b"raw_tracepoint__"): 1479 fn = self.load_func(func_name, BPF.RAW_TRACEPOINT) 1480 tp = fn.name[len(b"raw_tracepoint__"):] 1481 self.attach_raw_tracepoint(tp=tp, fn_name=fn.name) 1482 elif func_name.startswith(b"kfunc__"): 1483 self.attach_kfunc(fn_name=func_name) 1484 elif func_name.startswith(b"kretfunc__"): 1485 self.attach_kretfunc(fn_name=func_name) 1486 elif func_name.startswith(b"lsm__"): 1487 self.attach_lsm(fn_name=func_name) 1488 1489 def trace_open(self, nonblocking=False): 1490 """trace_open(nonblocking=False) 1491 1492 Open the trace_pipe if not already open 1493 """ 1494 if not self.tracefile: 1495 self.tracefile = open("%s/trace_pipe" % TRACEFS, "rb") 1496 if nonblocking: 1497 fd = self.tracefile.fileno() 1498 fl = fcntl.fcntl(fd, fcntl.F_GETFL) 1499 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 1500 return self.tracefile 1501 1502 def trace_fields(self, nonblocking=False): 1503 """trace_fields(nonblocking=False) 1504 1505 Read from the kernel debug trace pipe and return a tuple of the 1506 fields (task, pid, cpu, flags, timestamp, msg) or None if no 1507 line was read (nonblocking=True) 1508 """ 1509 while True: 1510 line = self.trace_readline(nonblocking) 1511 if not line and nonblocking: return (None,) * 6 1512 # don't print messages related to lost events 1513 if line.startswith(b"CPU:"): continue 1514 task = line[:16].lstrip() 1515 line = line[17:] 1516 ts_end = line.find(b":") 1517 try: 1518 pid, cpu, flags, ts = line[:ts_end].split() 1519 except Exception as e: 1520 continue 1521 cpu = cpu[1:-1] 1522 # line[ts_end:] will have ": [sym_or_addr]: msgs" 1523 # For trace_pipe debug output, the addr typically 1524 # is invalid (e.g., 0x1). For kernel 4.12 or earlier, 1525 # if address is not able to match a kernel symbol, 1526 # nothing will be printed out. For kernel 4.13 and later, 1527 # however, the illegal address will be printed out. 1528 # Hence, both cases are handled here. 1529 line = line[ts_end + 1:] 1530 sym_end = line.find(b":") 1531 msg = line[sym_end + 2:] 1532 try: 1533 return (task, int(pid), int(cpu), flags, float(ts), msg) 1534 except Exception as e: 1535 return ("Unknown", 0, 0, "Unknown", 0.0, "Unknown") 1536 1537 def trace_readline(self, nonblocking=False): 1538 """trace_readline(nonblocking=False) 1539 1540 Read from the kernel debug trace pipe and return one line 1541 If nonblocking is False, this will block until ctrl-C is pressed. 1542 """ 1543 1544 trace = self.trace_open(nonblocking) 1545 1546 line = None 1547 try: 1548 line = trace.readline(1024).rstrip() 1549 except IOError: 1550 pass 1551 return line 1552 1553 def trace_print(self, fmt=None): 1554 """trace_print(self, fmt=None) 1555 1556 Read from the kernel debug trace pipe and print on stdout. 1557 If fmt is specified, apply as a format string to the output. See 1558 trace_fields for the members of the tuple 1559 example: trace_print(fmt="pid {1}, msg = {5}") 1560 """ 1561 1562 while True: 1563 if fmt: 1564 fields = self.trace_fields(nonblocking=False) 1565 if not fields: continue 1566 line = fmt.format(*fields) 1567 else: 1568 line = self.trace_readline(nonblocking=False) 1569 print(line) 1570 sys.stdout.flush() 1571 1572 @staticmethod 1573 def _sym_cache(pid): 1574 """_sym_cache(pid) 1575 1576 Returns a symbol cache for the specified PID. 1577 The kernel symbol cache is accessed by providing any PID less than zero. 1578 """ 1579 if pid < 0 and pid != -1: 1580 pid = -1 1581 if not pid in BPF._sym_caches: 1582 BPF._sym_caches[pid] = SymbolCache(pid) 1583 return BPF._sym_caches[pid] 1584 1585 @staticmethod 1586 def sym(addr, pid, show_module=False, show_offset=False, demangle=True): 1587 """sym(addr, pid, show_module=False, show_offset=False) 1588 1589 Translate a memory address into a function name for a pid, which is 1590 returned. When show_module is True, the module name is also included. 1591 When show_offset is True, the instruction offset as a hexadecimal 1592 number is also included in the string. 1593 1594 A pid of less than zero will access the kernel symbol cache. 1595 1596 Example output when both show_module and show_offset are True: 1597 "start_thread+0x202 [libpthread-2.24.so]" 1598 1599 Example output when both show_module and show_offset are False: 1600 "start_thread" 1601 """ 1602 1603 #addr is of type stacktrace_build_id 1604 #so invoke the bsym address resolver 1605 typeofaddr = str(type(addr)) 1606 if typeofaddr.find('bpf_stack_build_id') != -1: 1607 sym = bcc_symbol() 1608 b = bcc_stacktrace_build_id() 1609 b.status = addr.status 1610 b.build_id = addr.build_id 1611 b.u.offset = addr.offset 1612 res = lib.bcc_buildsymcache_resolve(BPF._bsymcache, 1613 ct.byref(b), 1614 ct.byref(sym)) 1615 if res < 0: 1616 if sym.module and sym.offset: 1617 name,offset,module = (None, sym.offset, 1618 ct.cast(sym.module, ct.c_char_p).value) 1619 else: 1620 name, offset, module = (None, addr, None) 1621 else: 1622 name, offset, module = (sym.name, sym.offset, 1623 ct.cast(sym.module, ct.c_char_p).value) 1624 else: 1625 name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle) 1626 1627 offset = b"+0x%x" % offset if show_offset and name is not None else b"" 1628 name = name or b"[unknown]" 1629 name = name + offset 1630 module = b" [%s]" % os.path.basename(module) \ 1631 if show_module and module is not None else b"" 1632 return name + module 1633 1634 @staticmethod 1635 def ksym(addr, show_module=False, show_offset=False): 1636 """ksym(addr) 1637 1638 Translate a kernel memory address into a kernel function name, which is 1639 returned. When show_module is True, the module name ("kernel") is also 1640 included. When show_offset is true, the instruction offset as a 1641 hexadecimal number is also included in the string. 1642 1643 Example output when both show_module and show_offset are True: 1644 "default_idle+0x0 [kernel]" 1645 """ 1646 return BPF.sym(addr, -1, show_module, show_offset, False) 1647 1648 @staticmethod 1649 def ksymname(name): 1650 """ksymname(name) 1651 1652 Translate a kernel name into an address. This is the reverse of 1653 ksym. Returns -1 when the function name is unknown.""" 1654 return BPF._sym_cache(-1).resolve_name(None, name) 1655 1656 def num_open_kprobes(self): 1657 """num_open_kprobes() 1658 1659 Get the number of open K[ret]probes. Can be useful for scenarios where 1660 event_re is used while attaching and detaching probes. 1661 """ 1662 return len(self.kprobe_fds) 1663 1664 def num_open_uprobes(self): 1665 """num_open_uprobes() 1666 1667 Get the number of open U[ret]probes. 1668 """ 1669 return len(self.uprobe_fds) 1670 1671 def num_open_tracepoints(self): 1672 """num_open_tracepoints() 1673 1674 Get the number of open tracepoints. 1675 """ 1676 return len(self.tracepoint_fds) 1677 1678 def perf_buffer_poll(self, timeout = -1): 1679 """perf_buffer_poll(self) 1680 1681 Poll from all open perf ring buffers, calling the callback that was 1682 provided when calling open_perf_buffer for each entry. 1683 """ 1684 readers = (ct.c_void_p * len(self.perf_buffers))() 1685 for i, v in enumerate(self.perf_buffers.values()): 1686 readers[i] = v 1687 lib.perf_reader_poll(len(readers), readers, timeout) 1688 1689 def perf_buffer_consume(self): 1690 """perf_buffer_consume(self) 1691 1692 Consume all open perf buffers, regardless of whether or not 1693 they currently contain events data. Necessary to catch 'remainder' 1694 events when wakeup_events > 1 is set in open_perf_buffer 1695 """ 1696 readers = (ct.c_void_p * len(self.perf_buffers))() 1697 for i, v in enumerate(self.perf_buffers.values()): 1698 readers[i] = v 1699 lib.perf_reader_consume(len(readers), readers) 1700 1701 def kprobe_poll(self, timeout = -1): 1702 """kprobe_poll(self) 1703 1704 Deprecated. Use perf_buffer_poll instead. 1705 """ 1706 self.perf_buffer_poll(timeout) 1707 1708 def _open_ring_buffer(self, map_fd, fn, ctx=None): 1709 if not self._ringbuf_manager: 1710 self._ringbuf_manager = lib.bpf_new_ringbuf(map_fd, fn, ctx) 1711 if not self._ringbuf_manager: 1712 raise Exception("Could not open ring buffer") 1713 else: 1714 ret = lib.bpf_add_ringbuf(self._ringbuf_manager, map_fd, fn, ctx) 1715 if ret < 0: 1716 raise Exception("Could not open ring buffer") 1717 1718 def ring_buffer_poll(self, timeout = -1): 1719 """ring_buffer_poll(self) 1720 1721 Poll from all open ringbuf buffers, calling the callback that was 1722 provided when calling open_ring_buffer for each entry. 1723 """ 1724 if not self._ringbuf_manager: 1725 raise Exception("No ring buffers to poll") 1726 lib.bpf_poll_ringbuf(self._ringbuf_manager, timeout) 1727 1728 def ring_buffer_consume(self): 1729 """ring_buffer_consume(self) 1730 1731 Consume all open ringbuf buffers, regardless of whether or not 1732 they currently contain events data. This is best for use cases 1733 where low latency is desired, but it can impact performance. 1734 If you are unsure, use ring_buffer_poll instead. 1735 """ 1736 if not self._ringbuf_manager: 1737 raise Exception("No ring buffers to poll") 1738 lib.bpf_consume_ringbuf(self._ringbuf_manager) 1739 1740 def free_bcc_memory(self): 1741 return lib.bcc_free_memory() 1742 1743 @staticmethod 1744 def add_module(modname): 1745 """add_module(modname) 1746 1747 Add a library or exe to buildsym cache 1748 """ 1749 try: 1750 lib.bcc_buildsymcache_add_module(BPF._bsymcache, modname.encode()) 1751 except Exception as e: 1752 print("Error adding module to build sym cache"+str(e)) 1753 1754 def donothing(self): 1755 """the do nothing exit handler""" 1756 1757 1758 def close(self): 1759 """close(self) 1760 1761 Closes all associated files descriptors. Attached BPF programs are not 1762 detached. 1763 """ 1764 for name, fn in list(self.funcs.items()): 1765 os.close(fn.fd) 1766 del self.funcs[name] 1767 if self.module: 1768 lib.bpf_module_destroy(self.module) 1769 self.module = None 1770 1771 def cleanup(self): 1772 # Clean up opened probes 1773 for k, v in list(self.kprobe_fds.items()): 1774 self.detach_kprobe_event(k) 1775 for k, v in list(self.uprobe_fds.items()): 1776 self.detach_uprobe_event(k) 1777 for k, v in list(self.tracepoint_fds.items()): 1778 self.detach_tracepoint(k) 1779 for k, v in list(self.raw_tracepoint_fds.items()): 1780 self.detach_raw_tracepoint(k) 1781 for k, v in list(self.kfunc_entry_fds.items()): 1782 self.detach_kfunc(k) 1783 for k, v in list(self.kfunc_exit_fds.items()): 1784 self.detach_kretfunc(k) 1785 for k, v in list(self.lsm_fds.items()): 1786 self.detach_lsm(k) 1787 1788 # Clean up opened perf ring buffer and perf events 1789 table_keys = list(self.tables.keys()) 1790 for key in table_keys: 1791 if isinstance(self.tables[key], PerfEventArray): 1792 del self.tables[key] 1793 for (ev_type, ev_config) in list(self.open_perf_events.keys()): 1794 self.detach_perf_event(ev_type, ev_config) 1795 if self.tracefile: 1796 self.tracefile.close() 1797 self.tracefile = None 1798 1799 self.close() 1800 1801 # Clean up ringbuf 1802 if self._ringbuf_manager: 1803 lib.bpf_free_ringbuf(self._ringbuf_manager) 1804 self._ringbuf_manager = None 1805 1806 def __enter__(self): 1807 return self 1808 1809 def __exit__(self, exc_type, exc_val, exc_tb): 1810 self.cleanup() 1811