rbbcc 0.3.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +3 -1
- data/Gemfile +5 -0
- data/Gemfile.lock +6 -6
- data/README.md +4 -0
- data/docs/README.md +2 -0
- data/docs/answers/01-hello-world.rb +16 -0
- data/docs/answers/02-sys_sync.rb +18 -0
- data/docs/answers/03-hello_fields.rb +33 -0
- data/docs/answers/04-sync_timing.rb +46 -0
- data/docs/answers/05-sync_count.rb +54 -0
- data/docs/answers/06-disksnoop.rb +71 -0
- data/docs/answers/07-hello_perf_output.rb +59 -0
- data/docs/answers/08-sync_perf_output.rb +60 -0
- data/docs/answers/09-bitehist.rb +32 -0
- data/docs/answers/10-disklatency.rb +51 -0
- data/docs/answers/11-vfsreadlat.c +46 -0
- data/docs/answers/11-vfsreadlat.rb +66 -0
- data/docs/answers/12-urandomread.rb +38 -0
- data/docs/answers/13-disksnoop_fixed.rb +108 -0
- data/docs/answers/14-strlen_count.rb +46 -0
- data/docs/answers/15-nodejs_http_server.rb +44 -0
- data/docs/answers/16-task_switch.c +23 -0
- data/docs/answers/16-task_switch.rb +17 -0
- data/docs/answers/node-server.js +11 -0
- data/docs/projects_using_rbbcc.md +43 -0
- data/docs/tutorial_bcc_ruby_developer.md +774 -0
- data/docs/tutorial_bcc_ruby_developer_japanese.md +770 -0
- data/examples/networking/http_filter/http-parse-simple.c +114 -0
- data/examples/networking/http_filter/http-parse-simple.rb +85 -0
- data/examples/ruby_usdt.rb +105 -0
- data/examples/sbrk_trace.rb +204 -0
- data/examples/tools/bashreadline.rb +83 -0
- data/lib/rbbcc/bcc.rb +73 -20
- data/lib/rbbcc/clib.rb +7 -2
- data/lib/rbbcc/debug.rb +17 -0
- data/lib/rbbcc/table.rb +16 -22
- data/lib/rbbcc/usdt.rb +21 -4
- data/lib/rbbcc/version.rb +1 -1
- data/rbbcc.gemspec +1 -5
- metadata +34 -61
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require 'rbbcc'
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
# load BPF program
|
8
|
+
b = BCC.new(text: <<BPF)
|
9
|
+
#include <uapi/linux/ptrace.h>
|
10
|
+
#include <linux/blkdev.h>
|
11
|
+
|
12
|
+
BPF_HISTOGRAM(dist);
|
13
|
+
|
14
|
+
int kprobe__blk_account_io_completion(struct pt_regs *ctx, struct request *req)
|
15
|
+
{
|
16
|
+
dist.increment(bpf_log2l(req->__data_len / 1024));
|
17
|
+
return 0;
|
18
|
+
}
|
19
|
+
BPF
|
20
|
+
|
21
|
+
# header
|
22
|
+
puts("Tracing... Hit Ctrl-C to end.")
|
23
|
+
|
24
|
+
# trace until Ctrl-C
|
25
|
+
begin
|
26
|
+
loop { sleep 0.1 }
|
27
|
+
rescue Interrupt
|
28
|
+
puts
|
29
|
+
end
|
30
|
+
|
31
|
+
# output
|
32
|
+
b["dist"].print_log2_hist("kbytes")
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
3
|
+
|
4
|
+
require 'rbbcc'
|
5
|
+
include RbBCC
|
6
|
+
|
7
|
+
b = BCC.new(text: <<BPF)
|
8
|
+
#include <uapi/linux/ptrace.h>
|
9
|
+
#include <linux/blkdev.h>
|
10
|
+
|
11
|
+
BPF_HASH(start, struct request *);
|
12
|
+
BPF_HISTOGRAM(dist);
|
13
|
+
|
14
|
+
// note this program mixes R/W
|
15
|
+
// For next step, handle req->cmd_flags and prepare hist hash per op.
|
16
|
+
|
17
|
+
void trace_start(struct pt_regs *ctx, struct request *req) {
|
18
|
+
// stash start timestamp by request ptr
|
19
|
+
u64 ts = bpf_ktime_get_ns();
|
20
|
+
|
21
|
+
start.update(&req, &ts);
|
22
|
+
}
|
23
|
+
|
24
|
+
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
25
|
+
u64 *tsp, delta;
|
26
|
+
|
27
|
+
tsp = start.lookup(&req);
|
28
|
+
if (tsp != 0) {
|
29
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
30
|
+
dist.increment(bpf_log2l(delta / 1000)); // us
|
31
|
+
start.delete(&req);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
BPF
|
35
|
+
|
36
|
+
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
37
|
+
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
38
|
+
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
39
|
+
|
40
|
+
# header
|
41
|
+
puts("Tracing... Hit Ctrl-C to end.")
|
42
|
+
|
43
|
+
# trace until Ctrl-C
|
44
|
+
begin
|
45
|
+
loop { sleep 0.1 }
|
46
|
+
rescue Interrupt
|
47
|
+
puts
|
48
|
+
end
|
49
|
+
|
50
|
+
# output
|
51
|
+
b["dist"].print_log2_hist("usec")
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* From: https://github.com/iovisor/bcc/blob/master/examples/tracing/vfsreadlat.c
|
3
|
+
*
|
4
|
+
* vfsreadlat.c VFS read latency distribution.
|
5
|
+
* For Linux, uses BCC, eBPF. See .py/.rb file.
|
6
|
+
*
|
7
|
+
* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
|
8
|
+
* This program is free software; you can redistribute it and/or
|
9
|
+
* modify it under the terms of version 2 of the GNU General Public
|
10
|
+
* License as published by the Free Software Foundation.
|
11
|
+
*
|
12
|
+
* 15-Aug-2015 Brendan Gregg Created this.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#include <uapi/linux/ptrace.h>
|
16
|
+
|
17
|
+
BPF_HASH(start, u32);
|
18
|
+
BPF_HISTOGRAM(dist);
|
19
|
+
|
20
|
+
int do_entry(struct pt_regs *ctx)
|
21
|
+
{
|
22
|
+
u32 pid;
|
23
|
+
u64 ts, *val;
|
24
|
+
|
25
|
+
pid = bpf_get_current_pid_tgid();
|
26
|
+
ts = bpf_ktime_get_ns();
|
27
|
+
start.update(&pid, &ts);
|
28
|
+
return 0;
|
29
|
+
}
|
30
|
+
|
31
|
+
int do_return(struct pt_regs *ctx)
|
32
|
+
{
|
33
|
+
u32 pid;
|
34
|
+
u64 *tsp, delta;
|
35
|
+
|
36
|
+
pid = bpf_get_current_pid_tgid();
|
37
|
+
tsp = start.lookup(&pid);
|
38
|
+
|
39
|
+
if (tsp != 0) {
|
40
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
41
|
+
dist.increment(bpf_log2l(delta / 1000));
|
42
|
+
start.delete(&pid);
|
43
|
+
}
|
44
|
+
|
45
|
+
return 0;
|
46
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Original: from vfsreadlat.py
|
4
|
+
# Copyright (c) 2015 Brendan Gregg.
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
6
|
+
# Ruby version follows.
|
7
|
+
#
|
8
|
+
# vfsreadlat.rb VFS read latency distribution.
|
9
|
+
# For Linux, uses BCC, eBPF. See .c file.
|
10
|
+
#
|
11
|
+
# Written as a basic example of a function latency distribution histogram.
|
12
|
+
#
|
13
|
+
# USAGE: vfsreadlat.rb [interval [count]]
|
14
|
+
#
|
15
|
+
# The default interval is 5 seconds. A Ctrl-C will print the partially
|
16
|
+
# gathered histogram then exit.
|
17
|
+
|
18
|
+
require "rbbcc"
|
19
|
+
include RbBCC
|
20
|
+
|
21
|
+
def usage
|
22
|
+
puts("USAGE: %s [interval [count]]" % $0)
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
# arguments
|
27
|
+
interval = 5
|
28
|
+
count = -1
|
29
|
+
if ARGV.size > 0
|
30
|
+
begin
|
31
|
+
interval = ARGV[0].to_i
|
32
|
+
raise if interval == 0
|
33
|
+
count = ARGV[1].to_i if ARGV[1]
|
34
|
+
rescue => e # also catches -h, --help
|
35
|
+
usage()
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# load BPF program
|
40
|
+
b = BCC.new(src_file: "11-vfsreadlat.c")
|
41
|
+
b.attach_kprobe(event: "vfs_read", fn_name: "do_entry")
|
42
|
+
b.attach_kretprobe(event: "vfs_read", fn_name: "do_return")
|
43
|
+
|
44
|
+
# header
|
45
|
+
print("Tracing... Hit Ctrl-C to end.")
|
46
|
+
|
47
|
+
# output
|
48
|
+
cycle = 0
|
49
|
+
do_exit = false
|
50
|
+
loop do
|
51
|
+
if count > 0
|
52
|
+
cycle += 1
|
53
|
+
exit if cycle > count
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
sleep(interval)
|
58
|
+
rescue Interrupt
|
59
|
+
do_exit = true
|
60
|
+
end
|
61
|
+
|
62
|
+
puts
|
63
|
+
b["dist"].print_log2_hist("usecs")
|
64
|
+
b["dist"].clear
|
65
|
+
exit if do_exit
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# urandomread.rb Example of instrumenting a kernel tracepoint.
|
4
|
+
# For Linux, uses BCC, BPF. Embedded C.
|
5
|
+
#
|
6
|
+
# REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support).
|
7
|
+
#
|
8
|
+
# Test by running this, then in another shell, run:
|
9
|
+
# dd if=/dev/urandom of=/dev/null bs=1k count=5
|
10
|
+
#
|
11
|
+
# Original urandomread.py Copyright 2016 Netflix, Inc.
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
13
|
+
# Ruby version follows.
|
14
|
+
|
15
|
+
require 'rbbcc'
|
16
|
+
include RbBCC
|
17
|
+
|
18
|
+
b = BCC.new(text: <<BPF)
|
19
|
+
TRACEPOINT_PROBE(random, urandom_read) {
|
20
|
+
// args is from /sys/kernel/debug/tracing/events/random/urandom_read/format
|
21
|
+
bpf_trace_printk("%d\\n", args->got_bits);
|
22
|
+
return 0;
|
23
|
+
}
|
24
|
+
BPF
|
25
|
+
|
26
|
+
# header
|
27
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "GOTBITS"])
|
28
|
+
|
29
|
+
# format output
|
30
|
+
loop do
|
31
|
+
begin
|
32
|
+
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
33
|
+
puts("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
34
|
+
end
|
35
|
+
rescue Interrupt
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# disksnoop_fixed.rb Trace block device I/O: basic version of iosnoop.
|
4
|
+
# For Linux, uses BCC, eBPF. Embedded C.
|
5
|
+
# This is ported from original disksnoop.py
|
6
|
+
#
|
7
|
+
# Written as a basic example of tracing latency.
|
8
|
+
#
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
10
|
+
#
|
11
|
+
# 11-Aug-2015 Brendan Gregg Created disksnoop.py
|
12
|
+
|
13
|
+
=begin
|
14
|
+
name: block_rq_issue
|
15
|
+
ID: 1093
|
16
|
+
format:
|
17
|
+
field:unsigned short common_type; offset:0; size:2; signed:0;
|
18
|
+
field:unsigned char common_flags; offset:2; size:1; signed:0;
|
19
|
+
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
|
20
|
+
field:int common_pid; offset:4; size:4; signed:1;
|
21
|
+
|
22
|
+
field:dev_t dev; offset:8; size:4; signed:0;
|
23
|
+
field:sector_t sector; offset:16; size:8; signed:0;
|
24
|
+
field:unsigned int nr_sector; offset:24; size:4; signed:0;
|
25
|
+
field:unsigned int bytes; offset:28; size:4; signed:0;
|
26
|
+
field:char rwbs[8]; offset:32; size:8; signed:1;
|
27
|
+
field:char comm[16]; offset:40; size:16; signed:1;
|
28
|
+
field:__data_loc char[] cmd; offset:56; size:4; signed:1;
|
29
|
+
|
30
|
+
print fmt: "%d,%d %s %u (%s) %llu + %u [%s]", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), REC->rwbs, REC->bytes, __get_str(cmd), (unsigned long long)REC->sector, REC->nr_sector, REC->comm
|
31
|
+
|
32
|
+
name: block_rq_complete
|
33
|
+
ID: 1095
|
34
|
+
format:
|
35
|
+
field:unsigned short common_type; offset:0; size:2; signed:0;
|
36
|
+
field:unsigned char common_flags; offset:2; size:1; signed:0;
|
37
|
+
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
|
38
|
+
field:int common_pid; offset:4; size:4; signed:1;
|
39
|
+
|
40
|
+
field:dev_t dev; offset:8; size:4; signed:0;
|
41
|
+
field:sector_t sector; offset:16; size:8; signed:0;
|
42
|
+
field:unsigned int nr_sector; offset:24; size:4; signed:0;
|
43
|
+
field:int error; offset:28; size:4; signed:1;
|
44
|
+
field:char rwbs[8]; offset:32; size:8; signed:1;
|
45
|
+
field:__data_loc char[] cmd; offset:40; size:4; signed:1;
|
46
|
+
|
47
|
+
print fmt: "%d,%d %s (%s) %llu + %u [%d]", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), REC->rwbs, __get_str(cmd), (unsigned long long)REC->sector, REC->nr_sector, REC->error
|
48
|
+
|
49
|
+
in kernel 5.0.
|
50
|
+
This implementation shows the count of sector.
|
51
|
+
=end
|
52
|
+
|
53
|
+
require 'rbbcc'
|
54
|
+
include RbBCC
|
55
|
+
|
56
|
+
# load BPF program
|
57
|
+
b = BCC.new(text: <<CLANG)
|
58
|
+
#include <uapi/linux/ptrace.h>
|
59
|
+
#include <linux/blkdev.h>
|
60
|
+
|
61
|
+
BPF_HASH(start, u32);
|
62
|
+
|
63
|
+
TRACEPOINT_PROBE(block, block_rq_issue) {
|
64
|
+
// stash start timestamp by request ptr
|
65
|
+
u64 ts = bpf_ktime_get_ns();
|
66
|
+
u32 tid = bpf_get_current_pid_tgid();
|
67
|
+
|
68
|
+
start.update(&tid, &ts);
|
69
|
+
return 0;
|
70
|
+
}
|
71
|
+
|
72
|
+
TRACEPOINT_PROBE(block, block_rq_complete) {
|
73
|
+
u64 *tsp, delta;
|
74
|
+
u32 tid = bpf_get_current_pid_tgid();
|
75
|
+
|
76
|
+
tsp = start.lookup(&tid);
|
77
|
+
if (tsp != 0) {
|
78
|
+
char dst[8];
|
79
|
+
int i;
|
80
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
81
|
+
if (bpf_probe_read_str(dst, sizeof(dst), args->rwbs) < 0) {
|
82
|
+
dst[0] = '?';
|
83
|
+
for(i = 1; i < sizeof(dst); ++i)
|
84
|
+
dst[i] = 0;
|
85
|
+
}
|
86
|
+
bpf_trace_printk("%d %s %d\\n", args->nr_sector,
|
87
|
+
dst, delta / 1000);
|
88
|
+
start.delete(&tid);
|
89
|
+
}
|
90
|
+
return 0;
|
91
|
+
}
|
92
|
+
CLANG
|
93
|
+
|
94
|
+
# header
|
95
|
+
puts("%-18s %-8s %-7s %8s" % ["TIME(s)", "RWBS", "SECTORS", "LAT(ms)"])
|
96
|
+
|
97
|
+
# format output
|
98
|
+
loop do
|
99
|
+
begin
|
100
|
+
task, pid, cpu, flags, ts, msg = b.trace_fields
|
101
|
+
sector_s, rwbs, us_s = msg.split
|
102
|
+
ms = us_s.to_i.to_f / 1000
|
103
|
+
|
104
|
+
puts("%-18.9f %-8s %-7s %8.2f" % [ts, rwbs, sector_s, ms])
|
105
|
+
rescue Interrupt
|
106
|
+
exit
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rbbcc'
|
2
|
+
include RbBCC
|
3
|
+
|
4
|
+
# load BPF program
|
5
|
+
b = BCC.new(text: <<BPF)
|
6
|
+
#include <uapi/linux/ptrace.h>
|
7
|
+
|
8
|
+
struct key_t {
|
9
|
+
char c[80];
|
10
|
+
};
|
11
|
+
BPF_HASH(counts, struct key_t);
|
12
|
+
|
13
|
+
int count(struct pt_regs *ctx) {
|
14
|
+
if (!PT_REGS_PARM1(ctx))
|
15
|
+
return 0;
|
16
|
+
|
17
|
+
struct key_t key = {};
|
18
|
+
u64 zero = 0, *val;
|
19
|
+
|
20
|
+
bpf_probe_read(&key.c, sizeof(key.c), (void *)PT_REGS_PARM1(ctx));
|
21
|
+
// could also use `counts.increment(key)`
|
22
|
+
val = counts.lookup_or_try_init(&key, &zero);
|
23
|
+
if (val) {
|
24
|
+
(*val)++;
|
25
|
+
}
|
26
|
+
return 0;
|
27
|
+
};
|
28
|
+
BPF
|
29
|
+
b.attach_uprobe(name: "c", sym: "strlen", fn_name: "count")
|
30
|
+
|
31
|
+
# header
|
32
|
+
print("Tracing strlen()... Hit Ctrl-C to end.")
|
33
|
+
|
34
|
+
# sleep until Ctrl-C
|
35
|
+
begin
|
36
|
+
sleep(99999999)
|
37
|
+
rescue Interrupt
|
38
|
+
puts
|
39
|
+
end
|
40
|
+
|
41
|
+
# print output
|
42
|
+
puts("%10s %s" % ["COUNT", "STRING"])
|
43
|
+
counts = b.get_table("counts")
|
44
|
+
counts.items.sort_by{|k, v| v.to_bcc_value }.each do |k, v|
|
45
|
+
puts("%10d %s" % [v.to_bcc_value, k[0, k.size].unpack("Z*")[0]])
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rbbcc'
|
2
|
+
include RbBCC
|
3
|
+
|
4
|
+
if ARGV.size != 1
|
5
|
+
print("USAGE: #{$0} PID")
|
6
|
+
exit()
|
7
|
+
end
|
8
|
+
pid = ARGV[0]
|
9
|
+
debug = !!ENV['DEBUG']
|
10
|
+
|
11
|
+
# load BPF program
|
12
|
+
bpf_text = <<BPF
|
13
|
+
#include <uapi/linux/ptrace.h>
|
14
|
+
int do_trace(struct pt_regs *ctx) {
|
15
|
+
uint64_t addr;
|
16
|
+
char path[128]={0};
|
17
|
+
bpf_usdt_readarg(6, ctx, &addr);
|
18
|
+
bpf_probe_read(&path, sizeof(path), (void *)addr);
|
19
|
+
bpf_trace_printk("path:%s\\n", path);
|
20
|
+
return 0;
|
21
|
+
};
|
22
|
+
BPF
|
23
|
+
|
24
|
+
# enable USDT probe from given PID
|
25
|
+
u = USDT.new(pid: pid.to_i)
|
26
|
+
u.enable_probe(probe: "http__server__request", fn_name: "do_trace")
|
27
|
+
if debug
|
28
|
+
puts(u.get_text)
|
29
|
+
puts(bpf_text)
|
30
|
+
end
|
31
|
+
|
32
|
+
# initialize BPF
|
33
|
+
b = BCC.new(text: bpf_text, usdt_contexts: [u])
|
34
|
+
|
35
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "ARGS"])
|
36
|
+
loop do
|
37
|
+
begin
|
38
|
+
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
39
|
+
puts("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
40
|
+
end
|
41
|
+
rescue Interrupt
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#include <uapi/linux/ptrace.h>
|
2
|
+
#include <linux/sched.h>
|
3
|
+
|
4
|
+
struct key_t {
|
5
|
+
u32 prev_pid;
|
6
|
+
u32 curr_pid;
|
7
|
+
};
|
8
|
+
|
9
|
+
BPF_HASH(stats, struct key_t, u64, 1024);
|
10
|
+
int count_sched(struct pt_regs *ctx, struct task_struct *prev) {
|
11
|
+
struct key_t key = {};
|
12
|
+
u64 zero = 0, *val;
|
13
|
+
|
14
|
+
key.curr_pid = bpf_get_current_pid_tgid();
|
15
|
+
key.prev_pid = prev->pid;
|
16
|
+
|
17
|
+
// could also use `stats.increment(key);`
|
18
|
+
val = stats.lookup_or_try_init(&key, &zero);
|
19
|
+
if (val) {
|
20
|
+
(*val)++;
|
21
|
+
}
|
22
|
+
return 0;
|
23
|
+
}
|