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.
Files changed (88) hide show
  1. data/History.txt +34 -0
  2. data/Manifest.txt +58 -0
  3. data/README.txt +88 -0
  4. data/Rakefile +73 -0
  5. data/examples/scsi.rb +442 -0
  6. data/ext/dof/constants.c +49 -0
  7. data/ext/dof/dof.h +55 -0
  8. data/ext/dof/dof_api.c +57 -0
  9. data/ext/dof/dof_helper.c +82 -0
  10. data/ext/dof/extconf.rb +4 -0
  11. data/ext/dof/file.c +56 -0
  12. data/ext/dof/generator.c +9 -0
  13. data/ext/dof/header.c +80 -0
  14. data/ext/dof/parser.c +415 -0
  15. data/ext/dof/parser.h +10 -0
  16. data/ext/dof/section.c +302 -0
  17. data/ext/dtrace_aggdata.c +142 -0
  18. data/ext/dtrace_api.c +119 -0
  19. data/ext/dtrace_api.h +150 -0
  20. data/ext/dtrace_bufdata.c +139 -0
  21. data/ext/dtrace_dropdata.c +131 -0
  22. data/ext/dtrace_errdata.c +110 -0
  23. data/ext/dtrace_hdl.c +577 -0
  24. data/ext/dtrace_probedata.c +267 -0
  25. data/ext/dtrace_probedesc.c +78 -0
  26. data/ext/dtrace_process.c +37 -0
  27. data/ext/dtrace_program.c +62 -0
  28. data/ext/dtrace_programinfo.c +60 -0
  29. data/ext/dtrace_recdesc.c +46 -0
  30. data/ext/dtrace_util.c +92 -0
  31. data/ext/extconf.rb +28 -0
  32. data/ext/stubs.txt +78 -0
  33. data/lib/dtrace/aggregate.rb +40 -0
  34. data/lib/dtrace/aggregateset.rb +19 -0
  35. data/lib/dtrace/consumer.rb +174 -0
  36. data/lib/dtrace/data.rb +82 -0
  37. data/lib/dtrace/dof/file.rb +63 -0
  38. data/lib/dtrace/dof/section/strtab.rb +21 -0
  39. data/lib/dtrace/dof/section.rb +69 -0
  40. data/lib/dtrace/dof.rb +8 -0
  41. data/lib/dtrace/printfrecord.rb +10 -0
  42. data/lib/dtrace/probe.rb +46 -0
  43. data/lib/dtrace/probedata.rb +23 -0
  44. data/lib/dtrace/probedesc.rb +15 -0
  45. data/lib/dtrace/provider/probedef.rb +24 -0
  46. data/lib/dtrace/provider.rb +231 -0
  47. data/lib/dtrace/record.rb +11 -0
  48. data/lib/dtrace/stackrecord.rb +31 -0
  49. data/lib/dtrace/tracer.rb +35 -0
  50. data/lib/dtrace.rb +74 -0
  51. data/lib/dtraceconsumer.rb +9 -0
  52. data/plugin/dtrace/README +81 -0
  53. data/plugin/dtrace/Rakefile +22 -0
  54. data/plugin/dtrace/bin/dtracer.rb +29 -0
  55. data/plugin/dtrace/init.rb +7 -0
  56. data/plugin/dtrace/lib/dtrace_helper.rb +2 -0
  57. data/plugin/dtrace/lib/dtrace_report.rb +67 -0
  58. data/plugin/dtrace/lib/dtracer.rb +52 -0
  59. data/plugin/dtrace/lib/dtracer_client.rb +26 -0
  60. data/plugin/dtrace/public/stylesheets/dtrace.css +48 -0
  61. data/plugin/dtrace/scripts/default.d +11 -0
  62. data/plugin/dtrace/scripts/rails_mysql.d +29 -0
  63. data/plugin/dtrace/tasks/dtrace.rake +52 -0
  64. data/plugin/dtrace/test/dtrace_test.rb +8 -0
  65. data/plugin/dtrace/views/dtrace/_report.rhtml +26 -0
  66. data/test/apple-dof +0 -0
  67. data/test/disabled_probe_effect.txt +19 -0
  68. data/test/dof +0 -0
  69. data/test/dof2 +0 -0
  70. data/test/test_disabled_probe_effect.rb +60 -0
  71. data/test/test_dof_generator.rb +142 -0
  72. data/test/test_dof_helper.rb +106 -0
  73. data/test/test_dof_parser.rb +25 -0
  74. data/test/test_dof_providers.rb +282 -0
  75. data/test/test_dof_strtabs.rb +92 -0
  76. data/test/test_dtrace.rb +111 -0
  77. data/test/test_dtrace_aggregates.rb +56 -0
  78. data/test/test_dtrace_drops_errors.rb +183 -0
  79. data/test/test_dtrace_probe.rb +383 -0
  80. data/test/test_dtrace_probes.rb +400 -0
  81. data/test/test_dtrace_processes.rb +83 -0
  82. data/test/test_dtrace_profile.rb +232 -0
  83. data/test/test_dtrace_provider.rb +153 -0
  84. data/test/test_dtrace_repeat.rb +51 -0
  85. data/test/test_dtrace_rubyprobe.rb +52 -0
  86. data/test/test_dtrace_typefilter.rb +108 -0
  87. data/test/test_legacy_consumer.rb +56 -0
  88. 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
+