bcc/python: remove unused imports, remove redundant semicolon
[platform/upstream/bcc.git] / src / python / bcc / __init__.py
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
15 from __future__ import print_function
16 import atexit
17 import ctypes as ct
18 import fcntl
19 import json
20 import os
21 import re
22 import errno
23 import sys
24 import platform
25
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
33
34 try:
35     basestring
36 except NameError:  # Python 3
37     basestring = str
38
39 _probe_limit = 1000
40 _num_open_probes = 0
41
42 # for tests
43 def _get_num_open_probes():
44     global _num_open_probes
45     return _num_open_probes
46
47 TRACEFS = "/sys/kernel/debug/tracing"
48
49 # Debug flags
50
51 # Debug output compiled LLVM IR.
52 DEBUG_LLVM_IR = 0x1
53 # Debug output loaded BPF bytecode and register state on branches.
54 DEBUG_BPF = 0x2
55 # Debug output pre-processor result.
56 DEBUG_PREPROCESSOR = 0x4
57 # Debug output ASM instructions embedded with source.
58 DEBUG_SOURCE = 0x8
59 # Debug output register state on all instructions in addition to DEBUG_BPF.
60 DEBUG_BPF_REGISTER_STATE = 0x10
61 # Debug BTF.
62 DEBUG_BTF = 0x20
63
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)))
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
107
108 class PerfType:
109     # From perf_type_id in uapi/linux/perf_event.h
110     HARDWARE = 0
111     SOFTWARE = 1
112     TRACEPOINT = 2
113     HW_CACHE = 3
114     RAW = 4
115     BREAKPOINT = 5
116
117 class PerfHWConfig:
118     # From perf_hw_id in uapi/linux/perf_event.h
119     CPU_CYCLES = 0
120     INSTRUCTIONS = 1
121     CACHE_REFERENCES = 2
122     CACHE_MISSES = 3
123     BRANCH_INSTRUCTIONS = 4
124     BRANCH_MISSES = 5
125     BUS_CYCLES = 6
126     STALLED_CYCLES_FRONTEND = 7
127     STALLED_CYCLES_BACKEND = 8
128     REF_CPU_CYCLES = 9
129
130 class PerfSWConfig:
131     # From perf_sw_id in uapi/linux/perf_event.h
132     CPU_CLOCK = 0
133     TASK_CLOCK = 1
134     PAGE_FAULTS = 2
135     CONTEXT_SWITCHES = 3
136     CPU_MIGRATIONS = 4
137     PAGE_FAULTS_MIN = 5
138     PAGE_FAULTS_MAJ = 6
139     ALIGNMENT_FAULTS = 7
140     EMULATION_FAULTS = 8
141     DUMMY = 9
142     BPF_OUTPUT = 10
143
144 class BPFProgType:
145     # From bpf_prog_type in uapi/linux/bpf.h
146     SOCKET_FILTER = 1
147     KPROBE = 2
148     SCHED_CLS = 3
149     SCHED_ACT = 4
150     TRACEPOINT = 5
151     XDP = 6
152     PERF_EVENT = 7
153     CGROUP_SKB = 8
154     CGROUP_SOCK = 9
155     LWT_IN = 10
156     LWT_OUT = 11
157     LWT_XMIT = 12
158     SOCK_OPS = 13
159     SK_SKB = 14
160     CGROUP_DEVICE = 15
161     SK_MSG = 16
162     RAW_TRACEPOINT = 17
163     CGROUP_SOCK_ADDR = 18
164     TRACING = 26
165     LSM = 29
166
167 class BPFAttachType:
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
172     CGROUP_SOCK_OPS = 3
173     SK_SKB_STREAM_PARSER = 4
174     SK_SKB_STREAM_VERDICT = 5
175     CGROUP_DEVICE = 6
176     SK_MSG_VERDICT = 7
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
185     LIRC_MODE2 = 16
186     FLOW_DISSECTOR = 17
187     CGROUP_SYSCTL = 18
188     CGROUP_UDP4_RECVMSG = 19
189     CGROUP_UDP6_RECVMSG = 20
190     CGROUP_GETSOCKOPT = 21
191     CGROUP_SETSOCKOPT = 22
192     TRACE_RAW_TP = 23
193     TRACE_FENTRY = 24
194     TRACE_FEXIT  = 25
195     MODIFY_RETURN = 26
196     LSM_MAC = 27
197     TRACE_ITER = 28
198     CGROUP_INET4_GETPEERNAME = 29
199     CGROUP_INET6_GETPEERNAME = 30
200     CGROUP_INET4_GETSOCKNAME = 31
201     CGROUP_INET6_GETSOCKNAME = 32
202     XDP_DEVMAP = 33
203     CGROUP_INET_SOCK_RELEASE = 34
204     XDP_CPUMAP = 35
205     SK_LOOKUP = 36
206     XDP = 37
207     SK_SKB_VERDICT = 38
208
209 class XDPAction:
210     # from xdp_action uapi/linux/bpf.h
211     XDP_ABORTED = 0
212     XDP_DROP = 1
213     XDP_PASS = 2
214     XDP_TX = 3
215     XDP_REDIRECT = 4
216
217 class XDPFlags:
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)
222     SKB_MODE = (1 << 1)
223     DRV_MODE = (1 << 2)
224     HW_MODE = (1 << 3)
225     REPLACE = (1 << 4)
226
227 class BPF(object):
228     # Here for backwards compatibility only, add new enum members and types
229     # the appropriate wrapper class elsewhere in this file to avoid namespace
230     # collision issues
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
251
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
257
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
264
265     _probe_repl = re.compile(b"[^a-zA-Z0-9_]")
266     _sym_caches = {}
267     _bsymcache =  lib.bcc_buildsymcache_new()
268
269     _auto_includes = {
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"]
275     }
276
277     _syscall_prefixes = [
278         b"sys_",
279         b"__x64_sys_",
280         b"__x32_compat_sys_",
281         b"__ia32_compat_sys_",
282         b"__arm64_sys_",
283         b"__s390x_sys_",
284         b"__s390_sys_",
285     ]
286
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>
291
292     class timespec(ct.Structure):
293         _fields_ = [('tv_sec', ct.c_long), ('tv_nsec', ct.c_long)]
294
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)]
298
299     @classmethod
300     def monotonic_time(cls):
301         """monotonic_time()
302         Returns the system monotonic time from clock_gettime, using the
303         CLOCK_MONOTONIC constant. The time returned is in nanoseconds.
304         """
305         t = cls.timespec()
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
310
311     @classmethod
312     def generate_auto_includes(cls, program_words):
313         """
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>".
318         """
319         headers = ""
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
325         return headers
326
327     # defined for compatibility reasons, to be removed
328     Table = Table
329
330     class Function(object):
331         def __init__(self, bpf, name, fd):
332             self.bpf = bpf
333             self.name = name
334             self.fd = fd
335
336     @staticmethod
337     def _find_file(filename):
338         """ If filename is invalid, search in ./ of argv[0] """
339         if filename:
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):
344                     filename = t
345                 else:
346                     raise Exception("Could not find file %s" % filename)
347         return filename
348
349     @staticmethod
350     def find_exe(bin_path):
351         """
352         find_exe(bin_path)
353
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.
360         """
361         # Source: http://stackoverflow.com/a/377028
362         def is_exe(fpath):
363             return os.path.isfile(fpath) and \
364                 os.access(fpath, os.X_OK)
365
366         fpath, fname = os.path.split(bin_path)
367         if fpath:
368             if is_exe(bin_path):
369                 return bin_path
370         else:
371             for path in os.environ["PATH"].split(os.pathsep):
372                 path = path.strip('"')
373                 exe_file = os.path.join(path.encode(), bin_path)
374                 if is_exe(exe_file):
375                     return exe_file
376         return None
377
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.
382
383         Note:
384             All fields are marked as optional, but either `src_file` or `text`
385             must be supplied, and not both.
386
387         Args:
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
393         """
394
395         src_file = _assert_is_bytes(src_file)
396         hdr_file = _assert_is_bytes(hdr_file)
397         text = _assert_is_bytes(text)
398
399         assert not (text and src_file)
400
401         self.kprobe_fds = {}
402         self.uprobe_fds = {}
403         self.tracepoint_fds = {}
404         self.raw_tracepoint_fds = {}
405         self.kfunc_entry_fds = {}
406         self.kfunc_exit_fds = {}
407         self.lsm_fds = {}
408         self.perf_buffers = {}
409         self.open_perf_events = {}
410         self._ringbuf_manager = None
411         self.tracefile = None
412         atexit.register(self.cleanup)
413
414         self.debug = debug
415         self.funcs = {}
416         self.tables = {}
417         self.module = None
418         cflags_array = (ct.c_char_p * len(cflags))()
419         for i, s in enumerate(cflags): cflags_array[i] = bytes(ArgString(s))
420
421         if src_file:
422             src_file = BPF._find_file(src_file)
423             hdr_file = BPF._find_file(hdr_file)
424
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)
428         else:
429             if src_file:
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:
433                     text = file.read()
434
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 " +
443                                 "locations")
444             text = usdt_text + text
445
446
447             self.module = lib.bpf_module_create_c_from_string(text,
448                                                               self.debug,
449                                                               cflags_array, len(cflags_array),
450                                                               allow_rlimit, device)
451         if not self.module:
452             raise Exception("Failed to compile BPF module %s" % (src_file or "<text>"))
453
454         for usdt_context in usdt_contexts:
455             usdt_context.attach_uprobes(self, attach_usdt_ignore_pid)
456
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()
461
462     def load_funcs(self, prog_type=KPROBE):
463         """load_funcs(prog_type=KPROBE)
464
465         Load all functions in this BPF module with the given type.
466         Returns a list of the function handles."""
467
468         fns = []
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))
472
473         return fns
474
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)
481         log_level = 0
482         if (self.debug & DEBUG_BPF_REGISTER_STATE):
483             log_level = 2
484         elif (self.debug & DEBUG_BPF):
485             log_level = 1
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)
492
493         if fd < 0:
494             atexit.register(self.donothing)
495             if ct.get_errno() == errno.EPERM:
496                 raise Exception("Need super-user privileges to run")
497
498             errstr = os.strerror(ct.get_errno())
499             raise Exception("Failed to load BPF program %s: %s" %
500                             (func_name, errstr))
501
502         fn = BPF.Function(self, func_name, fd)
503         self.funcs[func_name] = fn
504
505         return fn
506
507     def dump_func(self, func_name):
508         """
509         Return the eBPF bytecodes for the specified function as a string
510         """
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)
514
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)
518
519     def disassemble_func(self, func_name):
520         bpfstr = self.dump_func(func_name)
521         return disassemble_prog(func_name, bpfstr)
522
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)
527
528     str2ctype = {
529         u"_Bool": ct.c_bool,
530         u"char": ct.c_char,
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,
535         u"int": ct.c_int,
536         u"unsigned int": ct.c_uint,
537         u"long": ct.c_long,
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,
546     }
547     @staticmethod
548     def _decode_table_type(desc):
549         if isinstance(desc, basestring):
550             return BPF.str2ctype[desc]
551         anon = []
552         fields = []
553         for t in desc[1]:
554             if len(t) == 2:
555                 fields.append((t[0], BPF._decode_table_type(t[1])))
556             elif len(t) == 3:
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"):
564                     name = t[0]
565                     if name == "":
566                         name = "__anon%d" % len(anon)
567                         anon.append(name)
568                     fields.append((name, BPF._decode_table_type(t)))
569                 else:
570                     raise Exception("Failed to decode type %s" % str(t))
571             else:
572                 raise Exception("Failed to decode type %s" % str(t))
573         base = ct.Structure
574         is_packed = False
575         if len(desc) > 2:
576             if desc[2] == u"union":
577                 base = ct.Union
578             elif desc[2] == u"struct":
579                 base = ct.Structure
580             elif desc[2] == u"struct_packed":
581                 base = ct.Structure
582                 is_packed = True
583         if is_packed:
584             cls = type(str(desc[0]), (base,), dict(_anonymous_=anon, _pack_=1,
585                 _fields_=fields))
586         else:
587             cls = type(str(desc[0]), (base,), dict(_anonymous_=anon,
588                 _fields_=fields))
589         return cls
590
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]
596         if map_fd < 0:
597             raise KeyError
598         if not keytype and not is_queuestack:
599             key_desc = lib.bpf_table_key_desc(self.module, name).decode("utf-8")
600             if not key_desc:
601                 raise Exception("Failed to load BPF Table %s key desc" % name)
602             keytype = BPF._decode_table_type(json.loads(key_desc))
603         if not leaftype:
604             leaf_desc = lib.bpf_table_leaf_desc(self.module, name).decode("utf-8")
605             if not leaf_desc:
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)
609
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]
614
615     def __setitem__(self, key, leaf):
616         self.tables[key] = leaf
617
618     def __len__(self):
619         return len(self.tables)
620
621     def __delitem__(self, key):
622         del self.tables[key]
623
624     def __iter__(self):
625         return self.tables.__iter__()
626
627     @staticmethod
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")
631
632         res = lib.bpf_prog_attach(fn.fd, attachable_fd, attach_type, flags)
633         if res < 0:
634             raise Exception("Failed to attach BPF function with attach_type "\
635                             "{0}: {1}".format(attach_type, os.strerror(-res)))
636
637     @staticmethod
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")
641
642         res = lib.bpf_prog_detach2(fn.fd, attachable_fd, attach_type)
643         if res < 0:
644             raise Exception("Failed to detach BPF function with attach_type "\
645                             "{0}: {1}".format(attach_type, os.strerror(-res)))
646
647     @staticmethod
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)
653         if sock < 0:
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)
657         if res < 0:
658             errstr = os.strerror(ct.get_errno())
659             raise Exception("Failed to attach BPF to device %s: %s"
660                     % (dev, errstr))
661         fn.sock = sock
662
663     @staticmethod
664     def get_kprobe_functions(event_re):
665         blacklist_file = "%s/../kprobes/blacklist" % TRACEFS
666         try:
667             with open(blacklist_file, "rb") as blacklist_f:
668                 blacklist = set([line.rstrip().split()[1] for line in blacklist_f])
669         except IOError as e:
670             if e.errno != errno.EPERM:
671                 raise e
672             blacklist = set([])
673
674         fns = []
675
676         in_init_section = 0
677         in_irq_section = 0
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
682                 # __init_end
683                 if in_init_section == 0:
684                     if fn == b'__init_begin':
685                         in_init_section = 1
686                         continue
687                 elif in_init_section == 1:
688                     if fn == b'__init_end':
689                         in_init_section = 2
690                     continue
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':
695                         in_irq_section = 1
696                         continue
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':
701                         in_irq_section = 2
702                         continue
703                 elif in_irq_section == 1:
704                     if fn == b'__irqentry_text_end':
705                         in_irq_section = 2
706                     continue
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
710                 # modules.
711                 if fn.startswith(b'_kbl_addr_'):
712                     continue
713                 # Explicitly blacklist perf-related functions, they are all
714                 # non-attachable.
715                 elif fn.startswith(b'__perf') or fn.startswith(b'perf_'):
716                     continue
717                 # Exclude all gcc 8's extra .cold functions
718                 elif re.match(b'^.*\.cold(\.\d+)?$', fn):
719                     continue
720                 if (t.lower() in [b't', b'w']) and re.match(event_re, fn) \
721                     and fn not in blacklist:
722                     fns.append(fn)
723         return set(fns)     # Some functions may appear more than once
724
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")
729
730     def _add_kprobe_fd(self, name, fd):
731         global _num_open_probes
732         self.kprobe_fds[name] = fd
733         _num_open_probes += 1
734
735     def _del_kprobe_fd(self, name):
736         global _num_open_probes
737         del self.kprobe_fds[name]
738         _num_open_probes -= 1
739
740     def _add_uprobe_fd(self, name, fd):
741         global _num_open_probes
742         self.uprobe_fds[name] = fd
743         _num_open_probes += 1
744
745     def _del_uprobe_fd(self, name):
746         global _num_open_probes
747         del self.uprobe_fds[name]
748         _num_open_probes -= 1
749
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:
756                 return prefix
757         return self._syscall_prefixes[0]
758
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
765
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):])
774         return name
775
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)
780
781         # allow the caller to glob multiple functions together
782         if event_re:
783             matches = BPF.get_kprobe_functions(event_re)
784             self._check_probe_quota(len(matches))
785             for line in matches:
786                 try:
787                     self.attach_kprobe(event=line, fn_name=fn_name)
788                 except:
789                     pass
790             return
791
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)
796         if fd < 0:
797             raise Exception("Failed to attach BPF program %s to kprobe %s" %
798                             (fn_name, event))
799         self._add_kprobe_fd(ev_name, fd)
800         return self
801
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)
806
807         # allow the caller to glob multiple functions together
808         if event_re:
809             for line in BPF.get_kprobe_functions(event_re):
810                 try:
811                     self.attach_kretprobe(event=line, fn_name=fn_name,
812                                           maxactive=maxactive)
813                 except:
814                     pass
815             return
816
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)
821         if fd < 0:
822             raise Exception("Failed to attach BPF program %s to kretprobe %s" %
823                             (fn_name, event))
824         self._add_kprobe_fd(ev_name, fd)
825         return self
826
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])
831         if res < 0:
832             raise Exception("Failed to close kprobe FD")
833         res = lib.bpf_detach_kprobe(ev_name)
834         if res < 0:
835             raise Exception("Failed to detach BPF from kprobe")
836         self._del_kprobe_fd(ev_name)
837
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)
842
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)
847
848     @staticmethod
849     def attach_xdp(dev, fn, flags=0):
850         '''
851             This function attaches a BPF function to a device on the device
852             driver level (XDP)
853         '''
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)
858         if res < 0:
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!")
863             else:
864                 errstr = os.strerror(err_no)
865                 raise Exception("Failed to attach BPF to device %s: %s"
866                             % (dev, errstr))
867
868     @staticmethod
869     def remove_xdp(dev, flags=0):
870         '''
871             This function removes any BPF function from a device on the
872             device driver level (XDP)
873         '''
874         dev = _assert_is_bytes(dev)
875         res = lib.bpf_attach_xdp(dev, -1, flags)
876         if res < 0:
877             errstr = os.strerror(ct.get_errno())
878             raise Exception("Failed to detach BPF from device %s: %s"
879                             % (dev, errstr))
880
881
882
883     @classmethod
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)
887         sym = bcc_symbol()
888         c_pid = 0 if pid == -1 else pid
889         if lib.bcc_resolve_symname(
890             module, symname,
891             addr or 0x0, c_pid,
892             ct.cast(None, ct.POINTER(bcc_symbol_option)),
893             ct.byref(sym),
894         ) < 0:
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
900
901     @staticmethod
902     def find_library(libname):
903         libname = _assert_is_bytes(libname)
904         res = lib.bcc_procutils_which_so(libname, 0)
905         if not res:
906             return None
907         libpath = ct.cast(res, ct.c_char_p).value
908         lib.bcc_procutils_free(res)
909         return libpath
910
911     @staticmethod
912     def get_tracepoints(tp_re):
913         results = []
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):
918                 continue
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):
924                         results.append(tp)
925         return results
926
927     @staticmethod
928     def tracepoint_exists(category, event):
929         evt_dir = os.path.join(TRACEFS, "events", category, event)
930         return os.path.isdir(evt_dir)
931
932     def attach_tracepoint(self, tp=b"", tp_re=b"", fn_name=b""):
933         """attach_tracepoint(tp="", tp_re="", fn_name="")
934
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.
940
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.
944
945         To obtain a list of kernel tracepoints, use the tplist tool or cat the
946         file /sys/kernel/debug/tracing/available_events.
947
948         Examples:
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")
951         """
952
953         tp = _assert_is_bytes(tp)
954         tp_re = _assert_is_bytes(tp_re)
955         fn_name = _assert_is_bytes(fn_name)
956         if tp_re:
957             for tp in BPF.get_tracepoints(tp_re):
958                 self.attach_tracepoint(tp=tp, fn_name=fn_name)
959             return
960
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)
964         if fd < 0:
965             raise Exception("Failed to attach BPF program %s to tracepoint %s" %
966                             (fn_name, tp))
967         self.tracepoint_fds[tp] = fd
968         return self
969
970     def attach_raw_tracepoint(self, tp=b"", fn_name=b""):
971         """attach_raw_tracepoint(self, tp=b"", fn_name=b"")
972
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.
977
978         Examples:
979             BPF(text).attach_raw_tracepoint(tp="sched_switch", fn_name="on_switch")
980         """
981
982         tp = _assert_is_bytes(tp)
983         if tp in self.raw_tracepoint_fds:
984             raise Exception("Raw tracepoint %s has been attached" % tp)
985
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)
989         if fd < 0:
990             raise Exception("Failed to attach BPF to raw tracepoint")
991         self.raw_tracepoint_fds[tp] = fd
992         return self
993
994     def detach_raw_tracepoint(self, tp=b""):
995         """detach_raw_tracepoint(tp="")
996
997         Stop running the bpf function that is attached to the kernel tracepoint
998         specified by 'tp'.
999
1000         Example: bpf.detach_raw_tracepoint("sched_switch")
1001         """
1002
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]
1008
1009     @staticmethod
1010     def add_prefix(prefix, name):
1011         if not name.startswith(prefix):
1012             name = prefix + name
1013         return name
1014
1015     @staticmethod
1016     def support_kfunc():
1017         # there's no trampoline support for other than x86_64 arch
1018         if platform.machine() != 'x86_64':
1019             return False
1020         if not lib.bpf_has_kernel_btf():
1021             return False
1022         # kernel symbol "bpf_trampoline_link_prog" indicates kfunc support
1023         if BPF.ksymname("bpf_trampoline_link_prog") != -1:
1024             return True
1025         return False
1026
1027     @staticmethod
1028     def support_lsm():
1029         if not lib.bpf_has_kernel_btf():
1030             return False
1031         # kernel symbol "bpf_lsm_bpf" indicates BPF LSM support
1032         if BPF.ksymname(b"bpf_lsm_bpf") != -1:
1033             return True
1034         return False
1035
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)
1039
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]
1044
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)
1048
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]
1053
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)
1057
1058         if fn_name in self.kfunc_entry_fds:
1059             raise Exception("Kernel entry func %s has been attached" % fn_name)
1060
1061         fn = self.load_func(fn_name, BPF.TRACING)
1062         fd = lib.bpf_attach_kfunc(fn.fd)
1063         if fd < 0:
1064             raise Exception("Failed to attach BPF to entry kernel func")
1065         self.kfunc_entry_fds[fn_name] = fd
1066         return self
1067
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)
1071
1072         if fn_name in self.kfunc_exit_fds:
1073             raise Exception("Kernel exit func %s has been attached" % fn_name)
1074
1075         fn = self.load_func(fn_name, BPF.TRACING)
1076         fd = lib.bpf_attach_kfunc(fn.fd)
1077         if fd < 0:
1078             raise Exception("Failed to attach BPF to exit kernel func")
1079         self.kfunc_exit_fds[fn_name] = fd
1080         return self
1081
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)
1085
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]
1090
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)
1094
1095         if fn_name in self.lsm_fds:
1096             raise Exception("LSM %s has been attached" % fn_name)
1097
1098         fn = self.load_func(fn_name, BPF.LSM)
1099         fd = lib.bpf_attach_lsm(fn.fd)
1100         if fd < 0:
1101             raise Exception("Failed to attach LSM")
1102         self.lsm_fds[fn_name] = fd
1103         return self
1104
1105     @staticmethod
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:
1110             return True
1111         return False
1112
1113     def detach_tracepoint(self, tp=b""):
1114         """detach_tracepoint(tp="")
1115
1116         Stop running a bpf function that is attached to the kernel tracepoint
1117         specified by 'tp'.
1118
1119         Example: bpf.detach_tracepoint("sched:sched_switch")
1120         """
1121
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])
1126         if res < 0:
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)
1130         if res < 0:
1131             raise Exception("Failed to detach BPF from tracepoint")
1132         del self.tracepoint_fds[tp]
1133
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)
1138         if res < 0:
1139             raise Exception("Failed to attach BPF to perf event")
1140         return res
1141
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)
1146         res = {}
1147         if cpu >= 0:
1148             res[cpu] = self._attach_perf_event(fn.fd, ev_type, ev_config,
1149                     sample_period, sample_freq, pid, cpu, group_fd)
1150         else:
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
1155
1156     def detach_perf_event(self, ev_type=-1, ev_config=-1):
1157         try:
1158             fds = self.open_perf_events[(ev_type, ev_config)]
1159         except KeyError:
1160             raise Exception("Perf event type {} config {} not attached".format(
1161                 ev_type, ev_config))
1162
1163         res = 0
1164         for fd in fds.values():
1165             res = lib.bpf_close_perf_event_fd(fd) or res
1166         if res != 0:
1167             raise Exception("Failed to detach BPF from perf event")
1168         del self.open_perf_events[(ev_type, ev_config)]
1169
1170     @staticmethod
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)])
1174
1175     @staticmethod
1176     def get_user_addresses(name, sym_re):
1177         """
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.
1184         """
1185         return set([address for (_, address) in
1186                     BPF.get_user_functions_and_addresses(name, sym_re)])
1187
1188     @staticmethod
1189     def get_user_functions_and_addresses(name, sym_re):
1190         name = _assert_is_bytes(name)
1191         sym_re = _assert_is_bytes(sym_re)
1192         addresses = []
1193         def sym_cb(sym_name, addr):
1194             dname = sym_name
1195             if re.match(sym_re, dname):
1196                 addresses.append((dname, addr))
1197             return 0
1198
1199         res = lib.bcc_foreach_function_symbol(name, _SYM_CB_TYPE(sym_cb))
1200         if res < 0:
1201             raise Exception("Error %d enumerating symbols in %s" % (res, name))
1202         return addresses
1203
1204     def _get_uprobe_evname(self, prefix, path, addr, pid):
1205         if pid == -1:
1206             return b"%s_%s_0x%x" % (prefix, self._probe_repl.sub(b"_", path), addr)
1207         else:
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)
1211
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=""
1215                          pid=-1, sym_off=0)
1216
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.
1220
1221         If sym_off is given, attach uprobe to offset within the symbol.
1222
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.
1227
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
1230         regular expression.
1231
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.
1236
1237         Example: BPF(text).attach_uprobe("c", "malloc")
1238                  BPF(text).attach_uprobe("/usr/bin/python", "main")
1239         """
1240
1241         assert sym_off >= 0
1242         if addr is not None:
1243             assert sym_off == 0, "offset with addr is not supported"
1244
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)
1249
1250         if sym_re:
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)
1256             return
1257
1258         (path, addr) = BPF._check_path_symbol(name, sym, addr, pid, sym_off)
1259
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)
1264         if fd < 0:
1265             raise Exception("Failed to attach BPF to uprobe")
1266         self._add_uprobe_fd(ev_name, fd)
1267         return self
1268
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=""
1272                             pid=-1)
1273
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.
1277         """
1278
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)
1283
1284         if sym_re:
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)
1288             return
1289
1290         (path, addr) = BPF._check_path_symbol(name, sym, addr, pid)
1291
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)
1296         if fd < 0:
1297             raise Exception("Failed to attach BPF to uretprobe")
1298         self._add_uprobe_fd(ev_name, fd)
1299         return self
1300
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])
1305         if res < 0:
1306             raise Exception("Failed to detach BPF from uprobe")
1307         res = lib.bpf_detach_uprobe(ev_name)
1308         if res < 0:
1309             raise Exception("Failed to detach BPF from uprobe")
1310         self._del_uprobe_fd(ev_name)
1311
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)
1314
1315         Stop running a bpf function that is attached to symbol 'sym' in library
1316         or binary 'name'.
1317         """
1318
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)
1324
1325     def detach_uretprobe(self, name=b"", sym=b"", addr=None, pid=-1):
1326         """detach_uretprobe(name="", sym="", addr=None, pid=-1)
1327
1328         Stop running a bpf function that is attached to symbol 'sym' in library
1329         or binary 'name'.
1330         """
1331
1332         name = _assert_is_bytes(name)
1333         sym = _assert_is_bytes(sym)
1334
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)
1338
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)
1344                 self.attach_kprobe(
1345                     event=self.fix_syscall_fnname(func_name[8:]),
1346                     fn_name=fn.name)
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:]),
1351                     fn_name=fn.name)
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)
1366
1367     def trace_open(self, nonblocking=False):
1368         """trace_open(nonblocking=False)
1369
1370         Open the trace_pipe if not already open
1371         """
1372         if not self.tracefile:
1373             self.tracefile = open("%s/trace_pipe" % TRACEFS, "rb")
1374             if nonblocking:
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
1379
1380     def trace_fields(self, nonblocking=False):
1381         """trace_fields(nonblocking=False)
1382
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)
1386         """
1387         while 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()
1393             line = line[17:]
1394             ts_end = line.find(b":")
1395             try:
1396                 pid, cpu, flags, ts = line[:ts_end].split()
1397             except Exception as e:
1398                 continue
1399             cpu = cpu[1:-1]
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:]
1410             try:
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")
1414
1415     def trace_readline(self, nonblocking=False):
1416         """trace_readline(nonblocking=False)
1417
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.
1420         """
1421
1422         trace = self.trace_open(nonblocking)
1423
1424         line = None
1425         try:
1426             line = trace.readline(1024).rstrip()
1427         except IOError:
1428             pass
1429         return line
1430
1431     def trace_print(self, fmt=None):
1432         """trace_print(self, fmt=None)
1433
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}")
1438         """
1439
1440         while True:
1441             if fmt:
1442                 fields = self.trace_fields(nonblocking=False)
1443                 if not fields: continue
1444                 line = fmt.format(*fields)
1445             else:
1446                 line = self.trace_readline(nonblocking=False)
1447             print(line)
1448             sys.stdout.flush()
1449
1450     @staticmethod
1451     def _sym_cache(pid):
1452         """_sym_cache(pid)
1453
1454         Returns a symbol cache for the specified PID.
1455         The kernel symbol cache is accessed by providing any PID less than zero.
1456         """
1457         if pid < 0 and pid != -1:
1458             pid = -1
1459         if not pid in BPF._sym_caches:
1460             BPF._sym_caches[pid] = SymbolCache(pid)
1461         return BPF._sym_caches[pid]
1462
1463     @staticmethod
1464     def sym(addr, pid, show_module=False, show_offset=False, demangle=True):
1465         """sym(addr, pid, show_module=False, show_offset=False)
1466
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.
1471
1472         A pid of less than zero will access the kernel symbol cache.
1473
1474         Example output when both show_module and show_offset are True:
1475             "start_thread+0x202 [libpthread-2.24.so]"
1476
1477         Example output when both show_module and show_offset are False:
1478             "start_thread"
1479         """
1480
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:
1485           sym = bcc_symbol()
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,
1491                                               ct.byref(b),
1492                                               ct.byref(sym))
1493           if res < 0:
1494             if sym.module and sym.offset:
1495               name,offset,module = (None, sym.offset,
1496                         ct.cast(sym.module, ct.c_char_p).value)
1497             else:
1498               name, offset, module = (None, addr, None)
1499           else:
1500             name, offset, module = (sym.name, sym.offset,
1501                                     ct.cast(sym.module, ct.c_char_p).value)
1502         else:
1503           name, offset, module = BPF._sym_cache(pid).resolve(addr, demangle)
1504
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
1511
1512     @staticmethod
1513     def ksym(addr, show_module=False, show_offset=False):
1514         """ksym(addr)
1515
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.
1520
1521         Example output when both show_module and show_offset are True:
1522             "default_idle+0x0 [kernel]"
1523         """
1524         return BPF.sym(addr, -1, show_module, show_offset, False)
1525
1526     @staticmethod
1527     def ksymname(name):
1528         """ksymname(name)
1529
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)
1533
1534     def num_open_kprobes(self):
1535         """num_open_kprobes()
1536
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.
1539         """
1540         return len(self.kprobe_fds)
1541
1542     def num_open_uprobes(self):
1543         """num_open_uprobes()
1544
1545         Get the number of open U[ret]probes.
1546         """
1547         return len(self.uprobe_fds)
1548
1549     def num_open_tracepoints(self):
1550         """num_open_tracepoints()
1551
1552         Get the number of open tracepoints.
1553         """
1554         return len(self.tracepoint_fds)
1555
1556     def perf_buffer_poll(self, timeout = -1):
1557         """perf_buffer_poll(self)
1558
1559         Poll from all open perf ring buffers, calling the callback that was
1560         provided when calling open_perf_buffer for each entry.
1561         """
1562         readers = (ct.c_void_p * len(self.perf_buffers))()
1563         for i, v in enumerate(self.perf_buffers.values()):
1564             readers[i] = v
1565         lib.perf_reader_poll(len(readers), readers, timeout)
1566
1567     def kprobe_poll(self, timeout = -1):
1568         """kprobe_poll(self)
1569
1570         Deprecated. Use perf_buffer_poll instead.
1571         """
1572         self.perf_buffer_poll(timeout)
1573
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")
1579         else:
1580             ret = lib.bpf_add_ringbuf(self._ringbuf_manager, map_fd, fn, ctx)
1581             if ret < 0:
1582                 raise Exception("Could not open ring buffer")
1583
1584     def ring_buffer_poll(self, timeout = -1):
1585         """ring_buffer_poll(self)
1586
1587         Poll from all open ringbuf buffers, calling the callback that was
1588         provided when calling open_ring_buffer for each entry.
1589         """
1590         if not self._ringbuf_manager:
1591             raise Exception("No ring buffers to poll")
1592         lib.bpf_poll_ringbuf(self._ringbuf_manager, timeout)
1593
1594     def ring_buffer_consume(self):
1595         """ring_buffer_consume(self)
1596
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.
1601         """
1602         if not self._ringbuf_manager:
1603             raise Exception("No ring buffers to poll")
1604         lib.bpf_consume_ringbuf(self._ringbuf_manager)
1605
1606     def free_bcc_memory(self):
1607         return lib.bcc_free_memory()
1608
1609     @staticmethod
1610     def add_module(modname):
1611       """add_module(modname)
1612
1613         Add a library or exe to buildsym cache
1614       """
1615       try:
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))
1619
1620     def donothing(self):
1621         """the do nothing exit handler"""
1622
1623     def cleanup(self):
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()):
1638             self.detach_lsm(k)
1639
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)
1647         if self.tracefile:
1648             self.tracefile.close()
1649             self.tracefile = None
1650         for name, fn in list(self.funcs.items()):
1651             os.close(fn.fd)
1652             del self.funcs[name]
1653         if self.module:
1654             lib.bpf_module_destroy(self.module)
1655             self.module = None
1656
1657         # Clean up ringbuf
1658         if self._ringbuf_manager:
1659             lib.bpf_free_ringbuf(self._ringbuf_manager)
1660             self._ringbuf_manager = None
1661
1662     def __enter__(self):
1663         return self
1664
1665     def __exit__(self, exc_type, exc_val, exc_tb):
1666         self.cleanup()