def _attach_probes(self): self.bpf = BPF(text=self.program) Tracepoint.attach(self.bpf) for probe in self.probes: if self.args.verbose: print(probe) probe.attach(self.bpf, self.args.verbose)
def _attach(self): Tracepoint.attach(self.bpf) for probe in self.probes: probe.attach(self.bpf) if self.args.verbose: print("open uprobes: %s" % BPF.open_uprobes()) print("open kprobes: %s" % BPF.open_kprobes())
def _attach(self): Tracepoint.attach(self.bpf) for specifier in self.specifiers: specifier.attach(self.bpf) if self.args.verbose: print("open uprobes: %s" % BPF.open_uprobes()) print("open kprobes: %s" % BPF.open_kprobes())
def _generate_program(self): self.program = """ #include <linux/ptrace.h> #include <linux/sched.h> /* For TASK_COMM_LEN */ """ self.program += BPF.generate_auto_includes( map(lambda p: p.raw_probe, self.probes)) self.program += Tracepoint.generate_decl() self.program += Tracepoint.generate_entry_probe() for probe in self.probes: self.program += probe.generate_program(self.args.include_self) if self.args.verbose: print(self.program)
def _attach_probes(self): usdt_contexts = [] for probe in self.probes: if probe.usdt: # USDT probes must be enabled before the BPF object # is initialized, because that's where the actual # uprobe is being attached. probe.usdt.enable_probe(probe.usdt_name, probe.probe_name) usdt_contexts.append(probe.usdt) self.bpf = BPF(text=self.program, usdt_contexts=usdt_contexts) Tracepoint.attach(self.bpf) for probe in self.probes: if self.args.verbose: print(probe) probe.attach(self.bpf, self.args.verbose)
def _parse_spec(self, spec): parts = spec.split(":") # Two special cases: 'func' means 'p::func', 'lib:func' means # 'p:lib:func'. Other combinations need to provide an empty # value between delimiters, e.g. 'r::func' for a kretprobe on # the function func. if len(parts) == 1: parts = ["p", "", parts[0]] elif len(parts) == 2: parts = ["p", parts[0], parts[1]] if len(parts[0]) == 0: self.probe_type = "p" elif parts[0] in ["p", "r", "t", "u"]: self.probe_type = parts[0] else: self._bail("probe type must be '', 'p', 't', 'r', " + "or 'u', but got '%s'" % parts[0]) if self.probe_type == "t": self.tp_category = parts[1] self.tp_event = parts[2] self.tp = Tracepoint.enable_tracepoint( self.tp_category, self.tp_event) self.library = "" # kernel self.function = "perf_trace_%s" % self.tp_event elif self.probe_type == "u": self.library = parts[1] self.usdt_name = parts[2] self.function = "" # no function, just address # We will discover the USDT provider by matching on # the USDT name in the specified library self._find_usdt_probe() self._enable_usdt_probe() else: self.library = parts[1] self.function = parts[2]
def _parse_spec(self, spec): parts = spec.split(":") # Two special cases: 'func' means 'p::func', 'lib:func' means # 'p:lib:func'. Other combinations need to provide an empty # value between delimiters, e.g. 'r::func' for a kretprobe on # the function func. if len(parts) == 1: parts = ["p", "", parts[0]] elif len(parts) == 2: parts = ["p", parts[0], parts[1]] if len(parts[0]) == 0: self.probe_type = "p" elif parts[0] in ["p", "r", "t"]: self.probe_type = parts[0] else: self._bail("expected '', 'p', 't', or 'r', got '%s'" % parts[0]) if self.probe_type == "t": self.tp_category = parts[1] self.tp_event = parts[2] self.tp = Tracepoint.enable_tracepoint( self.tp_category, self.tp_event) self.library = "" # kernel self.function = "perf_trace_%s" % self.tp_event else: self.library = parts[1] self.function = parts[2]
def _parse_spec(self, spec): parts = spec.split(":") # Two special cases: 'func' means 'p::func', 'lib:func' means # 'p:lib:func'. Other combinations need to provide an empty # value between delimiters, e.g. 'r::func' for a kretprobe on # the function func. if len(parts) == 1: parts = ["p", "", parts[0]] elif len(parts) == 2: parts = ["p", parts[0], parts[1]] if len(parts[0]) == 0: self.probe_type = "p" elif parts[0] in ["p", "r", "t"]: self.probe_type = parts[0] else: self._bail("expected '', 'p', 't', or 'r', got '%s'" % parts[0]) if self.probe_type == "t": self.tp_category = parts[1] self.tp_event = parts[2] self.tp = Tracepoint.enable_tracepoint(self.tp_category, self.tp_event) self.library = "" # kernel self.function = "perf_trace_%s" % self.tp_event else: self.library = parts[1] self.function = parts[2]
def __init__(self, type, specifier, pid): self.raw_spec = specifier self._validate_specifier() spec_and_label = specifier.split('#') self.label = spec_and_label[1] \ if len(spec_and_label) == 2 else None parts = spec_and_label[0].strip().split(':') self.type = type # hist or freq self.probe_type = parts[0] fparts = parts[2].split('(') self.function = fparts[0].strip() if self.probe_type == "t": self.library = "" # kernel self.tp_category = parts[1] self.tp_event = self.function self.tp = Tracepoint.enable_tracepoint(self.tp_category, self.tp_event) self.function = "perf_trace_" + self.function else: self.library = parts[1] self.is_user = len(self.library) > 0 self.signature = fparts[1].strip()[:-1] self._parse_signature() # If the user didn't specify an expression to probe, we probe # the retval in a ret probe, or simply the value "1" otherwise. self.is_default_expr = len(parts) < 5 if not self.is_default_expr: self._parse_expr_types(parts[3]) self._parse_exprs(parts[4]) if len(self.exprs) != len(self.expr_types): self._bail("mismatched # of exprs and types") if self.type == "hist" and len(self.expr_types) > 1: self._bail("histograms can only have 1 expr") else: if not self.probe_type == "r" and self.type == "hist": self._bail("histograms must have expr") self.expr_types = \ ["u64" if not self.probe_type == "r" else "int"] self.exprs = \ ["1" if not self.probe_type == "r" else "$retval"] self.filter = "" if len(parts) != 6 else parts[5] self._substitute_exprs() # Do we need to attach an entry probe so that we can collect an # argument that is required for an exit (return) probe? def check(expr): keywords = ["$entry", "$latency"] return any(map(lambda kw: kw in expr, keywords)) self.entry_probe_required = self.probe_type == "r" and \ (any(map(check, self.exprs)) or check(self.filter)) self.pid = pid self.probe_func_name = "%s_probe%d" % \ (self.function, Specifier.next_probe_index) self.probe_hash_name = "%s_hash%d" % \ (self.function, Specifier.next_probe_index) Specifier.next_probe_index += 1
def _generate_program(self): self.program = """ #include <linux/ptrace.h> #include <linux/sched.h> /* For TASK_COMM_LEN */ """ self.program += BPF.generate_auto_includes( map(lambda p: p.raw_probe, self.probes)) self.program += Tracepoint.generate_decl() self.program += Tracepoint.generate_entry_probe() for probe in self.probes: self.program += probe.generate_program( self.args.include_self) if self.args.verbose: print(self.program)
def __init__(self, type, specifier, pid): self.raw_spec = specifier self._validate_specifier() spec_and_label = specifier.split('#') self.label = spec_and_label[1] \ if len(spec_and_label) == 2 else None parts = spec_and_label[0].strip().split(':') self.type = type # hist or freq self.probe_type = parts[0] fparts = parts[2].split('(') self.function = fparts[0].strip() if self.probe_type == "t": self.library = "" # kernel self.tp_category = parts[1] self.tp_event = self.function self.tp = Tracepoint.enable_tracepoint( self.tp_category, self.tp_event) self.function = "perf_trace_" + self.function else: self.library = parts[1] self.is_user = len(self.library) > 0 self.signature = fparts[1].strip()[:-1] self._parse_signature() # If the user didn't specify an expression to probe, we probe # the retval in a ret probe, or simply the value "1" otherwise. self.is_default_expr = len(parts) < 5 if not self.is_default_expr: self._parse_expr_types(parts[3]) self._parse_exprs(parts[4]) if len(self.exprs) != len(self.expr_types): self._bail("mismatched # of exprs and types") if self.type == "hist" and len(self.expr_types) > 1: self._bail("histograms can only have 1 expr") else: if not self.probe_type == "r" and self.type == "hist": self._bail("histograms must have expr") self.expr_types = \ ["u64" if not self.probe_type == "r" else "int"] self.exprs = \ ["1" if not self.probe_type == "r" else "$retval"] self.filter = "" if len(parts) != 6 else parts[5] self._substitute_exprs() # Do we need to attach an entry probe so that we can collect an # argument that is required for an exit (return) probe? def check(expr): keywords = ["$entry", "$latency"] return any(map(lambda kw: kw in expr, keywords)) self.entry_probe_required = self.probe_type == "r" and \ (any(map(check, self.exprs)) or check(self.filter)) self.pid = pid self.probe_func_name = "%s_probe%d" % \ (self.function, Specifier.next_probe_index) self.probe_hash_name = "%s_hash%d" % \ (self.function, Specifier.next_probe_index) Specifier.next_probe_index += 1
def _attach_probes(self): usdt_contexts = [] for probe in self.probes: if probe.usdt: # USDT probes must be enabled before the BPF object # is initialized, because that's where the actual # uprobe is being attached. probe.usdt.enable_probe( probe.usdt_name, probe.probe_name) usdt_contexts.append(probe.usdt) self.bpf = BPF(text=self.program, usdt_contexts=usdt_contexts) Tracepoint.attach(self.bpf) for probe in self.probes: if self.args.verbose: print(probe) probe.attach(self.bpf, self.args.verbose)
def _generate_program(self): bpf_source = """ struct __string_t { char s[%d]; }; #include <uapi/linux/ptrace.h> """ % self.args.string_size for include in (self.args.include or []): bpf_source += "#include <%s>\n" % include bpf_source += BPF.generate_auto_includes( map(lambda p: p.raw_spec, self.probes)) bpf_source += Tracepoint.generate_decl() bpf_source += Tracepoint.generate_entry_probe() for probe in self.probes: bpf_source += probe.generate_text() if self.args.verbose: print(bpf_source) self.bpf = BPF(text=bpf_source)