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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bfc5d3f19fd4dbfa744a6380055103b5c45a0a72d956ced238154472ae4d7b5
|
4
|
+
data.tar.gz: 160c2a313f7181c6a9dab665c265fe2760d743ecbcab4797cc25e920e00d7f11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e2f72abd18698c9dca81342474a38e10a2e65d88e4acc7d0bbb3d924d9019d7204639f407a14418664d49ef4eb0666729fda06e3a06f2066dd0c8bfa0cf6701
|
7
|
+
data.tar.gz: e651213860bacc705b8b3f8c51c962aba9f5f1d67cb041eab850eee64b1c8ab6d7fe71a6bd630cddc224bea2af465323c3b4ef728995d124c954f194e9cd6714
|
data/.semaphore/semaphore.yml
CHANGED
@@ -10,10 +10,12 @@ blocks:
|
|
10
10
|
jobs:
|
11
11
|
- name: ruby test
|
12
12
|
matrix:
|
13
|
+
- env_var: RUBY_VERSION
|
14
|
+
values: [ "2.6.5", "2.6.6", "2.7.1" ]
|
13
15
|
- env_var: LIBBCC_VERSION
|
14
16
|
values: [ "0.12.0", "0.11.0", "0.10.0" ]
|
15
17
|
commands:
|
16
18
|
- sem-version c 7
|
17
|
-
- sem-version ruby
|
19
|
+
- sem-version ruby $RUBY_VERSION
|
18
20
|
- checkout
|
19
21
|
- ./semaphore.sh
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rbbcc (0.
|
4
|
+
rbbcc (0.6.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -12,17 +12,17 @@ GEM
|
|
12
12
|
pry (0.12.2)
|
13
13
|
coderay (~> 1.1.0)
|
14
14
|
method_source (~> 0.9.0)
|
15
|
-
rake (
|
15
|
+
rake (13.0.1)
|
16
16
|
|
17
17
|
PLATFORMS
|
18
18
|
ruby
|
19
19
|
|
20
20
|
DEPENDENCIES
|
21
21
|
bundler (~> 2.0)
|
22
|
-
minitest
|
23
|
-
pry
|
24
|
-
rake (~>
|
22
|
+
minitest (>= 5)
|
23
|
+
pry (~> 0.12)
|
24
|
+
rake (~> 13.0)
|
25
25
|
rbbcc!
|
26
26
|
|
27
27
|
BUNDLED WITH
|
28
|
-
2.1.
|
28
|
+
2.1.4
|
data/README.md
CHANGED
@@ -94,6 +94,10 @@ $ docker run --privileged \
|
|
94
94
|
runc-5025 [003] d... 1237.797464: : Hello, World!
|
95
95
|
```
|
96
96
|
|
97
|
+
## Documents
|
98
|
+
|
99
|
+
See [docs/](docs/) for getting started and tutorial.
|
100
|
+
|
97
101
|
## Development
|
98
102
|
|
99
103
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/docs/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# RbBCC Docs
|
2
2
|
|
3
3
|
* [Getting Started](getting_started.md)
|
4
|
+
* [Ruby Tutorial](tutorial_bcc_ruby_developer.md)
|
5
|
+
* [Projects Using RbBCC](projects_using_rbbcc.md)
|
4
6
|
|
5
7
|
**Please see also [BCC itself's README](https://github.com/iovisor/bcc/#readme) and [docs](https://github.com/iovisor/bcc/tree/master/docs).**
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Original hello_world.py:
|
3
|
+
# Copyright (c) PLUMgrid, Inc.
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
5
|
+
#
|
6
|
+
# This Ruby version follows the Apache License 2.0
|
7
|
+
|
8
|
+
# run in project examples directory with:
|
9
|
+
# sudo ./hello_world.rb"
|
10
|
+
# see trace_fields.rb for a longer example
|
11
|
+
|
12
|
+
require "rbbcc"
|
13
|
+
include RbBCC
|
14
|
+
|
15
|
+
# This may not work for 4.17 on x64, you need replace kprobe__sys_clone with kprobe____x64_sys_clone
|
16
|
+
BCC.new(text: 'int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print
|
@@ -0,0 +1,18 @@
|
|
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
|
+
puts "Tracing sys_sync()... Ctrl-C to end."
|
8
|
+
begin
|
9
|
+
BCC.new(text: <<~BPF).trace_print
|
10
|
+
int kprobe__sys_sync(void *ctx) {
|
11
|
+
bpf_trace_printk("sys_sync() called\\n");
|
12
|
+
return 0;
|
13
|
+
}
|
14
|
+
BPF
|
15
|
+
rescue Interrupt
|
16
|
+
puts
|
17
|
+
puts "Done"
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
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
|
+
# define BPF program
|
8
|
+
prog = <<BPF
|
9
|
+
int hello(void *ctx) {
|
10
|
+
bpf_trace_printk("Hello, World!\\n");
|
11
|
+
return 0;
|
12
|
+
}
|
13
|
+
BPF
|
14
|
+
|
15
|
+
# load BPF program
|
16
|
+
b = BCC.new(text: prog)
|
17
|
+
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
18
|
+
|
19
|
+
# header
|
20
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
21
|
+
|
22
|
+
# format output
|
23
|
+
begin
|
24
|
+
b.trace_fields do |task, pid, cpu, flags, ts, msg|
|
25
|
+
print("%-18.9f %-16s %-6d %s" % [ts, task, pid, msg])
|
26
|
+
end
|
27
|
+
rescue Interrupt
|
28
|
+
puts
|
29
|
+
puts "Done"
|
30
|
+
rescue => e
|
31
|
+
p e
|
32
|
+
retry
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Original sync_timing.py:
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License")
|
4
|
+
#
|
5
|
+
# This Ruby version follows the Apache License 2.0
|
6
|
+
|
7
|
+
require "rbbcc"
|
8
|
+
include RbBCC
|
9
|
+
|
10
|
+
# load BPF program
|
11
|
+
b = BCC.new(text: <<BPF)
|
12
|
+
#include <uapi/linux/ptrace.h>
|
13
|
+
|
14
|
+
BPF_HASH(last);
|
15
|
+
|
16
|
+
int do_trace(struct pt_regs *ctx) {
|
17
|
+
u64 ts, *tsp, delta, key = 0;
|
18
|
+
|
19
|
+
// attempt to read stored timestamp
|
20
|
+
tsp = last.lookup(&key);
|
21
|
+
if (tsp != 0) {
|
22
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
23
|
+
if (delta < 1000000000) {
|
24
|
+
// output if time is less than 1 second
|
25
|
+
bpf_trace_printk("%d\\n", delta / 1000000);
|
26
|
+
}
|
27
|
+
last.delete(&key);
|
28
|
+
}
|
29
|
+
|
30
|
+
// update stored timestamp
|
31
|
+
ts = bpf_ktime_get_ns();
|
32
|
+
last.update(&key, &ts);
|
33
|
+
return 0;
|
34
|
+
}
|
35
|
+
BPF
|
36
|
+
|
37
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
38
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
39
|
+
|
40
|
+
# format output
|
41
|
+
start = 0
|
42
|
+
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
43
|
+
start = ts.to_f if start.zero?
|
44
|
+
ts = ts.to_f - start
|
45
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
46
|
+
end
|
@@ -0,0 +1,54 @@
|
|
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
|
+
|
11
|
+
BPF_HASH(last);
|
12
|
+
|
13
|
+
int do_trace(struct pt_regs *ctx) {
|
14
|
+
u64 ts, *tsp, delta, key = 0, counter_key = 1, zero = 0;
|
15
|
+
|
16
|
+
// initialize counter key
|
17
|
+
if (last.lookup_or_try_init(&counter_key, &zero))
|
18
|
+
last.increment(counter_key);
|
19
|
+
|
20
|
+
// attempt to read stored timestamp
|
21
|
+
tsp = last.lookup(&key);
|
22
|
+
if (tsp != 0) {
|
23
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
24
|
+
if (delta < 1000000000) {
|
25
|
+
// output if time is less than 1 second
|
26
|
+
bpf_trace_printk("%d\\n", delta / 1000000);
|
27
|
+
}
|
28
|
+
last.delete(&key);
|
29
|
+
}
|
30
|
+
|
31
|
+
// update stored timestamp
|
32
|
+
ts = bpf_ktime_get_ns();
|
33
|
+
last.update(&key, &ts);
|
34
|
+
return 0;
|
35
|
+
}
|
36
|
+
BPF
|
37
|
+
|
38
|
+
COUNTER_KEY = 1
|
39
|
+
|
40
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
41
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
42
|
+
|
43
|
+
# format output
|
44
|
+
start = 0
|
45
|
+
begin
|
46
|
+
b.trace_fields do |task, pid, cpu, flags, ts, ms|
|
47
|
+
start = ts.to_f if start.zero?
|
48
|
+
ts = ts.to_f - start
|
49
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [ts, ms.chomp])
|
50
|
+
end
|
51
|
+
rescue Interrupt
|
52
|
+
table = b["last"]
|
53
|
+
puts "Count of sys_sync: %d" % table[COUNTER_KEY].to_bcc_value
|
54
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# disksnoop.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
|
+
require 'rbbcc'
|
14
|
+
include RbBCC
|
15
|
+
|
16
|
+
REQ_WRITE = 1 # from include/linux/blk_types.h
|
17
|
+
|
18
|
+
# load BPF program
|
19
|
+
b = BCC.new(text: <<CLANG)
|
20
|
+
#include <uapi/linux/ptrace.h>
|
21
|
+
#include <linux/blkdev.h>
|
22
|
+
|
23
|
+
BPF_HASH(start, struct request *);
|
24
|
+
|
25
|
+
void trace_start(struct pt_regs *ctx, struct request *req) {
|
26
|
+
// stash start timestamp by request ptr
|
27
|
+
u64 ts = bpf_ktime_get_ns();
|
28
|
+
|
29
|
+
start.update(&req, &ts);
|
30
|
+
}
|
31
|
+
|
32
|
+
void trace_completion(struct pt_regs *ctx, struct request *req) {
|
33
|
+
u64 *tsp, delta;
|
34
|
+
|
35
|
+
tsp = start.lookup(&req);
|
36
|
+
if (tsp != 0) {
|
37
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
38
|
+
bpf_trace_printk("%d %x %d\\n", req->__data_len,
|
39
|
+
req->cmd_flags, delta / 1000);
|
40
|
+
start.delete(&req);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
CLANG
|
44
|
+
|
45
|
+
b.attach_kprobe(event: "blk_start_request", fn_name: "trace_start") if BCC.get_kprobe_functions('blk_start_request')
|
46
|
+
b.attach_kprobe(event: "blk_mq_start_request", fn_name: "trace_start")
|
47
|
+
b.attach_kprobe(event: "blk_account_io_completion", fn_name: "trace_completion")
|
48
|
+
|
49
|
+
# header
|
50
|
+
puts("%-18s %-2s %-7s %8s" % ["TIME(s)", "T", "BYTES", "LAT(ms)"])
|
51
|
+
|
52
|
+
# format output
|
53
|
+
loop do
|
54
|
+
begin
|
55
|
+
task, pid, cpu, flags, ts, msg = b.trace_fields
|
56
|
+
bytes_s, bflags_s, us_s = msg.split
|
57
|
+
|
58
|
+
if (bflags_s.to_i(16) & REQ_WRITE).nonzero?
|
59
|
+
type_s = "W"
|
60
|
+
elsif bytes_s == "0" # see blk_fill_rwbs() for logic
|
61
|
+
type_s = "M"
|
62
|
+
else
|
63
|
+
type_s = "R"
|
64
|
+
end
|
65
|
+
ms = us_s.to_i.to_f / 1000
|
66
|
+
|
67
|
+
puts("%-18.9f %-2s %-7s %8.2f" % [ts, type_s, bytes_s, ms])
|
68
|
+
rescue Interrupt
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This is a Hello World example that uses BPF_PERF_OUTPUT.
|
4
|
+
# Ported from hello_perf_output.py
|
5
|
+
|
6
|
+
require 'rbbcc'
|
7
|
+
include RbBCC
|
8
|
+
|
9
|
+
# define BPF program
|
10
|
+
prog = """
|
11
|
+
#include <linux/sched.h>
|
12
|
+
|
13
|
+
// define output data structure in C
|
14
|
+
struct data_t {
|
15
|
+
u32 pid;
|
16
|
+
u64 ts;
|
17
|
+
char comm[TASK_COMM_LEN];
|
18
|
+
};
|
19
|
+
BPF_PERF_OUTPUT(events);
|
20
|
+
|
21
|
+
int hello(struct pt_regs *ctx) {
|
22
|
+
struct data_t data = {};
|
23
|
+
|
24
|
+
data.pid = bpf_get_current_pid_tgid();
|
25
|
+
data.ts = bpf_ktime_get_ns();
|
26
|
+
bpf_get_current_comm(&data.comm, sizeof(data.comm));
|
27
|
+
|
28
|
+
events.perf_submit(ctx, &data, sizeof(data));
|
29
|
+
|
30
|
+
return 0;
|
31
|
+
}
|
32
|
+
"""
|
33
|
+
|
34
|
+
# load BPF program
|
35
|
+
b = BCC.new(text: prog)
|
36
|
+
b.attach_kprobe(event: b.get_syscall_fnname("clone"), fn_name: "hello")
|
37
|
+
|
38
|
+
# header
|
39
|
+
puts("%-18s %-16s %-6s %s" % ["TIME(s)", "COMM", "PID", "MESSAGE"])
|
40
|
+
|
41
|
+
# process event
|
42
|
+
start = 0
|
43
|
+
print_event = lambda { |cpu, data, size|
|
44
|
+
event = b["events"].event(data)
|
45
|
+
if start == 0
|
46
|
+
start = event.ts
|
47
|
+
end
|
48
|
+
|
49
|
+
time_s = ((event.ts - start).to_f) / 1000000000
|
50
|
+
puts("%-18.9f %-16s %-6d %s" % [time_s, event.comm, event.pid,
|
51
|
+
"Hello, perf_output!"])
|
52
|
+
}
|
53
|
+
|
54
|
+
# loop with callback to print_event
|
55
|
+
b["events"].open_perf_buffer(&print_event)
|
56
|
+
|
57
|
+
loop do
|
58
|
+
b.perf_buffer_poll()
|
59
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
|
11
|
+
struct data_t {
|
12
|
+
u32 pid;
|
13
|
+
u64 ts;
|
14
|
+
u64 delta;
|
15
|
+
};
|
16
|
+
BPF_PERF_OUTPUT(events);
|
17
|
+
BPF_HASH(last);
|
18
|
+
|
19
|
+
int do_trace(struct pt_regs *ctx) {
|
20
|
+
u64 ts, *tsp, delta, key = 0;
|
21
|
+
|
22
|
+
// attempt to read stored timestamp
|
23
|
+
tsp = last.lookup(&key);
|
24
|
+
if (tsp != 0) {
|
25
|
+
struct data_t data = {};
|
26
|
+
delta = bpf_ktime_get_ns() - *tsp;
|
27
|
+
if (delta < 1000000000) {
|
28
|
+
data.pid = bpf_get_current_pid_tgid();
|
29
|
+
data.ts = bpf_ktime_get_ns();
|
30
|
+
data.delta = delta;
|
31
|
+
events.perf_submit(ctx, &data, sizeof(data));
|
32
|
+
}
|
33
|
+
last.delete(&key);
|
34
|
+
}
|
35
|
+
|
36
|
+
// update stored timestamp
|
37
|
+
ts = bpf_ktime_get_ns();
|
38
|
+
last.update(&key, &ts);
|
39
|
+
return 0;
|
40
|
+
}
|
41
|
+
BPF
|
42
|
+
|
43
|
+
b.attach_kprobe(event: b.get_syscall_fnname("sync"), fn_name: "do_trace")
|
44
|
+
puts("Tracing for quick sync's... Ctrl-C to end")
|
45
|
+
|
46
|
+
# format output
|
47
|
+
start = 0
|
48
|
+
b["events"].open_perf_buffer do |_, data, _|
|
49
|
+
event = b["events"].event(data)
|
50
|
+
if start == 0
|
51
|
+
start = event.ts
|
52
|
+
end
|
53
|
+
|
54
|
+
time_s = ((event.ts - start).to_f) / 1_000_000_000
|
55
|
+
puts("At time %.2f s: multiple syncs detected, last %s ms ago" % [time_s, event.delta / 1_000_000])
|
56
|
+
end
|
57
|
+
|
58
|
+
loop do
|
59
|
+
b.perf_buffer_poll()
|
60
|
+
end
|