ruby-static-tracing 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ruby-static-tracing/lib/deps-extconf.rb +1 -1
  3. data/ext/ruby-static-tracing/lib/libstapsdt/Makefile +76 -0
  4. data/ext/ruby-static-tracing/lib/libstapsdt/example/demo.c +42 -0
  5. data/ext/ruby-static-tracing/lib/libstapsdt/src/asm/libstapsdt-x86_64.s +14 -0
  6. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.c +41 -0
  7. data/ext/ruby-static-tracing/lib/libstapsdt/src/dynamic-symbols.h +34 -0
  8. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.c +30 -0
  9. data/ext/ruby-static-tracing/lib/libstapsdt/src/errors.h +8 -0
  10. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.c +27 -0
  11. data/ext/ruby-static-tracing/lib/libstapsdt/src/hash-table.h +3 -0
  12. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.c +258 -0
  13. data/ext/ruby-static-tracing/lib/libstapsdt/src/libstapsdt.h +67 -0
  14. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.c +176 -0
  15. data/ext/ruby-static-tracing/lib/libstapsdt/src/sdtnote.h +46 -0
  16. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.c +30 -0
  17. data/ext/ruby-static-tracing/lib/libstapsdt/src/section.h +21 -0
  18. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.c +563 -0
  19. data/ext/ruby-static-tracing/lib/libstapsdt/src/shared-lib.h +46 -0
  20. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.c +67 -0
  21. data/ext/ruby-static-tracing/lib/libstapsdt/src/string-table.h +28 -0
  22. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.c +12 -0
  23. data/ext/ruby-static-tracing/lib/libstapsdt/src/util.h +6 -0
  24. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-errors.c +77 -0
  25. data/ext/ruby-static-tracing/lib/libstapsdt/tests/test-memory-leaks.c +25 -0
  26. data/ext/ruby-static-tracing/lib/libusdt/Makefile +168 -0
  27. data/ext/ruby-static-tracing/lib/libusdt/test_mem_usage.c +77 -0
  28. data/ext/ruby-static-tracing/lib/libusdt/test_usdt.c +87 -0
  29. data/ext/ruby-static-tracing/lib/libusdt/usdt.c +321 -0
  30. data/ext/ruby-static-tracing/lib/libusdt/usdt.h +65 -0
  31. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof.c +126 -0
  32. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof_file.c +290 -0
  33. data/ext/ruby-static-tracing/lib/libusdt/usdt_dof_sections.c +180 -0
  34. data/ext/ruby-static-tracing/lib/libusdt/usdt_internal.h +107 -0
  35. data/ext/ruby-static-tracing/lib/libusdt/usdt_probe.c +133 -0
  36. data/ext/ruby-static-tracing/lib/libusdt/usdt_tracepoints_i386.s +69 -0
  37. data/ext/ruby-static-tracing/lib/libusdt/usdt_tracepoints_x86_64.s +123 -0
  38. data/lib/ruby-static-tracing/version.rb +1 -1
  39. metadata +38 -2
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt.h"
6
+
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <string.h>
10
+
11
+ static void
12
+ fire_probe(usdt_probedef_t *probedef, int argc, void **argv)
13
+ {
14
+ if (usdt_is_enabled(probedef->probe))
15
+ usdt_fire_probe(probedef->probe, argc, argv);
16
+ }
17
+
18
+ int main(int argc, char **argv) {
19
+ usdt_provider_t *provider;
20
+ usdt_probedef_t *probedef;
21
+ char char_argv[USDT_ARG_MAX];
22
+ int int_argv[USDT_ARG_MAX * 2];
23
+ void **args = NULL;
24
+ int i;
25
+ char buf[255];
26
+
27
+ for (i = 0; i < USDT_ARG_MAX; i++)
28
+ int_argv[i] = i + 1;
29
+ for (i = 0; i < USDT_ARG_MAX; i++)
30
+ char_argv[i] = (char) i + 65;
31
+
32
+ if (argc < 3) {
33
+ fprintf(stderr, "usage: %s func name [types ...]\n", argv[0]);
34
+ return(1);
35
+ }
36
+
37
+ if (argc > 3) {
38
+ args = malloc((argc-3) * sizeof(void *));
39
+ }
40
+
41
+ for (i = 0; i < USDT_ARG_MAX; i++) {
42
+ if (argv[i+3] != NULL && i+3 < argc) {
43
+ if (strncmp("c", argv[i+3], 1) == 0) {
44
+ args[i] = (void *)strndup(&char_argv[i], 1);
45
+ argv[i+3] = strdup("char *");
46
+ }
47
+ if (strncmp("i", argv[i+3], 1) == 0) {
48
+ args[i] = (void *)(long)int_argv[i];
49
+ argv[i+3] = strdup("int");
50
+ }
51
+ }
52
+ }
53
+
54
+ if ((provider = usdt_create_provider("testlibusdt", "modname")) == NULL) {
55
+ fprintf(stderr, "unable to create provider\n");
56
+ exit (1);
57
+ }
58
+ if ((probedef = usdt_create_probe((const char *)argv[1],
59
+ (const char *)argv[2],
60
+ (argc-3), (const char **)&argv[3])) == NULL)
61
+ {
62
+ fprintf(stderr, "unable to create probe\n");
63
+ exit (1);
64
+ }
65
+ usdt_provider_add_probe(provider, probedef);
66
+
67
+ if ((usdt_provider_enable(provider)) < 0) {
68
+ fprintf(stderr, "unable to enable provider: %s\n", usdt_errstr(provider));
69
+ exit (1);
70
+ }
71
+
72
+ fprintf(stdout, "enabled\n");
73
+ fflush(stdout);
74
+ fgets(buf, 255, stdin);
75
+
76
+ fire_probe(probedef, (argc-3), (void **)args);
77
+ usdt_probe_release(probedef);
78
+
79
+ if ((usdt_provider_disable(provider)) < 0) {
80
+ fprintf(stderr, "unable to disable provider: %s\n", usdt_errstr(provider));
81
+ exit (1);
82
+ }
83
+
84
+ usdt_provider_free(provider);
85
+
86
+ return 0;
87
+ }
@@ -0,0 +1,321 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt_internal.h"
6
+
7
+ #include <stdarg.h>
8
+ #include <string.h>
9
+ #include <stdio.h>
10
+
11
+ char *usdt_errors[] = {
12
+ "failed to allocate memory",
13
+ "failed to allocate page-aligned memory",
14
+ "no probes defined",
15
+ "failed to load DOF: %s",
16
+ "provider is already enabled",
17
+ "failed to unload DOF: %s",
18
+ "probe named %s:%s:%s:%s already exists",
19
+ "failed to remove probe %s:%s:%s:%s"
20
+ };
21
+
22
+ static void
23
+ free_probedef(usdt_probedef_t *pd)
24
+ {
25
+ int i;
26
+
27
+ switch (pd->refcnt) {
28
+ case 1:
29
+ free((char *)pd->function);
30
+ free((char *)pd->name);
31
+ if (pd->probe) {
32
+ usdt_free_tracepoints(pd->probe);
33
+ free(pd->probe);
34
+ }
35
+ for (i = 0; i < pd->argc; i++)
36
+ free(pd->types[i]);
37
+ free(pd);
38
+ break;
39
+ case 2:
40
+ pd->refcnt = 1;
41
+ break;
42
+ default:
43
+ break;
44
+ }
45
+ }
46
+
47
+ usdt_provider_t *
48
+ usdt_create_provider(const char *name, const char *module)
49
+ {
50
+ usdt_provider_t *provider;
51
+
52
+ if ((provider = malloc(sizeof *provider)) == NULL)
53
+ return NULL;
54
+
55
+ provider->name = strdup(name);
56
+ provider->module = strdup(module);
57
+ provider->probedefs = NULL;
58
+ provider->enabled = 0;
59
+
60
+ return provider;
61
+ }
62
+
63
+ usdt_probedef_t *
64
+ usdt_create_probe(const char *func, const char *name, size_t argc, const char **types)
65
+ {
66
+ int i;
67
+ usdt_probedef_t *p;
68
+
69
+ if (argc > USDT_ARG_MAX)
70
+ argc = USDT_ARG_MAX;
71
+
72
+ if ((p = malloc(sizeof *p)) == NULL)
73
+ return (NULL);
74
+
75
+ p->refcnt = 2;
76
+ p->function = strdup(func);
77
+ p->name = strdup(name);
78
+ p->argc = argc;
79
+ p->probe = NULL;
80
+
81
+ for (i = 0; i < argc; i++)
82
+ p->types[i] = strdup(types[i]);
83
+
84
+ return (p);
85
+ }
86
+
87
+ void
88
+ usdt_probe_release(usdt_probedef_t *probedef)
89
+ {
90
+ free_probedef(probedef);
91
+ }
92
+
93
+ int
94
+ usdt_provider_add_probe(usdt_provider_t *provider, usdt_probedef_t *probedef)
95
+ {
96
+ usdt_probedef_t *pd;
97
+
98
+ if (provider->probedefs != NULL) {
99
+ for (pd = provider->probedefs; (pd != NULL); pd = pd->next) {
100
+ if ((strcmp(pd->name, probedef->name) == 0) &&
101
+ (strcmp(pd->function, probedef->function) == 0)) {
102
+ usdt_error(provider, USDT_ERROR_DUP_PROBE,
103
+ provider->name, provider->module,
104
+ probedef->function, probedef->name);
105
+ return (-1);
106
+ }
107
+ }
108
+ }
109
+
110
+ probedef->next = NULL;
111
+ if (provider->probedefs == NULL)
112
+ provider->probedefs = probedef;
113
+ else {
114
+ for (pd = provider->probedefs; (pd->next != NULL); pd = pd->next) ;
115
+ pd->next = probedef;
116
+ }
117
+
118
+ return (0);
119
+ }
120
+
121
+ int
122
+ usdt_provider_remove_probe(usdt_provider_t *provider, usdt_probedef_t *probedef)
123
+ {
124
+ usdt_probedef_t *pd, *prev_pd = NULL;
125
+
126
+ if (provider->probedefs == NULL) {
127
+ usdt_error(provider, USDT_ERROR_NOPROBES);
128
+ return (-1);
129
+ }
130
+
131
+ for (pd = provider->probedefs; (pd != NULL);
132
+ prev_pd = pd, pd = pd->next) {
133
+
134
+ if ((strcmp(pd->name, probedef->name) == 0) &&
135
+ (strcmp(pd->function, probedef->function) == 0)) {
136
+
137
+ if (prev_pd == NULL)
138
+ provider->probedefs = pd->next;
139
+ else
140
+ prev_pd->next = pd->next;
141
+
142
+ return (0);
143
+ }
144
+ }
145
+
146
+ usdt_error(provider, USDT_ERROR_REMOVE_PROBE,
147
+ provider->name, provider->module,
148
+ probedef->function, probedef->name);
149
+ return (-1);
150
+ }
151
+
152
+ int
153
+ usdt_provider_enable(usdt_provider_t *provider)
154
+ {
155
+ usdt_strtab_t strtab;
156
+ usdt_dof_file_t *file;
157
+ usdt_probedef_t *pd;
158
+ int i;
159
+ size_t size;
160
+ usdt_dof_section_t sects[5];
161
+
162
+ if (provider->enabled == 1) {
163
+ usdt_error(provider, USDT_ERROR_ALREADYENABLED);
164
+ return (0); /* not fatal */
165
+ }
166
+
167
+ if (provider->probedefs == NULL) {
168
+ usdt_error(provider, USDT_ERROR_NOPROBES);
169
+ return (-1);
170
+ }
171
+
172
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
173
+ if ((pd->probe = malloc(sizeof(*pd->probe))) == NULL) {
174
+ usdt_error(provider, USDT_ERROR_MALLOC);
175
+ return (-1);
176
+ }
177
+ }
178
+
179
+ if ((usdt_strtab_init(&strtab, 0)) < 0) {
180
+ usdt_error(provider, USDT_ERROR_MALLOC);
181
+ return (-1);
182
+ }
183
+
184
+ if ((usdt_strtab_add(&strtab, provider->name)) == 0) {
185
+ usdt_error(provider, USDT_ERROR_MALLOC);
186
+ return (-1);
187
+ }
188
+
189
+ if ((usdt_dof_probes_sect(&sects[0], provider, &strtab)) < 0)
190
+ return (-1);
191
+ if ((usdt_dof_prargs_sect(&sects[1], provider)) < 0)
192
+ return (-1);
193
+
194
+ size = usdt_provider_dof_size(provider, &strtab);
195
+ if ((file = usdt_dof_file_init(provider, size)) == NULL)
196
+ return (-1);
197
+
198
+ if ((usdt_dof_proffs_sect(&sects[2], provider, file->dof)) < 0)
199
+ return (-1);
200
+ if ((usdt_dof_prenoffs_sect(&sects[3], provider, file->dof)) < 0)
201
+ return (-1);
202
+ if ((usdt_dof_provider_sect(&sects[4], provider)) < 0)
203
+ return (-1);
204
+
205
+ for (i = 0; i < 5; i++)
206
+ usdt_dof_file_append_section(file, &sects[i]);
207
+
208
+ usdt_dof_file_generate(file, &strtab);
209
+
210
+ usdt_dof_section_free((usdt_dof_section_t *)&strtab);
211
+ for (i = 0; i < 5; i++)
212
+ usdt_dof_section_free(&sects[i]);
213
+
214
+ if ((usdt_dof_file_load(file, provider->module)) < 0) {
215
+ usdt_error(provider, USDT_ERROR_LOADDOF, strerror(errno));
216
+ return (-1);
217
+ }
218
+
219
+ provider->enabled = 1;
220
+ provider->file = file;
221
+
222
+ return (0);
223
+ }
224
+
225
+ int
226
+ usdt_provider_disable(usdt_provider_t *provider)
227
+ {
228
+ usdt_probedef_t *pd;
229
+
230
+ if (provider->enabled == 0)
231
+ return (0);
232
+
233
+ if ((usdt_dof_file_unload((usdt_dof_file_t *)provider->file)) < 0) {
234
+ usdt_error(provider, USDT_ERROR_UNLOADDOF, strerror(errno));
235
+ return (-1);
236
+ }
237
+
238
+ usdt_dof_file_free(provider->file);
239
+ provider->file = NULL;
240
+
241
+ /* We would like to free the tracepoints here too, but OS X
242
+ * (and to a lesser extent Illumos) struggle with this:
243
+ *
244
+ * If a provider is repeatedly disabled and re-enabled, and is
245
+ * allowed to reuse the same memory for its tracepoints, *and*
246
+ * there's a DTrace consumer running with enablings for these
247
+ * probes, tracepoints are not always cleaned up sufficiently
248
+ * that the newly-created probes work.
249
+ *
250
+ * Here, then, we will leak the memory holding the
251
+ * tracepoints, which serves to stop us reusing the same
252
+ * memory address for new tracepoints, avoiding the bug.
253
+ */
254
+
255
+ for (pd = provider->probedefs; (pd != NULL); pd = pd->next) {
256
+ /* may have an as yet never-enabled probe on an
257
+ otherwise enabled provider */
258
+ if (pd->probe) {
259
+ /* usdt_free_tracepoints(pd->probe); */
260
+ free(pd->probe);
261
+ pd->probe = NULL;
262
+ }
263
+ }
264
+
265
+ provider->enabled = 0;
266
+
267
+ return (0);
268
+ }
269
+
270
+ void
271
+ usdt_provider_free(usdt_provider_t *provider)
272
+ {
273
+ usdt_probedef_t *pd, *next;
274
+
275
+ for (pd = provider->probedefs; pd != NULL; pd = next) {
276
+ next = pd->next;
277
+ free_probedef(pd);
278
+ }
279
+
280
+ free((char *)provider->name);
281
+ free((char *)provider->module);
282
+ free(provider);
283
+ }
284
+
285
+ int
286
+ usdt_is_enabled(usdt_probe_t *probe)
287
+ {
288
+ if (probe != NULL)
289
+ return (*probe->isenabled_addr)();
290
+ else
291
+ return 0;
292
+ }
293
+
294
+ void
295
+ usdt_fire_probe(usdt_probe_t *probe, size_t argc, void **nargv)
296
+ {
297
+ if (probe != NULL)
298
+ usdt_probe_args(probe->probe_addr, argc, nargv);
299
+ }
300
+
301
+ static void
302
+ usdt_verror(usdt_provider_t *provider, usdt_error_t error, va_list argp)
303
+ {
304
+ vasprintf(&provider->error, usdt_errors[error], argp);
305
+ }
306
+
307
+ void
308
+ usdt_error(usdt_provider_t *provider, usdt_error_t error, ...)
309
+ {
310
+ va_list argp;
311
+
312
+ va_start(argp, error);
313
+ usdt_verror(provider, error, argp);
314
+ va_end(argp);
315
+ }
316
+
317
+ char *
318
+ usdt_errstr(usdt_provider_t *provider)
319
+ {
320
+ return (provider->error);
321
+ }
@@ -0,0 +1,65 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #ifndef __LIB_USDT_USDT_H__
6
+ #define __LIB_USDT_USDT_H__
7
+
8
+ #include <stdint.h>
9
+ #include <unistd.h>
10
+
11
+ #define USDT_ARG_MAX 32
12
+
13
+ typedef enum usdt_error {
14
+ USDT_ERROR_MALLOC = 0,
15
+ USDT_ERROR_VALLOC,
16
+ USDT_ERROR_NOPROBES,
17
+ USDT_ERROR_LOADDOF,
18
+ USDT_ERROR_ALREADYENABLED,
19
+ USDT_ERROR_UNLOADDOF,
20
+ USDT_ERROR_DUP_PROBE,
21
+ USDT_ERROR_REMOVE_PROBE
22
+ } usdt_error_t;
23
+
24
+ typedef struct usdt_probe {
25
+ int (*isenabled_addr)(void);
26
+ void *probe_addr;
27
+ } usdt_probe_t;
28
+
29
+ int usdt_is_enabled(usdt_probe_t *probe);
30
+ void usdt_fire_probe(usdt_probe_t *probe, size_t argc, void **argv);
31
+
32
+ typedef struct usdt_probedef {
33
+ const char *name;
34
+ const char *function;
35
+ size_t argc;
36
+ char *types[USDT_ARG_MAX];
37
+ struct usdt_probe *probe;
38
+ struct usdt_probedef *next;
39
+ int refcnt;
40
+ } usdt_probedef_t;
41
+
42
+ usdt_probedef_t *usdt_create_probe(const char *func, const char *name,
43
+ size_t argc, const char **types);
44
+ void usdt_probe_release(usdt_probedef_t *probedef);
45
+
46
+ typedef struct usdt_provider {
47
+ const char *name;
48
+ const char *module;
49
+ usdt_probedef_t *probedefs;
50
+ char *error;
51
+ int enabled;
52
+ void *file;
53
+ } usdt_provider_t;
54
+
55
+ usdt_provider_t *usdt_create_provider(const char *name, const char *module);
56
+ int usdt_provider_add_probe(usdt_provider_t *provider, usdt_probedef_t *probedef);
57
+ int usdt_provider_remove_probe(usdt_provider_t *provider, usdt_probedef_t *probedef);
58
+ int usdt_provider_enable(usdt_provider_t *provider);
59
+ int usdt_provider_disable(usdt_provider_t *provider);
60
+ void usdt_provider_free(usdt_provider_t *provider);
61
+
62
+ void usdt_error(usdt_provider_t *provider, usdt_error_t error, ...);
63
+ char *usdt_errstr(usdt_provider_t *provider);
64
+
65
+ #endif // __LIB_USDT_USDT_H__