ruby-dtrace 0.0.6 → 0.2.8
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.
- 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
|
+
}
|