ruby-static-tracing 0.0.12 → 0.0.13

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 (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__