chrisa-ruby-dtrace 0.2.0 → 0.2.1
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/examples/scsi.rb +1 -1
- data/ext/dof/header.c +2 -0
- data/ext/dof/section.c +11 -0
- data/ext/i386-darwin/dtrace_probe.c +276 -0
- data/ext/i386-solaris/dtrace_probe.c +225 -0
- metadata +10 -12
data/examples/scsi.rb
CHANGED
data/ext/dof/header.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
|
10
10
|
RUBY_EXTERN eDtraceDofException;
|
11
11
|
|
12
|
+
/* :nodoc: */
|
12
13
|
VALUE dof_generate_header(VALUE self) {
|
13
14
|
dof_hdr_t hdr;
|
14
15
|
uint32_t secnum;
|
@@ -69,6 +70,7 @@ VALUE dof_generate_header(VALUE self) {
|
|
69
70
|
return hdr_data;
|
70
71
|
}
|
71
72
|
|
73
|
+
/* :nodoc: */
|
72
74
|
VALUE dof_header_len(VALUE self) {
|
73
75
|
uint64_t hdrlen;
|
74
76
|
uint32_t secnum;
|
data/ext/dof/section.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
|
10
10
|
RUBY_EXTERN eDtraceDofException;
|
11
11
|
|
12
|
+
/* :nodoc: */
|
12
13
|
VALUE dof_generate_section_header(VALUE self) {
|
13
14
|
VALUE hdr_data;
|
14
15
|
dof_sec_t hdr;
|
@@ -30,6 +31,7 @@ VALUE dof_generate_section_header(VALUE self) {
|
|
30
31
|
return hdr_data;
|
31
32
|
}
|
32
33
|
|
34
|
+
/* :nodoc: */
|
33
35
|
VALUE dof_generate_comments(VALUE self) {
|
34
36
|
VALUE dof;
|
35
37
|
VALUE comments = rb_iv_get(self, "@data");
|
@@ -45,6 +47,7 @@ VALUE dof_generate_comments(VALUE self) {
|
|
45
47
|
return dof;
|
46
48
|
}
|
47
49
|
|
50
|
+
/* :nodoc: */
|
48
51
|
VALUE dof_generate_probes(VALUE self) {
|
49
52
|
VALUE dof;
|
50
53
|
VALUE probes = rb_iv_get(self, "@data");
|
@@ -88,6 +91,7 @@ VALUE dof_generate_probes(VALUE self) {
|
|
88
91
|
return dof;
|
89
92
|
}
|
90
93
|
|
94
|
+
/* :nodoc: */
|
91
95
|
VALUE dof_generate_strtab(VALUE self) {
|
92
96
|
VALUE dof;
|
93
97
|
VALUE strings = rb_iv_get(self, "@data");
|
@@ -114,6 +118,7 @@ VALUE dof_generate_strtab(VALUE self) {
|
|
114
118
|
return dof;
|
115
119
|
}
|
116
120
|
|
121
|
+
/* :nodoc: */
|
117
122
|
VALUE dof_generate_utsname(VALUE self) {
|
118
123
|
VALUE dof;
|
119
124
|
struct utsname u;
|
@@ -127,6 +132,7 @@ VALUE dof_generate_utsname(VALUE self) {
|
|
127
132
|
return dof;
|
128
133
|
}
|
129
134
|
|
135
|
+
/* :nodoc: */
|
130
136
|
VALUE dof_generate_prargs(VALUE self) {
|
131
137
|
VALUE dof;
|
132
138
|
VALUE args = rb_iv_get(self, "@data");
|
@@ -154,6 +160,7 @@ VALUE dof_generate_prargs(VALUE self) {
|
|
154
160
|
return dof;
|
155
161
|
}
|
156
162
|
|
163
|
+
/* :nodoc: */
|
157
164
|
VALUE dof_generate_proffs(VALUE self) {
|
158
165
|
VALUE dof;
|
159
166
|
VALUE args = rb_iv_get(self, "@data");
|
@@ -179,6 +186,7 @@ VALUE dof_generate_proffs(VALUE self) {
|
|
179
186
|
return dof;
|
180
187
|
}
|
181
188
|
|
189
|
+
/* :nodoc: */
|
182
190
|
VALUE dof_generate_prenoffs(VALUE self) {
|
183
191
|
VALUE dof;
|
184
192
|
VALUE args = rb_iv_get(self, "@data");
|
@@ -220,6 +228,7 @@ dof_attr_t _dof_generate_dof_attr_t(VALUE data) {
|
|
220
228
|
return attr;
|
221
229
|
}
|
222
230
|
|
231
|
+
/* :nodoc: */
|
223
232
|
VALUE dof_generate_provider(VALUE self) {
|
224
233
|
VALUE dof;
|
225
234
|
VALUE provider = rb_iv_get(self, "@data");
|
@@ -247,6 +256,7 @@ VALUE dof_generate_provider(VALUE self) {
|
|
247
256
|
return dof;
|
248
257
|
}
|
249
258
|
|
259
|
+
/* :nodoc: */
|
250
260
|
VALUE dof_generate_reltab(VALUE self) {
|
251
261
|
VALUE dof;
|
252
262
|
VALUE relos = rb_iv_get(self, "@data");
|
@@ -281,6 +291,7 @@ VALUE dof_generate_reltab(VALUE self) {
|
|
281
291
|
return dof;
|
282
292
|
}
|
283
293
|
|
294
|
+
/* :nodoc: */
|
284
295
|
VALUE dof_generate_relhdr(VALUE self) {
|
285
296
|
VALUE dof;
|
286
297
|
VALUE relhdr = rb_iv_get(self, "@data");
|
@@ -0,0 +1,276 @@
|
|
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 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
|
+
0xc9, 0xc3
|
33
|
+
};
|
34
|
+
|
35
|
+
#define OP_PUSHL_EBP 0x55
|
36
|
+
#define OP_MOVL_ESP_EBP_U 0x89
|
37
|
+
#define OP_MOVL_ESP_EBP_L 0xe5
|
38
|
+
#define OP_SUBL_N_ESP_U 0x83
|
39
|
+
#define OP_SUBL_N_ESP_L 0xec
|
40
|
+
#define OP_PUSHL_N_EBP_U 0xff
|
41
|
+
#define OP_PUSHL_N_EBP_L 0x75
|
42
|
+
#define OP_NOP 0x90
|
43
|
+
#define OP_ADDL_ESP_U 0x83
|
44
|
+
#define OP_ADDL_ESP_L 0xc4
|
45
|
+
#define OP_LEAVE 0xc9
|
46
|
+
#define OP_RET 0xc3
|
47
|
+
#define OP_MOVL_EAX_U 0x8b
|
48
|
+
#define OP_MOVL_EAX_L 0x45
|
49
|
+
#define OP_MOVL_ESP 0x89
|
50
|
+
|
51
|
+
/* Set up probe function */
|
52
|
+
ip = insns + IS_ENABLED_FUNC_LEN;
|
53
|
+
|
54
|
+
*ip++ = OP_PUSHL_EBP;
|
55
|
+
*ip++ = OP_MOVL_ESP_EBP_U;
|
56
|
+
*ip++ = OP_MOVL_ESP_EBP_L;
|
57
|
+
*ip++ = OP_SUBL_N_ESP_U;
|
58
|
+
*ip++ = OP_SUBL_N_ESP_L;
|
59
|
+
|
60
|
+
switch(argc) {
|
61
|
+
case 0:
|
62
|
+
case 1:
|
63
|
+
case 2:
|
64
|
+
case 3:
|
65
|
+
case 4:
|
66
|
+
case 5:
|
67
|
+
case 6:
|
68
|
+
*ip++ = 0x18;
|
69
|
+
break;
|
70
|
+
case 7:
|
71
|
+
case 8:
|
72
|
+
*ip++ = 0x28;
|
73
|
+
break;
|
74
|
+
}
|
75
|
+
|
76
|
+
/* args */
|
77
|
+
for (i = (4*argc - 4); i >= 0; i -= 4) {
|
78
|
+
/* mov 0xN(%ebp),%eax */
|
79
|
+
*ip++ = OP_MOVL_EAX_U;
|
80
|
+
*ip++ = OP_MOVL_EAX_L;
|
81
|
+
*ip++ = i + 8;
|
82
|
+
/* mov %eax,N(%esp) */
|
83
|
+
*ip++ = OP_MOVL_ESP;
|
84
|
+
if (i > 0) {
|
85
|
+
*ip++ = 0x44;
|
86
|
+
*ip++ = 0x24;
|
87
|
+
*ip++ = i;
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
*ip++ = 0x04;
|
91
|
+
*ip++ = 0x24;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
/* tracepoint */
|
96
|
+
*ip++ = 0x90;
|
97
|
+
*ip++ = 0x0f;
|
98
|
+
*ip++ = 0x1f;
|
99
|
+
*ip++ = 0x40;
|
100
|
+
*ip++ = 0x00;
|
101
|
+
|
102
|
+
/* ret */
|
103
|
+
*ip++ = OP_LEAVE;
|
104
|
+
*ip++ = OP_RET;
|
105
|
+
|
106
|
+
/* allocate memory on a page boundary, for mprotect */
|
107
|
+
probe->func = (void *)valloc(FUNC_SIZE);
|
108
|
+
if (probe->func < 0) {
|
109
|
+
rb_raise(eDtraceException, "malloc failed: %s\n", strerror(errno));
|
110
|
+
return Qnil;
|
111
|
+
}
|
112
|
+
|
113
|
+
if ((mprotect((void *)probe->func, FUNC_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) < 0) {
|
114
|
+
rb_raise(eDtraceException, "mprotect failed: %s\n", strerror(errno));
|
115
|
+
return Qnil;
|
116
|
+
}
|
117
|
+
|
118
|
+
if ((memcpy(probe->func, insns, FUNC_SIZE)) < 0) {
|
119
|
+
rb_raise(eDtraceException, "memcpy failed: %s\n", strerror(errno));
|
120
|
+
return Qnil;
|
121
|
+
}
|
122
|
+
|
123
|
+
return self;
|
124
|
+
}
|
125
|
+
|
126
|
+
VALUE dtraceprobe_free(void *arg)
|
127
|
+
{
|
128
|
+
dtrace_probe_t *probe = (dtrace_probe_t *)arg;
|
129
|
+
|
130
|
+
if (probe) {
|
131
|
+
free(probe);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
VALUE dtraceprobe_alloc(VALUE klass)
|
136
|
+
{
|
137
|
+
VALUE obj;
|
138
|
+
dtrace_probe_t *probe;
|
139
|
+
|
140
|
+
probe = ALLOC(dtrace_probe_t);
|
141
|
+
if (!probe) {
|
142
|
+
rb_raise(eDtraceException, "alloc failed");
|
143
|
+
return Qnil;
|
144
|
+
}
|
145
|
+
|
146
|
+
/* no mark function: no ruby objects hung off this struct */
|
147
|
+
obj = Data_Wrap_Struct(klass, NULL, dtraceprobe_free, probe);
|
148
|
+
return obj;
|
149
|
+
}
|
150
|
+
|
151
|
+
/*
|
152
|
+
* Returns the address of the probe's generated code.
|
153
|
+
*/
|
154
|
+
VALUE dtraceprobe_addr(VALUE self)
|
155
|
+
{
|
156
|
+
dtrace_probe_t *probe;
|
157
|
+
|
158
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
159
|
+
return INT2FIX(probe->func);
|
160
|
+
}
|
161
|
+
|
162
|
+
/*
|
163
|
+
* Returns whether or not this probe is currently enabled, by invoking
|
164
|
+
* the is-enabled tracepoint attached to the probe.
|
165
|
+
*/
|
166
|
+
VALUE dtraceprobe_is_enabled(VALUE self)
|
167
|
+
{
|
168
|
+
dtrace_probe_t *probe;
|
169
|
+
|
170
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
171
|
+
return INT2FIX((int)(*probe->func)());
|
172
|
+
}
|
173
|
+
|
174
|
+
/*
|
175
|
+
* Fires the probe, converting arguments based on the data provided -
|
176
|
+
* no validation is done against the probe's declared types.
|
177
|
+
*/
|
178
|
+
VALUE dtraceprobe_fire(int argc, VALUE *ruby_argv, VALUE self) {
|
179
|
+
dtrace_probe_t *probe;
|
180
|
+
int i;
|
181
|
+
void *argv[8]; // probe argc max for now.
|
182
|
+
void (*func)();
|
183
|
+
|
184
|
+
Data_Get_Struct(self, dtrace_probe_t, probe);
|
185
|
+
|
186
|
+
/* munge Ruby values to either char *s or ints. */
|
187
|
+
for (i = 0; i < argc; i++) {
|
188
|
+
switch (TYPE(ruby_argv[i])) {
|
189
|
+
case T_STRING:
|
190
|
+
argv[i] = (void *)RSTRING(ruby_argv[i])->ptr;
|
191
|
+
break;
|
192
|
+
case T_FIXNUM:
|
193
|
+
argv[i] = (void *)FIX2INT(ruby_argv[i]);
|
194
|
+
break;
|
195
|
+
default:
|
196
|
+
rb_raise(eDtraceException, "type of arg[%d] is not string or fixnum", i);
|
197
|
+
break;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
func = (void (*)())(probe->func + IS_ENABLED_FUNC_LEN);
|
202
|
+
|
203
|
+
switch (argc) {
|
204
|
+
case 0:
|
205
|
+
(void)(*func)();
|
206
|
+
break;
|
207
|
+
case 1:
|
208
|
+
(void)(*func)(argv[0]);
|
209
|
+
break;
|
210
|
+
case 2:
|
211
|
+
(void)(*func)(argv[0], argv[1]);
|
212
|
+
break;
|
213
|
+
case 3:
|
214
|
+
(void)(*func)(argv[0], argv[1], argv[2]);
|
215
|
+
break;
|
216
|
+
case 4:
|
217
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3]);
|
218
|
+
break;
|
219
|
+
case 5:
|
220
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
221
|
+
argv[4]);
|
222
|
+
break;
|
223
|
+
case 6:
|
224
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
225
|
+
argv[4], argv[5]);
|
226
|
+
break;
|
227
|
+
case 7:
|
228
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
229
|
+
argv[4], argv[5], argv[6]);
|
230
|
+
break;
|
231
|
+
case 8:
|
232
|
+
(void)(*func)(argv[0], argv[1], argv[2], argv[3],
|
233
|
+
argv[4], argv[5], argv[6], argv[7]);
|
234
|
+
break;
|
235
|
+
default:
|
236
|
+
rb_raise(eDtraceException, "probe argc max is 8");
|
237
|
+
break;
|
238
|
+
}
|
239
|
+
|
240
|
+
return Qnil;
|
241
|
+
}
|
242
|
+
|
243
|
+
/*
|
244
|
+
* Returns the offset for this probe in the PROFFS section, based on
|
245
|
+
* the location of the DOF, and the location of this probe.
|
246
|
+
*/
|
247
|
+
VALUE dtraceprobe_probe_offset(VALUE self, VALUE file_addr, VALUE argc)
|
248
|
+
{
|
249
|
+
void *probe_addr;
|
250
|
+
int offset;
|
251
|
+
probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
|
252
|
+
switch FIX2INT(argc) {
|
253
|
+
case 0:
|
254
|
+
offset = 40; /* 32 + 6 + 2 */
|
255
|
+
break;
|
256
|
+
case 1:
|
257
|
+
offset = 46; /* 32 + 6 + 6 + 2 */
|
258
|
+
break;
|
259
|
+
default:
|
260
|
+
offset = 46 + (FIX2INT(argc)-1) * 7; /* 32 + 6 + 6 + 7 per subsequent arg + 2 */
|
261
|
+
break;
|
262
|
+
}
|
263
|
+
return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + offset);
|
264
|
+
}
|
265
|
+
|
266
|
+
/*
|
267
|
+
* Returns the offset for this probe's is-enabled tracepoint in the
|
268
|
+
* PRENOFFS section, based on the location of the DOF, and the
|
269
|
+
* location of this probe.
|
270
|
+
*/
|
271
|
+
VALUE dtraceprobe_is_enabled_offset(VALUE self, VALUE file_addr)
|
272
|
+
{
|
273
|
+
void *probe_addr;
|
274
|
+
probe_addr = (void *)FIX2INT(rb_funcall(self, rb_intern("addr"), 0));
|
275
|
+
return INT2FIX((int)probe_addr - (int)FIX2INT(file_addr) + 8);
|
276
|
+
}
|
@@ -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 INT2FIX((int)(*probe->func)());
|
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
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chrisa-ruby-dtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Andrews
|
@@ -17,8 +17,9 @@ description:
|
|
17
17
|
email: chris@nodnol.org
|
18
18
|
executables: []
|
19
19
|
|
20
|
-
extensions:
|
21
|
-
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
|
+
- ext/dof/extconf.rb
|
22
23
|
extra_rdoc_files: []
|
23
24
|
|
24
25
|
files:
|
@@ -44,7 +45,6 @@ files:
|
|
44
45
|
- ext/dtrace_dropdata.c
|
45
46
|
- ext/dtrace_errdata.c
|
46
47
|
- ext/dtrace_hdl.c
|
47
|
-
- ext/dtrace_probe.c
|
48
48
|
- ext/dtrace_probedata.c
|
49
49
|
- ext/dtrace_probedesc.c
|
50
50
|
- ext/dtrace_process.c
|
@@ -53,12 +53,10 @@ files:
|
|
53
53
|
- ext/dtrace_recdesc.c
|
54
54
|
- ext/dtrace_util.c
|
55
55
|
- ext/extconf.rb
|
56
|
-
- ext/i386-
|
57
|
-
- ext/i386-
|
58
|
-
- ext/
|
59
|
-
- ext/
|
60
|
-
- ext/sparc-solaris2.10
|
61
|
-
- ext/sparc-solaris2.10/dtrace_probe.c
|
56
|
+
- ext/i386-solaris
|
57
|
+
- ext/i386-solaris/dtrace_probe.c
|
58
|
+
- ext/i386-darwin
|
59
|
+
- ext/i386-darwin/dtrace_probe.c
|
62
60
|
- ext/stubs.txt
|
63
61
|
- lib/dtrace
|
64
62
|
- lib/dtrace/aggregate.rb
|
@@ -82,7 +80,6 @@ files:
|
|
82
80
|
- lib/dtrace/stackrecord.rb
|
83
81
|
- lib/dtrace/tracer.rb
|
84
82
|
- lib/dtrace/version.rb
|
85
|
-
- lib/dtrace/version.rb~
|
86
83
|
- lib/dtrace.rb
|
87
84
|
- lib/dtraceconsumer.rb
|
88
85
|
- plugin/dtrace
|
@@ -142,6 +139,7 @@ rdoc_options: []
|
|
142
139
|
|
143
140
|
require_paths:
|
144
141
|
- lib
|
142
|
+
- ext
|
145
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
146
144
|
requirements:
|
147
145
|
- - ">="
|
@@ -160,6 +158,6 @@ rubyforge_project: ruby-dtrace
|
|
160
158
|
rubygems_version: 1.0.1
|
161
159
|
signing_key:
|
162
160
|
specification_version: 2
|
163
|
-
summary:
|
161
|
+
summary: Ruby-DTrace is Ruby bindings for Dtrace, which allows you to add DTrace probes to your Ruby programs, and to write D-based programs with Ruby.
|
164
162
|
test_files: []
|
165
163
|
|