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