ruby-static-tracing 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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__
@@ -0,0 +1,126 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt_internal.h"
6
+
7
+ int
8
+ usdt_dof_section_add_data(usdt_dof_section_t *section, void *data, size_t length)
9
+ {
10
+ int newlen = section->size + length;
11
+
12
+ if ((section->data = realloc((char *)section->data, newlen)) == NULL)
13
+ return (-1);
14
+
15
+ memcpy(section->data + section->size, data, length);
16
+ section->size = newlen;
17
+ return (0);
18
+ }
19
+
20
+ size_t
21
+ usdt_provider_dof_size(usdt_provider_t *provider, usdt_strtab_t *strtab)
22
+ {
23
+ uint8_t i, j;
24
+ int args = 0;
25
+ int probes = 0;
26
+ size_t size = 0;
27
+ usdt_probedef_t *pd;
28
+ size_t sections[8];
29
+
30
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
31
+ args += pd->argc;
32
+ probes++;
33
+ }
34
+
35
+ sections[0] = sizeof(dof_hdr_t);
36
+ sections[1] = sizeof(dof_sec_t) * 6;
37
+ sections[2] = strtab->size;
38
+ sections[3] = sizeof(dof_probe_t) * probes;
39
+ sections[4] = sizeof(uint8_t) * args;
40
+ sections[5] = sizeof(uint32_t) * probes;
41
+ sections[6] = sizeof(uint32_t) * probes;
42
+ sections[7] = sizeof(dof_provider_t);
43
+
44
+ for (i = 0; i < 8; i++) {
45
+ size += sections[i];
46
+ j = size % 8;
47
+ if (j > 0)
48
+ size += (8 - j);
49
+ }
50
+
51
+ return size;
52
+ }
53
+
54
+ int
55
+ usdt_dof_section_init(usdt_dof_section_t *section, uint32_t type, dof_secidx_t index)
56
+ {
57
+ section->type = type;
58
+ section->index = index;
59
+ section->flags = DOF_SECF_LOAD;
60
+ section->offset = 0;
61
+ section->size = 0;
62
+ section->entsize = 0;
63
+ section->pad = 0;
64
+ section->next = NULL;
65
+
66
+ if ((section->data = malloc(1)) == NULL)
67
+ return (-1);
68
+
69
+ switch(type) {
70
+ case DOF_SECT_PROBES: section->align = 8; break;
71
+ case DOF_SECT_PRARGS: section->align = 1; break;
72
+ case DOF_SECT_PROFFS: section->align = 4; break;
73
+ case DOF_SECT_PRENOFFS: section->align = 4; break;
74
+ case DOF_SECT_PROVIDER: section->align = 4; break;
75
+ }
76
+
77
+ return (0);
78
+ }
79
+
80
+ void
81
+ usdt_dof_section_free(usdt_dof_section_t *section)
82
+ {
83
+ free(section->data);
84
+ }
85
+
86
+ int
87
+ usdt_strtab_init(usdt_strtab_t *strtab, dof_secidx_t index)
88
+ {
89
+ strtab->type = DOF_SECT_STRTAB;;
90
+ strtab->index = index;
91
+ strtab->flags = DOF_SECF_LOAD;
92
+ strtab->offset = 0;
93
+ strtab->size = 0;
94
+ strtab->entsize = 0;
95
+ strtab->pad = 0;
96
+ strtab->data = NULL;
97
+ strtab->align = 1;
98
+ strtab->strindex = 1;
99
+
100
+ if ((strtab->data = (char *) malloc(1)) == NULL)
101
+ return (-1);
102
+
103
+ *strtab->data = '\0';
104
+
105
+ return (0);
106
+ }
107
+
108
+ dof_stridx_t
109
+ usdt_strtab_add(usdt_strtab_t *strtab, const char *string)
110
+ {
111
+ size_t length;
112
+ int index;
113
+
114
+ length = strlen(string);
115
+ index = strtab->strindex;
116
+ strtab->strindex += (length + 1);
117
+
118
+ if ((strtab->data = realloc(strtab->data, strtab->strindex)) == NULL)
119
+ return (0);
120
+
121
+ memcpy((char *) (strtab->data + index), (char *)string, length + 1);
122
+ strtab->size = index + length + 1;
123
+
124
+ return (index);
125
+ }
126
+