chrisa-ruby-dtrace 0.2.0
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 +34 -0
- data/Manifest.txt +58 -0
- data/README.txt +88 -0
- data/Rakefile +73 -0
- data/examples/scsi.rb +442 -0
- data/ext/dof/constants.c +49 -0
- data/ext/dof/dof.h +55 -0
- data/ext/dof/dof_api.c +57 -0
- data/ext/dof/dof_helper.c +82 -0
- data/ext/dof/extconf.rb +4 -0
- data/ext/dof/file.c +56 -0
- data/ext/dof/generator.c +9 -0
- data/ext/dof/header.c +80 -0
- data/ext/dof/parser.c +415 -0
- data/ext/dof/parser.h +10 -0
- data/ext/dof/section.c +302 -0
- data/ext/dtrace_aggdata.c +142 -0
- data/ext/dtrace_api.c +119 -0
- data/ext/dtrace_api.h +150 -0
- data/ext/dtrace_bufdata.c +139 -0
- data/ext/dtrace_dropdata.c +131 -0
- data/ext/dtrace_errdata.c +110 -0
- data/ext/dtrace_hdl.c +577 -0
- data/ext/dtrace_probedata.c +267 -0
- data/ext/dtrace_probedesc.c +78 -0
- data/ext/dtrace_process.c +37 -0
- data/ext/dtrace_program.c +62 -0
- data/ext/dtrace_programinfo.c +60 -0
- data/ext/dtrace_recdesc.c +46 -0
- data/ext/dtrace_util.c +92 -0
- data/ext/extconf.rb +28 -0
- data/ext/stubs.txt +78 -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 +82 -0
- data/lib/dtrace/dof/file.rb +63 -0
- data/lib/dtrace/dof/section/strtab.rb +21 -0
- data/lib/dtrace/dof/section.rb +69 -0
- data/lib/dtrace/dof.rb +8 -0
- data/lib/dtrace/printfrecord.rb +10 -0
- data/lib/dtrace/probe.rb +46 -0
- data/lib/dtrace/probedata.rb +23 -0
- data/lib/dtrace/probedesc.rb +15 -0
- data/lib/dtrace/provider/probedef.rb +24 -0
- data/lib/dtrace/provider.rb +231 -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.rb +74 -0
- data/lib/dtraceconsumer.rb +9 -0
- data/plugin/dtrace/README +81 -0
- data/plugin/dtrace/Rakefile +22 -0
- data/plugin/dtrace/bin/dtracer.rb +29 -0
- data/plugin/dtrace/init.rb +7 -0
- data/plugin/dtrace/lib/dtrace_helper.rb +2 -0
- data/plugin/dtrace/lib/dtrace_report.rb +67 -0
- data/plugin/dtrace/lib/dtracer.rb +52 -0
- data/plugin/dtrace/lib/dtracer_client.rb +26 -0
- data/plugin/dtrace/public/stylesheets/dtrace.css +48 -0
- data/plugin/dtrace/scripts/default.d +11 -0
- data/plugin/dtrace/scripts/rails_mysql.d +29 -0
- data/plugin/dtrace/tasks/dtrace.rake +52 -0
- data/plugin/dtrace/test/dtrace_test.rb +8 -0
- data/plugin/dtrace/views/dtrace/_report.rhtml +26 -0
- 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 +60 -0
- data/test/test_dof_generator.rb +142 -0
- data/test/test_dof_helper.rb +106 -0
- data/test/test_dof_parser.rb +25 -0
- data/test/test_dof_providers.rb +282 -0
- data/test/test_dof_strtabs.rb +92 -0
- data/test/test_dtrace.rb +111 -0
- data/test/test_dtrace_aggregates.rb +56 -0
- data/test/test_dtrace_drops_errors.rb +183 -0
- data/test/test_dtrace_probe.rb +383 -0
- data/test/test_dtrace_probes.rb +400 -0
- data/test/test_dtrace_processes.rb +83 -0
- data/test/test_dtrace_profile.rb +232 -0
- data/test/test_dtrace_provider.rb +153 -0
- data/test/test_dtrace_repeat.rb +51 -0
- data/test/test_dtrace_rubyprobe.rb +52 -0
- data/test/test_dtrace_typefilter.rb +108 -0
- data/test/test_legacy_consumer.rb +56 -0
- metadata +165 -0
@@ -0,0 +1,267 @@
|
|
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
|
+
VALUE stack;
|
22
|
+
stack = rb_ary_new();
|
23
|
+
|
24
|
+
/* TODO, apple and solaris ustack */
|
25
|
+
return stack;
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE _handle_stack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
|
29
|
+
{
|
30
|
+
VALUE stack = Qnil;
|
31
|
+
int size, i;
|
32
|
+
int depth;
|
33
|
+
uint64_t pc;
|
34
|
+
dtrace_syminfo_t dts;
|
35
|
+
char c[PATH_MAX * 2];
|
36
|
+
|
37
|
+
#ifdef __APPLE__
|
38
|
+
__GElf_Sym sym;
|
39
|
+
#else
|
40
|
+
GElf_Sym sym;
|
41
|
+
#endif
|
42
|
+
|
43
|
+
size = rec->dtrd_size / rec->dtrd_arg;
|
44
|
+
depth = rec->dtrd_arg;
|
45
|
+
|
46
|
+
stack = rb_ary_new();
|
47
|
+
|
48
|
+
for (i = 0; i < depth; i++) {
|
49
|
+
|
50
|
+
switch (size) {
|
51
|
+
case sizeof (uint32_t):
|
52
|
+
pc = *((uint32_t *)addr);
|
53
|
+
break;
|
54
|
+
|
55
|
+
case sizeof (uint64_t):
|
56
|
+
pc = *((uint64_t *)addr);
|
57
|
+
break;
|
58
|
+
|
59
|
+
default:
|
60
|
+
rb_raise(eDtraceException, "bad stack pc");
|
61
|
+
return Qnil;
|
62
|
+
}
|
63
|
+
|
64
|
+
if (pc == (uint64_t)NULL)
|
65
|
+
break;
|
66
|
+
|
67
|
+
addr += size;
|
68
|
+
|
69
|
+
if (dtrace_lookup_by_addr(handle, pc, &sym, &dts) == 0) {
|
70
|
+
if (pc > sym.st_value) {
|
71
|
+
(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
|
72
|
+
dts.dts_object, dts.dts_name,
|
73
|
+
pc - sym.st_value);
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
(void) snprintf(c, sizeof (c), "%s`%s",
|
77
|
+
dts.dts_object, dts.dts_name);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
else {
|
81
|
+
if (dtrace_lookup_by_addr(handle, pc, NULL, &dts) == 0) {
|
82
|
+
(void) snprintf(c, sizeof (c), "%s`0x%llx",
|
83
|
+
dts.dts_object, pc);
|
84
|
+
}
|
85
|
+
else {
|
86
|
+
(void) snprintf(c, sizeof (c), "0x%llx", pc);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
rb_ary_push(stack, rb_str_new2(c));
|
91
|
+
}
|
92
|
+
|
93
|
+
return stack;
|
94
|
+
}
|
95
|
+
|
96
|
+
/*
|
97
|
+
* Returns the enabled probe id which generated this data
|
98
|
+
*/
|
99
|
+
VALUE dtraceprobedata_epid(VALUE self)
|
100
|
+
{
|
101
|
+
dtrace_probedata_t *data;
|
102
|
+
|
103
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
104
|
+
return INT2FIX(data->dtpda_edesc->dtepd_epid);
|
105
|
+
}
|
106
|
+
|
107
|
+
/*
|
108
|
+
* Returns the DtraceProbe for the probe which generated this data
|
109
|
+
*/
|
110
|
+
VALUE dtraceprobedata_probe(VALUE self)
|
111
|
+
{
|
112
|
+
VALUE dtraceprobe;
|
113
|
+
dtrace_probedata_t *data;
|
114
|
+
dtrace_probedesc_t *pd;
|
115
|
+
|
116
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
117
|
+
pd = data->dtpda_pdesc;
|
118
|
+
|
119
|
+
if (pd) {
|
120
|
+
dtraceprobe = Data_Wrap_Struct(cDtraceProbeDesc, 0, NULL, (dtrace_probedesc_t *)pd);
|
121
|
+
return dtraceprobe;
|
122
|
+
}
|
123
|
+
|
124
|
+
return Qnil;
|
125
|
+
}
|
126
|
+
|
127
|
+
/* Returns the CPU which generated this data */
|
128
|
+
VALUE dtraceprobedata_cpu(VALUE self)
|
129
|
+
{
|
130
|
+
dtrace_probedata_t *data;
|
131
|
+
processorid_t cpu;
|
132
|
+
|
133
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
134
|
+
|
135
|
+
if (data) {
|
136
|
+
cpu = data->dtpda_cpu;
|
137
|
+
return INT2FIX(cpu);
|
138
|
+
}
|
139
|
+
else {
|
140
|
+
return Qnil;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
/* Returns the indent level given to this data by DTrace */
|
145
|
+
VALUE dtraceprobedata_indent(VALUE self)
|
146
|
+
{
|
147
|
+
dtrace_probedata_t *data;
|
148
|
+
int indent;
|
149
|
+
|
150
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
151
|
+
|
152
|
+
if (data) {
|
153
|
+
indent = data->dtpda_indent;
|
154
|
+
return INT2FIX(indent / 2);
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
/* Returns the prefix given to this data by DTrace */
|
162
|
+
VALUE dtraceprobedata_prefix(VALUE self)
|
163
|
+
{
|
164
|
+
dtrace_probedata_t *data;
|
165
|
+
const char *prefix;
|
166
|
+
|
167
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
168
|
+
prefix = data->dtpda_prefix;
|
169
|
+
|
170
|
+
if (prefix)
|
171
|
+
return rb_str_new2(prefix);
|
172
|
+
else
|
173
|
+
return Qnil;
|
174
|
+
}
|
175
|
+
|
176
|
+
/* Returns the flow kind given to this data by DTrace */
|
177
|
+
VALUE dtraceprobedata_flow(VALUE self)
|
178
|
+
{
|
179
|
+
dtrace_probedata_t *data;
|
180
|
+
|
181
|
+
Data_Get_Struct(self, dtrace_probedata_t, data);
|
182
|
+
|
183
|
+
switch (data->dtpda_flow) {
|
184
|
+
case DTRACEFLOW_ENTRY:
|
185
|
+
return rb_str_new2("->");
|
186
|
+
break;
|
187
|
+
case DTRACEFLOW_RETURN:
|
188
|
+
return rb_str_new2("<-");
|
189
|
+
break;
|
190
|
+
default:
|
191
|
+
return Qnil;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
/*
|
196
|
+
* Yields each record in this DtraceProbedata in turn. Records are
|
197
|
+
* yielded as either DtraceRecords or DtraceStackRecords as
|
198
|
+
* appropriate for the type of action.
|
199
|
+
*/
|
200
|
+
VALUE dtraceprobedata_each_record(VALUE self)
|
201
|
+
{
|
202
|
+
dtrace_probedata_t *data;
|
203
|
+
dtrace_eprobedesc_t *eprobe;
|
204
|
+
dtrace_recdesc_t *rec;
|
205
|
+
dtrace_handle_t *handle;
|
206
|
+
dtrace_actkind_t act;
|
207
|
+
int i;
|
208
|
+
caddr_t addr;
|
209
|
+
VALUE dtracerecord;
|
210
|
+
VALUE dtrace;
|
211
|
+
VALUE v;
|
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
|
+
case DTRACEACT_USTACK:
|
229
|
+
case DTRACEACT_JSTACK:
|
230
|
+
/* Stack records come from bufdata */
|
231
|
+
/* v = _handle_stack_record(handle->hdl, addr, rec); */
|
232
|
+
/* v = _handle_ustack_record(handle->hdl, addr, rec); */
|
233
|
+
break;
|
234
|
+
case DTRACEACT_PRINTA:
|
235
|
+
/* don't want the probedata record for a printa() action */
|
236
|
+
break;
|
237
|
+
default:
|
238
|
+
switch (rec->dtrd_size) {
|
239
|
+
case 1:
|
240
|
+
v = INT2FIX((int)(*((uint8_t *)addr)));
|
241
|
+
break;
|
242
|
+
case 2:
|
243
|
+
v = INT2FIX((int)(*((uint16_t *)addr)));
|
244
|
+
break;
|
245
|
+
case 4:
|
246
|
+
v = INT2FIX(*((int32_t *)addr));
|
247
|
+
break;
|
248
|
+
case 8:
|
249
|
+
v = INT2FIX(*((int64_t *)addr));
|
250
|
+
break;
|
251
|
+
default:
|
252
|
+
v = handle_bytedata(addr, rec->dtrd_size);
|
253
|
+
break;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
if (v) {
|
258
|
+
dtracerecord = rb_class_new_instance(0, NULL, rb_path2class("Dtrace::Record"));
|
259
|
+
rb_iv_set(dtracerecord, "@value", v);
|
260
|
+
rb_iv_set(dtracerecord, "@from", rb_str_new2("probedata"));
|
261
|
+
rb_iv_set(dtracerecord, "@index", INT2FIX(i));
|
262
|
+
rb_iv_set(dtracerecord, "@action", INT2FIX(act));
|
263
|
+
rb_yield(dtracerecord);
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}
|
267
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
/* :nodoc: */
|
8
|
+
VALUE dtraceprobedesc_init(VALUE self)
|
9
|
+
{
|
10
|
+
dtrace_probedesc_t *pdp;
|
11
|
+
|
12
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
13
|
+
return self;
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
* Returns the id of the probedesc. Corresponds to the ID displayed by
|
18
|
+
* dtrace -l
|
19
|
+
*/
|
20
|
+
VALUE dtraceprobedesc_probe_id(VALUE self)
|
21
|
+
{
|
22
|
+
dtrace_probedesc_t *pdp;
|
23
|
+
|
24
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
25
|
+
return INT2NUM(pdp->dtpd_id);
|
26
|
+
}
|
27
|
+
|
28
|
+
/*
|
29
|
+
* Returns the name of the probe's provider.
|
30
|
+
*/
|
31
|
+
VALUE dtraceprobedesc_provider(VALUE self)
|
32
|
+
{
|
33
|
+
VALUE string;
|
34
|
+
dtrace_probedesc_t *pdp;
|
35
|
+
|
36
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
37
|
+
string = rb_str_new2(pdp->dtpd_provider);
|
38
|
+
return string;
|
39
|
+
}
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Returns the name of the module where the probe is defined.
|
43
|
+
*/
|
44
|
+
VALUE dtraceprobedesc_mod(VALUE self)
|
45
|
+
{
|
46
|
+
VALUE string;
|
47
|
+
dtrace_probedesc_t *pdp;
|
48
|
+
|
49
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
50
|
+
string = rb_str_new2(pdp->dtpd_mod);
|
51
|
+
return string;
|
52
|
+
}
|
53
|
+
|
54
|
+
/*
|
55
|
+
* Returns the name of the function where the probe is defined.
|
56
|
+
*/
|
57
|
+
VALUE dtraceprobedesc_func(VALUE self)
|
58
|
+
{
|
59
|
+
VALUE string;
|
60
|
+
dtrace_probedesc_t *pdp;
|
61
|
+
|
62
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
63
|
+
string = rb_str_new2(pdp->dtpd_func);
|
64
|
+
return string;
|
65
|
+
}
|
66
|
+
|
67
|
+
/*
|
68
|
+
* Returns the name of the probe.
|
69
|
+
*/
|
70
|
+
VALUE dtraceprobedesc_name(VALUE self)
|
71
|
+
{
|
72
|
+
VALUE string;
|
73
|
+
dtrace_probedesc_t *pdp;
|
74
|
+
|
75
|
+
Data_Get_Struct(self, dtrace_probedesc_t, pdp);
|
76
|
+
string = rb_str_new2(pdp->dtpd_name);
|
77
|
+
return string;
|
78
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
/* :nodoc: */
|
8
|
+
VALUE dtrace_process_init(VALUE self)
|
9
|
+
{
|
10
|
+
dtrace_process_t *process;
|
11
|
+
|
12
|
+
Data_Get_Struct(self, dtrace_process_t, process);
|
13
|
+
if (process)
|
14
|
+
return self;
|
15
|
+
else
|
16
|
+
return Qnil;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* :nodoc: */
|
20
|
+
void dtrace_process_release(dtrace_process_t *process)
|
21
|
+
{
|
22
|
+
dtrace_proc_release(process->handle, process->proc);
|
23
|
+
free(process);
|
24
|
+
}
|
25
|
+
|
26
|
+
/*
|
27
|
+
* Start or restart the process. Call this having configured tracing
|
28
|
+
* for the process, using $target in the D program.
|
29
|
+
*/
|
30
|
+
VALUE dtrace_process_continue(VALUE self)
|
31
|
+
{
|
32
|
+
dtrace_process_t *process;
|
33
|
+
|
34
|
+
Data_Get_Struct(self, dtrace_process_t, process);
|
35
|
+
dtrace_proc_continue(process->handle, process->proc);
|
36
|
+
}
|
37
|
+
|
@@ -0,0 +1,62 @@
|
|
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 cDtraceProgramInfo;
|
9
|
+
|
10
|
+
/* :nodoc: */
|
11
|
+
VALUE dtraceprogram_init(VALUE self)
|
12
|
+
{
|
13
|
+
dtrace_prog_t *prog;
|
14
|
+
|
15
|
+
Data_Get_Struct(self, dtrace_prog_t, prog);
|
16
|
+
return self;
|
17
|
+
}
|
18
|
+
|
19
|
+
/*
|
20
|
+
* Execute the D program. Returns a DtraceProgramInfo object if
|
21
|
+
* successful, otherwise raises a DtraceException.
|
22
|
+
*/
|
23
|
+
VALUE dtraceprogram_exec(VALUE self)
|
24
|
+
{
|
25
|
+
dtrace_prog_t *prog;
|
26
|
+
dtrace_proginfo_t *proginfo;
|
27
|
+
dtrace_handle_t *handle;
|
28
|
+
VALUE dtrace;
|
29
|
+
VALUE dtraceprograminfo;
|
30
|
+
int ret;
|
31
|
+
|
32
|
+
Data_Get_Struct(self, dtrace_prog_t, prog);
|
33
|
+
dtrace = rb_iv_get(self, "@handle");
|
34
|
+
Data_Get_Struct(dtrace, dtrace_handle_t, handle);
|
35
|
+
|
36
|
+
proginfo = ALLOC(dtrace_proginfo_t);
|
37
|
+
if (!proginfo) {
|
38
|
+
rb_raise(eDtraceException, "alloc failed");
|
39
|
+
return Qnil;
|
40
|
+
}
|
41
|
+
|
42
|
+
ret = dtrace_program_exec(handle->hdl, prog, proginfo);
|
43
|
+
|
44
|
+
if (ret == 0) {
|
45
|
+
dtraceprograminfo = Data_Wrap_Struct(cDtraceProgramInfo, 0, NULL, proginfo);
|
46
|
+
rb_iv_set(self, "@proginfo", dtraceprograminfo);
|
47
|
+
}
|
48
|
+
|
49
|
+
if (ret < 0)
|
50
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
|
51
|
+
|
52
|
+
return Qnil;
|
53
|
+
}
|
54
|
+
|
55
|
+
/*
|
56
|
+
* Return this program's DtraceProgramInfo object. Returns nil unless
|
57
|
+
* the program has been executed.
|
58
|
+
*/
|
59
|
+
VALUE dtraceprogram_info(VALUE self)
|
60
|
+
{
|
61
|
+
return rb_iv_get(self, "@proginfo");
|
62
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
/* :nodoc: */
|
8
|
+
VALUE dtraceprograminfo_init(VALUE self)
|
9
|
+
{
|
10
|
+
dtrace_proginfo_t *proginfo;
|
11
|
+
|
12
|
+
Data_Get_Struct(self, dtrace_proginfo_t, proginfo);
|
13
|
+
return self;
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
* Returns the number of aggregates associated with this program.
|
18
|
+
*/
|
19
|
+
VALUE dtraceprograminfo_aggregates_count(VALUE self)
|
20
|
+
{
|
21
|
+
dtrace_proginfo_t *proginfo;
|
22
|
+
|
23
|
+
Data_Get_Struct(self, dtrace_proginfo_t, proginfo);
|
24
|
+
return INT2NUM(proginfo->dpi_aggregates);
|
25
|
+
}
|
26
|
+
|
27
|
+
/*
|
28
|
+
* Returns the number of record generating probes associated with this
|
29
|
+
* program.
|
30
|
+
*/
|
31
|
+
VALUE dtraceprograminfo_recgens_count(VALUE self)
|
32
|
+
{
|
33
|
+
dtrace_proginfo_t *proginfo;
|
34
|
+
|
35
|
+
Data_Get_Struct(self, dtrace_proginfo_t, proginfo);
|
36
|
+
return INT2NUM(proginfo->dpi_recgens);
|
37
|
+
}
|
38
|
+
|
39
|
+
/*
|
40
|
+
* Returns the number of probes matched by this program.
|
41
|
+
*/
|
42
|
+
VALUE dtraceprograminfo_matches_count(VALUE self)
|
43
|
+
{
|
44
|
+
dtrace_proginfo_t *proginfo;
|
45
|
+
|
46
|
+
Data_Get_Struct(self, dtrace_proginfo_t, proginfo);
|
47
|
+
return INT2NUM(proginfo->dpi_matches);
|
48
|
+
}
|
49
|
+
|
50
|
+
/*
|
51
|
+
* Returns the number of speculations specified by this program.
|
52
|
+
*/
|
53
|
+
VALUE dtraceprograminfo_speculations_count(VALUE self)
|
54
|
+
{
|
55
|
+
dtrace_proginfo_t *proginfo;
|
56
|
+
|
57
|
+
Data_Get_Struct(self, dtrace_proginfo_t, proginfo);
|
58
|
+
return INT2NUM(proginfo->dpi_speculations);
|
59
|
+
}
|
60
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
/* :nodoc: */
|
8
|
+
VALUE dtracerecdesc_init(VALUE self)
|
9
|
+
{
|
10
|
+
dtrace_recdesc_t *recdesc;
|
11
|
+
|
12
|
+
Data_Get_Struct(self, dtrace_recdesc_t, recdesc);
|
13
|
+
return self;
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
* Returns the type of action which generated this recdesc.
|
18
|
+
* (exit, printf, printa or "other" for all other actions).
|
19
|
+
*/
|
20
|
+
VALUE dtracerecdesc_action(VALUE self)
|
21
|
+
{
|
22
|
+
dtrace_recdesc_t *recdesc;
|
23
|
+
VALUE v;
|
24
|
+
Data_Get_Struct(self, dtrace_recdesc_t, recdesc);
|
25
|
+
|
26
|
+
if (recdesc){
|
27
|
+
switch (recdesc->dtrd_action) {
|
28
|
+
case DTRACEACT_EXIT:
|
29
|
+
v = rb_str_new2("exit");
|
30
|
+
break;
|
31
|
+
case DTRACEACT_PRINTF:
|
32
|
+
v = rb_str_new2("printf");
|
33
|
+
break;
|
34
|
+
case DTRACEACT_PRINTA:
|
35
|
+
v = rb_str_new2("printa");
|
36
|
+
break;
|
37
|
+
default:
|
38
|
+
v = rb_str_new2("other");
|
39
|
+
break;
|
40
|
+
}
|
41
|
+
return v;
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
return Qnil;
|
45
|
+
}
|
46
|
+
}
|
data/ext/dtrace_util.c
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
#include <ctype.h>
|
7
|
+
|
8
|
+
RUBY_EXTERN VALUE eDtraceException;
|
9
|
+
|
10
|
+
/*
|
11
|
+
* Most of this function lifted from libdtrace/common/dt_consume.c
|
12
|
+
* dt_print_bytes().
|
13
|
+
*/
|
14
|
+
VALUE handle_bytedata(caddr_t addr, uint32_t nbytes)
|
15
|
+
{
|
16
|
+
/*
|
17
|
+
* If the byte stream is a series of printable characters, followed by
|
18
|
+
* a terminating byte, we print it out as a string. Otherwise, we
|
19
|
+
* assume that it's something else and just print the bytes.
|
20
|
+
*/
|
21
|
+
int i, j;
|
22
|
+
char *c = addr;
|
23
|
+
|
24
|
+
VALUE robj;
|
25
|
+
|
26
|
+
if (nbytes == 0) {
|
27
|
+
return rb_str_new2("");
|
28
|
+
}
|
29
|
+
|
30
|
+
for (i = 0; i < nbytes; i++) {
|
31
|
+
/*
|
32
|
+
* We define a "printable character" to be one for which
|
33
|
+
* isprint(3C) returns non-zero, isspace(3C) returns non-zero,
|
34
|
+
* or a character which is either backspace or the bell.
|
35
|
+
* Backspace and the bell are regrettably special because
|
36
|
+
* they fail the first two tests -- and yet they are entirely
|
37
|
+
* printable. These are the only two control characters that
|
38
|
+
* have meaning for the terminal and for which isprint(3C) and
|
39
|
+
* isspace(3C) return 0.
|
40
|
+
*/
|
41
|
+
if (isprint(c[i]) || isspace(c[i]) ||
|
42
|
+
c[i] == '\b' || c[i] == '\a')
|
43
|
+
continue;
|
44
|
+
|
45
|
+
if (c[i] == '\0' && i > 0) {
|
46
|
+
/*
|
47
|
+
* This looks like it might be a string. Before we
|
48
|
+
* assume that it is indeed a string, check the
|
49
|
+
* remainder of the byte range; if it contains
|
50
|
+
* additional non-nul characters, we'll assume that
|
51
|
+
* it's a binary stream that just happens to look like
|
52
|
+
* a string.
|
53
|
+
*/
|
54
|
+
for (j = i + 1; j < nbytes; j++) {
|
55
|
+
if (c[j] != '\0')
|
56
|
+
break;
|
57
|
+
}
|
58
|
+
|
59
|
+
if (j != nbytes)
|
60
|
+
break;
|
61
|
+
|
62
|
+
/* It's a string */
|
63
|
+
return (rb_str_new2((char *)addr));
|
64
|
+
}
|
65
|
+
|
66
|
+
break;
|
67
|
+
}
|
68
|
+
|
69
|
+
if (i == nbytes) {
|
70
|
+
/*
|
71
|
+
* The byte range is all printable characters, but there is
|
72
|
+
* no trailing nul byte. We'll assume that it's a string.
|
73
|
+
*/
|
74
|
+
char *s = malloc(nbytes + 1);
|
75
|
+
if (!s) {
|
76
|
+
rb_raise(eDtraceException, "out of memory: failed to allocate string value");
|
77
|
+
return (Qnil);
|
78
|
+
}
|
79
|
+
(void) strncpy(s, c, nbytes);
|
80
|
+
s[nbytes] = '\0';
|
81
|
+
robj = rb_str_new2(s);
|
82
|
+
free(s);
|
83
|
+
return (robj);
|
84
|
+
}
|
85
|
+
|
86
|
+
/* return byte array */
|
87
|
+
robj = rb_ary_new();
|
88
|
+
for (i = 0; i < nbytes; i++)
|
89
|
+
rb_ary_push(robj, INT2FIX(addr[i]));
|
90
|
+
|
91
|
+
return (robj);
|
92
|
+
}
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
def symlink(old, new)
|
5
|
+
if File.exists?(new) && File.symlink?(new)
|
6
|
+
File.unlink(new)
|
7
|
+
end
|
8
|
+
File.symlink(old, new)
|
9
|
+
end
|
10
|
+
|
11
|
+
$CFLAGS += " -D_LONGLONG_TYPE -g"
|
12
|
+
have_library("dtrace", "dtrace_open")
|
13
|
+
|
14
|
+
# Update machine-dependent symlinks in the source, based on $Config::CONFIG
|
15
|
+
|
16
|
+
cpu = Config::CONFIG['target_cpu']
|
17
|
+
os = Config::CONFIG['target_os']
|
18
|
+
|
19
|
+
cpu.gsub! /^i[4-6]86/, 'i386'
|
20
|
+
os.gsub! /[0-9.]+$/, ''
|
21
|
+
|
22
|
+
dir = "#{cpu}-#{os}"
|
23
|
+
symlink "#{dir}/dtrace_probe.c", "dtrace_probe.c"
|
24
|
+
|
25
|
+
# Create makefile in the usual way
|
26
|
+
|
27
|
+
create_makefile("dtrace_api")
|
28
|
+
|