ruby-dtrace 0.0.6 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +21 -0
- data/Manifest.txt +86 -19
- data/README.txt +48 -6
- data/Rakefile +61 -20
- data/examples/scsi.rb +1 -1
- data/ext/dof/Makefile +154 -0
- data/ext/dof/constants.c +57 -0
- data/ext/dof/dof.h +56 -0
- data/ext/dof/dof_api.c +58 -0
- data/ext/dof/dof_helper.c +82 -0
- data/ext/dof/extconf.rb +4 -0
- data/ext/dof/file.c +90 -0
- data/ext/dof/generator.c +9 -0
- data/ext/dof/header.c +79 -0
- data/ext/dof/mkmf.log +10 -0
- data/ext/dof/parser.c +415 -0
- data/ext/dof/parser.h +10 -0
- data/ext/dof/section.c +312 -0
- data/ext/dtrace_aggdata.c +2 -2
- data/ext/dtrace_api.c +46 -34
- data/ext/dtrace_api.h +31 -7
- data/ext/dtrace_bufdata.c +3 -3
- data/ext/dtrace_hdl.c +66 -3
- data/ext/dtrace_probedata.c +4 -4
- data/ext/{dtrace_probe.c → dtrace_probedesc.c} +7 -7
- data/ext/extconf.rb +25 -0
- data/ext/i386-darwin/dtrace_probe.c +278 -0
- data/ext/i386-solaris/dtrace_probe.c +225 -0
- data/ext/stubs.txt +78 -0
- data/lib/dtrace.rb +34 -13
- data/lib/dtrace/aggregate.rb +40 -0
- data/lib/dtrace/aggregateset.rb +19 -0
- data/lib/dtrace/consumer.rb +174 -0
- data/lib/dtrace/data.rb +82 -0
- data/lib/dtrace/dof.rb +8 -0
- data/lib/dtrace/dof/file.rb +64 -0
- data/lib/dtrace/dof/section.rb +75 -0
- data/lib/dtrace/dof/section/strtab.rb +28 -0
- data/lib/{dtraceprintfrecord.rb → dtrace/printfrecord.rb} +4 -2
- data/lib/dtrace/probe.rb +3 -6
- data/lib/dtrace/probedata.rb +23 -0
- data/lib/dtrace/probedesc.rb +15 -0
- data/lib/dtrace/provider.rb +190 -169
- data/lib/dtrace/provider/klass.rb +33 -0
- data/lib/dtrace/provider/probedef.rb +24 -0
- data/lib/{dtracerecord.rb → dtrace/record.rb} +4 -2
- data/lib/{dtracestackrecord.rb → dtrace/stackrecord.rb} +10 -8
- data/lib/dtrace/version.rb +9 -0
- data/lib/dtraceconsumer.rb +3 -167
- data/plugin/dtrace/lib/dtracer.rb +4 -4
- data/test/apple-dof +0 -0
- data/test/disabled_probe_effect.txt +19 -0
- data/test/dof +0 -0
- data/test/dof2 +0 -0
- data/test/test_disabled_probe_effect.rb +56 -0
- data/test/test_dof_generator.rb +142 -0
- data/test/test_dof_helper.rb +106 -0
- data/test/test_dof_parser.rb +27 -0
- data/test/test_dof_providers.rb +278 -0
- data/test/test_dof_strtabs.rb +98 -0
- data/test/test_dtrace.rb +67 -1
- data/test/test_dtrace_aggregates.rb +5 -5
- data/test/test_dtrace_drops_errors.rb +5 -5
- data/test/test_dtrace_probe.rb +385 -0
- data/test/test_dtrace_probes.rb +414 -0
- data/test/test_dtrace_processes.rb +2 -2
- data/test/test_dtrace_profile.rb +12 -12
- data/test/test_dtrace_provider.rb +138 -0
- data/test/test_dtrace_repeat.rb +1 -1
- data/test/test_dtrace_rubyprobe.rb +3 -1
- data/test/test_dtrace_typefilter.rb +9 -9
- data/test/test_legacy_consumer.rb +56 -0
- metadata +112 -71
- data/lib/dtrace/provider/osx.rb +0 -25
- data/lib/dtrace/provider/solaris.rb +0 -29
- data/lib/dtraceaggregate.rb +0 -37
- data/lib/dtraceaggregateset.rb +0 -17
- data/lib/dtracedata.rb +0 -80
- data/lib/dtraceprobe.rb +0 -13
- data/lib/dtraceprobedata.rb +0 -21
- data/test/test_dynusdt.rb +0 -135
@@ -0,0 +1,278 @@
|
|
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 FUNC_SIZE 128 /* 32 bytes of is_enabled, plus then good for 16
|
14
|
+
arguments: 16 + 7 * argc */
|
15
|
+
#define IS_ENABLED_FUNC_LEN 32
|
16
|
+
|
17
|
+
/* :nodoc: */
|
18
|
+
VALUE
|
19
|
+
dtraceprobe_init(VALUE self, VALUE rargc)
|
20
|
+
{
|
21
|
+
dtrace_probe_t *probe;
|
22
|
+
uint8_t *ip;
|
23
|
+
int i;
|
24
|
+
int argc = FIX2INT(rargc);
|
25
|
+
|
26
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
27
|
+
|
28
|
+
/* First initialise the is_enabled tracepoint */
|
29
|
+
uint8_t insns[FUNC_SIZE] = {
|
30
|
+
0x55, 0x89, 0xe5, 0x83, 0xec, 0x08,
|
31
|
+
0x33, 0xc0,
|
32
|
+
0x90, 0x90, 0x90,
|
33
|
+
0xc9, 0xc3
|
34
|
+
};
|
35
|
+
|
36
|
+
#define OP_PUSHL_EBP 0x55
|
37
|
+
#define OP_MOVL_ESP_EBP_U 0x89
|
38
|
+
#define OP_MOVL_ESP_EBP_L 0xe5
|
39
|
+
#define OP_SUBL_N_ESP_U 0x83
|
40
|
+
#define OP_SUBL_N_ESP_L 0xec
|
41
|
+
#define OP_PUSHL_N_EBP_U 0xff
|
42
|
+
#define OP_PUSHL_N_EBP_L 0x75
|
43
|
+
#define OP_NOP 0x90
|
44
|
+
#define OP_ADDL_ESP_U 0x83
|
45
|
+
#define OP_ADDL_ESP_L 0xc4
|
46
|
+
#define OP_LEAVE 0xc9
|
47
|
+
#define OP_RET 0xc3
|
48
|
+
#define OP_MOVL_EAX_U 0x8b
|
49
|
+
#define OP_MOVL_EAX_L 0x45
|
50
|
+
#define OP_MOVL_ESP 0x89
|
51
|
+
|
52
|
+
/* Set up probe function */
|
53
|
+
ip = insns + IS_ENABLED_FUNC_LEN;
|
54
|
+
|
55
|
+
*ip++ = OP_PUSHL_EBP;
|
56
|
+
*ip++ = OP_MOVL_ESP_EBP_U;
|
57
|
+
*ip++ = OP_MOVL_ESP_EBP_L;
|
58
|
+
*ip++ = OP_SUBL_N_ESP_U;
|
59
|
+
*ip++ = OP_SUBL_N_ESP_L;
|
60
|
+
|
61
|
+
switch(argc) {
|
62
|
+
case 0:
|
63
|
+
case 1:
|
64
|
+
case 2:
|
65
|
+
case 3:
|
66
|
+
case 4:
|
67
|
+
case 5:
|
68
|
+
case 6:
|
69
|
+
*ip++ = 0x18;
|
70
|
+
break;
|
71
|
+
case 7:
|
72
|
+
case 8:
|
73
|
+
*ip++ = 0x28;
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
|
77
|
+
/* args */
|
78
|
+
for (i = (4*argc - 4); i >= 0; i -= 4) {
|
79
|
+
/* mov 0xN(%ebp),%eax */
|
80
|
+
*ip++ = OP_MOVL_EAX_U;
|
81
|
+
*ip++ = OP_MOVL_EAX_L;
|
82
|
+
*ip++ = i + 8;
|
83
|
+
/* mov %eax,N(%esp) */
|
84
|
+
*ip++ = OP_MOVL_ESP;
|
85
|
+
if (i > 0) {
|
86
|
+
*ip++ = 0x44;
|
87
|
+
*ip++ = 0x24;
|
88
|
+
*ip++ = i;
|
89
|
+
}
|
90
|
+
else {
|
91
|
+
*ip++ = 0x04;
|
92
|
+
*ip++ = 0x24;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
/* tracepoint */
|
97
|
+
*ip++ = 0x90;
|
98
|
+
*ip++ = 0x0f;
|
99
|
+
*ip++ = 0x1f;
|
100
|
+
*ip++ = 0x40;
|
101
|
+
*ip++ = 0x00;
|
102
|
+
|
103
|
+
/* ret */
|
104
|
+
*ip++ = OP_LEAVE;
|
105
|
+
*ip++ = OP_RET;
|
106
|
+
|
107
|
+
/* allocate memory on a page boundary, for mprotect */
|
108
|
+
probe->func = (void *)valloc(FUNC_SIZE);
|
109
|
+
if (probe->func < 0) {
|
110
|
+
rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
|
111
|
+
return Qnil;
|
112
|
+
}
|
113
|
+
|
114
|
+
if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
|
115
|
+
rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
|
116
|
+
return Qnil;
|
117
|
+
}
|
118
|
+
|
119
|
+
if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
|
120
|
+
rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
|
121
|
+
return Qnil;
|
122
|
+
}
|
123
|
+
|
124
|
+
return self;
|
125
|
+
}
|
126
|
+
|
127
|
+
VALUE dtraceprobe_free(void *arg)
|
128
|
+
{
|
129
|
+
dtrace_probe_t *probe = (dtrace_probe_t *)arg;
|
130
|
+
|
131
|
+
if (probe) {
|
132
|
+
free(probe->func);
|
133
|
+
free(probe);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
VALUE dtraceprobe_alloc(VALUE klass)
|
138
|
+
{
|
139
|
+
VALUE obj;
|
140
|
+
dtrace_probe_t *probe;
|
141
|
+
|
142
|
+
probe = ALLOC(dtrace_probe_t);
|
143
|
+
if (!probe) {
|
144
|
+
rb_raise(eDtraceException, "alloc failed");
|
145
|
+
return Qnil;
|
146
|
+
}
|
147
|
+
|
148
|
+
/* no mark function: no ruby objects hung off this struct */
|
149
|
+
obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
|
150
|
+
return obj;
|
151
|
+
}
|
152
|
+
|
153
|
+
/*
|
154
|
+
* Returns the address of the probe's generated code.
|
155
|
+
*/
|
156
|
+
VALUE dtraceprobe_addr(VALUE self)
|
157
|
+
{
|
158
|
+
dtrace_probe_t *probe;
|
159
|
+
|
160
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
161
|
+
return INT2FIX(probe->func);
|
162
|
+
}
|
163
|
+
|
164
|
+
/*
|
165
|
+
* Returns whether or not this probe is currently enabled, by invoking
|
166
|
+
* the is-enabled tracepoint attached to the probe.
|
167
|
+
*/
|
168
|
+
VALUE dtraceprobe_is_enabled(VALUE self)
|
169
|
+
{
|
170
|
+
dtrace_probe_t *probe;
|
171
|
+
|
172
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
173
|
+
return ((int)(*probe->func)()) ? Qtrue : Qfalse;
|
174
|
+
}
|
175
|
+
|
176
|
+
/*
|
177
|
+
* Fires the probe, converting arguments based on the data provided -
|
178
|
+
* no validation is done against the probe's declared types.
|
179
|
+
*/
|
180
|
+
VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
|
181
|
+
dtrace_probe_t *probe;
|
182
|
+
int i;
|
183
|
+
void *argv[8]; // probe argc max for now.
|
184
|
+
void (*func)();
|
185
|
+
|
186
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
187
|
+
|
188
|
+
/* munge Ruby values to either char *s or ints. */
|
189
|
+
for (i = 0; i < argc; i++) {
|
190
|
+
switch (TYPE(ruby_argv[i])) {
|
191
|
+
case T_STRING:
|
192
|
+
argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
|
193
|
+
break;
|
194
|
+
case T_FIXNUM:
|
195
|
+
argv[i] = (void *)FIX2INT(ruby_argv[i]);
|
196
|
+
break;
|
197
|
+
default:
|
198
|
+
rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
|
199
|
+
break;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
|
204
|
+
|
205
|
+
switch (argc) {
|
206
|
+
case 0:
|
207
|
+
(void)(*func)();
|
208
|
+
break;
|
209
|
+
case 1:
|
210
|
+
(void)(*func)(argv[0]);
|
211
|
+
break;
|
212
|
+
case 2:
|
213
|
+
(void)(*func)(argv[0], argv[1]);
|
214
|
+
break;
|
215
|
+
case 3:
|
216
|
+
(void)(*func)(argv[0], argv[1], argv[2]);
|
217
|
+
break;
|
218
|
+
case 4:
|
219
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3]);
|
220
|
+
break;
|
221
|
+
case 5:
|
222
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
223
|
+
argv[4]);
|
224
|
+
break;
|
225
|
+
case 6:
|
226
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
227
|
+
argv[4], argv[5]);
|
228
|
+
break;
|
229
|
+
case 7:
|
230
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
231
|
+
argv[4], argv[5], argv[6]);
|
232
|
+
break;
|
233
|
+
case 8:
|
234
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
235
|
+
argv[4], argv[5], argv[6], argv[7]);
|
236
|
+
break;
|
237
|
+
default:
|
238
|
+
rb_raise(eDtraceException, "probe argc max is 8");
|
239
|
+
break;
|
240
|
+
}
|
241
|
+
|
242
|
+
return Qnil;
|
243
|
+
}
|
244
|
+
|
245
|
+
/*
|
246
|
+
* Returns the offset for this probe in the PROFFS section, based on
|
247
|
+
* the location of the DOF, and the location of this probe.
|
248
|
+
*/
|
249
|
+
VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
|
250
|
+
{
|
251
|
+
void *probe_addr;
|
252
|
+
int offset;
|
253
|
+
probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
|
254
|
+
switch FIX2INT(argc) {
|
255
|
+
case 0:
|
256
|
+
offset = 40; /* 32 + 6 + 2 */
|
257
|
+
break;
|
258
|
+
case 1:
|
259
|
+
offset = 46; /* 32 + 6 + 6 + 2 */
|
260
|
+
break;
|
261
|
+
default:
|
262
|
+
offset = 46 + (FIX2INT(argc)-1) * 7; /* 32 + 6 + 6 + 7 per subsequent arg + 2 */
|
263
|
+
break;
|
264
|
+
}
|
265
|
+
return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + offset);
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* Returns the offset for this probe's is-enabled tracepoint in the
|
270
|
+
* PRENOFFS section, based on the location of the DOF, and the
|
271
|
+
* location of this probe.
|
272
|
+
*/
|
273
|
+
VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE file_addr)
|
274
|
+
{
|
275
|
+
void *probe_addr;
|
276
|
+
probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
|
277
|
+
return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + 8);
|
278
|
+
}
|
@@ -0,0 +1,225 @@
|
|
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 FUNC_SIZE 96 /* 32 bytes of is_enabled, plus then good for 16
|
14
|
+
arguments: 16 + 3 * argc */
|
15
|
+
#define IS_ENABLED_FUNC_LEN 32
|
16
|
+
|
17
|
+
/* :nodoc: */
|
18
|
+
VALUE dtraceprobe_init(VALUE self, VALUE rargc)
|
19
|
+
{
|
20
|
+
dtrace_probe_t *probe;
|
21
|
+
uint8_t *ip;
|
22
|
+
int i;
|
23
|
+
int argc = FIX2INT(rargc);
|
24
|
+
|
25
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
26
|
+
|
27
|
+
/* First initialise the is_enabled tracepoint */
|
28
|
+
uint8_t insns[FUNC_SIZE] = {
|
29
|
+
0x55, 0x89, 0xe5, 0x83, 0xec, 0x08,
|
30
|
+
0x33, 0xc0,
|
31
|
+
0x90, 0x90, 0x90,
|
32
|
+
0x89, 0x45, 0xfc, 0x83, 0x7d, 0xfc,
|
33
|
+
0x00, 0x0f, 0x95, 0xc0, 0x0f, 0xb6,
|
34
|
+
0xc0, 0x89, 0x45, 0xfc, 0x8b, 0x45,
|
35
|
+
0xfc,
|
36
|
+
0xc9, 0xc3
|
37
|
+
};
|
38
|
+
|
39
|
+
#define OP_PUSHL_EBP 0x55
|
40
|
+
#define OP_MOVL_ESP_EBP 0x89, 0xe5
|
41
|
+
#define OP_SUBL_N_ESP 0x83, 0xec
|
42
|
+
#define OP_PUSHL_N_EBP_U 0xff
|
43
|
+
#define OP_PUSHL_N_EBP_L 0x75
|
44
|
+
#define OP_NOP 0x90
|
45
|
+
#define OP_ADDL_ESP_U 0x83
|
46
|
+
#define OP_ADDL_ESP_L 0xc4
|
47
|
+
#define OP_LEAVE 0xc9
|
48
|
+
#define OP_RET 0xc3
|
49
|
+
|
50
|
+
/* Set up probe function */
|
51
|
+
ip = insns + IS_ENABLED_FUNC_LEN;
|
52
|
+
|
53
|
+
uint8_t func_in[7] = {
|
54
|
+
OP_PUSHL_EBP, OP_MOVL_ESP_EBP, OP_SUBL_N_ESP, 0x08, NULL
|
55
|
+
|
56
|
+
};
|
57
|
+
|
58
|
+
uint8_t func_out[3] = {
|
59
|
+
OP_LEAVE, OP_RET, NULL
|
60
|
+
};
|
61
|
+
|
62
|
+
for (i = 0; func_in[i]; i++)
|
63
|
+
*ip++ = func_in[i];
|
64
|
+
|
65
|
+
for (i = (4 + 4*argc); i >= 0x08; i -= 4) {
|
66
|
+
*ip++ = OP_PUSHL_N_EBP_U;
|
67
|
+
*ip++ = OP_PUSHL_N_EBP_L;
|
68
|
+
*ip++ = i;
|
69
|
+
}
|
70
|
+
|
71
|
+
for (i = 0; i <=5; i++)
|
72
|
+
*ip++ = OP_NOP;
|
73
|
+
|
74
|
+
*ip++ = OP_ADDL_ESP_U;
|
75
|
+
*ip++ = OP_ADDL_ESP_L;
|
76
|
+
*ip++ = argc * 4;
|
77
|
+
|
78
|
+
for (i = 0; func_out[i]; i++)
|
79
|
+
*ip++ = func_out[i];
|
80
|
+
|
81
|
+
/* allocate memory on a page boundary, for mprotect */
|
82
|
+
probe->func = (void *)memalign(PAGESIZE, FUNC_SIZE);
|
83
|
+
if (probe->func < 0) {
|
84
|
+
rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
|
85
|
+
return Qnil;
|
86
|
+
}
|
87
|
+
|
88
|
+
if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
|
89
|
+
rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
|
90
|
+
return Qnil;
|
91
|
+
}
|
92
|
+
|
93
|
+
if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
|
94
|
+
rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
|
95
|
+
return Qnil;
|
96
|
+
}
|
97
|
+
|
98
|
+
return self;
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE dtraceprobe_free(void *arg)
|
102
|
+
{
|
103
|
+
dtrace_probe_t *probe = (dtrace_probe_t *)arg;
|
104
|
+
|
105
|
+
if (probe) {
|
106
|
+
free(probe);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
VALUE dtraceprobe_alloc(VALUE klass)
|
111
|
+
{
|
112
|
+
VALUE obj;
|
113
|
+
dtrace_probe_t *probe;
|
114
|
+
|
115
|
+
probe = ALLOC(dtrace_probe_t);
|
116
|
+
if (!probe) {
|
117
|
+
rb_raise(eDtraceException, "alloc failed");
|
118
|
+
return Qnil;
|
119
|
+
}
|
120
|
+
|
121
|
+
/* no mark function: no ruby objects hung off this struct */
|
122
|
+
obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
|
123
|
+
return obj;
|
124
|
+
}
|
125
|
+
|
126
|
+
VALUE dtraceprobe_addr(VALUE self)
|
127
|
+
{
|
128
|
+
dtrace_probe_t *probe;
|
129
|
+
|
130
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
131
|
+
return INT2FIX(probe->func);
|
132
|
+
}
|
133
|
+
|
134
|
+
VALUE dtraceprobe_is_enabled(VALUE self)
|
135
|
+
{
|
136
|
+
dtrace_probe_t *probe;
|
137
|
+
|
138
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
139
|
+
return ((int)(*probe->func)()) ? Qtrue : Qfalse;
|
140
|
+
}
|
141
|
+
|
142
|
+
VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
|
143
|
+
dtrace_probe_t *probe;
|
144
|
+
int i;
|
145
|
+
void *argv[8]; // probe argc max for now.
|
146
|
+
void (*func)();
|
147
|
+
|
148
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
149
|
+
|
150
|
+
/* munge Ruby values to either char *s or ints. */
|
151
|
+
for (i = 0; i < argc; i++) {
|
152
|
+
switch (TYPE(ruby_argv[i])) {
|
153
|
+
case T_STRING:
|
154
|
+
argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
|
155
|
+
break;
|
156
|
+
case T_FIXNUM:
|
157
|
+
argv[i] = (void *)FIX2INT(ruby_argv[i]);
|
158
|
+
break;
|
159
|
+
default:
|
160
|
+
rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
|
161
|
+
break;
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
|
166
|
+
|
167
|
+
switch (argc) {
|
168
|
+
case 0:
|
169
|
+
(void)(*func)();
|
170
|
+
break;
|
171
|
+
case 1:
|
172
|
+
(void)(*func)(argv[0]);
|
173
|
+
break;
|
174
|
+
case 2:
|
175
|
+
(void)(*func)(argv[0], argv[1]);
|
176
|
+
break;
|
177
|
+
case 3:
|
178
|
+
(void)(*func)(argv[0], argv[1], argv[2]);
|
179
|
+
break;
|
180
|
+
case 4:
|
181
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3]);
|
182
|
+
break;
|
183
|
+
case 5:
|
184
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
185
|
+
argv[4]);
|
186
|
+
break;
|
187
|
+
case 6:
|
188
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
189
|
+
argv[4], argv[5]);
|
190
|
+
break;
|
191
|
+
case 7:
|
192
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
193
|
+
argv[4], argv[5], argv[6]);
|
194
|
+
break;
|
195
|
+
case 8:
|
196
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
197
|
+
argv[4], argv[5], argv[6], argv[7]);
|
198
|
+
break;
|
199
|
+
default:
|
200
|
+
rb_raise(eDtraceException, "probe argc max is 8");
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
|
204
|
+
return Qnil;
|
205
|
+
}
|
206
|
+
|
207
|
+
VALUE dtraceprobe_probe_offset(VALUE self, VALUE rfile, VALUE argc)
|
208
|
+
{
|
209
|
+
/*
|
210
|
+
* compute offset into stub: see dtrace_probe.c
|
211
|
+
*
|
212
|
+
* 32 bytes - length of is_enabled function
|
213
|
+
* +
|
214
|
+
* 6 bytes - function entry
|
215
|
+
* +
|
216
|
+
* 3 bytes per argument - arg->stack push
|
217
|
+
*
|
218
|
+
*/
|
219
|
+
return INT2FIX(32 + 6 + FIX2INT(argc) * 3);
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE rfile)
|
223
|
+
{
|
224
|
+
return INT2FIX(8);
|
225
|
+
}
|