class Probe(object):
next_probe_index = 0
- aliases = { "$PID": "bpf_get_current_pid_tgid()" }
+ aliases = {"$PID": "bpf_get_current_pid_tgid()"}
def _substitute_aliases(self, expr):
if expr is None:
# supported right now.
index = param.rfind('*')
index = index if index != -1 else param.rfind(' ')
- param_type = param[0:index+1].strip()
- param_name = param[index+1:].strip()
+ param_type = param[0:index + 1].strip()
+ param_name = param[index + 1:].strip()
self.param_types[param_name] = param_type
def _generate_entry(self):
collect += """
u64 __time = bpf_ktime_get_ns();
%s.update(&pid, &__time);
-""" % param_hash
+ """ % param_hash
else:
collect += "%s.update(&pid, &%s);\n" % \
(param_hash, pname)
self.param_types["__latency"] = "u64" # nanoseconds
for pname in self.args_to_probe:
if pname not in self.param_types:
- raise ValueError("$entry(%s): no such param" \
- % arg)
+ raise ValueError("$entry(%s): no such param" %
+ arg)
self.hashname_prefix = "%s_param_" % self.probe_hash_name
text = ""
if len(parts) > 6:
self._bail("extraneous ':'-separated parts detected")
if parts[0] not in ["r", "p", "t", "u"]:
- self._bail("probe type must be 'p', 'r', 't', or 'u' " +
- "but got '%s'" % parts[0])
+ self._bail("probe type must be 'p', 'r', 't', or 'u'" +
+ " but got '%s'" % parts[0])
if re.match(r"\w+\(.*\)", parts[2]) is None:
self._bail(("function signature '%s' has an invalid " +
"format") % parts[2])
expr = self.exprs[i]
if self.probe_type == "u" and expr[0:3] == "arg":
return (" u64 %s = 0;\n" +
- " bpf_usdt_readarg(%s, ctx, &%s);\n") % \
- (expr, expr[3], expr)
+ " bpf_usdt_readarg(%s, ctx, &%s);\n") \
+ % (expr, expr[3], expr)
else:
return ""
def _generate_key_assignment(self):
if self.type == "hist":
return self._generate_usdt_arg_assignment(0) + \
- ("%s __key = %s;\n" % \
+ ("%s __key = %s;\n" %
(self.expr_types[0], self.exprs[0]))
else:
text = "struct %s_key_t __key = {};\n" % \
program = ""
probe_text = """
DATA_DECL
-""" + (
- "TRACEPOINT_PROBE(%s, %s)" % (self.tp_category, self.tp_event) \
- if self.probe_type == "t" \
- else "int PROBENAME(struct pt_regs *ctx SIGNATURE)") + """
+ """ + (
+ "TRACEPOINT_PROBE(%s, %s)" %
+ (self.tp_category, self.tp_event)
+ if self.probe_type == "t"
+ else "int PROBENAME(struct pt_regs *ctx SIGNATURE)") + """
{
PID_FILTER
PREFIX
# signatures. Other probes force it to ().
signature = ", " + self.signature
- program += probe_text.replace("PROBENAME", self.probe_func_name)
+ program += probe_text.replace("PROBENAME",
+ self.probe_func_name)
program = program.replace("SIGNATURE", signature)
program = program.replace("PID_FILTER",
self._generate_pid_filter())
def attach(self, bpf):
self.bpf = bpf
- if self.probe_type == "u": return;
+ if self.probe_type == "u":
+ return
if self.is_user:
self._attach_u()
else:
if self.type == "freq":
print(self.label or self.raw_spec)
print("\t%-10s %s" % ("COUNT", "EVENT"))
- sdata = sorted(data.items(), key=lambda kv: kv[1].value)
+ sdata = sorted(data.items(), key=lambda p: p[1].value)
if top is not None:
sdata = sdata[-top:]
for key, value in sdata:
self._v2s(key.v0)
else:
key_str = self._display_key(key)
- print("\t%-10s %s" % \
+ print("\t%-10s %s" %
(str(value.value), key_str))
elif self.type == "hist":
label = self.label or (self._display_expr(0)
- if not self.is_default_expr else "retval")
+ if not self.is_default_expr else "retval")
data.print_log2_hist(val_type=label)
if not self.cumulative:
data.clear()
Probe specifier syntax:
{p,r,t,u}:{[library],category}:function(signature)[:type[,type...]:expr[,expr...][:filter]][#label]
Where:
- p,r,t,u -- probe at function entry, function exit, kernel tracepoint,
- or USDT probe
+ p,r,t,u -- probe at function entry, function exit, kernel
+ tracepoint, or USDT probe
in exit probes: can use $retval, $entry(param), $latency
library -- the library that contains the function
(leave empty for kernel functions)
argdist -H 'r::__kmalloc(size_t size):u64:$latency/$entry(size)#ns per byte'
Print a histogram of nanoseconds per byte from kmalloc allocations
-argdist -C 'p::__kmalloc(size_t size, gfp_t flags):size_t:size:flags&GFP_ATOMIC'
+argdist -C 'p::__kmalloc(size_t sz, gfp_t flags):size_t:sz:flags&GFP_ATOMIC'
Print frequency count of kmalloc allocation sizes that have GFP_ATOMIC
argdist -p 1005 -C 'p:c:write(int fd):int:fd' -T 5
argdist -C 'r::__vfs_read():u32:$PID:$latency > 100000'
Print frequency of reads by process where the latency was >0.1ms
-argdist -H 'r::__vfs_read(void *file, void *buf, size_t count):size_t:$entry(count):$latency > 1000000'
+argdist -H 'r::__vfs_read(void *file, void *buf, size_t count):size_t
+ $entry(count):$latency > 1000000'
Print a histogram of read sizes that were longer than 1ms
argdist -H \\
parser.add_argument("-v", "--verbose", action="store_true",
help="print resulting BPF program code before executing")
parser.add_argument("-c", "--cumulative", action="store_true",
- help="do not clear histograms and freq counts at each interval")
+ help="do not clear histograms and freq counts at " +
+ "each interval")
parser.add_argument("-T", "--top", type=int,
help="number of top results to show (not applicable to " +
"histograms)")
for probe in self.probes:
bpf_source += probe.generate_text()
if self.args.verbose:
- for text in [probe.usdt_ctx.get_text() \
- for probe in self.probes if probe.usdt_ctx]:
+ for text in [probe.usdt_ctx.get_text()
+ for probe in self.probes
+ if probe.usdt_ctx]:
print(text)
print(bpf_source)
usdt_contexts = [probe.usdt_ctx
countdown -= 1
if exiting or countdown == 0:
exit()
-
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
- // create data here and pass to submit_arg to save space on the stack (#555)
+ // create data here and pass to submit_arg to save stack space (#555)
struct data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&data.comm, sizeof(data.comm));
argv = defaultdict(list)
# TODO: This is best-effort PPID matching. Short-lived processes may exit
-# before we get a chance to read the PPID. This should be replaced with fetching
-# PPID via C when available (#364).
+# before we get a chance to read the PPID. This should be replaced with
+# fetching PPID via C when available (#364).
def get_ppid(pid):
try:
with open("/proc/%d/status" % pid) as status:
#
# Run "funclatency -h" for full usage.
#
-# The pattern is a string with optional '*' wildcards, similar to file globbing.
-# If you'd prefer to use regular expressions, use the -r option.
+# The pattern is a string with optional '*' wildcards, similar to file
+# globbing. If you'd prefer to use regular expressions, use the -r option.
#
# Currently nested or recursive functions are not supported properly, and
# timestamps will be overwritten, creating dubious output. Try to match single
matched = b.num_open_kprobes()
else:
b.attach_uprobe(name=library, sym_re=pattern, fn_name="trace_func_entry")
- b.attach_uretprobe(name=library, sym_re=pattern, fn_name="trace_func_return")
+ b.attach_uretprobe(name=library, sym_re=pattern,
+ fn_name="trace_func_return")
matched = b.num_open_uprobes()
if matched == 0:
u32 pid = bpf_get_current_pid_tgid();
if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
- bpf_probe_read(&val.host, sizeof(val.host), (void *)PT_REGS_PARM1(ctx));
+ bpf_probe_read(&val.host, sizeof(val.host),
+ (void *)PT_REGS_PARM1(ctx));
val.pid = bpf_get_current_pid_tgid();
val.ts = bpf_ktime_get_ns();
start.update(&pid, &val);
from time import sleep, strftime
import argparse
-### arguments
+# arguments
examples = """examples:
./hardirqs # sum hard irq event time
./hardirqs -d # show hard irq event time as histograms
label = "usecs"
debug = 0
-### define BPF program
+# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/irq.h>
}
"""
-### code substitutions
+# code substitutions
if args.dist:
bpf_text = bpf_text.replace('STORE',
'irq_key_t key = {.slot = bpf_log2l(delta)};' +
if debug:
print(bpf_text)
-### load BPF program
+# load BPF program
b = BPF(text=bpf_text)
# these should really use irq:irq_handler_entry/exit tracepoints:
print("Tracing hard irq event time... Hit Ctrl-C to end.")
-### output
+# output
exiting = 0 if args.interval else 1
dist = b.get_table("dist")
while (1):
alloc_info[info.stack_id].update(info.size)
else:
stack = list(stack_traces.walk(info.stack_id, decoder))
- alloc_info[info.stack_id] = Allocation(stack, info.size)
+ alloc_info[info.stack_id] = Allocation(stack,
+ info.size)
if args.show_allocs:
print("\taddr = %x size = %s" %
(address.value, info.size))
- to_show = sorted(alloc_info.values(), key=lambda a: a.size)[-top_stacks:]
+ to_show = sorted(alloc_info.values(),
+ key=lambda a: a.size)[-top_stacks:]
for alloc in to_show:
print("\t%d bytes in %d allocations from stack\n\t\t%s" %
(alloc.size, alloc.count, "\n\t\t".join(alloc.stack)))
event.type == EventType.EVENT_UMOUNT_RET):
if event.type == EventType.EVENT_MOUNT_RET:
syscall = mounts.pop(event.pid)
- call = 'mount({source}, {target}, {type}, {flags}, {data}) = {retval}'.format(
+ call = ('mount({source}, {target}, {type}, {flags}, {data}) ' +
+ '= {retval}').format(
source=decode_mount_string(syscall['source']),
target=decode_mount_string(syscall['target']),
type=decode_mount_string(syscall['type']),
./offcputime # trace off-CPU stack time until Ctrl-C
./offcputime 5 # trace for 5 seconds only
./offcputime -f 5 # 5 seconds, and output in folded format
- ./offcputime -m 1000 # trace only events that last more than 1000 usec.
- ./offcputime -M 10000 # trace only events that last less than 10000 usec.
+ ./offcputime -m 1000 # trace only events that last more than 1000 usec
+ ./offcputime -M 10000 # trace only events that last less than 10000 usec
./offcputime -p 185 # only trace threads for PID 185
./offcputime -t 188 # only trace thread 188
./offcputime -u # only trace user threads (no kernel)
help="duration of trace, in seconds")
parser.add_argument("-m", "--min-block-time", default=1,
type=positive_nonzero_int,
- help="the amount of time in microseconds over which we store traces (default 1)")
-parser.add_argument("-M", "--max-block-time", default=(1<<64)-1,
+ help="the amount of time in microseconds over which we " +
+ "store traces (default 1)")
+parser.add_argument("-M", "--max-block-time", default=(1 << 64) - 1,
type=positive_nonzero_int,
- help="the amount of time in microseconds under which we store traces (default U64_MAX)")
+ help="the amount of time in microseconds under which we " +
+ "store traces (default U64_MAX)")
args = parser.parse_args()
if args.pid and args.tgid:
parser.error("specify only one of -p and -t")
bpf_text = bpf_text.replace('USER_STACK_GET', user_stack_get)
bpf_text = bpf_text.replace('KERNEL_STACK_GET', kernel_stack_get)
-need_delimiter = args.delimited and not (args.kernel_stacks_only or args.user_stacks_only)
+need_delimiter = args.delimited and not (args.kernel_stacks_only or
+ args.user_stacks_only)
# check for an edge case; the code below will handle this case correctly
# but ultimately nothing will be displayed
if args.kernel_threads_only and args.user_stacks_only:
- print("ERROR: Displaying user stacks for kernel threads " \
- "doesn't make sense.", file=stderr)
+ print("ERROR: Displaying user stacks for kernel threads " +
+ "doesn't make sense.", file=stderr)
exit(1)
# initialize BPF
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
# handle get_stackid erorrs
if (not args.user_stacks_only and k.kernel_stack_id < 0) or \
- (not args.kernel_stacks_only and k.user_stack_id < 0 and \
- k.user_stack_id != -errno.EFAULT):
+ (not args.kernel_stacks_only and k.user_stack_id < 0 and
+ k.user_stack_id != -errno.EFAULT):
missing_stacks += 1
# check for an ENOMEM error
if k.kernel_stack_id == -errno.ENOMEM or \
from time import sleep, strftime
import argparse
-### arguments
+# arguments
examples = """examples:
./softirqs # sum soft irq event time
./softirqs -d # show soft irq event time as histograms
label = "usecs"
debug = 0
-### define BPF program
+# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
}
"""
-### code substitutions
+# code substitutions
if args.dist:
bpf_text = bpf_text.replace('STORE',
'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};' +
if debug:
print(bpf_text)
-### load BPF program
+# load BPF program
b = BPF(text=bpf_text)
# this should really use irq:softirq_entry/exit tracepoints; for now the
# soft irq functions are individually traced (search your kernel for
# open_softirq() calls, and adjust the following list as needed).
for softirqfunc in ("blk_iopoll_softirq", "blk_done_softirq",
- "rcu_process_callbacks", "run_rebalance_domains", "tasklet_action",
- "tasklet_hi_action", "run_timer_softirq", "net_tx_action",
- "net_rx_action"):
+ "rcu_process_callbacks", "run_rebalance_domains", "tasklet_action",
+ "tasklet_hi_action", "run_timer_softirq", "net_tx_action",
+ "net_rx_action"):
b.attach_kprobe(event=softirqfunc, fn_name="trace_start")
b.attach_kretprobe(event=softirqfunc, fn_name="trace_completion")
print("Tracing soft irq event time... Hit Ctrl-C to end.")
-### output
+# output
exiting = 0 if args.interval else 1
dist = b.get_table("dist")
while (1):
#!/usr/bin/env python
#
-# solisten Trace TCP listen events
-# For Linux, uses BCC, eBPF. Embedded C.
+# solisten Trace TCP listen events
+# For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: solisten.py [-h] [-p PID] [--show-netns]
#
examples = """Examples:
./solisten.py # Stream socket listen
./solisten.py -p 1234 # Stream socket listen for specified PID only
- ./solisten.py --netns 4242 # Stream socket listen for specified network namespace ID only
- ./solisten.py --show-netns # Show network namespace ID. Probably usefull if you run containers
+ ./solisten.py --netns 4242 # " for the specified network namespace ID only
+ ./solisten.py --show-netns # Show network ns ID (useful for containers)
"""
parser = argparse.ArgumentParser(
# BPF Program
-bpf_text = """
+bpf_text = """
#include <net/sock.h>
#include <net/inet_sock.h>
#include <net/net_namespace.h>
.backlog = backlog,
};
- // Get process comm. Needs LLVM >= 3.7.1 see https://github.com/iovisor/bcc/issues/393
+ // Get process comm. Needs LLVM >= 3.7.1
+ // see https://github.com/iovisor/bcc/issues/393
bpf_get_current_comm(evt.task, TASK_COMM_LEN);
// Get socket IP family
bpf_probe_read(evt.laddr, sizeof(u32), &(inet->inet_rcv_saddr));
evt.laddr[0] = be32_to_cpu(evt.laddr[0]);
} else if (family == AF_INET6) {
- bpf_probe_read(evt.laddr, sizeof(evt.laddr), sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
+ bpf_probe_read(evt.laddr, sizeof(evt.laddr),
+ sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
evt.laddr[0] = be64_to_cpu(evt.laddr[0]);
evt.laddr[1] = be64_to_cpu(evt.laddr[1]);
}
protocol += "v4"
address = netaddr.IPAddress(event.laddr[0])
elif proto_type == socket.AF_INET6:
- address = netaddr.IPAddress(event.laddr[0]<<64 | event.laddr[1], version=6)
+ address = netaddr.IPAddress(event.laddr[0] << 64 | event.laddr[1],
+ version=6)
protocol += "v6"
# Display
# Print headers
if args.show_netns:
- print("%-6s %-12s %-12s %-6s %-8s %-5s %-39s" % ("PID", "COMM", "NETNS", "PROTO", "BACKLOG", "PORT", "ADDR"))
+ print("%-6s %-12s %-12s %-6s %-8s %-5s %-39s" %
+ ("PID", "COMM", "NETNS", "PROTO", "BACKLOG", "PORT", "ADDR"))
else:
- print("%-6s %-12s %-6s %-8s %-5s %-39s" % ("PID", "COMM", "PROTO", "BACKLOG", "PORT", "ADDR"))
+ print("%-6s %-12s %-6s %-8s %-5s %-39s" %
+ ("PID", "COMM", "PROTO", "BACKLOG", "PORT", "ADDR"))
# Read events
while 1:
b.kprobe_poll()
-
ts = time.time() - start_ts
if verbose:
- print("%-18.9f %-12.12s %-6d %-3d %s" % (ts, event.comm, event.pid, cpu,
- function))
+ print("%-18.9f %-12.12s %-6d %-3d %s" %
+ (ts, event.comm, event.pid, cpu, function))
else:
print("%-18.9f %s" % (ts, function))
trace_root = "/sys/kernel/debug/tracing"
event_root = os.path.join(trace_root, "events")
-parser = argparse.ArgumentParser(description=
- "Display kernel tracepoints or USDT probes and their formats.",
- formatter_class=argparse.RawDescriptionHelpFormatter)
-parser.add_argument("-p", "--pid", type=int, default=None, help=
- "List USDT probes in the specified process")
-parser.add_argument("-l", "--lib", default="", help=
- "List USDT probes in the specified library or executable")
-parser.add_argument("-v", dest="verbosity", action="count", help=
- "Increase verbosity level (print variables, arguments, etc.)")
-parser.add_argument(dest="filter", nargs="?", help=
- "A filter that specifies which probes/tracepoints to print")
+parser = argparse.ArgumentParser(
+ description="Display kernel tracepoints or USDT probes " +
+ "and their formats.",
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+parser.add_argument("-p", "--pid", type=int, default=None,
+ help="List USDT probes in the specified process")
+parser.add_argument("-l", "--lib", default="",
+ help="List USDT probes in the specified library or executable")
+parser.add_argument("-v", dest="verbosity", action="count",
+ help="Increase verbosity level (print variables, arguments, etc.)")
+parser.add_argument(dest="filter", nargs="?",
+ help="A filter that specifies which probes/tracepoints to print")
args = parser.parse_args()
def print_tpoint_format(category, event):
- fmt = open(os.path.join(event_root, category, event, "format")
- ).readlines()
+ fmt = open(os.path.join(event_root, category, event, "format")) \
+ .readlines()
for line in fmt:
match = re.search(r'field:([^;]*);', line)
if match is None:
print(" %d location(s)" % probe.num_locations)
print(" %d argument(s)" % probe.num_arguments)
else:
- print("%s %s:%s" % (probe.bin_path, probe.provider, probe.name))
+ print("%s %s:%s" %
+ (probe.bin_path, probe.provider, probe.name))
def print_usdt(pid, lib):
reader = USDT(path=lib, pid=pid)
except:
if sys.exc_info()[0] is not SystemExit:
print(sys.exc_info()[1])
-
if text[i] == ")":
balance -= 1
if balance == 0:
- self._parse_filter(text[:i+1])
- text = text[i+1:]
+ self._parse_filter(text[:i + 1])
+ text = text[i + 1:]
break
if self.filter is None:
self._bail("unmatched end of predicate")
self.tp_category = parts[1]
self.tp_event = parts[2]
self.library = "" # kernel
- self.function = "" # generated from TRACEPOINT_PROBE
+ self.function = "" # from TRACEPOINT_PROBE
elif self.probe_type == "u":
self.library = parts[1]
self.usdt_name = parts[2]
self.usdt = USDT(path=self.library, pid=Probe.pid)
for probe in self.usdt.enumerate_probes():
if probe.name == self.usdt_name:
- return # Found it, will enable later
+ return # Found it, will enable later
self._bail("unrecognized USDT probe %s" % self.usdt_name)
def _parse_filter(self, filt):
def _parse_types(self, fmt):
for match in re.finditer(
- r'[^%]%(s|u|d|llu|lld|hu|hd|x|llx|c|K|U)', fmt):
+ r'[^%]%(s|u|d|llu|lld|hu|hd|x|llx|c|K|U)', fmt):
self.types.append(match.group(1))
fmt = re.sub(r'([^%]%)(u|d|llu|lld|hu|hd)', r'\1d', fmt)
fmt = re.sub(r'([^%]%)(x|llx)', r'\1x', fmt)
def _replace_args(self, expr):
for alias, replacement in Probe.aliases.items():
# For USDT probes, we replace argN values with the
- # actual arguments for that probe obtained using special
+ # actual arguments for that probe obtained using
# bpf_readarg_N macros emitted at BPF construction.
if alias.startswith("arg") and self.probe_type == "u":
continue
expr = expr.replace(alias, replacement)
return expr
- p_type = { "u": ct.c_uint, "d": ct.c_int,
- "llu": ct.c_ulonglong, "lld": ct.c_longlong,
- "hu": ct.c_ushort, "hd": ct.c_short,
- "x": ct.c_uint, "llx": ct.c_ulonglong, "c": ct.c_ubyte,
- "K": ct.c_ulonglong, "U": ct.c_ulonglong }
+ p_type = {"u": ct.c_uint, "d": ct.c_int,
+ "llu": ct.c_ulonglong, "lld": ct.c_longlong,
+ "hu": ct.c_ushort, "hd": ct.c_short,
+ "x": ct.c_uint, "llx": ct.c_ulonglong, "c": ct.c_ubyte,
+ "K": ct.c_ulonglong, "U": ct.c_ulonglong}
def _generate_python_field_decl(self, idx, fields):
field_type = self.types[idx]
return type(self.python_struct_name, (ct.Structure,),
dict(_fields_=fields))
- c_type = { "u": "unsigned int", "d": "int",
- "llu": "unsigned long long", "lld": "long long",
- "hu": "unsigned short", "hd": "short",
- "x": "unsigned int", "llx": "unsigned long long",
- "c": "char", "K": "unsigned long long",
- "U": "unsigned long long" }
+ c_type = {"u": "unsigned int", "d": "int",
+ "llu": "unsigned long long", "lld": "long long",
+ "hu": "unsigned short", "hd": "short",
+ "x": "unsigned int", "llx": "unsigned long long",
+ "c": "char", "K": "unsigned long long",
+ "U": "unsigned long long"}
fmt_types = c_type.keys()
def _generate_field_decl(self, idx):
text = ""
if self.probe_type == "u" and expr[0:3] == "arg":
text = (" u64 %s = 0;\n" +
- " bpf_usdt_readarg(%s, ctx, &%s);\n") % \
- (expr, expr[3], expr)
+ " bpf_usdt_readarg(%s, ctx, &%s);\n") \
+ % (expr, expr[3], expr)
if field_type == "s":
return text + """
if (%s != 0) {
bpf_probe_read(&__data.v%d, sizeof(__data.v%d), (void *)%s);
}
-""" % (expr, idx, idx, expr)
+ """ % (expr, idx, idx, expr)
if field_type in Probe.fmt_types:
return text + " __data.v%d = (%s)%s;\n" % \
(idx, Probe.c_type[field_type], expr)
text = ""
if self.probe_type == "u":
for arg, _ in Probe.aliases.items():
- if not (arg.startswith("arg") and (arg in self.filter)):
+ if not (arg.startswith("arg") and
+ (arg in self.filter)):
continue
arg_index = int(arg.replace("arg", ""))
arg_ctype = self.usdt.get_probe_arg_ctype(
pid_filter = """
u32 __pid = bpf_get_current_pid_tgid();
if (__pid != %d) { return 0; }
-""" % Probe.pid
+ """ % Probe.pid
elif not include_self:
pid_filter = """
u32 __pid = bpf_get_current_pid_tgid();
if (__pid == %d) { return 0; }
-""" % os.getpid()
+ """ % os.getpid()
else:
pid_filter = ""
# Replace each %K with kernel sym and %U with user sym in pid
kernel_placeholders = [i for i in xrange(0, len(self.types))
if self.types[i] == 'K']
- user_placeholders = [i for i in xrange(0, len(self.types))
- if self.types[i] == 'U']
+ user_placeholders = [i for i in xrange(0, len(self.types))
+ if self.types[i] == 'U']
for kp in kernel_placeholders:
values[kp] = bpf.ksymaddr(values[kp])
for up in user_placeholders:
msg = self._format_message(bpf, event.pid, values)
time = strftime("%H:%M:%S") if Probe.use_localtime else \
Probe._time_off_str(event.timestamp_ns)
- print("%-8s %-6d %-12s %-16s %s" % \
+ print("%-8s %-6d %-12s %-16s %s" %
(time[:8], event.pid, event.comm[:12],
self._display_function(), msg))
self._bail("unable to find library %s" % self.library)
if self.probe_type == "u":
- pass # Was already enabled by the BPF constructor
+ pass # Was already enabled by the BPF constructor
elif self.probe_type == "r":
bpf.attach_uretprobe(name=libpath,
sym=self.function,
"""
def __init__(self):
- parser = argparse.ArgumentParser(description=
- "Attach to functions and print trace messages.",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=Tool.examples)
+ parser = argparse.ArgumentParser(description="Attach to " +
+ "functions and print trace messages.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=Tool.examples)
parser.add_argument("-p", "--pid", type=int,
help="id of the process to trace (optional)")
parser.add_argument("-v", "--verbose", action="store_true",
help="print resulting BPF program code before executing")
parser.add_argument("-Z", "--string-size", type=int,
default=80, help="maximum size to read from strings")
- parser.add_argument("-S", "--include-self", action="store_true",
+ parser.add_argument("-S", "--include-self",
+ action="store_true",
help="do not filter trace's own pid from the trace")
parser.add_argument("-M", "--max-events", type=int,
help="number of events to print before quitting")
parser.add_argument("-o", "--offset", action="store_true",
help="use relative time from first traced message")
- parser.add_argument("-K", "--kernel-stack", action="store_true",
- help="output kernel stack trace")
- parser.add_argument("-U", "--user-stack", action="store_true",
- help="output user stack trace")
+ parser.add_argument("-K", "--kernel-stack",
+ action="store_true", help="output kernel stack trace")
+ parser.add_argument("-U", "--user-stack",
+ action="store_true", help="output user stack trace")
parser.add_argument(metavar="probe", dest="probes", nargs="+",
help="probe specifier (see examples)")
parser.add_argument("-I", "--include", action="append",
self.probes))
# Print header
- print("%-8s %-6s %-12s %-16s %s" % \
+ print("%-8s %-6s %-12s %-16s %s" %
("TIME", "PID", "COMM", "FUNC",
"-" if not all_probes_trivial else ""))
print(sys.exc_info()[1])
if __name__ == "__main__":
- Tool().run()
+ Tool().run()