ruby-dtrace 0.2.8 → 0.3.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.
@@ -0,0 +1,177 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2008 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ #include <errno.h>
8
+ #include <stdlib.h>
9
+ #include <sys/mman.h>
10
+
11
+ RUBY_EXTERN VALUE eDtraceException;
12
+
13
+ #define ARGC_MAX 6
14
+ #define FUNC_SIZE 256
15
+ #define IS_ENABLED_FUNC_LEN 12
16
+
17
+ void install_insns(uint8_t *probe_insns, uint8_t *insns, int count)
18
+ {
19
+ int i,j;
20
+ uint8_t *ip;
21
+ ip = insns;
22
+ for (j = 1; j <= count; j++) {
23
+ for (i = 0; i < 4; i++) {
24
+ *ip++ = *probe_insns++;
25
+ }
26
+ }
27
+ }
28
+
29
+ /* :nodoc: */
30
+ VALUE dtraceprobe_init(VALUE self, VALUE rargc)
31
+ {
32
+ dtrace_probe_t *probe;
33
+ uint8_t *ip;
34
+ int i;
35
+ int argc = FIX2INT(rargc);
36
+ uint8_t probe_insns[FUNC_SIZE];
37
+
38
+ Data_Get_Struct(self, dtrace_probe_t, probe);
39
+
40
+ /* First initialise the is_enabled tracepoint */
41
+ uint8_t insns[FUNC_SIZE] = {
42
+ 0x55, 0x48, 0x89, 0xe5,
43
+ 0x48, 0x33, 0xc0, 0x90,
44
+ 0x90, 0xc9, 0xc3, 0x00
45
+ };
46
+
47
+ if (argc <= ARGC_MAX) {
48
+ {
49
+ uint8_t probe_insns[FUNC_SIZE] = {
50
+ 0x55, 0x48, 0x89, 0xe5,
51
+ 0x90, 0x0f, 0x1f, 0x40,
52
+ 0x00, 0xc9, 0xc3, 0x0f,
53
+ 0x1f, 0x44, 0x00, 0x00
54
+ };
55
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 4);
56
+ }
57
+ }
58
+ else {
59
+ rb_raise(eDtraceException, "probe argc max is %d", ARGC_MAX);
60
+ return Qnil;
61
+ }
62
+
63
+ /* allocate memory on a page boundary, for mprotect */
64
+ probe->func = (void *)valloc(FUNC_SIZE);
65
+ if (probe->func < 0) {
66
+ rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
67
+ return Qnil;
68
+ }
69
+
70
+ if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
71
+ rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
72
+ return Qnil;
73
+ }
74
+
75
+ if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
76
+ rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
77
+ return Qnil;
78
+ }
79
+
80
+ return self;
81
+ }
82
+
83
+ VALUE dtraceprobe_free(void *arg)
84
+ {
85
+ dtrace_probe_t *probe = (dtrace_probe_t *)arg;
86
+
87
+ if (probe) {
88
+ free(probe->func);
89
+ free(probe);
90
+ }
91
+ }
92
+
93
+ VALUE dtraceprobe_alloc(VALUE klass)
94
+ {
95
+ VALUE obj;
96
+ dtrace_probe_t *probe;
97
+
98
+ probe = ALLOC(dtrace_probe_t);
99
+ if (!probe) {
100
+ rb_raise(eDtraceException, "alloc failed");
101
+ return Qnil;
102
+ }
103
+
104
+ /* no mark function: no ruby objects hung off this struct */
105
+ obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
106
+ return obj;
107
+ }
108
+
109
+ VALUE dtraceprobe_addr(VALUE self)
110
+ {
111
+ dtrace_probe_t *probe;
112
+
113
+ Data_Get_Struct(self, dtrace_probe_t, probe);
114
+ return LL2NUM((uint64_t)(probe->func));
115
+ }
116
+
117
+ VALUE dtraceprobe_is_enabled(VALUE self)
118
+ {
119
+ dtrace_probe_t *probe;
120
+
121
+ Data_Get_Struct(self, dtrace_probe_t, probe);
122
+ return ((int)(*probe->func)()) ? Qtrue : Qfalse;
123
+ }
124
+
125
+ VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
126
+ dtrace_probe_t *probe;
127
+ int i;
128
+ void *argv[ARGC_MAX]; // probe argc max for now.
129
+ void (*func)();
130
+
131
+ Data_Get_Struct(self, dtrace_probe_t, probe);
132
+
133
+ /* munge Ruby values to either char *s or ints. */
134
+ for (i = 0; i < argc; i++) {
135
+ switch (TYPE(ruby_argv[i])) {
136
+ case T_STRING:
137
+ argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
138
+ break;
139
+ case T_FIXNUM:
140
+ argv[i] = (void *)FIX2INT(ruby_argv[i]);
141
+ break;
142
+ default:
143
+ rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
144
+ break;
145
+ }
146
+ }
147
+
148
+ func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
149
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
150
+
151
+ return Qnil;
152
+ }
153
+
154
+ /*
155
+ * Returns the offset for this probe in the PROFFS section, based on
156
+ * the location of the DOF, and the location of this probe.
157
+ */
158
+ VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
159
+ {
160
+ void *probe_addr;
161
+ int offset;
162
+ offset = 6 + IS_ENABLED_FUNC_LEN;
163
+ probe_addr = (void *)NUM2LL(rb_funcall(self, rb_intern("addr"), 0));
164
+ return INT2FIX((uint64_t)probe_addr - (uint64_t)NUM2LL(file_addr) + offset);
165
+ }
166
+
167
+ /*
168
+ * Returns the offset for this probe's is-enabled tracepoint in the
169
+ * PRENOFFS section, based on the location of the DOF, and the
170
+ * location of this probe.
171
+ */
172
+ VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE file_addr)
173
+ {
174
+ void *probe_addr;
175
+ probe_addr = (void *)NUM2LL(rb_funcall(self, rb_intern("addr"), 0));
176
+ return INT2FIX((uint64_t)probe_addr - (uint64_t)NUM2LL(file_addr) + 6);
177
+ }
@@ -0,0 +1,159 @@
1
+ /* Ruby-Dtrace
2
+ * (c) 2008 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ #include <errno.h>
8
+ #include <stdlib.h>
9
+ #include <sys/mman.h>
10
+
11
+ RUBY_EXTERN VALUE eDtraceException;
12
+
13
+ #define ARGC_MAX 6
14
+ #define FUNC_SIZE 256
15
+ #define IS_ENABLED_FUNC_LEN 8
16
+
17
+ void install_insns(uint8_t *probe_insns, uint8_t *insns, int count)
18
+ {
19
+ int i,j;
20
+ uint8_t *ip;
21
+ ip = insns;
22
+ for (j = 1; j <= count; j++) {
23
+ for (i = 0; i < 4; i++) {
24
+ *ip++ = *probe_insns++;
25
+ }
26
+ }
27
+ }
28
+
29
+ /* :nodoc: */
30
+ VALUE dtraceprobe_init(VALUE self, VALUE rargc)
31
+ {
32
+ dtrace_probe_t *probe;
33
+ uint8_t *ip;
34
+ int i;
35
+ int argc = FIX2INT(rargc);
36
+ uint8_t probe_insns[FUNC_SIZE];
37
+
38
+ Data_Get_Struct(self, dtrace_probe_t, probe);
39
+
40
+ /* First initialise the is_enabled tracepoint */
41
+ uint8_t insns[FUNC_SIZE] = {
42
+ 0x48, 0x33, 0xc0, 0xc3,
43
+ 0x90, 0x00, 0x00, 0x00
44
+ };
45
+
46
+ if (argc <= ARGC_MAX) {
47
+ {
48
+ uint8_t probe_insns[FUNC_SIZE] = {
49
+ 0xc3, 0x90, 0x90, 0x90,
50
+ 0x90, 0x00, 0x00, 0x00
51
+ };
52
+ install_insns(probe_insns, &insns[IS_ENABLED_FUNC_LEN], 2);
53
+ }
54
+ }
55
+ else {
56
+ rb_raise(eDtraceException, "probe argc max is %d", ARGC_MAX);
57
+ return Qnil;
58
+ }
59
+
60
+ /* allocate memory on a page boundary, for mprotect */
61
+ probe->func = (void *)memalign(PAGESIZE, FUNC_SIZE);
62
+ if (probe->func < 0) {
63
+ rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
64
+ return Qnil;
65
+ }
66
+
67
+ if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
68
+ rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
69
+ return Qnil;
70
+ }
71
+
72
+ if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
73
+ rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
74
+ return Qnil;
75
+ }
76
+
77
+ return self;
78
+ }
79
+
80
+ VALUE dtraceprobe_free(void *arg)
81
+ {
82
+ dtrace_probe_t *probe = (dtrace_probe_t *)arg;
83
+
84
+ if (probe) {
85
+ free(probe->func);
86
+ free(probe);
87
+ }
88
+ }
89
+
90
+ VALUE dtraceprobe_alloc(VALUE klass)
91
+ {
92
+ VALUE obj;
93
+ dtrace_probe_t *probe;
94
+
95
+ probe = ALLOC(dtrace_probe_t);
96
+ if (!probe) {
97
+ rb_raise(eDtraceException, "alloc failed");
98
+ return Qnil;
99
+ }
100
+
101
+ /* no mark function: no ruby objects hung off this struct */
102
+ obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
103
+ return obj;
104
+ }
105
+
106
+ VALUE dtraceprobe_addr(VALUE self)
107
+ {
108
+ dtrace_probe_t *probe;
109
+
110
+ Data_Get_Struct(self, dtrace_probe_t, probe);
111
+ return LL2NUM((uint64_t)(probe->func));
112
+ }
113
+
114
+ VALUE dtraceprobe_is_enabled(VALUE self)
115
+ {
116
+ dtrace_probe_t *probe;
117
+
118
+ Data_Get_Struct(self, dtrace_probe_t, probe);
119
+ return ((int)(*probe->func)()) ? Qtrue : Qfalse;
120
+ }
121
+
122
+ VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
123
+ dtrace_probe_t *probe;
124
+ int i;
125
+ void *argv[ARGC_MAX]; // probe argc max for now.
126
+ void (*func)();
127
+
128
+ Data_Get_Struct(self, dtrace_probe_t, probe);
129
+
130
+ /* munge Ruby values to either char *s or ints. */
131
+ for (i = 0; i < argc; i++) {
132
+ switch (TYPE(ruby_argv[i])) {
133
+ case T_STRING:
134
+ argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
135
+ break;
136
+ case T_FIXNUM:
137
+ argv[i] = (void *)FIX2INT(ruby_argv[i]);
138
+ break;
139
+ default:
140
+ rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
141
+ break;
142
+ }
143
+ }
144
+
145
+ func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
146
+ (void)(*func)(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
147
+
148
+ return Qnil;
149
+ }
150
+
151
+ VALUE dtraceprobe_probe_offset(VALUE self, VALUE rfile, VALUE argc)
152
+ {
153
+ return INT2FIX(IS_ENABLED_FUNC_LEN);
154
+ }
155
+
156
+ VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE rfile)
157
+ {
158
+ return INT2FIX(1);
159
+ }
@@ -1,9 +1,9 @@
1
1
  #
2
2
  # Ruby-Dtrace
3
- # (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ # (c) 2007-2011 Chris Andrews <chris@nodnol.org>
4
4
  #
5
5
 
6
6
  class Dtrace
7
- VERSION = '0.2.8'
7
+ VERSION = '0.3.0'
8
8
  end
9
9
 
File without changes
@@ -30,7 +30,9 @@ class TestDofProviders < Test::Unit::TestCase
30
30
  :addr => 0,
31
31
  :nargc => 0,
32
32
  :func => 6,
33
- :xargc => 0
33
+ :xargc => 0,
34
+ :nargv => 0,
35
+ :xargv => 0
34
36
  },
35
37
  ]
36
38
  f.sections << s
@@ -229,7 +231,9 @@ class TestDofProviders < Test::Unit::TestCase
229
231
  :addr => 0,
230
232
  :nargc => 0,
231
233
  :func => 6,
232
- :xargc => 0
234
+ :xargc => 0,
235
+ :nargv => 0,
236
+ :xargv => 0
233
237
  },
234
238
  ]
235
239
  f.sections << s
@@ -38,7 +38,9 @@ class TestDofStrtabs < Test::Unit::TestCase
38
38
  :offidx => 0,
39
39
  :addr => 0,
40
40
  :nargc => 0,
41
- :xargc => 0
41
+ :xargc => 0,
42
+ :nargv => 0,
43
+ :xargv => 0
42
44
  },
43
45
  ]
44
46
  f.sections << s
@@ -47,7 +47,9 @@ class TestDtraceProbe < Test::Unit::TestCase
47
47
  :addr => addr,
48
48
  :nargc => 0,
49
49
  :func => 6,
50
- :xargc => 0
50
+ :xargc => 0,
51
+ :nargv => 0,
52
+ :xargv => 0
51
53
  },
52
54
  ]
53
55
  f.sections << s
@@ -316,7 +318,9 @@ EOD
316
318
  :addr => addr,
317
319
  :nargc => 0,
318
320
  :func => 6,
319
- :xargc => 0
321
+ :xargc => 0,
322
+ :nargv => 0,
323
+ :xargv => 0
320
324
  },
321
325
  ]
322
326
  f.sections << s
@@ -185,7 +185,7 @@ EOD
185
185
 
186
186
  end
187
187
 
188
- def test_all_argcs
188
+ def test_six_argcs
189
189
  Dtrace::Provider.create :foo5 do |p|
190
190
  p.probe :bar1, :integer
191
191
  p.probe :bar2, :integer, :integer
@@ -195,10 +195,6 @@ EOD
195
195
  :integer
196
196
  p.probe :bar6, :integer, :integer, :integer, :integer,
197
197
  :integer, :integer
198
- p.probe :bar7, :integer, :integer, :integer, :integer,
199
- :integer, :integer, :integer
200
- p.probe :bar8, :integer, :integer, :integer, :integer,
201
- :integer, :integer, :integer, :integer
202
198
  end
203
199
 
204
200
  t = Dtrace.new
@@ -254,28 +250,6 @@ foo5*:ruby:*:bar6
254
250
  trace(arg5);
255
251
  }
256
252
 
257
- foo5*:ruby:*:bar7
258
- {
259
- trace(arg0);
260
- trace(arg1);
261
- trace(arg2);
262
- trace(arg3);
263
- trace(arg4);
264
- trace(arg5);
265
- trace(arg6);
266
- }
267
-
268
- foo5*:ruby:*:bar8
269
- {
270
- trace(arg0);
271
- trace(arg1);
272
- trace(arg2);
273
- trace(arg3);
274
- trace(arg4);
275
- trace(arg5);
276
- trace(arg6);
277
- trace(arg7);
278
- }
279
253
  EOD
280
254
 
281
255
  prog = t.compile progtext
@@ -301,19 +275,13 @@ EOD
301
275
  Dtrace::Probe::Foo5.bar6 do |p|
302
276
  p.fire(61, 62, 63, 64, 65, 66)
303
277
  end
304
- Dtrace::Probe::Foo5.bar7 do |p|
305
- p.fire(71, 72, 73, 74, 75, 76, 77)
306
- end
307
- Dtrace::Probe::Foo5.bar8 do |p|
308
- p.fire(81, 82, 83, 84, 85, 86, 87, 88)
309
- end
310
278
 
311
279
  data = []
312
280
  c.consume_once do |d|
313
281
  data << d
314
282
  end
315
-
316
- assert_equal 8, data.length
283
+
284
+ assert_equal 6, data.length
317
285
 
318
286
  assert_equal 11, data[0].data[0].value
319
287
 
@@ -341,30 +309,13 @@ EOD
341
309
  assert_equal 64, data[5].data[3].value
342
310
  assert_equal 65, data[5].data[4].value
343
311
  assert_equal 66, data[5].data[5].value
344
-
345
- assert_equal 71, data[6].data[0].value
346
- assert_equal 72, data[6].data[1].value
347
- assert_equal 73, data[6].data[2].value
348
- assert_equal 74, data[6].data[3].value
349
- assert_equal 75, data[6].data[4].value
350
- assert_equal 76, data[6].data[5].value
351
- assert_equal 77, data[6].data[6].value
352
-
353
- assert_equal 81, data[7].data[0].value
354
- assert_equal 82, data[7].data[1].value
355
- assert_equal 83, data[7].data[2].value
356
- assert_equal 84, data[7].data[3].value
357
- assert_equal 85, data[7].data[4].value
358
- assert_equal 86, data[7].data[5].value
359
- assert_equal 87, data[7].data[6].value
360
- assert_equal 88, data[7].data[7].value
361
312
 
362
313
  end
363
314
 
364
- def test_all_eight_args_chars
315
+ def test_all_six_args_chars
365
316
  Dtrace::Provider.create :foo6 do |p|
366
- p.probe :bar, :string, :string, :string, :string,
367
- :string, :string, :string, :string
317
+ p.probe :bar,
318
+ :string, :string, :string, :string, :string, :string
368
319
  end
369
320
 
370
321
  t = Dtrace.new
@@ -379,8 +330,6 @@ foo6*:ruby:*:bar
379
330
  trace(copyinstr(arg3));
380
331
  trace(copyinstr(arg4));
381
332
  trace(copyinstr(arg5));
382
- trace(copyinstr(arg6));
383
- trace(copyinstr(arg7));
384
333
  }
385
334
  EOD
386
335
 
@@ -390,8 +339,7 @@ EOD
390
339
  c = Dtrace::Consumer.new(t)
391
340
 
392
341
  Dtrace::Probe::Foo6.bar do |p|
393
- p.fire('one', 'two', 'three', 'four',
394
- 'five', 'six', 'seven', 'eight')
342
+ p.fire('one', 'two', 'three', 'four', 'five', 'six')
395
343
  end
396
344
 
397
345
  data = []
@@ -406,9 +354,6 @@ EOD
406
354
  assert_equal 'four', data[0].data[3].value
407
355
  assert_equal 'five', data[0].data[4].value
408
356
  assert_equal 'six', data[0].data[5].value
409
- assert_equal 'seven', data[0].data[6].value
410
- assert_equal 'eight', data[0].data[7].value
411
-
412
357
  end
413
-
358
+
414
359
  end