Commit f41ae861 authored by Sasha Goldshtein's avatar Sasha Goldshtein Committed by 4ast

Tools lint cleanup (#764)

* argdist: linter cleanup

* cpudist: linter cleanup

* execsnoop: linter cleanup

* funclatency: linter cleanup

* gethostlatency: linter cleanup

* hardirqs: linter cleanup

* memleak: linter cleanup

* mountsnoop: linter cleanup

* offcputime: linter cleanup

* softirqs: linter cleanup

* solisten: linter cleanup and u+x mode

* stacksnoop: linter cleanup

* tplist: linter cleanup

* trace: linter cleanup
parent 78a3341c
......@@ -19,7 +19,7 @@ import sys
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:
......@@ -37,8 +37,8 @@ class Probe(object):
# 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):
......@@ -65,7 +65,7 @@ int PROBENAME(struct pt_regs *ctx SIGNATURE)
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)
......@@ -88,8 +88,8 @@ u64 __time = bpf_ktime_get_ns();
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 = ""
......@@ -156,8 +156,8 @@ u64 __time = bpf_ktime_get_ns();
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])
......@@ -263,8 +263,8 @@ u64 __time = bpf_ktime_get_ns();
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 ""
......@@ -294,7 +294,7 @@ u64 __time = bpf_ktime_get_ns();
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" % \
......@@ -323,10 +323,11 @@ u64 __time = bpf_ktime_get_ns();
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
......@@ -353,7 +354,8 @@ DATA_DECL
# 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())
......@@ -400,7 +402,8 @@ DATA_DECL
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:
......@@ -447,7 +450,7 @@ DATA_DECL
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:
......@@ -461,11 +464,11 @@ DATA_DECL
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()
......@@ -478,8 +481,8 @@ class Tool(object):
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)
......@@ -506,7 +509,7 @@ argdist -C 'r:c:gets():char*:(char*)$retval#snooped strings'
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
......@@ -520,7 +523,8 @@ argdist -p 1005 -H 'r:c:read()'
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 \\
......@@ -569,7 +573,8 @@ argdist -p 2780 -z 120 \\
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)")
......@@ -610,8 +615,9 @@ struct __string_t { char s[%d]; };
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
......
......@@ -183,4 +183,3 @@ while (1):
countdown -= 1
if exiting or countdown == 0:
exit()
......@@ -88,7 +88,7 @@ int kprobe__sys_execve(struct pt_regs *ctx, struct filename *filename,
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));
......@@ -167,8 +167,8 @@ start_ts = time.time()
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:
......
......@@ -9,8 +9,8 @@
#
# 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
......@@ -202,7 +202,8 @@ if not library:
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:
......
......@@ -51,7 +51,8 @@ int do_entry(struct pt_regs *ctx) {
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);
......
......@@ -18,7 +18,7 @@ from bcc import BPF
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
......@@ -49,7 +49,7 @@ else:
label = "usecs"
debug = 0
### define BPF program
# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/irq.h>
......@@ -106,7 +106,7 @@ int trace_completion(struct pt_regs *ctx)
}
"""
### code substitutions
# code substitutions
if args.dist:
bpf_text = bpf_text.replace('STORE',
'irq_key_t key = {.slot = bpf_log2l(delta)};' +
......@@ -121,7 +121,7 @@ else:
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:
......@@ -130,7 +130,7 @@ b.attach_kretprobe(event="handle_irq_event_percpu", fn_name="trace_completion")
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):
......
......@@ -280,11 +280,13 @@ def print_outstanding():
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)))
......
......@@ -369,7 +369,8 @@ def print_event(mounts, umounts, cpu, data, size):
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']),
......
......@@ -40,8 +40,8 @@ examples = """examples:
./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)
......@@ -82,10 +82,12 @@ parser.add_argument("duration", nargs="?", default=99999999,
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")
......@@ -198,13 +200,14 @@ else:
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
......@@ -240,8 +243,8 @@ stack_traces = b.get_table("stack_traces")
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 \
......
......@@ -16,7 +16,7 @@ from bcc import BPF
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
......@@ -47,7 +47,7 @@ else:
label = "usecs"
debug = 0
### define BPF program
# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
......@@ -92,7 +92,7 @@ int trace_completion(struct pt_regs *ctx)
}
"""
### code substitutions
# code substitutions
if args.dist:
bpf_text = bpf_text.replace('STORE',
'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};' +
......@@ -105,22 +105,22 @@ else:
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]
#
......@@ -28,8 +28,8 @@ import ctypes as ct
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(
......@@ -45,7 +45,7 @@ parser.add_argument("-n", "--netns", default=0, type=int,
# BPF Program
bpf_text = """
bpf_text = """
#include <net/sock.h>
#include <net/inet_sock.h>
#include <net/net_namespace.h>
......@@ -77,7 +77,8 @@ int kprobe__inet_listen(struct pt_regs *ctx, struct socket *sock, int backlog)
.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
......@@ -107,7 +108,8 @@ int kprobe__inet_listen(struct pt_regs *ctx, struct socket *sock, int backlog)
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]);
}
......@@ -157,7 +159,8 @@ def event_printer(show_netns):
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
......@@ -195,11 +198,12 @@ if __name__ == "__main__":
# 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()
......@@ -114,8 +114,8 @@ def print_event(cpu, data, size):
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))
......
......@@ -18,22 +18,23 @@ from bcc import USDT
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:
......@@ -81,7 +82,8 @@ def print_usdt_details(probe):
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)
......@@ -103,4 +105,3 @@ if __name__ == "__main__":
except:
if sys.exc_info()[0] is not SystemExit:
print(sys.exc_info()[1])
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment