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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.semaphore/semaphore.yml +3 -1
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +6 -6
  5. data/README.md +4 -0
  6. data/docs/README.md +2 -0
  7. data/docs/answers/01-hello-world.rb +16 -0
  8. data/docs/answers/02-sys_sync.rb +18 -0
  9. data/docs/answers/03-hello_fields.rb +33 -0
  10. data/docs/answers/04-sync_timing.rb +46 -0
  11. data/docs/answers/05-sync_count.rb +54 -0
  12. data/docs/answers/06-disksnoop.rb +71 -0
  13. data/docs/answers/07-hello_perf_output.rb +59 -0
  14. data/docs/answers/08-sync_perf_output.rb +60 -0
  15. data/docs/answers/09-bitehist.rb +32 -0
  16. data/docs/answers/10-disklatency.rb +51 -0
  17. data/docs/answers/11-vfsreadlat.c +46 -0
  18. data/docs/answers/11-vfsreadlat.rb +66 -0
  19. data/docs/answers/12-urandomread.rb +38 -0
  20. data/docs/answers/13-disksnoop_fixed.rb +108 -0
  21. data/docs/answers/14-strlen_count.rb +46 -0
  22. data/docs/answers/15-nodejs_http_server.rb +44 -0
  23. data/docs/answers/16-task_switch.c +23 -0
  24. data/docs/answers/16-task_switch.rb +17 -0
  25. data/docs/answers/node-server.js +11 -0
  26. data/docs/projects_using_rbbcc.md +43 -0
  27. data/docs/tutorial_bcc_ruby_developer.md +774 -0
  28. data/docs/tutorial_bcc_ruby_developer_japanese.md +770 -0
  29. data/examples/networking/http_filter/http-parse-simple.c +114 -0
  30. data/examples/networking/http_filter/http-parse-simple.rb +85 -0
  31. data/examples/ruby_usdt.rb +105 -0
  32. data/examples/sbrk_trace.rb +204 -0
  33. data/examples/tools/bashreadline.rb +83 -0
  34. data/lib/rbbcc/bcc.rb +73 -20
  35. data/lib/rbbcc/clib.rb +7 -2
  36. data/lib/rbbcc/debug.rb +17 -0
  37. data/lib/rbbcc/table.rb +16 -22
  38. data/lib/rbbcc/usdt.rb +21 -4
  39. data/lib/rbbcc/version.rb +1 -1
  40. data/rbbcc.gemspec +1 -5
  41. metadata +34 -61
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # bashreadline Print entered bash commands from all running shells.
4
+ # For Linux, uses BCC, eBPF. Embedded C.
5
+ #
6
+ # USAGE: bashreadline [-s SHARED]
7
+ # This works by tracing the readline() function using a uretprobe (uprobes).
8
+ # When you failed to run the script directly with error:
9
+ # `Exception: could not determine address of symbol b'readline'`,
10
+ # you may need specify the location of libreadline.so library
11
+ # with `-s` option.
12
+ #
13
+ # Original bashreadline.py:
14
+ # Copyright 2016 Netflix, Inc.
15
+ # Licensed under the Apache License, Version 2.0 (the "License")
16
+ # And Ruby version follows.
17
+ #
18
+ # 28-Jan-2016 Brendan Gregg Created bashreadline.py.
19
+ # 12-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT
20
+ # 05-Jun-2020 Uchio Kondo Ported bashreadline.rb
21
+
22
+ require 'rbbcc'
23
+ require 'optparse'
24
+ include RbBCC
25
+
26
+ args = {}
27
+ opts = OptionParser.new
28
+ opts.on("-s", "--shared=LIBREADLINE_PATH"){|v| args[:shared] = v }
29
+ opts.parse!(ARGV)
30
+
31
+ name = args[:shared] || "/bin/bash"
32
+
33
+ # load BPF program
34
+ bpf_text = <<BPF
35
+ #include <uapi/linux/ptrace.h>
36
+ #include <linux/sched.h>
37
+
38
+ struct str_t {
39
+ u64 pid;
40
+ char str[80];
41
+ };
42
+
43
+ BPF_PERF_OUTPUT(events);
44
+
45
+ int printret(struct pt_regs *ctx) {
46
+ struct str_t data = {};
47
+ char comm[TASK_COMM_LEN] = {};
48
+ u32 pid;
49
+ if (!PT_REGS_RC(ctx))
50
+ return 0;
51
+ pid = bpf_get_current_pid_tgid();
52
+ data.pid = pid;
53
+ bpf_probe_read(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx));
54
+
55
+ bpf_get_current_comm(&comm, sizeof(comm));
56
+ if (comm[0] == 'b' && comm[1] == 'a' && comm[2] == 's' && comm[3] == 'h' && comm[4] == 0 ) {
57
+ events.perf_submit(ctx,&data,sizeof(data));
58
+ }
59
+
60
+
61
+ return 0;
62
+ };
63
+ BPF
64
+
65
+ b = BCC.new(text: bpf_text)
66
+ b.attach_uretprobe(name: name, sym: "readline", fn_name: "printret")
67
+
68
+ # header
69
+ puts("%-9s %-6s %s" % ["TIME", "PID", "COMMAND"])
70
+
71
+ b["events"].open_perf_buffer do |cpu, data, size|
72
+ event = b["events"].event(data)
73
+ puts("%-9s %-6d %s" % [
74
+ Time.now.strftime("%H:%M:%S"),
75
+ event.pid,
76
+ event.str
77
+ ])
78
+ end
79
+
80
+ trap(:INT) { puts; exit }
81
+ loop do
82
+ b.perf_buffer_poll
83
+ end
@@ -1,6 +1,7 @@
1
1
  require 'rbbcc/consts'
2
2
  require 'rbbcc/table'
3
3
  require 'rbbcc/symbol_cache'
4
+ require 'rbbcc/debug'
4
5
 
5
6
  module RbBCC
6
7
  SYSCALL_PREFIXES = [
@@ -14,6 +15,20 @@ module RbBCC
14
15
 
15
16
  class BCC
16
17
  class << self
18
+ def _find_file(filename)
19
+ if filename
20
+ unless File.exist?(filename)
21
+ t = File.expand_path "../#{filename}", $0
22
+ if File.exist?(t)
23
+ filename = t
24
+ else
25
+ raise "Could not find file #{filename}"
26
+ end
27
+ end
28
+ end
29
+ return filename
30
+ end
31
+
17
32
  def ksym(addr, show_module: false, show_offset: false)
18
33
  self.sym(addr, -1, show_module: show_module, show_offset: show_offset, demangle: false)
19
34
  end
@@ -161,25 +176,63 @@ module RbBCC
161
176
  module_ = (show_module && module_) ? " [#{File.basename.basename(module_)}]" : ""
162
177
  return name + module_
163
178
  end
179
+
180
+ def attach_raw_socket(fn, dev)
181
+ unless fn.is_a?(Hash)
182
+ raise "arg 1 must be of BPF.Function Hash"
183
+ end
184
+ sock = Clib.bpf_open_raw_sock(dev)
185
+ if sock < 0
186
+ raise SystemCallError.new("Failed to open raw device %s" % dev, Fiddle.last_error)
187
+ end
188
+
189
+ res = Clib.bpf_attach_socket(sock, fn[:fd])
190
+ if res < 0
191
+ raise SystemCallError.new("Failed to attach BPF to device %s" % dev, Fiddle.last_error)
192
+ end
193
+ fn[:sock] = sock
194
+ fn
195
+ end
164
196
  end
165
197
 
166
- def initialize(text:, debug: 0, cflags: [], usdt_contexts: [], allow_rlimit: 0)
198
+ def initialize(text: "", src_file: nil, hdr_file: nil, debug: 0, cflags: [], usdt_contexts: [], allow_rlimit: 0)
167
199
  @kprobe_fds = {}
168
200
  @uprobe_fds = {}
169
201
  @tracepoint_fds = {}
170
202
  @raw_tracepoint_fds = {}
171
- @usdt_contexts = usdt_contexts
172
- if code = gen_args_from_usdt
173
- text = code + text
174
- end
175
-
176
- @module = Clib.bpf_module_create_c_from_string(
177
- text,
178
- debug,
179
- cflags.pack('p*'),
180
- cflags.size,
181
- allow_rlimit
182
- )
203
+
204
+ if src_file
205
+ src_file = BCC._find_file(src_file)
206
+ hdr_file = BCC._find_file(hdr_file)
207
+ end
208
+
209
+ if src_file && src_file.end_with?(".b")
210
+ @module = Clib.bpf_module_create_b(src_file, hdr_file, debug, device)
211
+ else
212
+ if src_file
213
+ text = File.read(src_file)
214
+ end
215
+
216
+ @usdt_contexts = usdt_contexts
217
+ if code = gen_args_from_usdt
218
+ text = code + text
219
+ end
220
+
221
+ # Util.debug text
222
+ cflags_p = if cflags.empty?
223
+ nil
224
+ else
225
+ cflags.pack('p*')
226
+ end
227
+
228
+ @module = Clib.bpf_module_create_c_from_string(
229
+ text,
230
+ debug,
231
+ cflags_p,
232
+ cflags.size,
233
+ allow_rlimit
234
+ )
235
+ end
183
236
  @funcs = {}
184
237
  @tables = {}
185
238
  @perf_buffers = {}
@@ -237,7 +290,7 @@ module RbBCC
237
290
  if fd < 0
238
291
  raise SystemCallError.new("Failed to attach BPF program #{fn_name} to tracepoint #{tp}", Fiddle.last_error)
239
292
  end
240
- puts "Attach: #{tp}"
293
+ Util.debug "Attach: #{tp}"
241
294
  @tracepoint_fds[tp] = fd
242
295
  self
243
296
  end
@@ -252,7 +305,7 @@ module RbBCC
252
305
  if fd < 0
253
306
  raise SystemCallError.new("Failed to attach BPF program #{fn_name} to raw tracepoint #{tp}", Fiddle.last_error)
254
307
  end
255
- puts "Attach: #{tp}"
308
+ Util.debug "Attach: #{tp}"
256
309
  @raw_tracepoint_fds[tp] = fd
257
310
  self
258
311
  end
@@ -264,7 +317,7 @@ module RbBCC
264
317
  if fd < 0
265
318
  raise SystemCallError.new("Failed to attach BPF program #{fn_name} to kprobe #{event}", Fiddle.last_error)
266
319
  end
267
- puts "Attach: #{ev_name}"
320
+ Util.debug "Attach: #{ev_name}"
268
321
  @kprobe_fds[ev_name] = fd
269
322
  [ev_name, fd]
270
323
  end
@@ -277,7 +330,7 @@ module RbBCC
277
330
  if fd < 0
278
331
  raise SystemCallError.new("Failed to attach BPF program #{fn_name} to kretprobe #{event}", Fiddle.last_error)
279
332
  end
280
- puts "Attach: #{ev_name}"
333
+ Util.debug "Attach: #{ev_name}"
281
334
  @kprobe_fds[ev_name] = fd
282
335
  [ev_name, fd]
283
336
  end
@@ -291,7 +344,7 @@ module RbBCC
291
344
  if fd < 0
292
345
  raise SystemCallError.new(Fiddle.last_error)
293
346
  end
294
- puts "Attach: #{ev_name}"
347
+ Util.debug "Attach: #{ev_name}"
295
348
 
296
349
  @uprobe_fds[ev_name] = fd
297
350
  [ev_name, fd]
@@ -306,7 +359,7 @@ module RbBCC
306
359
  if fd < 0
307
360
  raise SystemCallError.new(Fiddle.last_error)
308
361
  end
309
- puts "Attach: #{ev_name}"
362
+ Util.debug "Attach: #{ev_name}"
310
363
 
311
364
  @uprobe_fds[ev_name] = fd
312
365
  [ev_name, fd]
@@ -507,7 +560,7 @@ module RbBCC
507
560
  else
508
561
  next
509
562
  end
510
- puts "Found fnc: #{func_name}"
563
+ Util.debug "Found fnc: #{func_name}"
511
564
  if func_name.start_with?("kprobe__")
512
565
  fn = load_func(func_name, BPF::KPROBE)
513
566
  attach_kprobe(
@@ -25,7 +25,7 @@ module RbBCC
25
25
  end
26
26
 
27
27
  extend Fiddle::Importer
28
- targets = %w(0.12.0 0.11.0 0.10.0)
28
+ targets = %w(0.14.0 0.13.0 0.12.0 0.11.0 0.10.0)
29
29
  if default_load = ENV['LIBBCC_VERSION']
30
30
  targets.unshift(default_load)
31
31
  targets.uniq!
@@ -45,6 +45,7 @@ module RbBCC
45
45
  typealias "size_t", "int"
46
46
 
47
47
  extern 'void * bpf_module_create_c_from_string(char *, unsigned int, char **, int, long)'
48
+ extern 'void * bpf_module_create_b(char *filename, char *proto_filename, unsigned int flags, char *dev_name)'
48
49
  extern 'int bpf_num_functions(void *)'
49
50
  extern 'char * bpf_function_name(void *, int)'
50
51
  extern 'void bpf_module_destroy(void *)'
@@ -119,10 +120,11 @@ module RbBCC
119
120
  extern 'char * bpf_perf_event_field(void *program, const char *event, size_t i)'
120
121
 
121
122
  extern 'void * bcc_usdt_new_frompid(int, char *)'
123
+ extern 'void * bcc_usdt_new_frompath(char *path)'
122
124
  extern 'int bcc_usdt_enable_probe(void *, char *, char *)'
123
125
  extern 'char * bcc_usdt_genargs(void **, int)'
124
126
  extern 'void bcc_usdt_foreach_uprobe(void *, void *)'
125
-
127
+ extern 'void bcc_usdt_close(void *usdt)'
126
128
  BCCSymbol = struct([
127
129
  "const char *name",
128
130
  "const char *demangle_name",
@@ -155,6 +157,9 @@ module RbBCC
155
157
  extern 'int perf_reader_poll(int num_readers, struct perf_reader **readers, int timeout)'
156
158
 
157
159
  extern 'void bcc_procutils_free(const char *ptr)'
160
+
161
+ extern 'int bpf_open_raw_sock(const char *name)'
162
+ extern 'int bpf_attach_socket(int sockfd, int progfd)'
158
163
  end
159
164
  end
160
165
 
@@ -0,0 +1,17 @@
1
+ if ENV['RBBCC_DEBUG'] || ENV['BCC_DEBUG']
2
+ module RbBCC
3
+ module Util
4
+ def self.debug(msg)
5
+ puts msg
6
+ end
7
+ end
8
+ end
9
+ else
10
+ module RbBCC
11
+ module Util
12
+ def self.debug(msg)
13
+ # nop
14
+ end
15
+ end
16
+ end
17
+ end
@@ -78,7 +78,9 @@ module RbBCC
78
78
  return next_key
79
79
  end
80
80
 
81
- def [](key)
81
+ def [](_key)
82
+ key = normalize_key(_key)
83
+
82
84
  leaf = Fiddle::Pointer.malloc(self.leafsize)
83
85
  res = Clib.bpf_lookup_elem(self.map_fd, key, leaf)
84
86
  if res < 0
@@ -91,7 +93,8 @@ module RbBCC
91
93
  self[key] || raise(KeyError, "key not found")
92
94
  end
93
95
 
94
- def []=(key, leaf)
96
+ def []=(_key, leaf)
97
+ key = normalize_key(_key)
95
98
  res = Clib.bpf_update_elem(self.map_fd, key, leaf, 0)
96
99
  if res < 0
97
100
  raise SystemCallError.new("Could not update table", Fiddle.last_error)
@@ -180,6 +183,17 @@ module RbBCC
180
183
  end
181
184
 
182
185
  private
186
+ def normalize_key(key)
187
+ case key
188
+ when Fiddle::Pointer
189
+ key
190
+ when Integer
191
+ byref(key, keysize)
192
+ else
193
+ raise KeyError, "#{key.inspect} must be integer or pointor"
194
+ end
195
+ end
196
+
183
197
  def byref(value, size=sizeof("int"))
184
198
  pack_fmt = case size
185
199
  when sizeof("int") ; "i!"
@@ -207,14 +221,6 @@ module RbBCC
207
221
  end
208
222
  alias length size
209
223
 
210
- def [](key)
211
- super(normalize_key(key))
212
- end
213
-
214
- def []=(key, value)
215
- super(normalize_key(key), value)
216
- end
217
-
218
224
  def clearitem(key)
219
225
  self[key] = byref(0, @leafsize)
220
226
  end
@@ -229,18 +235,6 @@ module RbBCC
229
235
  b.call(v.to_bcc_value)
230
236
  end
231
237
  end
232
-
233
- private
234
- def normalize_key(key)
235
- case key
236
- when Fiddle::Pointer
237
- key
238
- when Integer
239
- byref(key, keysize)
240
- else
241
- raise KeyError, "#{key.inspect} must be integer or pointor"
242
- end
243
- end
244
238
  end
245
239
 
246
240
  class PerfEventArray < TableBase
@@ -4,15 +4,21 @@ module RbBCC
4
4
  USDTProbe = Struct.new(:binpath, :fn_name, :addr, :pid)
5
5
 
6
6
  class USDT
7
- # TODO path:
8
- def initialize(pid:)
7
+ def initialize(pid: nil, path: nil)
9
8
  @pid = pid
10
- @context = Clib.bcc_usdt_new_frompid(pid, nil)
9
+ @path = path
10
+ if pid
11
+ @context = Clib.bcc_usdt_new_frompid(pid, path)
12
+ elsif path
13
+ @context = Clib.bcc_usdt_new_frompath(path)
14
+ else
15
+ raise "Either a pid or a binary path must be specified"
16
+ end
11
17
  if !@context || @context.null?
12
18
  raise SystemCallError.new(Fiddle.last_error)
13
19
  end
14
20
  end
15
- attr_reader :pid, :context
21
+ attr_reader :pid, :path, :context
16
22
 
17
23
  def enable_probe(probe:, fn_name:)
18
24
  ret = Clib.bcc_usdt_enable_probe(@context, probe, fn_name)
@@ -33,5 +39,16 @@ module RbBCC
33
39
 
34
40
  return probes
35
41
  end
42
+
43
+ private
44
+ def __del__
45
+ lambda { Clib.bcc_usdt_close(@context); Util.debug("USDT GC'ed.") }
46
+ end
47
+ end
48
+ end
49
+
50
+ at_exit do
51
+ ObjectSpace.each_object(RbBCC::USDT) do |o|
52
+ o.send(:__del__).call
36
53
  end
37
54
  end
@@ -1,3 +1,3 @@
1
1
  module RbBCC
2
- VERSION = "0.3.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -7,6 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.version = RbBCC::VERSION
8
8
  spec.authors = ["Uchio Kondo"]
9
9
  spec.email = ["udzura@udzura.jp"]
10
+ spec.license = "Apache-2.0"
10
11
 
11
12
  spec.summary = %q{BCC port for MRI}
12
13
  spec.description = %q{BCC port for MRI. See https://github.com/iovisor/bcc}
@@ -20,9 +21,4 @@ Gem::Specification.new do |spec|
20
21
  #spec.bindir = "exe"
21
22
  #spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
23
  spec.require_paths = ["lib"]
23
-
24
- spec.add_development_dependency "bundler", "~> 2.0"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "pry"
27
- spec.add_development_dependency "minitest"
28
24
  end
metadata CHANGED
@@ -1,71 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbbcc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uchio Kondo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-20 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: pry
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
+ dependencies: []
69
13
  description: BCC port for MRI. See https://github.com/iovisor/bcc
70
14
  email:
71
15
  - udzura@udzura.jp
@@ -85,7 +29,29 @@ files:
85
29
  - bin/console
86
30
  - bin/setup
87
31
  - docs/README.md
32
+ - docs/answers/01-hello-world.rb
33
+ - docs/answers/02-sys_sync.rb
34
+ - docs/answers/03-hello_fields.rb
35
+ - docs/answers/04-sync_timing.rb
36
+ - docs/answers/05-sync_count.rb
37
+ - docs/answers/06-disksnoop.rb
38
+ - docs/answers/07-hello_perf_output.rb
39
+ - docs/answers/08-sync_perf_output.rb
40
+ - docs/answers/09-bitehist.rb
41
+ - docs/answers/10-disklatency.rb
42
+ - docs/answers/11-vfsreadlat.c
43
+ - docs/answers/11-vfsreadlat.rb
44
+ - docs/answers/12-urandomread.rb
45
+ - docs/answers/13-disksnoop_fixed.rb
46
+ - docs/answers/14-strlen_count.rb
47
+ - docs/answers/15-nodejs_http_server.rb
48
+ - docs/answers/16-task_switch.c
49
+ - docs/answers/16-task_switch.rb
50
+ - docs/answers/node-server.js
88
51
  - docs/getting_started.md
52
+ - docs/projects_using_rbbcc.md
53
+ - docs/tutorial_bcc_ruby_developer.md
54
+ - docs/tutorial_bcc_ruby_developer_japanese.md
89
55
  - examples/bitehist.rb
90
56
  - examples/charty/Gemfile
91
57
  - examples/charty/Gemfile.lock
@@ -99,6 +65,11 @@ files:
99
65
  - examples/hello_world.rb
100
66
  - examples/kvm_hypercall.rb
101
67
  - examples/mallocstack.rb
68
+ - examples/networking/http_filter/http-parse-simple.c
69
+ - examples/networking/http_filter/http-parse-simple.rb
70
+ - examples/ruby_usdt.rb
71
+ - examples/sbrk_trace.rb
72
+ - examples/tools/bashreadline.rb
102
73
  - examples/tools/execsnoop.rb
103
74
  - examples/tools/runqlat.rb
104
75
  - examples/urandomread-explicit.rb
@@ -110,6 +81,7 @@ files:
110
81
  - lib/rbbcc/clib.rb
111
82
  - lib/rbbcc/consts.rb
112
83
  - lib/rbbcc/cpu_helper.rb
84
+ - lib/rbbcc/debug.rb
113
85
  - lib/rbbcc/disp_helper.rb
114
86
  - lib/rbbcc/fiddle_ext.rb
115
87
  - lib/rbbcc/symbol_cache.rb
@@ -120,7 +92,8 @@ files:
120
92
  - rbbcc.gemspec
121
93
  - semaphore.sh
122
94
  homepage: https://github.com/udzura/rbbcc
123
- licenses: []
95
+ licenses:
96
+ - Apache-2.0
124
97
  metadata: {}
125
98
  post_install_message:
126
99
  rdoc_options: []
@@ -137,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
110
  - !ruby/object:Gem::Version
138
111
  version: '0'
139
112
  requirements: []
140
- rubygems_version: 3.0.3
113
+ rubygems_version: 3.1.2
141
114
  signing_key:
142
115
  specification_version: 4
143
116
  summary: BCC port for MRI