1 # Copyright 2015 PLUMgrid
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 from __future__ import print_function
26 from .libbcc import lib, bcc_symbol, bcc_symbol_option, bcc_stacktrace_build_id, _SYM_CB_TYPE
27 from .table import Table, PerfEventArray, RingBuf, BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK
28 from .perf import Perf
29 from .utils import get_online_cpus, printb, _assert_is_bytes, ArgString, StrcmpRewrite
30 from .version import __version__
31 from .disassembler import disassemble_prog, decode_map
32 from .usdt import USDT, USDTException
36 except NameError: # Python 3
43 def _get_num_open_probes():
44 global _num_open_probes
45 return _num_open_probes
47 TRACEFS = "/sys/kernel/debug/tracing"
51 # Debug output compiled LLVM IR.
53 # Debug output loaded BPF bytecode and register state on branches.
55 # Debug output pre-processor result.
56 DEBUG_PREPROCESSOR = 0x4
57 # Debug output ASM instructions embedded with source.
59 # Debug output register state on all instructions in addition to DEBUG_BPF.
60 DEBUG_BPF_REGISTER_STATE = 0x10
64 class SymbolCache(object):
65 def __init__(self, pid):
66 self.cache = lib.bcc_symcache_new(
67 pid, ct.cast(None, ct.POINTER(bcc_symbol_option)))
69 def resolve(self, addr, demangle):
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.
82 res = lib.bcc_symcache_resolve(self.cache, addr, ct.byref(sym))
84 res = lib.bcc_symcache_resolve_no_demangle(self.cache, addr,
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)
92 name_res = sym.demangle_name
93 lib.bcc_symbol_free_demangle_name(ct.byref(sym))
96 return (name_res, sym.offset, ct.cast(sym.module, ct.c_char_p).value)
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,
109 # From perf_type_id in uapi/linux/perf_event.h
118 # From perf_hw_id in uapi/linux/perf_event.h
123 BRANCH_INSTRUCTIONS = 4
126 STALLED_CYCLES_FRONTEND = 7
127 STALLED_CYCLES_BACKEND = 8
131 # From perf_sw_id in uapi/linux/perf_event.h
145 # From bpf_prog_type in uapi/linux/bpf.h
163 CGROUP_SOCK_ADDR = 18
168 # from bpf_attach_type uapi/linux/bpf.h
169 CGROUP_INET_INGRESS = 0
170 CGROUP_INET_EGRESS = 1
171 CGROUP_INET_SOCK_CREATE = 2
173 SK_SKB_STREAM_PARSER = 4
174 SK_SKB_STREAM_VERDICT = 5
177 CGROUP_INET4_BIND = 8
178 CGROUP_INET6_BIND = 9
179 CGROUP_INET4_CONNECT = 10
180 CGROUP_INET6_CONNECT = 11
181 CGROUP_INET4_POST_BIND = 12
182 CGROUP_INET6_POST_BIND = 13
183 CGROUP_UDP4_SENDMSG = 14
184 CGROUP_UDP6_SENDMSG = 15
188 CGROUP_UDP4_RECVMSG = 19
189 CGROUP_UDP6_RECVMSG = 20
190 CGROUP_GETSOCKOPT = 21
191 CGROUP_SETSOCKOPT = 22
198 CGROUP_INET4_GETPEERNAME = 29
199 CGROUP_INET6_GETPEERNAME = 30
200 CGROUP_INET4_GETSOCKNAME = 31
201 CGROUP_INET6_GETSOCKNAME = 32
203 CGROUP_INET_SOCK_RELEASE = 34
210 # from xdp_action uapi/linux/bpf.h
218 # from xdp_flags uapi/linux/if_link.h
219 # unlike similar enum-type holder classes in this file, source for these
220 # is #define XDP_FLAGS_UPDATE_IF_NOEXIST, #define XDP_FLAGS_SKB_MODE, ...
221 UPDATE_IF_NOEXIST = (1 << 0)
228 # Here for backwards compatibility only, add new enum members and types
229 # the appropriate wrapper class elsewhere in this file to avoid namespace
231 SOCKET_FILTER = BPFProgType.SOCKET_FILTER
232 KPROBE = BPFProgType.KPROBE
233 SCHED_CLS = BPFProgType.SCHED_CLS
234 SCHED_ACT = BPFProgType.SCHED_ACT
235 TRACEPOINT = BPFProgType.TRACEPOINT
236 XDP = BPFProgType.XDP
237 PERF_EVENT = BPFProgType.PERF_EVENT
238 CGROUP_SKB = BPFProgType.CGROUP_SKB
239 CGROUP_SOCK = BPFProgType.CGROUP_SOCK
240 LWT_IN = BPFProgType.LWT_IN
241 LWT_OUT = BPFProgType.LWT_OUT
242 LWT_XMIT = BPFProgType.LWT_XMIT
243 SOCK_OPS = BPFProgType.SOCK_OPS
244 SK_SKB = BPFProgType.SK_SKB
245 CGROUP_DEVICE = BPFProgType.CGROUP_DEVICE
246 SK_MSG = BPFProgType.SK_MSG
247 RAW_TRACEPOINT = BPFProgType.RAW_TRACEPOINT
248 CGROUP_SOCK_ADDR = BPFProgType.CGROUP_SOCK_ADDR
249 TRACING = BPFProgType.TRACING
250 LSM = BPFProgType.LSM
252 XDP_ABORTED = XDPAction.XDP_ABORTED
253 XDP_DROP = XDPAction.XDP_DROP
254 XDP_PASS = XDPAction.XDP_PASS
255 XDP_TX = XDPAction.XDP_TX
256 XDP_REDIRECT = XDPAction.XDP_REDIRECT
258 XDP_FLAGS_UPDATE_IF_NOEXIST = XDPFlags.UPDATE_IF_NOEXIST
259 XDP_FLAGS_SKB_MODE = XDPFlags.SKB_MODE
260 XDP_FLAGS_DRV_MODE = XDPFlags.DRV_MODE
261 XDP_FLAGS_HW_MODE = XDPFlags.HW_MODE
262 XDP_FLAGS_REPLACE = XDPFlags.REPLACE
263 # END enum backwards compat
265 _probe_repl = re.compile(b"[^a-zA-Z0-9_]")
267 _bsymcache = lib.bcc_buildsymcache_new()
270 "linux/time.h": ["time"],
271 "linux/fs.h": ["fs", "file"],
272 "linux/blkdev.h": ["bio", "request"],
273 "linux/slab.h": ["alloc"],
274 "linux/netdevice.h": ["sk_buff", "net_device"]
277 _syscall_prefixes = [
280 b"__x32_compat_sys_",
281 b"__ia32_compat_sys_",
287 # BPF timestamps come from the monotonic clock. To be able to filter
288 # and compare them from Python, we need to invoke clock_gettime.
289 # Adapted from http://stackoverflow.com/a/1205762
290 CLOCK_MONOTONIC = 1 # see <linux/time.h>
292 class timespec(ct.Structure):
293 _fields_ = [('tv_sec', ct.c_long), ('tv_nsec', ct.c_long)]
295 _librt = ct.CDLL('librt.so.1', use_errno=True)
296 _clock_gettime = _librt.clock_gettime
297 _clock_gettime.argtypes = [ct.c_int, ct.POINTER(timespec)]
300 def monotonic_time(cls):
302 Returns the system monotonic time from clock_gettime, using the
303 CLOCK_MONOTONIC constant. The time returned is in nanoseconds.
306 if cls._clock_gettime(cls.CLOCK_MONOTONIC, ct.byref(t)) != 0:
307 errno = ct.get_errno()
308 raise OSError(errno, os.strerror(errno))
309 return t.tv_sec * 1e9 + t.tv_nsec
312 def generate_auto_includes(cls, program_words):
314 Generates #include statements automatically based on a set of
315 recognized types such as sk_buff and bio. The input is all the words
316 that appear in the BPF program, and the output is a (possibly empty)
317 string of #include statements, such as "#include <linux/fs.h>".
320 for header, keywords in cls._auto_includes.items():
321 for keyword in keywords:
322 for word in program_words:
323 if keyword in word and header not in headers:
324 headers += "#include <%s>\n" % header
327 # defined for compatibility reasons, to be removed
330 class Function(object):
331 def __init__(self, bpf, name, fd):
337 def _find_file(filename):
338 """ If filename is invalid, search in ./ of argv[0] """
340 if not os.path.isfile(filename):
341 argv0 = ArgString(sys.argv[0])
342 t = b"/".join([os.path.abspath(os.path.dirname(argv0.__bytes__())), filename])
343 if os.path.isfile(t):
346 raise Exception("Could not find file %s" % filename)
350 def find_exe(bin_path):
354 Traverses the PATH environment variable, looking for the first
355 directory that contains an executable file named bin_path, and
356 returns the full path to that file, or None if no such file
357 can be found. This is meant to replace invocations of the
358 "which" shell utility, which doesn't have portable semantics
359 for skipping aliases.
361 # Source: http://stackoverflow.com/a/377028
363 return os.path.isfile(fpath) and \
364 os.access(fpath, os.X_OK)
366 fpath, fname = os.path.split(bin_path)
371 for path in os.environ["PATH"].split(os.pathsep):
372 path = path.strip('"')
373 exe_file = os.path.join(path.encode(), bin_path)
378 def __init__(self, src_file=b"", hdr_file=b"", text=None, debug=0,
379 cflags=[], usdt_contexts=[], allow_rlimit=True, device=None,
380 attach_usdt_ignore_pid=False):
381 """Create a new BPF module with the given source code.
384 All fields are marked as optional, but either `src_file` or `text`
385 must be supplied, and not both.
388 src_file (Optional[str]): Path to a source file for the module
389 hdr_file (Optional[str]): Path to a helper header file for the `src_file`
390 text (Optional[str]): Contents of a source file for the module
391 debug (Optional[int]): Flags used for debug prints, can be |'d together
392 See "Debug flags" for explanation
395 src_file = _assert_is_bytes(src_file)
396 hdr_file = _assert_is_bytes(hdr_file)
397 text = _assert_is_bytes(text)
399 assert not (text and src_file)
403 self.tracepoint_fds = {}
404 self.raw_tracepoint_fds = {}
405 self.kfunc_entry_fds = {}
406 self.kfunc_exit_fds = {}
408 self.perf_buffers = {}
409 self.open_perf_events = {}
410 self._ringbuf_manager = None
411 self.tracefile = None
412 atexit.register(self.cleanup)
418 cflags_array = (ct.c_char_p * len(cflags))()
419 for i, s in enumerate(cflags): cflags_array[i] = bytes(ArgString(s))
422 src_file = BPF._find_file(src_file)
423 hdr_file = BPF._find_file(hdr_file)
425 # files that end in ".b" are treated as B files. Everything else is a (BPF-)C file
426 if src_file.endswith(b".b"):
427 self.module = lib.bpf_module_create_b(src_file, hdr_file, self.debug, device)
430 # Read the BPF C source file into the text variable. This ensures,
431 # that files and inline text are treated equally.
432 with open(src_file, mode="rb") as file:
435 ctx_array = (ct.c_void_p * len(usdt_contexts))()
436 for i, usdt in enumerate(usdt_contexts):
437 ctx_array[i] = ct.c_void_p(usdt.get_context())
438 usdt_text = lib.bcc_usdt_genargs(ctx_array, len(usdt_contexts))
439 if usdt_text is None:
440 raise Exception("can't generate USDT probe arguments; " +
441 "possible cause is missing pid when a " +
442 "probe in a shared object has multiple " +
444 text = usdt_text + text
447 self.module = lib.bpf_module_create_c_from_string(text,
449 cflags_array, len(cflags_array),
450 allow_rlimit, device)
452 raise Exception("Failed to compile BPF module %s" % (src_file or "<text>"))
454 for usdt_context in usdt_contexts:
455 usdt_context.attach_uprobes(self, attach_usdt_ignore_pid)
457 # If any "kprobe__" or "tracepoint__" or "raw_tracepoint__"
458 # prefixed functions were defined,
459 # they will be loaded and attached here.
460 self._trace_autoload()
462 def load_funcs(self, prog_type=KPROBE):
463 """load_funcs(prog_type=KPROBE)
465 Load all functions in this BPF module with the given type.
466 Returns a list of the function handles."""
469 for i in range(0, lib.bpf_num_functions(self.module)):
470 func_name = lib.bpf_function_name(self.module, i)
471 fns.append(self.load_func(func_name, prog_type))
475 def load_func(self, func_name, prog_type, device = None):
476 func_name = _assert_is_bytes(func_name)
477 if func_name in self.funcs:
478 return self.funcs[func_name]
479 if not lib.bpf_function_start(self.module, func_name):
480 raise Exception("Unknown program %s" % func_name)
482 if (self.debug & DEBUG_BPF_REGISTER_STATE):
484 elif (self.debug & DEBUG_BPF):
486 fd = lib.bcc_func_load(self.module, prog_type, func_name,
487 lib.bpf_function_start(self.module, func_name),
488 lib.bpf_function_size(self.module, func_name),
489 lib.bpf_module_license(self.module),
490 lib.bpf_module_kern_version(self.module),
491 log_level, None, 0, device)
494 atexit.register(self.donothing)
495 if ct.get_errno() == errno.EPERM:
496 raise Exception("Need super-user privileges to run")
498 errstr = os.strerror(ct.get_errno())
499 raise Exception("Failed to load BPF program %s: %s" %
502 fn = BPF.Function(self, func_name, fd)
503 self.funcs[func_name] = fn
507 def dump_func(self, func_name):
509 Return the eBPF bytecodes for the specified function as a string
511 func_name = _assert_is_bytes(func_name)
512 if not lib.bpf_function_start(self.module, func_name):
513 raise Exception("Unknown program %s" % func_name)
515 start, = lib.bpf_function_start(self.module, func_name),
516 size, = lib.bpf_function_size(self.module, func_name),
517 return ct.string_at(start, size)
519 def disassemble_func(self, func_name):
520 bpfstr = self.dump_func(func_name)
521 return disassemble_prog(func_name, bpfstr)
523 def decode_table(self, table_name, sizeinfo=False):
524 table_obj = self[table_name]
525 table_type = lib.bpf_table_type_id(self.module, table_obj.map_id)
526 return decode_map(table_name, table_obj, table_type, sizeinfo=sizeinfo)
531 u"wchar_t": ct.c_wchar,
532 u"unsigned char": ct.c_ubyte,
533 u"short": ct.c_short,
534 u"unsigned short": ct.c_ushort,
536 u"unsigned int": ct.c_uint,
538 u"unsigned long": ct.c_ulong,
539 u"long long": ct.c_longlong,
540 u"unsigned long long": ct.c_ulonglong,
541 u"float": ct.c_float,
542 u"double": ct.c_double,
543 u"long double": ct.c_longdouble,
544 u"__int128": ct.c_int64 * 2,
545 u"unsigned __int128": ct.c_uint64 * 2,
548 def _decode_table_type(desc):
549 if isinstance(desc, basestring):
550 return BPF.str2ctype[desc]
555 fields.append((t[0], BPF._decode_table_type(t[1])))
557 if isinstance(t[2], list):
558 fields.append((t[0], BPF._decode_table_type(t[1]) * t[2][0]))
559 elif isinstance(t[2], int):
560 fields.append((t[0], BPF._decode_table_type(t[1]), t[2]))
561 elif isinstance(t[2], basestring) and (
562 t[2] == u"union" or t[2] == u"struct" or
563 t[2] == u"struct_packed"):
566 name = "__anon%d" % len(anon)
568 fields.append((name, BPF._decode_table_type(t)))
570 raise Exception("Failed to decode type %s" % str(t))
572 raise Exception("Failed to decode type %s" % str(t))
576 if desc[2] == u"union":
578 elif desc[2] == u"struct":
580 elif desc[2] == u"struct_packed":
584 cls = type(str(desc[0]), (base,), dict(_anonymous_=anon, _pack_=1,
587 cls = type(str(desc[0]), (base,), dict(_anonymous_=anon,
591 def get_table(self, name, keytype=None, leaftype=None, reducer=None):
592 name = _assert_is_bytes(name)
593 map_id = lib.bpf_table_id(self.module, name)
594 map_fd = lib.bpf_table_fd(self.module, name)
595 is_queuestack = lib.bpf_table_type_id(self.module, map_id) in [BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_STACK]
598 if not keytype and not is_queuestack:
599 key_desc = lib.bpf_table_key_desc(self.module, name).decode("utf-8")
601 raise Exception("Failed to load BPF Table %s key desc" % name)
602 keytype = BPF._decode_table_type(json.loads(key_desc))
604 leaf_desc = lib.bpf_table_leaf_desc(self.module, name).decode("utf-8")
606 raise Exception("Failed to load BPF Table %s leaf desc" % name)
607 leaftype = BPF._decode_table_type(json.loads(leaf_desc))
608 return Table(self, map_id, map_fd, keytype, leaftype, name, reducer=reducer)
610 def __getitem__(self, key):
611 if key not in self.tables:
612 self.tables[key] = self.get_table(key)
613 return self.tables[key]
615 def __setitem__(self, key, leaf):
616 self.tables[key] = leaf
619 return len(self.tables)
621 def __delitem__(self, key):
625 return self.tables.__iter__()
628 def attach_func(fn, attachable_fd, attach_type, flags=0):
629 if not isinstance(fn, BPF.Function):
630 raise Exception("arg 1 must be of type BPF.Function")
632 res = lib.bpf_prog_attach(fn.fd, attachable_fd, attach_type, flags)
634 raise Exception("Failed to attach BPF function with attach_type "\
635 "{0}: {1}".format(attach_type, os.strerror(-res)))
638 def detach_func(fn, attachable_fd, attach_type):
639 if not isinstance(fn, BPF.Function):
640 raise Exception("arg 1 must be of type BPF.Function")
642 res = lib.bpf_prog_detach2(fn.fd, attachable_fd, attach_type)
644 raise Exception("Failed to detach BPF function with attach_type "\
645 "{0}: {1}".format(attach_type, os.strerror(-res)))
648 def attach_raw_socket(fn, dev):
649 dev = _assert_is_bytes(dev)
650 if not isinstance(fn, BPF.Function):
651 raise Exception("arg 1 must be of type BPF.Function")
652 sock = lib.bpf_open_raw_sock(dev)
654 errstr = os.strerror(ct.get_errno())
655 raise Exception("Failed to open raw device %s: %s" % (dev, errstr))
656 res = lib.bpf_attach_socket(sock, fn.fd)
658 errstr = os.strerror(ct.get_errno())
659 raise Exception("Failed to attach BPF to device %s: %s"
664 def get_kprobe_functions(event_re):
665 blacklist_file = "%s/../kprobes/blacklist" % TRACEFS
667 with open(blacklist_file, "rb") as blacklist_f:
668 blacklist = set([line.rstrip().split()[1] for line in blacklist_f])
670 if e.errno != errno.EPERM:
678 with open("/proc/kallsyms", "rb") as avail_file:
679 for line in avail_file:
680 (t, fn) = line.rstrip().split()[1:3]
681 # Skip all functions defined between __init_begin and
683 if in_init_section == 0:
684 if fn == b'__init_begin':
687 elif in_init_section == 1:
688 if fn == b'__init_end':
691 # Skip all functions defined between __irqentry_text_start and
692 # __irqentry_text_end
693 if in_irq_section == 0:
694 if fn == b'__irqentry_text_start':
697 # __irqentry_text_end is not always after
698 # __irqentry_text_start. But only happens when
699 # no functions between two irqentry_text
700 elif fn == b'__irqentry_text_end':
703 elif in_irq_section == 1:
704 if fn == b'__irqentry_text_end':
707 # All functions defined as NOKPROBE_SYMBOL() start with the
708 # prefix _kbl_addr_*, blacklisting them by looking at the name
709 # allows to catch also those symbols that are defined in kernel
711 if fn.startswith(b'_kbl_addr_'):
713 # Explicitly blacklist perf-related functions, they are all
715 elif fn.startswith(b'__perf') or fn.startswith(b'perf_'):
717 # Exclude all gcc 8's extra .cold functions
718 elif re.match(b'^.*\.cold(\.\d+)?$', fn):
720 if (t.lower() in [b't', b'w']) and re.match(event_re, fn) \
721 and fn not in blacklist:
723 return set(fns) # Some functions may appear more than once
725 def _check_probe_quota(self, num_new_probes):
726 global _num_open_probes
727 if _num_open_probes + num_new_probes > _probe_limit:
728 raise Exception("Number of open probes would exceed global quota")
730 def _add_kprobe_fd(self, name, fd):
731 global _num_open_probes
732 self.kprobe_fds[name] = fd
733 _num_open_probes += 1
735 def _del_kprobe_fd(self, name):
736 global _num_open_probes
737 del self.kprobe_fds[name]
738 _num_open_probes -= 1
740 def _add_uprobe_fd(self, name, fd):
741 global _num_open_probes
742 self.uprobe_fds[name] = fd
743 _num_open_probes += 1
745 def _del_uprobe_fd(self, name):
746 global _num_open_probes
747 del self.uprobe_fds[name]
748 _num_open_probes -= 1
750 # Find current system's syscall prefix by testing on the BPF syscall.
751 # If no valid value found, will return the first possible value which
752 # would probably lead to error in later API calls.
753 def get_syscall_prefix(self):
754 for prefix in self._syscall_prefixes:
755 if self.ksymname(b"%sbpf" % prefix) != -1:
757 return self._syscall_prefixes[0]
759 # Given a syscall's name, return the full Kernel function name with current
760 # system's syscall prefix. For example, given "clone" the helper would
761 # return "sys_clone" or "__x64_sys_clone".
762 def get_syscall_fnname(self, name):
763 name = _assert_is_bytes(name)
764 return self.get_syscall_prefix() + name
766 # Given a Kernel function name that represents a syscall but already has a
767 # prefix included, transform it to current system's prefix. For example,
768 # if "sys_clone" provided, the helper may translate it to "__x64_sys_clone".
769 def fix_syscall_fnname(self, name):
770 name = _assert_is_bytes(name)
771 for prefix in self._syscall_prefixes:
772 if name.startswith(prefix):
773 return self.get_syscall_fnname(name[len(prefix):])
776 def attach_kprobe(self, event=b"", event_off=0, fn_name=b"", event_re=b""):
777 event = _assert_is_bytes(event)
778 fn_name = _assert_is_bytes(fn_name)
779 event_re = _assert_is_bytes(event_re)
781 # allow the caller to glob multiple functions together
783 matches = BPF.get_kprobe_functions(event_re)
784 self._check_probe_quota(len(matches))
787 self.attach_kprobe(event=line, fn_name=fn_name)
792 self._check_probe_quota(1)
793 fn = self.load_func(fn_name, BPF.KPROBE)
794 ev_name = b"p_" + event.replace(b"+", b"_").replace(b".", b"_")
795 fd = lib.bpf_attach_kprobe(fn.fd, 0, ev_name, event, event_off, 0)
797 raise Exception("Failed to attach BPF program %s to kprobe %s" %
799 self._add_kprobe_fd(ev_name, fd)
802 def attach_kretprobe(self, event=b"", fn_name=b"", event_re=b"", maxactive=0):
803 event = _assert_is_bytes(event)
804 fn_name = _assert_is_bytes(fn_name)
805 event_re = _assert_is_bytes(event_re)
807 # allow the caller to glob multiple functions together
809 for line in BPF.get_kprobe_functions(event_re):
811 self.attach_kretprobe(event=line, fn_name=fn_name,
817 self._check_probe_quota(1)
818 fn = self.load_func(fn_name, BPF.KPROBE)
819 ev_name = b"r_" + event.replace(b"+", b"_").replace(b".", b"_")
820 fd = lib.bpf_attach_kprobe(fn.fd, 1, ev_name, event, 0, maxactive)
822 raise Exception("Failed to attach BPF program %s to kretprobe %s" %
824 self._add_kprobe_fd(ev_name, fd)
827 def detach_kprobe_event(self, ev_name):
828 if ev_name not in self.kprobe_fds:
829 raise Exception("Kprobe %s is not attached" % ev_name)
830 res = lib.bpf_close_perf_event_fd(self.kprobe_fds[ev_name])
832 raise Exception("Failed to close kprobe FD")
833 res = lib.bpf_detach_kprobe(ev_name)
835 raise Exception("Failed to detach BPF from kprobe")
836 self._del_kprobe_fd(ev_name)
838 def detach_kprobe(self, event):
839 event = _assert_is_bytes(event)
840 ev_name = b"p_" + event.replace(b"+", b"_").replace(b".", b"_")
841 self.detach_kprobe_event(ev_name)
843 def detach_kretprobe(self, event):
844 event = _assert_is_bytes(event)
845 ev_name = b"r_" + event.replace(b"+", b"_").replace(b".", b"_")
846 self.detach_kprobe_event(ev_name)
849 def attach_xdp(dev, fn, flags=0):
851 This function attaches a BPF function to a device on the device
854 dev = _assert_is_bytes(dev)
855 if not isinstance(fn, BPF.Function):
856 raise Exception("arg 1 must be of type BPF.Function")
857 res = lib.bpf_attach_xdp(dev, fn.fd, flags)
859 err_no = ct.get_errno()
860 if err_no == errno.EBADMSG:
861 raise Exception("Internal error while attaching BPF to device,"+
862 " try increasing the debug level!")
864 errstr = os.strerror(err_no)
865 raise Exception("Failed to attach BPF to device %s: %s"
869 def remove_xdp(dev, flags=0):
871 This function removes any BPF function from a device on the
872 device driver level (XDP)
874 dev = _assert_is_bytes(dev)
875 res = lib.bpf_attach_xdp(dev, -1, flags)
877 errstr = os.strerror(ct.get_errno())
878 raise Exception("Failed to detach BPF from device %s: %s"
884 def _check_path_symbol(cls, module, symname, addr, pid, sym_off=0):
885 module = _assert_is_bytes(module)
886 symname = _assert_is_bytes(symname)
888 c_pid = 0 if pid == -1 else pid
889 if lib.bcc_resolve_symname(
892 ct.cast(None, ct.POINTER(bcc_symbol_option)),
895 raise Exception("could not determine address of symbol %s" % symname)
896 new_addr = sym.offset + sym_off
897 module_path = ct.cast(sym.module, ct.c_char_p).value
898 lib.bcc_procutils_free(sym.module)
899 return module_path, new_addr
902 def find_library(libname):
903 libname = _assert_is_bytes(libname)
904 res = lib.bcc_procutils_which_so(libname, 0)
907 libpath = ct.cast(res, ct.c_char_p).value
908 lib.bcc_procutils_free(res)
912 def get_tracepoints(tp_re):
914 events_dir = os.path.join(TRACEFS, "events")
915 for category in os.listdir(events_dir):
916 cat_dir = os.path.join(events_dir, category)
917 if not os.path.isdir(cat_dir):
919 for event in os.listdir(cat_dir):
920 evt_dir = os.path.join(cat_dir, event)
921 if os.path.isdir(evt_dir):
922 tp = ("%s:%s" % (category, event))
923 if re.match(tp_re.decode(), tp):
928 def tracepoint_exists(category, event):
929 evt_dir = os.path.join(TRACEFS, "events", category, event)
930 return os.path.isdir(evt_dir)
932 def attach_tracepoint(self, tp=b"", tp_re=b"", fn_name=b""):
933 """attach_tracepoint(tp="", tp_re="", fn_name="")
935 Run the bpf function denoted by fn_name every time the kernel tracepoint
936 specified by 'tp' is hit. The optional parameters pid, cpu, and group_fd
937 can be used to filter the probe. The tracepoint specification is simply
938 the tracepoint category and the tracepoint name, separated by a colon.
939 For example: sched:sched_switch, syscalls:sys_enter_bind, etc.
941 Instead of a tracepoint name, a regular expression can be provided in
942 tp_re. The program will then attach to tracepoints that match the
943 provided regular expression.
945 To obtain a list of kernel tracepoints, use the tplist tool or cat the
946 file /sys/kernel/debug/tracing/available_events.
949 BPF(text).attach_tracepoint(tp="sched:sched_switch", fn_name="on_switch")
950 BPF(text).attach_tracepoint(tp_re="sched:.*", fn_name="on_switch")
953 tp = _assert_is_bytes(tp)
954 tp_re = _assert_is_bytes(tp_re)
955 fn_name = _assert_is_bytes(fn_name)
957 for tp in BPF.get_tracepoints(tp_re):
958 self.attach_tracepoint(tp=tp, fn_name=fn_name)
961 fn = self.load_func(fn_name, BPF.TRACEPOINT)
962 (tp_category, tp_name) = tp.split(b':')
963 fd = lib.bpf_attach_tracepoint(fn.fd, tp_category, tp_name)
965 raise Exception("Failed to attach BPF program %s to tracepoint %s" %
967 self.tracepoint_fds[tp] = fd
970 def attach_raw_tracepoint(self, tp=b"", fn_name=b""):
971 """attach_raw_tracepoint(self, tp=b"", fn_name=b"")
973 Run the bpf function denoted by fn_name every time the kernel tracepoint
974 specified by 'tp' is hit. The bpf function should be loaded as a
975 RAW_TRACEPOINT type. The fn_name is the kernel tracepoint name,
976 e.g., sched_switch, sys_enter_bind, etc.
979 BPF(text).attach_raw_tracepoint(tp="sched_switch", fn_name="on_switch")
982 tp = _assert_is_bytes(tp)
983 if tp in self.raw_tracepoint_fds:
984 raise Exception("Raw tracepoint %s has been attached" % tp)
986 fn_name = _assert_is_bytes(fn_name)
987 fn = self.load_func(fn_name, BPF.RAW_TRACEPOINT)
988 fd = lib.bpf_attach_raw_tracepoint(fn.fd, tp)
990 raise Exception("Failed to attach BPF to raw tracepoint")
991 self.raw_tracepoint_fds[tp] = fd
994 def detach_raw_tracepoint(self, tp=b""):
995 """detach_raw_tracepoint(tp="")
997 Stop running the bpf function that is attached to the kernel tracepoint
1000 Example: bpf.detach_raw_tracepoint("sched_switch")
1003 tp = _assert_is_bytes(tp)
1004 if tp not in self.raw_tracepoint_fds:
1005 raise Exception("Raw tracepoint %s is not attached" % tp)
1006 os.close(self.raw_tracepoint_fds[tp])
1007 del self.raw_tracepoint_fds[tp]
1010 def add_prefix(prefix, name):
1011 if not name.startswith(prefix):
1012 name = prefix + name
1016 def support_kfunc():
1017 # there's no trampoline support for other than x86_64 arch
1018 if platform.machine() != 'x86_64':
1020 if not lib.bpf_has_kernel_btf():
1022 # kernel symbol "bpf_trampoline_link_prog" indicates kfunc support
1023 if BPF.ksymname("bpf_trampoline_link_prog") != -1:
1029 if not lib.bpf_has_kernel_btf():
1031 # kernel symbol "bpf_lsm_bpf" indicates BPF LSM support
1032 if BPF.ksymname(b"bpf_lsm_bpf") != -1:
1036 def detach_kfunc(self, fn_name=b""):
1037 fn_name = _assert_is_bytes(fn_name)
1038 fn_name = BPF.add_prefix(b"kfunc__", fn_name)
1040 if fn_name not in self.kfunc_entry_fds:
1041 raise Exception("Kernel entry func %s is not attached" % fn_name)
1042 os.close(self.kfunc_entry_fds[fn_name])
1043 del self.kfunc_entry_fds[fn_name]
1045 def detach_kretfunc(self, fn_name=b""):
1046 fn_name = _assert_is_bytes(fn_name)
1047 fn_name = BPF.add_prefix(b"kretfunc__", fn_name)
1049 if fn_name not in self.kfunc_exit_fds:
1050 raise Exception("Kernel exit func %s is not attached" % fn_name)
1051 os.close(self.kfunc_exit_fds[fn_name])
1052 del self.kfunc_exit_fds[fn_name]
1054 def attach_kfunc(self, fn_name=b""):
1055 fn_name = _assert_is_bytes(fn_name)
1056 fn_name = BPF.add_prefix(b"kfunc__", fn_name)
1058 if fn_name in self.kfunc_entry_fds:
1059 raise Exception("Kernel entry func %s has been attached" % fn_name)
1061 fn = self.load_func(fn_name, BPF.TRACING)
1062 fd = lib.bpf_attach_kfunc(fn.fd)
1064 raise Exception("Failed to attach BPF to entry kernel func")
1065 self.kfunc_entry_fds[fn_name] = fd
1068 def attach_kretfunc(self, fn_name=b""):
1069 fn_name = _assert_is_bytes(fn_name)
1070 fn_name = BPF.add_prefix(b"kretfunc__", fn_name)
1072 if fn_name in self.kfunc_exit_fds:
1073 raise Exception("Kernel exit func %s has been attached" % fn_name)
1075 fn = self.load_func(fn_name, BPF.TRACING)
1076 fd = lib.bpf_attach_kfunc(fn.fd)
1078 raise Exception("Failed to attach BPF to exit kernel func")
1079 self.kfunc_exit_fds[fn_name] = fd
1082 def detach_lsm(self, fn_name=b""):
1083 fn_name = _assert_is_bytes(fn_name)
1084 fn_name = BPF.add_prefix(b"lsm__", fn_name)
1086 if fn_name not in self.lsm_fds:
1087 raise Exception("LSM %s is not attached" % fn_name)
1088 os.close(self.lsm_fds[fn_name])
1089 del self.lsm_fds[fn_name]
1091 def attach_lsm(self, fn_name=b""):
1092 fn_name = _assert_is_bytes(fn_name)
1093 fn_name = BPF.add_prefix(b"lsm__", fn_name)
1095 if fn_name in self.lsm_fds:
1096 raise Exception("LSM %s has been attached" % fn_name)
1098 fn = self.load_func(fn_name, BPF.LSM)
1099 fd = lib.bpf_attach_lsm(fn.fd)
1101 raise Exception("Failed to attach LSM")
1102 self.lsm_fds[fn_name] = fd
1106 def support_raw_tracepoint():
1107 # kernel symbol "bpf_find_raw_tracepoint" indicates raw_tracepoint support
1108 if BPF.ksymname("bpf_find_raw_tracepoint") != -1 or \
1109 BPF.ksymname("bpf_get_raw_tracepoint") != -1:
1113 def detach_tracepoint(self, tp=b""):
1114 """detach_tracepoint(tp="")
1116 Stop running a bpf function that is attached to the kernel tracepoint
1119 Example: bpf.detach_tracepoint("sched:sched_switch")
1122 tp = _assert_is_bytes(tp)
1123 if tp not in self.tracepoint_fds:
1124 raise Exception("Tracepoint %s is not attached" % tp)
1125 res = lib.bpf_close_perf_event_fd(self.tracepoint_fds[tp])
1127 raise Exception("Failed to detach BPF from tracepoint")
1128 (tp_category, tp_name) = tp.split(b':')
1129 res = lib.bpf_detach_tracepoint(tp_category, tp_name)
1131 raise Exception("Failed to detach BPF from tracepoint")
1132 del self.tracepoint_fds[tp]
1134 def _attach_perf_event(self, progfd, ev_type, ev_config,
1135 sample_period, sample_freq, pid, cpu, group_fd):
1136 res = lib.bpf_attach_perf_event(progfd, ev_type, ev_config,
1137 sample_period, sample_freq, pid, cpu, group_fd)
1139 raise Exception("Failed to attach BPF to perf event")
1142 def attach_perf_event(self, ev_type=-1, ev_config=-1, fn_name=b"",
1143 sample_period=0, sample_freq=0, pid=-1, cpu=-1, group_fd=-1):
1144 fn_name = _assert_is_bytes(fn_name)
1145 fn = self.load_func(fn_name, BPF.PERF_EVENT)
1148 res[cpu] = self._attach_perf_event(fn.fd, ev_type, ev_config,
1149 sample_period, sample_freq, pid, cpu, group_fd)
1151 for i in get_online_cpus():
1152 res[i] = self._attach_perf_event(fn.fd, ev_type, ev_config,
1153 sample_period, sample_freq, pid, i, group_fd)
1154 self.open_perf_events[(ev_type, ev_config)] = res
1156 def detach_perf_event(self, ev_type=-1, ev_config=-1):
1158 fds = self.open_perf_events[(ev_type, ev_config)]
1160 raise Exception("Perf event type {} config {} not attached".format(
1161 ev_type, ev_config))
1164 for fd in fds.values():
1165 res = lib.bpf_close_perf_event_fd(fd) or res
1167 raise Exception("Failed to detach BPF from perf event")
1168 del self.open_perf_events[(ev_type, ev_config)]
1171 def get_user_functions(name, sym_re):
1172 return set([name for (name, _) in
1173 BPF.get_user_functions_and_addresses(name, sym_re)])
1176 def get_user_addresses(name, sym_re):
1178 We are returning addresses here instead of symbol names because it
1179 turns out that the same name may appear multiple times with different
1180 addresses, and the same address may appear multiple times with the same
1181 name. We can't attach a uprobe to the same address more than once, so
1182 it makes sense to return the unique set of addresses that are mapped to
1183 a symbol that matches the provided regular expression.
1185 return set([address for (_, address) in
1186 BPF.get_user_functions_and_addresses(name, sym_re)])
1189 def get_user_functions_and_addresses(name, sym_re):
1190 name = _assert_is_bytes(name)
1191 sym_re = _assert_is_bytes(sym_re)
1193 def sym_cb(sym_name, addr):
1195 if re.match(sym_re, dname):
1196 addresses.append((dname, addr))
1199 res = lib.bcc_foreach_function_symbol(name, _SYM_CB_TYPE(sym_cb))
1201 raise Exception("Error %d enumerating symbols in %s" % (res, name))
1204 def _get_uprobe_evname(self, prefix, path, addr, pid):
1206 return b"%s_%s_0x%x" % (prefix, self._probe_repl.sub(b"_", path), addr)
1208 # if pid is valid, put pid in the name, so different pid
1209 # can have different event names
1210 return b"%s_%s_0x%x_%d" % (prefix, self._probe_repl.sub(b"_", path), addr, pid)
1212 def attach_uprobe(self, name=b"", sym=b"", sym_re=b"", addr=None,
1213 fn_name=b"", pid=-1, sym_off=0):
1214 """attach_uprobe(name="", sym="", sym_re="", addr=None, fn_name=""
1217 Run the bpf function denoted by fn_name every time the symbol sym in
1218 the library or binary 'name' is encountered. Optional parameters pid,
1219 cpu, and group_fd can be used to filter the probe.
1221 If sym_off is given, attach uprobe to offset within the symbol.
1223 The real address addr may be supplied in place of sym, in which case sym
1224 must be set to its default value. If the file is a non-PIE executable,
1225 addr must be a virtual address, otherwise it must be an offset relative
1226 to the file load address.
1228 Instead of a symbol name, a regular expression can be provided in
1229 sym_re. The uprobe will then attach to symbols that match the provided
1232 Libraries can be given in the name argument without the lib prefix, or
1233 with the full path (/usr/lib/...). Binaries can be given only with the
1234 full path (/bin/sh). If a PID is given, the uprobe will attach to the
1235 version of the library used by the process.
1237 Example: BPF(text).attach_uprobe("c", "malloc")
1238 BPF(text).attach_uprobe("/usr/bin/python", "main")
1242 if addr is not None:
1243 assert sym_off == 0, "offset with addr is not supported"
1245 name = _assert_is_bytes(name)
1246 sym = _assert_is_bytes(sym)
1247 sym_re = _assert_is_bytes(sym_re)
1248 fn_name = _assert_is_bytes(fn_name)
1251 addresses = BPF.get_user_addresses(name, sym_re)
1252 self._check_probe_quota(len(addresses))
1253 for sym_addr in addresses:
1254 self.attach_uprobe(name=name, addr=sym_addr,
1255 fn_name=fn_name, pid=pid)
1258 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid, sym_off)
1260 self._check_probe_quota(1)
1261 fn = self.load_func(fn_name, BPF.KPROBE)
1262 ev_name = self._get_uprobe_evname(b"p", path, addr, pid)
1263 fd = lib.bpf_attach_uprobe(fn.fd, 0, ev_name, path, addr, pid)
1265 raise Exception("Failed to attach BPF to uprobe")
1266 self._add_uprobe_fd(ev_name, fd)
1269 def attach_uretprobe(self, name=b"", sym=b"", sym_re=b"", addr=None,
1270 fn_name=b"", pid=-1):
1271 """attach_uretprobe(name="", sym="", sym_re="", addr=None, fn_name=""
1274 Run the bpf function denoted by fn_name every time the symbol sym in
1275 the library or binary 'name' finishes execution. See attach_uprobe for
1276 meaning of additional parameters.
1279 name = _assert_is_bytes(name)
1280 sym = _assert_is_bytes(sym)
1281 sym_re = _assert_is_bytes(sym_re)
1282 fn_name = _assert_is_bytes(fn_name)
1285 for sym_addr in BPF.get_user_addresses(name, sym_re):
1286 self.attach_uretprobe(name=name, addr=sym_addr,
1287 fn_name=fn_name, pid=pid)
1290 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid)
1292 self._check_probe_quota(1)
1293 fn = self.load_func(fn_name, BPF.KPROBE)
1294 ev_name = self._get_uprobe_evname(b"r", path, addr, pid)
1295 fd = lib.bpf_attach_uprobe(fn.fd, 1, ev_name, path, addr, pid)
1297 raise Exception("Failed to attach BPF to uretprobe")
1298 self._add_uprobe_fd(ev_name, fd)
1301 def detach_uprobe_event(self, ev_name):
1302 if ev_name not in self.uprobe_fds:
1303 raise Exception("Uprobe %s is not attached" % ev_name)
1304 res = lib.bpf_close_perf_event_fd(self.uprobe_fds[ev_name])
1306 raise Exception("Failed to detach BPF from uprobe")
1307 res = lib.bpf_detach_uprobe(ev_name)
1309 raise Exception("Failed to detach BPF from uprobe")
1310 self._del_uprobe_fd(ev_name)
1312 def detach_uprobe(self, name=b"", sym=b"", addr=None, pid=-1, sym_off=0):
1313 """detach_uprobe(name="", sym="", addr=None, pid=-1)
1315 Stop running a bpf function that is attached to symbol 'sym' in library
1319 name = _assert_is_bytes(name)
1320 sym = _assert_is_bytes(sym)
1321 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid, sym_off)
1322 ev_name = self._get_uprobe_evname(b"p", path, addr, pid)
1323 self.detach_uprobe_event(ev_name)
1325 def detach_uretprobe(self, name=b"", sym=b"", addr=None, pid=-1):
1326 """detach_uretprobe(name="", sym="", addr=None, pid=-1)
1328 Stop running a bpf function that is attached to symbol 'sym' in library
1332 name = _assert_is_bytes(name)
1333 sym = _assert_is_bytes(sym)
1335 (path, addr) = BPF._check_path_symbol(name, sym, addr, pid)
1336 ev_name = self._get_uprobe_evname(b"r", path, addr, pid)
1337 self.detach_uprobe_event(ev_name)
1339 def _trace_autoload(self):
1340 for i in range(0, lib.bpf_num_functions(self.module)):
1341 func_name = lib.bpf_function_name(self.module, i)
1342 if func_name.startswith(b"kprobe__"):
1343 fn = self.load_func(func_name, BPF.KPROBE)
1345 event=self.fix_syscall_fnname(func_name[8:]),
1347 elif func_name.startswith(b"kretprobe__"):
1348 fn = self.load_func(func_name, BPF.KPROBE)
1349 self.attach_kretprobe(
1350 event=self.fix_syscall_fnname(func_name[11:]),
1352 elif func_name.startswith(b"tracepoint__"):
1353 fn = self.load_func(func_name, BPF.TRACEPOINT)
1354 tp = fn.name[len(b"tracepoint__"):].replace(b"__", b":")
1355 self.attach_tracepoint(tp=tp, fn_name=fn.name)
1356 elif func_name.startswith(b"raw_tracepoint__"):
1357 fn = self.load_func(func_name, BPF.RAW_TRACEPOINT)
1358 tp = fn.name[len(b"raw_tracepoint__"):]
1359 self.attach_raw_tracepoint(tp=tp, fn_name=fn.name)
1360 elif func_name.startswith(b"kfunc__"):
1361 self.attach_kfunc(fn_name=func_name)
1362 elif func_name.startswith(b"kretfunc__"):
1363 self.attach_kretfunc(fn_name=func_name)
1364 elif func_name.startswith(b"lsm__"):
1365 self.attach_lsm(fn_name=func_name)
1367 def trace_open(self, nonblocking=False):
1368 """trace_open(nonblocking=False)
1370 Open the trace_pipe if not already open
1372 if not self.tracefile:
1373 self.tracefile = open("%s/trace_pipe" % TRACEFS, "rb")
1375 fd = self.tracefile.fileno()
1376 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
1377 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
1378 return self.tracefile
1380 def trace_fields(self, nonblocking=False):
1381 """trace_fields(nonblocking=False)
1383 Read from the kernel debug trace pipe and return a tuple of the
1384 fields (task, pid, cpu, flags, timestamp, msg) or None if no
1385 line was read (nonblocking=True)
1388 line = self.trace_readline(nonblocking)
1389 if not line and nonblocking: return (None,) * 6
1390 # don't print messages related to lost events
1391 if line.startswith(b"CPU:"): continue
1392 task = line[:16].lstrip()
1394 ts_end = line.find(b":")
1396 pid, cpu, flags, ts = line[:ts_end].split()
1397 except Exception as e:
1400 # line[ts_end:] will have ": [sym_or_addr]: msgs"
1401 # For trace_pipe debug output, the addr typically
1402 # is invalid (e.g., 0x1). For kernel 4.12 or earlier,
1403 # if address is not able to match a kernel symbol,
1404 # nothing will be printed out. For kernel 4.13 and later,
1405 # however, the illegal address will be printed out.
1406 # Hence, both cases are handled here.
1407 line = line[ts_end + 1:]
1408 sym_end = line.find(b":")
1409 msg = line[sym_end + 2:]
1411 return (task, int(pid), int(cpu), flags, float(ts), msg)
1412 except Exception as e:
1413 return ("Unknown", 0, 0, "Unknown", 0.0, "Unknown")
1415 def trace_readline(self, nonblocking=False):
1416 """trace_readline(nonblocking=False)
1418 Read from the kernel debug trace pipe and return one line
1419 If nonblocking is False, this will block until ctrl-C is pressed.
1422 trace = self.trace_open(nonblocking)
1426 line = trace.readline(1024).rstrip()
1431 def trace_print(self, fmt=None):
1432 """trace_print(self, fmt=None)
1434 Read from the kernel debug trace pipe and print on stdout.
1435 If fmt is specified, apply as a format string to the output. See
1436 trace_fields for the members of the tuple
1437 example: trace_print(fmt="pid {1}, msg = {5}")
1442 fields = self.trace_fields(nonblocking=False)
1443 if not fields: continue
1444 line = fmt.format(*fields)
1446 line = self.trace_readline(nonblocking=False)
1451 def _sym_cache(pid):
1454 Returns a symbol cache for the specified PID.
1455 The kernel symbol cache is accessed by providing any PID less than zero.
1457 if pid < 0 and pid != -1:
1459 if not pid in BPF._sym_caches:
1460 BPF._sym_caches[pid] = SymbolCache(pid)
1461 return BPF._sym_caches[pid]
1464 def sym(addr, pid, show_module=False, show_offset=False, demangle=True):
1465 """sym(addr, pid, show_module=False, show_offset=False)
1467 Translate a memory address into a function name for a pid, which is
1468 returned. When show_module is True, the module name is also included.
1469 When show_offset is True, the instruction offset as a hexadecimal
1470 number is also included in the string.
1472 A pid of less than zero will access the kernel symbol cache.
1474 Example output when both show_module and show_offset are True:
1475 "start_thread+0x202 [libpthread-2.24.so]"
1477 Example output when both show_module and show_offset are False:
1481 #addr is of type stacktrace_build_id
1482 #so invoke the bsym address resolver
1483 typeofaddr = str(type(addr))
1484 if typeofaddr.find('bpf_stack_build_id') != -1:
1486 b = bcc_stacktrace_build_id()
1487 b.status = addr.status
1488 b.build_id = addr.build_id
1489 b.u.offset = addr.offset
1490 res = lib.bcc_buildsymcache_resolve(BPF._bsymcache,
1494 if sym.module and sym.offset:
1495 name,offset,module = (None, sym.offset,
1496 ct.cast(sym.module, ct.c_char_p).value)
1498 name, offset, module = (None, addr, None)
1500 name, offset, module = (sym.name, sym.offset,
1501 ct.cast(sym.module, ct.c_char_p).value)
1503 name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle)
1505 offset = b"+0x%x" % offset if show_offset and name is not None else b""
1506 name = name or b"[unknown]"
1507 name = name + offset
1508 module = b" [%s]" % os.path.basename(module) \
1509 if show_module and module is not None else b""
1510 return name + module
1513 def ksym(addr, show_module=False, show_offset=False):
1516 Translate a kernel memory address into a kernel function name, which is
1517 returned. When show_module is True, the module name ("kernel") is also
1518 included. When show_offset is true, the instruction offset as a
1519 hexadecimal number is also included in the string.
1521 Example output when both show_module and show_offset are True:
1522 "default_idle+0x0 [kernel]"
1524 return BPF.sym(addr, -1, show_module, show_offset, False)
1530 Translate a kernel name into an address. This is the reverse of
1531 ksym. Returns -1 when the function name is unknown."""
1532 return BPF._sym_cache(-1).resolve_name(None, name)
1534 def num_open_kprobes(self):
1535 """num_open_kprobes()
1537 Get the number of open K[ret]probes. Can be useful for scenarios where
1538 event_re is used while attaching and detaching probes.
1540 return len(self.kprobe_fds)
1542 def num_open_uprobes(self):
1543 """num_open_uprobes()
1545 Get the number of open U[ret]probes.
1547 return len(self.uprobe_fds)
1549 def num_open_tracepoints(self):
1550 """num_open_tracepoints()
1552 Get the number of open tracepoints.
1554 return len(self.tracepoint_fds)
1556 def perf_buffer_poll(self, timeout = -1):
1557 """perf_buffer_poll(self)
1559 Poll from all open perf ring buffers, calling the callback that was
1560 provided when calling open_perf_buffer for each entry.
1562 readers = (ct.c_void_p * len(self.perf_buffers))()
1563 for i, v in enumerate(self.perf_buffers.values()):
1565 lib.perf_reader_poll(len(readers), readers, timeout)
1567 def kprobe_poll(self, timeout = -1):
1568 """kprobe_poll(self)
1570 Deprecated. Use perf_buffer_poll instead.
1572 self.perf_buffer_poll(timeout)
1574 def _open_ring_buffer(self, map_fd, fn, ctx=None):
1575 if not self._ringbuf_manager:
1576 self._ringbuf_manager = lib.bpf_new_ringbuf(map_fd, fn, ctx)
1577 if not self._ringbuf_manager:
1578 raise Exception("Could not open ring buffer")
1580 ret = lib.bpf_add_ringbuf(self._ringbuf_manager, map_fd, fn, ctx)
1582 raise Exception("Could not open ring buffer")
1584 def ring_buffer_poll(self, timeout = -1):
1585 """ring_buffer_poll(self)
1587 Poll from all open ringbuf buffers, calling the callback that was
1588 provided when calling open_ring_buffer for each entry.
1590 if not self._ringbuf_manager:
1591 raise Exception("No ring buffers to poll")
1592 lib.bpf_poll_ringbuf(self._ringbuf_manager, timeout)
1594 def ring_buffer_consume(self):
1595 """ring_buffer_consume(self)
1597 Consume all open ringbuf buffers, regardless of whether or not
1598 they currently contain events data. This is best for use cases
1599 where low latency is desired, but it can impact performance.
1600 If you are unsure, use ring_buffer_poll instead.
1602 if not self._ringbuf_manager:
1603 raise Exception("No ring buffers to poll")
1604 lib.bpf_consume_ringbuf(self._ringbuf_manager)
1606 def free_bcc_memory(self):
1607 return lib.bcc_free_memory()
1610 def add_module(modname):
1611 """add_module(modname)
1613 Add a library or exe to buildsym cache
1616 lib.bcc_buildsymcache_add_module(BPF._bsymcache, modname.encode())
1617 except Exception as e:
1618 print("Error adding module to build sym cache"+str(e))
1620 def donothing(self):
1621 """the do nothing exit handler"""
1624 # Clean up opened probes
1625 for k, v in list(self.kprobe_fds.items()):
1626 self.detach_kprobe_event(k)
1627 for k, v in list(self.uprobe_fds.items()):
1628 self.detach_uprobe_event(k)
1629 for k, v in list(self.tracepoint_fds.items()):
1630 self.detach_tracepoint(k)
1631 for k, v in list(self.raw_tracepoint_fds.items()):
1632 self.detach_raw_tracepoint(k)
1633 for k, v in list(self.kfunc_entry_fds.items()):
1634 self.detach_kfunc(k)
1635 for k, v in list(self.kfunc_exit_fds.items()):
1636 self.detach_kretfunc(k)
1637 for k, v in list(self.lsm_fds.items()):
1640 # Clean up opened perf ring buffer and perf events
1641 table_keys = list(self.tables.keys())
1642 for key in table_keys:
1643 if isinstance(self.tables[key], PerfEventArray):
1644 del self.tables[key]
1645 for (ev_type, ev_config) in list(self.open_perf_events.keys()):
1646 self.detach_perf_event(ev_type, ev_config)
1648 self.tracefile.close()
1649 self.tracefile = None
1650 for name, fn in list(self.funcs.items()):
1652 del self.funcs[name]
1654 lib.bpf_module_destroy(self.module)
1658 if self._ringbuf_manager:
1659 lib.bpf_free_ringbuf(self._ringbuf_manager)
1660 self._ringbuf_manager = None
1662 def __enter__(self):
1665 def __exit__(self, exc_type, exc_val, exc_tb):