ruby-dtrace-consumer 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE +20 -0
- data/README.md +51 -0
- data/ext/Makefile +187 -0
- data/ext/dtrace_aggdata.c +132 -0
- data/ext/dtrace_aggdata.c~ +141 -0
- data/ext/dtrace_aggdata.o +0 -0
- data/ext/dtrace_api.bundle +0 -0
- data/ext/dtrace_api.c +102 -0
- data/ext/dtrace_api.c~ +113 -0
- data/ext/dtrace_api.h +138 -0
- data/ext/dtrace_api.h~ +155 -0
- data/ext/dtrace_api.o +0 -0
- data/ext/dtrace_bufdata.c +130 -0
- data/ext/dtrace_bufdata.c~ +139 -0
- data/ext/dtrace_bufdata.o +0 -0
- data/ext/dtrace_dropdata.c +121 -0
- data/ext/dtrace_dropdata.c~ +131 -0
- data/ext/dtrace_dropdata.o +0 -0
- data/ext/dtrace_errdata.c +100 -0
- data/ext/dtrace_errdata.c~ +110 -0
- data/ext/dtrace_errdata.o +0 -0
- data/ext/dtrace_hdl.c +677 -0
- data/ext/dtrace_hdl.c~ +689 -0
- data/ext/dtrace_hdl.o +0 -0
- data/ext/dtrace_probedata.c +273 -0
- data/ext/dtrace_probedata.c~ +283 -0
- data/ext/dtrace_probedata.o +0 -0
- data/ext/dtrace_probedesc.c +93 -0
- data/ext/dtrace_probedesc.c~ +78 -0
- data/ext/dtrace_probedesc.o +0 -0
- data/ext/dtrace_process.c +44 -0
- data/ext/dtrace_process.c~ +56 -0
- data/ext/dtrace_process.o +0 -0
- data/ext/dtrace_program.c +52 -0
- data/ext/dtrace_program.c~ +62 -0
- data/ext/dtrace_program.o +0 -0
- data/ext/dtrace_programinfo.c +70 -0
- data/ext/dtrace_programinfo.c~ +60 -0
- data/ext/dtrace_programinfo.o +0 -0
- data/ext/dtrace_recdesc.c +37 -0
- data/ext/dtrace_recdesc.c~ +46 -0
- data/ext/dtrace_recdesc.o +0 -0
- data/ext/dtrace_util.c +92 -0
- data/ext/dtrace_util.o +0 -0
- data/ext/extconf.rb +7 -0
- data/lib/dtrace.rb +95 -0
- 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 +85 -0
- data/lib/dtrace/dof.rb +8 -0
- data/lib/dtrace/printfrecord.rb +10 -0
- data/lib/dtrace/probedata.rb +23 -0
- data/lib/dtrace/probedesc.rb +15 -0
- data/lib/dtrace/record.rb +11 -0
- data/lib/dtrace/stackrecord.rb +31 -0
- data/lib/dtrace/tracer.rb +35 -0
- data/lib/dtrace/version.rb +8 -0
- data/lib/dtrace/version.rb~ +8 -0
- data/lib/dtraceconsumer.rb +9 -0
- data/test/test_aggregates.rb +45 -0
- data/test/test_drops_errors.rb +166 -0
- data/test/test_dtrace.rb +155 -0
- data/test/test_gc.rb +11 -0
- data/test/test_helper.rb +20 -0
- data/test/test_helper.rb~ +16 -0
- data/test/test_legacy_consumer.rb +47 -0
- data/test/test_probedata.rb +30 -0
- data/test/test_processes.rb +66 -0
- data/test/test_profile.rb +198 -0
- data/test/test_repeat.rb +50 -0
- data/test/test_rubyprobe.rb +52 -0
- data/test/test_rubyprobe.rb~ +52 -0
- data/test/test_typefilter.rb +94 -0
- metadata +121 -0
data/ext/dtrace_hdl.o
ADDED
Binary file
|
@@ -0,0 +1,273 @@
|
|
1
|
+
/* Ruby-DTrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE eDTraceException;
|
8
|
+
|
9
|
+
static VALUE _handle_ustack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
|
10
|
+
{
|
11
|
+
/* TODO, apple and solaris ustack */
|
12
|
+
VALUE stack = rb_ary_new();
|
13
|
+
return stack;
|
14
|
+
}
|
15
|
+
|
16
|
+
static VALUE _handle_stack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
|
17
|
+
{
|
18
|
+
VALUE stack = Qnil;
|
19
|
+
int size, i;
|
20
|
+
int depth;
|
21
|
+
uint64_t pc;
|
22
|
+
dtrace_syminfo_t dts;
|
23
|
+
char c[PATH_MAX * 2];
|
24
|
+
int ret;
|
25
|
+
|
26
|
+
#ifdef __APPLE__
|
27
|
+
__GElf_Sym sym;
|
28
|
+
#else
|
29
|
+
GElf_Sym sym;
|
30
|
+
#endif
|
31
|
+
|
32
|
+
size = rec->dtrd_size / rec->dtrd_arg;
|
33
|
+
depth = rec->dtrd_arg;
|
34
|
+
|
35
|
+
stack = rb_ary_new2(depth);
|
36
|
+
|
37
|
+
for (i = 0; i < depth; i++) {
|
38
|
+
|
39
|
+
switch (size) {
|
40
|
+
case sizeof (uint32_t):
|
41
|
+
pc = *((uint32_t *)addr);
|
42
|
+
break;
|
43
|
+
|
44
|
+
case sizeof (uint64_t):
|
45
|
+
pc = *((uint64_t *)addr);
|
46
|
+
break;
|
47
|
+
|
48
|
+
default:
|
49
|
+
rb_raise(eDTraceException, "bad stack pc");
|
50
|
+
return Qnil;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (pc == (uint64_t)NULL)
|
54
|
+
break;
|
55
|
+
|
56
|
+
#ifdef __APPLE__
|
57
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, &sym, &dts);
|
58
|
+
#else
|
59
|
+
ret = dtrace_lookup_by_addr(handle, pc, &sym, &dts);
|
60
|
+
#endif
|
61
|
+
|
62
|
+
if (ret == 0) {
|
63
|
+
|
64
|
+
if (pc > sym.st_value)
|
65
|
+
(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
|
66
|
+
dts.dts_object, dts.dts_name,
|
67
|
+
pc - sym.st_value);
|
68
|
+
else
|
69
|
+
(void) snprintf(c, sizeof (c), "%s`%s",
|
70
|
+
dts.dts_object, dts.dts_name);
|
71
|
+
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
|
75
|
+
#ifdef __APPLE__
|
76
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, NULL, &dts);
|
77
|
+
#else
|
78
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, &dts);
|
79
|
+
#endif
|
80
|
+
|
81
|
+
if (ret == 0)
|
82
|
+
(void) snprintf(c, sizeof (c), "%s`0x%llx", dts.dts_object, pc);
|
83
|
+
else
|
84
|
+
(void) snprintf(c, sizeof (c), "0x%llx", pc);
|
85
|
+
|
86
|
+
}
|
87
|
+
|
88
|
+
rb_ary_push(stack, rb_str_new2(c));
|
89
|
+
addr += size;
|
90
|
+
}
|
91
|
+
|
92
|
+
return stack;
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* Returns the enabled probe id which generated this data
|
97
|
+
*/
|
98
|
+
VALUE dtraceprobedata_epid(VALUE self)
|
99
|
+
{
|
100
|
+
dtrace_probedata_t *data;
|
101
|
+
|
102
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
103
|
+
return INT2FIX(data->dtpda_edesc->dtepd_epid);
|
104
|
+
}
|
105
|
+
|
106
|
+
/*
|
107
|
+
* Returns the DTraceProbe for the probe which generated this data
|
108
|
+
*/
|
109
|
+
VALUE dtraceprobedata_probe(VALUE self)
|
110
|
+
{
|
111
|
+
VALUE dtraceprobe;
|
112
|
+
dtrace_probedata_t *data;
|
113
|
+
dtrace_probedesc_t *pd;
|
114
|
+
|
115
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
116
|
+
pd = data->dtpda_pdesc;
|
117
|
+
|
118
|
+
if (pd) {
|
119
|
+
dtraceprobe = dtraceprobedesc_init(pd);
|
120
|
+
return dtraceprobe;
|
121
|
+
}
|
122
|
+
|
123
|
+
return Qnil;
|
124
|
+
}
|
125
|
+
|
126
|
+
/* Returns the CPU which generated this data */
|
127
|
+
VALUE dtraceprobedata_cpu(VALUE self)
|
128
|
+
{
|
129
|
+
dtrace_probedata_t *data;
|
130
|
+
processorid_t cpu;
|
131
|
+
|
132
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
133
|
+
|
134
|
+
if (data) {
|
135
|
+
cpu = data->dtpda_cpu;
|
136
|
+
return INT2FIX(cpu);
|
137
|
+
}
|
138
|
+
else {
|
139
|
+
return Qnil;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
/* Returns the indent level given to this data by DTrace */
|
144
|
+
VALUE dtraceprobedata_indent(VALUE self)
|
145
|
+
{
|
146
|
+
dtrace_probedata_t *data;
|
147
|
+
int indent;
|
148
|
+
|
149
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
150
|
+
|
151
|
+
if (data) {
|
152
|
+
indent = data->dtpda_indent;
|
153
|
+
return INT2FIX(indent / 2);
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
return Qnil;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
/* Returns the prefix given to this data by DTrace */
|
161
|
+
VALUE dtraceprobedata_prefix(VALUE self)
|
162
|
+
{
|
163
|
+
dtrace_probedata_t *data;
|
164
|
+
const char *prefix;
|
165
|
+
|
166
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
167
|
+
prefix = data->dtpda_prefix;
|
168
|
+
|
169
|
+
if (prefix)
|
170
|
+
return rb_str_new2(prefix);
|
171
|
+
else
|
172
|
+
return Qnil;
|
173
|
+
}
|
174
|
+
|
175
|
+
/* Returns the flow kind given to this data by DTrace */
|
176
|
+
VALUE dtraceprobedata_flow(VALUE self)
|
177
|
+
{
|
178
|
+
dtrace_probedata_t *data;
|
179
|
+
|
180
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
181
|
+
|
182
|
+
switch (data->dtpda_flow) {
|
183
|
+
case DTRACEFLOW_ENTRY:
|
184
|
+
return rb_str_new2("->");
|
185
|
+
break;
|
186
|
+
case DTRACEFLOW_RETURN:
|
187
|
+
return rb_str_new2("<-");
|
188
|
+
break;
|
189
|
+
default:
|
190
|
+
return Qnil;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
/*
|
195
|
+
* Yields each record in this DTraceProbedata in turn. Records are
|
196
|
+
* yielded as either DTraceRecords or DTraceStackRecords as
|
197
|
+
* appropriate for the type of action.
|
198
|
+
*/
|
199
|
+
VALUE dtraceprobedata_each_record(VALUE self)
|
200
|
+
{
|
201
|
+
dtrace_probedata_t *data;
|
202
|
+
dtrace_eprobedesc_t *eprobe;
|
203
|
+
dtrace_recdesc_t *rec;
|
204
|
+
dtrace_handle_t *handle;
|
205
|
+
dtrace_actkind_t act;
|
206
|
+
int i;
|
207
|
+
caddr_t addr;
|
208
|
+
VALUE dtracerecord;
|
209
|
+
VALUE dtrace;
|
210
|
+
VALUE v;
|
211
|
+
VALUE class;
|
212
|
+
|
213
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
214
|
+
dtrace = rb_iv_get(self, "@handle");
|
215
|
+
Data_Get_Struct(dtrace, dtrace_handle_t, handle);
|
216
|
+
|
217
|
+
eprobe = data->dtpda_edesc;
|
218
|
+
|
219
|
+
for (i = 0; i < eprobe->dtepd_nrecs; i++) {
|
220
|
+
v = 0;
|
221
|
+
rec = &eprobe->dtepd_rec[i];
|
222
|
+
if (rec->dtrd_size > 0) {
|
223
|
+
act = rec->dtrd_action;
|
224
|
+
addr = data->dtpda_data + rec->dtrd_offset;
|
225
|
+
|
226
|
+
switch (act) {
|
227
|
+
case DTRACEACT_STACK:
|
228
|
+
v = _handle_stack_record(handle->hdl, addr, rec);
|
229
|
+
class = rb_path2class("DTrace::StackRecord");
|
230
|
+
break;
|
231
|
+
case DTRACEACT_USTACK:
|
232
|
+
v = _handle_ustack_record(handle->hdl, addr, rec);
|
233
|
+
class = rb_path2class("DTrace::StackRecord");
|
234
|
+
break;
|
235
|
+
case DTRACEACT_JSTACK:
|
236
|
+
/* not sure how to handle jstack */
|
237
|
+
break;
|
238
|
+
case DTRACEACT_PRINTA:
|
239
|
+
/* don't want the probedata record for a printa() action */
|
240
|
+
break;
|
241
|
+
default:
|
242
|
+
class = rb_path2class("DTrace::Record");
|
243
|
+
switch (rec->dtrd_size) {
|
244
|
+
case 1:
|
245
|
+
v = INT2FIX((int)(*((uint8_t *)addr)));
|
246
|
+
break;
|
247
|
+
case 2:
|
248
|
+
v = INT2FIX((int)(*((uint16_t *)addr)));
|
249
|
+
break;
|
250
|
+
case 4:
|
251
|
+
v = INT2FIX(*((int32_t *)addr));
|
252
|
+
break;
|
253
|
+
case 8:
|
254
|
+
v = LL2NUM(*((int64_t *)addr));
|
255
|
+
break;
|
256
|
+
default:
|
257
|
+
v = handle_bytedata(addr, rec->dtrd_size);
|
258
|
+
break;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
262
|
+
if (v) {
|
263
|
+
dtracerecord = rb_class_new_instance(0, NULL, class);
|
264
|
+
rb_iv_set(dtracerecord, "@value", v);
|
265
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("probedata"));
|
266
|
+
rb_iv_set(dtracerecord, "@index", INT2FIX(i));
|
267
|
+
rb_iv_set(dtracerecord, "@action", INT2FIX(act));
|
268
|
+
rb_yield(dtracerecord);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
return Qnil;
|
273
|
+
}
|
@@ -0,0 +1,283 @@
|
|
1
|
+
/* Ruby-DTrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE eDTraceException;
|
8
|
+
RUBY_EXTERN VALUE cDTraceProbeDesc;
|
9
|
+
|
10
|
+
/* :nodoc: */
|
11
|
+
VALUE dtraceprobedata_init(VALUE self)
|
12
|
+
{
|
13
|
+
dtrace_probedata_t *data;
|
14
|
+
|
15
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
16
|
+
return self;
|
17
|
+
}
|
18
|
+
|
19
|
+
static VALUE _handle_ustack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
|
20
|
+
{
|
21
|
+
/* TODO, apple and solaris ustack */
|
22
|
+
VALUE stack = rb_ary_new();
|
23
|
+
return stack;
|
24
|
+
}
|
25
|
+
|
26
|
+
static VALUE _handle_stack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
|
27
|
+
{
|
28
|
+
VALUE stack = Qnil;
|
29
|
+
int size, i;
|
30
|
+
int depth;
|
31
|
+
uint64_t pc;
|
32
|
+
dtrace_syminfo_t dts;
|
33
|
+
char c[PATH_MAX * 2];
|
34
|
+
int ret;
|
35
|
+
|
36
|
+
#ifdef __APPLE__
|
37
|
+
__GElf_Sym sym;
|
38
|
+
#else
|
39
|
+
GElf_Sym sym;
|
40
|
+
#endif
|
41
|
+
|
42
|
+
size = rec->dtrd_size / rec->dtrd_arg;
|
43
|
+
depth = rec->dtrd_arg;
|
44
|
+
|
45
|
+
stack = rb_ary_new2(depth);
|
46
|
+
|
47
|
+
for (i = 0; i < depth; i++) {
|
48
|
+
|
49
|
+
switch (size) {
|
50
|
+
case sizeof (uint32_t):
|
51
|
+
pc = *((uint32_t *)addr);
|
52
|
+
break;
|
53
|
+
|
54
|
+
case sizeof (uint64_t):
|
55
|
+
pc = *((uint64_t *)addr);
|
56
|
+
break;
|
57
|
+
|
58
|
+
default:
|
59
|
+
rb_raise(eDTraceException, "bad stack pc");
|
60
|
+
return Qnil;
|
61
|
+
}
|
62
|
+
|
63
|
+
if (pc == (uint64_t)NULL)
|
64
|
+
break;
|
65
|
+
|
66
|
+
#ifdef __APPLE__
|
67
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, &sym, &dts);
|
68
|
+
#else
|
69
|
+
ret = dtrace_lookup_by_addr(handle, pc, &sym, &dts);
|
70
|
+
#endif
|
71
|
+
|
72
|
+
if (ret == 0) {
|
73
|
+
|
74
|
+
if (pc > sym.st_value)
|
75
|
+
(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
|
76
|
+
dts.dts_object, dts.dts_name,
|
77
|
+
pc - sym.st_value);
|
78
|
+
else
|
79
|
+
(void) snprintf(c, sizeof (c), "%s`%s",
|
80
|
+
dts.dts_object, dts.dts_name);
|
81
|
+
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
|
85
|
+
#ifdef __APPLE__
|
86
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, NULL, &dts);
|
87
|
+
#else
|
88
|
+
ret = dtrace_lookup_by_addr(handle, pc, NULL, &dts);
|
89
|
+
#endif
|
90
|
+
|
91
|
+
if (ret == 0)
|
92
|
+
(void) snprintf(c, sizeof (c), "%s`0x%llx", dts.dts_object, pc);
|
93
|
+
else
|
94
|
+
(void) snprintf(c, sizeof (c), "0x%llx", pc);
|
95
|
+
|
96
|
+
}
|
97
|
+
|
98
|
+
rb_ary_push(stack, rb_str_new2(c));
|
99
|
+
addr += size;
|
100
|
+
}
|
101
|
+
|
102
|
+
return stack;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* Returns the enabled probe id which generated this data
|
107
|
+
*/
|
108
|
+
VALUE dtraceprobedata_epid(VALUE self)
|
109
|
+
{
|
110
|
+
dtrace_probedata_t *data;
|
111
|
+
|
112
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
113
|
+
return INT2FIX(data->dtpda_edesc->dtepd_epid);
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
* Returns the DTraceProbe for the probe which generated this data
|
118
|
+
*/
|
119
|
+
VALUE dtraceprobedata_probe(VALUE self)
|
120
|
+
{
|
121
|
+
VALUE dtraceprobe;
|
122
|
+
dtrace_probedata_t *data;
|
123
|
+
dtrace_probedesc_t *pd;
|
124
|
+
|
125
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
126
|
+
pd = data->dtpda_pdesc;
|
127
|
+
|
128
|
+
if (pd) {
|
129
|
+
dtraceprobe = Data_Wrap_Struct(cDTraceProbeDesc, 0, NULL, (dtrace_probedesc_t *)pd);
|
130
|
+
return dtraceprobe;
|
131
|
+
}
|
132
|
+
|
133
|
+
return Qnil;
|
134
|
+
}
|
135
|
+
|
136
|
+
/* Returns the CPU which generated this data */
|
137
|
+
VALUE dtraceprobedata_cpu(VALUE self)
|
138
|
+
{
|
139
|
+
dtrace_probedata_t *data;
|
140
|
+
processorid_t cpu;
|
141
|
+
|
142
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
143
|
+
|
144
|
+
if (data) {
|
145
|
+
cpu = data->dtpda_cpu;
|
146
|
+
return INT2FIX(cpu);
|
147
|
+
}
|
148
|
+
else {
|
149
|
+
return Qnil;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
/* Returns the indent level given to this data by DTrace */
|
154
|
+
VALUE dtraceprobedata_indent(VALUE self)
|
155
|
+
{
|
156
|
+
dtrace_probedata_t *data;
|
157
|
+
int indent;
|
158
|
+
|
159
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
160
|
+
|
161
|
+
if (data) {
|
162
|
+
indent = data->dtpda_indent;
|
163
|
+
return INT2FIX(indent / 2);
|
164
|
+
}
|
165
|
+
else {
|
166
|
+
return Qnil;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
/* Returns the prefix given to this data by DTrace */
|
171
|
+
VALUE dtraceprobedata_prefix(VALUE self)
|
172
|
+
{
|
173
|
+
dtrace_probedata_t *data;
|
174
|
+
const char *prefix;
|
175
|
+
|
176
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
177
|
+
prefix = data->dtpda_prefix;
|
178
|
+
|
179
|
+
if (prefix)
|
180
|
+
return rb_str_new2(prefix);
|
181
|
+
else
|
182
|
+
return Qnil;
|
183
|
+
}
|
184
|
+
|
185
|
+
/* Returns the flow kind given to this data by DTrace */
|
186
|
+
VALUE dtraceprobedata_flow(VALUE self)
|
187
|
+
{
|
188
|
+
dtrace_probedata_t *data;
|
189
|
+
|
190
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
191
|
+
|
192
|
+
switch (data->dtpda_flow) {
|
193
|
+
case DTRACEFLOW_ENTRY:
|
194
|
+
return rb_str_new2("->");
|
195
|
+
break;
|
196
|
+
case DTRACEFLOW_RETURN:
|
197
|
+
return rb_str_new2("<-");
|
198
|
+
break;
|
199
|
+
default:
|
200
|
+
return Qnil;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
/*
|
205
|
+
* Yields each record in this DTraceProbedata in turn. Records are
|
206
|
+
* yielded as either DTraceRecords or DTraceStackRecords as
|
207
|
+
* appropriate for the type of action.
|
208
|
+
*/
|
209
|
+
VALUE dtraceprobedata_each_record(VALUE self)
|
210
|
+
{
|
211
|
+
dtrace_probedata_t *data;
|
212
|
+
dtrace_eprobedesc_t *eprobe;
|
213
|
+
dtrace_recdesc_t *rec;
|
214
|
+
dtrace_handle_t *handle;
|
215
|
+
dtrace_actkind_t act;
|
216
|
+
int i;
|
217
|
+
caddr_t addr;
|
218
|
+
VALUE dtracerecord;
|
219
|
+
VALUE dtrace;
|
220
|
+
VALUE v;
|
221
|
+
VALUE class;
|
222
|
+
|
223
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
224
|
+
dtrace = rb_iv_get(self, "@handle");
|
225
|
+
Data_Get_Struct(dtrace, dtrace_handle_t, handle);
|
226
|
+
|
227
|
+
eprobe = data->dtpda_edesc;
|
228
|
+
|
229
|
+
for (i = 0; i < eprobe->dtepd_nrecs; i++) {
|
230
|
+
v = 0;
|
231
|
+
rec = &eprobe->dtepd_rec[i];
|
232
|
+
if (rec->dtrd_size > 0) {
|
233
|
+
act = rec->dtrd_action;
|
234
|
+
addr = data->dtpda_data + rec->dtrd_offset;
|
235
|
+
|
236
|
+
switch (act) {
|
237
|
+
case DTRACEACT_STACK:
|
238
|
+
v = _handle_stack_record(handle->hdl, addr, rec);
|
239
|
+
class = rb_path2class("DTrace::StackRecord");
|
240
|
+
break;
|
241
|
+
case DTRACEACT_USTACK:
|
242
|
+
v = _handle_ustack_record(handle->hdl, addr, rec);
|
243
|
+
class = rb_path2class("DTrace::StackRecord");
|
244
|
+
break;
|
245
|
+
case DTRACEACT_JSTACK:
|
246
|
+
/* not sure how to handle jstack */
|
247
|
+
break;
|
248
|
+
case DTRACEACT_PRINTA:
|
249
|
+
/* don't want the probedata record for a printa() action */
|
250
|
+
break;
|
251
|
+
default:
|
252
|
+
class = rb_path2class("DTrace::Record");
|
253
|
+
switch (rec->dtrd_size) {
|
254
|
+
case 1:
|
255
|
+
v = INT2FIX((int)(*((uint8_t *)addr)));
|
256
|
+
break;
|
257
|
+
case 2:
|
258
|
+
v = INT2FIX((int)(*((uint16_t *)addr)));
|
259
|
+
break;
|
260
|
+
case 4:
|
261
|
+
v = INT2FIX(*((int32_t *)addr));
|
262
|
+
break;
|
263
|
+
case 8:
|
264
|
+
v = LL2NUM(*((int64_t *)addr));
|
265
|
+
break;
|
266
|
+
default:
|
267
|
+
v = handle_bytedata(addr, rec->dtrd_size);
|
268
|
+
break;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
if (v) {
|
273
|
+
dtracerecord = rb_class_new_instance(0, NULL, class);
|
274
|
+
rb_iv_set(dtracerecord, "@value", v);
|
275
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("probedata"));
|
276
|
+
rb_iv_set(dtracerecord, "@index", INT2FIX(i));
|
277
|
+
rb_iv_set(dtracerecord, "@action", INT2FIX(act));
|
278
|
+
rb_yield(dtracerecord);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
}
|
282
|
+
return Qnil;
|
283
|
+
}
|