rbbcc 0.3.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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