ruby-dtrace 0.2.8 → 0.3.0

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