ruby-usdt 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt_internal.h"
6
+
7
+ #include <stdlib.h>
8
+
9
+ int
10
+ usdt_dof_section_add_data(usdt_dof_section_t *section, void *data, size_t length)
11
+ {
12
+ int newlen = section->size + length;
13
+
14
+ if ((section->data = realloc((char *)section->data, newlen)) == NULL)
15
+ return (-1);
16
+
17
+ memcpy(section->data + section->size, data, length);
18
+ section->size = newlen;
19
+ return (0);
20
+ }
21
+
22
+ size_t
23
+ usdt_provider_dof_size(usdt_provider_t *provider, usdt_strtab_t *strtab)
24
+ {
25
+ uint8_t i, j;
26
+ int args = 0;
27
+ int probes = 0;
28
+ size_t size = 0;
29
+ usdt_probedef_t *pd;
30
+ size_t sections[8];
31
+
32
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
33
+ args += pd->argc;
34
+ probes++;
35
+ }
36
+
37
+ sections[0] = sizeof(dof_hdr_t);
38
+ sections[1] = sizeof(dof_sec_t) * 6;
39
+ sections[2] = strtab->size;
40
+ sections[3] = sizeof(dof_probe_t) * probes;
41
+ sections[4] = sizeof(uint8_t) * args;
42
+ sections[5] = sizeof(uint32_t) * probes;
43
+ sections[6] = sizeof(uint32_t) * probes;
44
+ sections[7] = sizeof(dof_provider_t);
45
+
46
+ for (i = 0; i < 8; i++) {
47
+ size += sections[i];
48
+ j = size % 8;
49
+ if (j > 0)
50
+ size += (8 - j);
51
+ }
52
+
53
+ return size;
54
+ }
55
+
56
+ int
57
+ usdt_dof_section_init(usdt_dof_section_t *section, uint32_t type, dof_secidx_t index)
58
+ {
59
+ section->type = type;
60
+ section->index = index;
61
+ section->flags = DOF_SECF_LOAD;
62
+ section->offset = 0;
63
+ section->size = 0;
64
+ section->entsize = 0;
65
+ section->pad = 0;
66
+ section->next = NULL;
67
+
68
+ if ((section->data = malloc(1)) == NULL)
69
+ return (-1);
70
+
71
+ switch(type) {
72
+ case DOF_SECT_PROBES: section->align = 8; break;
73
+ case DOF_SECT_PRARGS: section->align = 1; break;
74
+ case DOF_SECT_PROFFS: section->align = 4; break;
75
+ case DOF_SECT_PRENOFFS: section->align = 4; break;
76
+ case DOF_SECT_PROVIDER: section->align = 4; break;
77
+ }
78
+
79
+ return (0);
80
+ }
81
+
82
+ void
83
+ usdt_dof_section_free(usdt_dof_section_t *section)
84
+ {
85
+ free(section->data);
86
+ }
87
+
88
+ int
89
+ usdt_strtab_init(usdt_strtab_t *strtab, dof_secidx_t index)
90
+ {
91
+ strtab->type = DOF_SECT_STRTAB;;
92
+ strtab->index = index;
93
+ strtab->flags = DOF_SECF_LOAD;
94
+ strtab->offset = 0;
95
+ strtab->size = 0;
96
+ strtab->entsize = 0;
97
+ strtab->pad = 0;
98
+ strtab->data = NULL;
99
+ strtab->align = 1;
100
+ strtab->strindex = 1;
101
+
102
+ if ((strtab->data = (char *) malloc(1)) == NULL)
103
+ return (-1);
104
+
105
+ *strtab->data = '\0';
106
+
107
+ return (0);
108
+ }
109
+
110
+ dof_stridx_t
111
+ usdt_strtab_add(usdt_strtab_t *strtab, const char *string)
112
+ {
113
+ size_t length;
114
+ int index;
115
+
116
+ length = strlen(string);
117
+ index = strtab->strindex;
118
+ strtab->strindex += (length + 1);
119
+
120
+ if ((strtab->data = realloc(strtab->data, strtab->strindex)) == NULL)
121
+ return (0);
122
+
123
+ memcpy((char *) (strtab->data + index), (char *)string, length + 1);
124
+ strtab->size = index + length + 1;
125
+
126
+ return (index);
127
+ }
128
+
@@ -0,0 +1,277 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt_internal.h"
6
+
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+
10
+ static uint8_t
11
+ dof_version(uint8_t header_version)
12
+ {
13
+ uint8_t dof_version;
14
+ /* DOF versioning: Apple always needs version 3, but Solaris can use
15
+ 1 or 2 depending on whether is-enabled probes are needed. */
16
+ #ifdef __APPLE__
17
+ dof_version = DOF_VERSION_3;
18
+ #else
19
+ switch(header_version) {
20
+ case 1:
21
+ dof_version = DOF_VERSION_1;
22
+ break;
23
+ case 2:
24
+ dof_version = DOF_VERSION_2;
25
+ break;
26
+ default:
27
+ dof_version = DOF_VERSION;
28
+ }
29
+ #endif
30
+ return dof_version;
31
+ }
32
+
33
+ #ifdef __APPLE__
34
+ static const char *helper = "/dev/dtracehelper";
35
+
36
+ static int
37
+ load_dof(int fd, dof_helper_t *dh)
38
+ {
39
+ int ret;
40
+ uint8_t buffer[sizeof(dof_ioctl_data_t) + sizeof(dof_helper_t)];
41
+ dof_ioctl_data_t* ioctlData = (dof_ioctl_data_t*)buffer;
42
+ user_addr_t val;
43
+
44
+ ioctlData->dofiod_count = 1;
45
+ memcpy(&ioctlData->dofiod_helpers[0], dh, sizeof(dof_helper_t));
46
+
47
+ val = (user_addr_t)(unsigned long)ioctlData;
48
+ ret = ioctl(fd, DTRACEHIOC_ADDDOF, &val);
49
+
50
+ if (ret < 0)
51
+ return ret;
52
+
53
+ return (int)(ioctlData->dofiod_helpers[0].dofhp_dof);
54
+ }
55
+
56
+ #else /* Solaris */
57
+
58
+ /* ignore Sol10 GA ... */
59
+ static const char *helper = "/dev/dtrace/helper";
60
+
61
+ static int
62
+ load_dof(int fd, dof_helper_t *dh)
63
+ {
64
+ return ioctl(fd, DTRACEHIOC_ADDDOF, dh);
65
+ }
66
+
67
+ #endif
68
+
69
+ static void
70
+ pad_section(usdt_dof_section_t *sec)
71
+ {
72
+ size_t i, pad;
73
+
74
+ if (sec->align > 1) {
75
+ i = sec->offset % sec->align;
76
+ if (i > 0) {
77
+ pad = sec->align - i;
78
+ sec->offset = (pad + sec->offset);
79
+ sec->pad = pad;
80
+ }
81
+ }
82
+ }
83
+
84
+ static void
85
+ dof_header(dof_hdr_t *header)
86
+ {
87
+ int i;
88
+
89
+ header->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;
90
+ header->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;
91
+ header->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;
92
+ header->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;
93
+
94
+ header->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE;
95
+ header->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
96
+ header->dofh_ident[DOF_ID_VERSION] = dof_version(2);
97
+ header->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION;
98
+ header->dofh_ident[DOF_ID_DIFIREG] = DIF_DIR_NREGS;
99
+ header->dofh_ident[DOF_ID_DIFTREG] = DIF_DTR_NREGS;
100
+
101
+ for (i = DOF_ID_PAD; i < DOF_ID_SIZE; i++)
102
+ header->dofh_ident[i] = 0;
103
+
104
+ header->dofh_flags = 0;
105
+
106
+ header->dofh_hdrsize = sizeof(dof_hdr_t);
107
+ header->dofh_secsize = sizeof(dof_sec_t);
108
+ header->dofh_secoff = sizeof(dof_hdr_t);
109
+
110
+ header->dofh_loadsz = 0;
111
+ header->dofh_filesz = 0;
112
+ header->dofh_pad = 0;
113
+ }
114
+
115
+ static size_t
116
+ add_header(usdt_dof_file_t *file, size_t offset, usdt_dof_section_t *section)
117
+ {
118
+ dof_sec_t header;
119
+
120
+ header.dofs_flags = section->flags;
121
+ header.dofs_type = section->type;
122
+ header.dofs_offset = section->offset;
123
+ header.dofs_size = section->size;
124
+ header.dofs_entsize = section->entsize;
125
+ header.dofs_align = section->align;
126
+
127
+ memcpy((file->dof + offset), &header, sizeof(dof_sec_t));
128
+ return (offset + sizeof(dof_sec_t));
129
+ }
130
+
131
+ static size_t
132
+ add_section(usdt_dof_file_t *file, size_t offset, usdt_dof_section_t *section)
133
+ {
134
+ if (section->pad > 0) {
135
+ /* maximum padding required is 7 */
136
+ memcpy((file->dof + offset), "\0\0\0\0\0\0\0", section->pad);
137
+ offset += section->pad;
138
+ }
139
+
140
+ memcpy((file->dof + offset), section->data, section->size);
141
+ return (offset + section->size);
142
+ }
143
+
144
+ int
145
+ usdt_dof_file_unload(usdt_dof_file_t *file)
146
+ {
147
+ int fd, ret;
148
+
149
+ if ((fd = open(helper, O_RDWR)) < 0)
150
+ return (-1);
151
+
152
+ ret = ioctl(fd, DTRACEHIOC_REMOVE, file->gen);
153
+
154
+ if (ret < 0)
155
+ return (-1);
156
+
157
+ if ((close(fd)) < 0)
158
+ return (-1);
159
+
160
+ return (0);
161
+ }
162
+
163
+ int
164
+ usdt_dof_file_load(usdt_dof_file_t *file, const char *module)
165
+ {
166
+ dof_helper_t dh;
167
+ dof_hdr_t *dof;
168
+ int fd;
169
+
170
+ dof = (dof_hdr_t *) file->dof;
171
+
172
+ dh.dofhp_dof = (uintptr_t)dof;
173
+ dh.dofhp_addr = (uintptr_t)dof;
174
+ (void) strncpy(dh.dofhp_mod, module, sizeof (dh.dofhp_mod));
175
+
176
+ if ((fd = open(helper, O_RDWR)) < 0)
177
+ return (-1);
178
+
179
+ file->gen = load_dof(fd, &dh);
180
+
181
+ if ((close(fd)) < 0)
182
+ return (-1);
183
+
184
+ if (file->gen < 0)
185
+ return (-1);
186
+
187
+ return (0);
188
+ }
189
+
190
+ void
191
+ usdt_dof_file_append_section(usdt_dof_file_t *file, usdt_dof_section_t *section)
192
+ {
193
+ usdt_dof_section_t *s;
194
+
195
+ if (file->sections == NULL) {
196
+ file->sections = section;
197
+ }
198
+ else {
199
+ for (s = file->sections; (s->next != NULL); s = s->next) ;
200
+ s->next = section;
201
+ }
202
+ }
203
+
204
+ void
205
+ usdt_dof_file_generate(usdt_dof_file_t *file, usdt_strtab_t *strtab)
206
+ {
207
+ dof_hdr_t header;
208
+ uint64_t filesz;
209
+ uint64_t loadsz;
210
+ usdt_dof_section_t *sec;
211
+ size_t offset;
212
+
213
+ dof_header(&header);
214
+ header.dofh_secnum = 6;
215
+
216
+ filesz = sizeof(dof_hdr_t) + (sizeof(dof_sec_t) * header.dofh_secnum);
217
+ loadsz = filesz;
218
+
219
+ strtab->offset = filesz;
220
+ pad_section((usdt_dof_section_t *)strtab);
221
+ filesz += strtab->size + strtab->pad;
222
+
223
+ if (strtab->flags & 1)
224
+ loadsz += strtab->size + strtab->pad;
225
+
226
+ for (sec = file->sections; sec != NULL; sec = sec->next) {
227
+ sec->offset = filesz;
228
+ pad_section(sec);
229
+ filesz += sec->size + sec->pad;
230
+ if (sec->flags & 1)
231
+ loadsz += sec->size + sec->pad;
232
+ }
233
+
234
+ header.dofh_loadsz = loadsz;
235
+ header.dofh_filesz = filesz;
236
+ memcpy(file->dof, &header, sizeof(dof_hdr_t));
237
+
238
+ offset = sizeof(dof_hdr_t);
239
+
240
+ offset = add_header(file, offset, (usdt_dof_section_t *)strtab);
241
+
242
+ for (sec = file->sections; sec != NULL; sec = sec->next)
243
+ offset = add_header(file, offset, sec);
244
+
245
+ offset = add_section(file, offset, (usdt_dof_section_t *)strtab);
246
+
247
+ for (sec = file->sections; sec != NULL; sec = sec->next)
248
+ offset = add_section(file, offset, sec);
249
+ }
250
+
251
+ usdt_dof_file_t *
252
+ usdt_dof_file_init(usdt_provider_t *provider, size_t size)
253
+ {
254
+ usdt_dof_file_t *file;
255
+
256
+ if ((file = malloc(sizeof(*file))) == NULL) {
257
+ usdt_error(provider, USDT_ERROR_MALLOC);
258
+ return (NULL);
259
+ }
260
+
261
+ if ((file->dof = valloc(size)) == NULL) {
262
+ usdt_error(provider, USDT_ERROR_VALLOC);
263
+ return (NULL);
264
+ }
265
+
266
+ file->sections = NULL;
267
+ file->size = size;
268
+
269
+ return (file);
270
+ }
271
+
272
+ void
273
+ usdt_dof_file_free(usdt_dof_file_t *file)
274
+ {
275
+ free(file->dof);
276
+ free(file);
277
+ }
@@ -0,0 +1,190 @@
1
+ /*
2
+ * Copyright (c) 2012, Chris Andrews. All rights reserved.
3
+ */
4
+
5
+ #include "usdt_internal.h"
6
+
7
+ int
8
+ usdt_dof_probes_sect(usdt_dof_section_t *probes,
9
+ usdt_provider_t *provider, usdt_strtab_t *strtab)
10
+ {
11
+ usdt_probedef_t *pd;
12
+ dof_probe_t p;
13
+ dof_stridx_t type, argv;
14
+ uint8_t argc, i;
15
+ uint32_t argidx = 0;
16
+ uint32_t offidx = 0;
17
+
18
+ usdt_dof_section_init(probes, DOF_SECT_PROBES, 1);
19
+
20
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
21
+ argc = 0;
22
+ argv = 0;
23
+ type = 0;
24
+
25
+ for (i = 0; i < pd->argc; i++) {
26
+ switch(pd->types[i]) {
27
+ case USDT_ARGTYPE_INTEGER:
28
+ type = usdt_strtab_add(strtab, "int");
29
+ break;
30
+ case USDT_ARGTYPE_STRING:
31
+ type = usdt_strtab_add(strtab, "char *");
32
+ break;
33
+ default:
34
+ break;
35
+ }
36
+
37
+ argc++;
38
+ if (argv == 0)
39
+ argv = type;
40
+ }
41
+
42
+ if (usdt_create_tracepoints(pd->probe) < 0) {
43
+ usdt_error(provider, USDT_ERROR_VALLOC);
44
+ return (-1);
45
+ }
46
+
47
+ #ifdef __x86_64__
48
+ p.dofpr_addr = (uint64_t) pd->probe->isenabled_addr;
49
+ #elif __i386__ || __i386
50
+ p.dofpr_addr = (uint32_t) pd->probe->isenabled_addr;
51
+ #else
52
+ #error "only x86_64 and i386 supported"
53
+ #endif
54
+ p.dofpr_func = usdt_strtab_add(strtab, pd->function);
55
+ p.dofpr_name = usdt_strtab_add(strtab, pd->name);
56
+ p.dofpr_nargv = argv;
57
+ p.dofpr_xargv = argv;
58
+ p.dofpr_argidx = argidx;
59
+ p.dofpr_offidx = offidx;
60
+ p.dofpr_nargc = argc;
61
+ p.dofpr_xargc = argc;
62
+ p.dofpr_noffs = 1;
63
+ p.dofpr_enoffidx = offidx;
64
+ p.dofpr_nenoffs = 1;
65
+ p.dofpr_pad1 = 0;
66
+ p.dofpr_pad2 = 0;
67
+
68
+ usdt_dof_section_add_data(probes, &p, sizeof(dof_probe_t));
69
+ probes->entsize = sizeof(dof_probe_t);
70
+
71
+ argidx += argc;
72
+ offidx++;
73
+ }
74
+
75
+ return (0);
76
+ }
77
+
78
+ int
79
+ usdt_dof_prargs_sect(usdt_dof_section_t *prargs, usdt_provider_t *provider)
80
+ {
81
+ usdt_probedef_t *pd;
82
+ uint8_t i;
83
+
84
+ usdt_dof_section_init(prargs, DOF_SECT_PRARGS, 2);
85
+ prargs->entsize = 1;
86
+
87
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
88
+ for (i = 0; i < pd->argc; i++)
89
+ usdt_dof_section_add_data(prargs, &i, 1);
90
+ }
91
+ if (prargs->size == 0) {
92
+ i = 0;
93
+ if (usdt_dof_section_add_data(prargs, &i, 1) < 0) {
94
+ usdt_error(provider, USDT_ERROR_MALLOC);
95
+ return (-1);
96
+ }
97
+ }
98
+
99
+ return (0);
100
+ }
101
+
102
+ int
103
+ usdt_dof_proffs_sect(usdt_dof_section_t *proffs,
104
+ usdt_provider_t *provider, char *dof)
105
+ {
106
+ usdt_probedef_t *pd;
107
+ uint32_t off;
108
+
109
+ usdt_dof_section_init(proffs, DOF_SECT_PROFFS, 3);
110
+ proffs->entsize = 4;
111
+
112
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
113
+ off = usdt_probe_offset(pd->probe, dof, pd->argc);
114
+ if (usdt_dof_section_add_data(proffs, &off, 4) < 0) {
115
+ usdt_error(provider, USDT_ERROR_MALLOC);
116
+ return (-1);
117
+ }
118
+ }
119
+
120
+ return (0);
121
+ }
122
+
123
+ int
124
+ usdt_dof_prenoffs_sect(usdt_dof_section_t *prenoffs,
125
+ usdt_provider_t *provider, char *dof)
126
+ {
127
+ usdt_probedef_t *pd;
128
+ uint32_t off;
129
+
130
+ usdt_dof_section_init(prenoffs, DOF_SECT_PRENOFFS, 4);
131
+ prenoffs->entsize = 4;
132
+
133
+ for (pd = provider->probedefs; pd != NULL; pd = pd->next) {
134
+ off = usdt_is_enabled_offset(pd->probe, dof);
135
+ if (usdt_dof_section_add_data(prenoffs, &off, 4) < 0) {
136
+ usdt_error(provider, USDT_ERROR_MALLOC);
137
+ return (-1);
138
+ }
139
+ }
140
+
141
+ return (0);
142
+ }
143
+
144
+ int
145
+ usdt_dof_provider_sect(usdt_dof_section_t *provider_s, usdt_provider_t *provider)
146
+ {
147
+ dof_provider_t p;
148
+
149
+ usdt_dof_section_init(provider_s, DOF_SECT_PROVIDER, 5);
150
+
151
+ p.dofpv_strtab = 0;
152
+ p.dofpv_probes = 1;
153
+ p.dofpv_prargs = 2;
154
+ p.dofpv_proffs = 3;
155
+ p.dofpv_prenoffs = 4;
156
+ p.dofpv_name = 1; /* provider name always first strtab entry. */
157
+
158
+ /*
159
+ * Stability is something of a hack. Everything is marked *
160
+ * "stable" here to permit use of the "args" array, which is *
161
+ * needed to access arguments past "arg9".
162
+ *
163
+ * It should be up to the creator of the provider to decide
164
+ * this, though, and it should be possible to set the
165
+ * appropriate stability at creation time.
166
+ */
167
+
168
+ p.dofpv_provattr = DOF_ATTR(DTRACE_STABILITY_STABLE,
169
+ DTRACE_STABILITY_STABLE,
170
+ DTRACE_STABILITY_STABLE);
171
+ p.dofpv_modattr = DOF_ATTR(DTRACE_STABILITY_STABLE,
172
+ DTRACE_STABILITY_STABLE,
173
+ DTRACE_STABILITY_STABLE);
174
+ p.dofpv_funcattr = DOF_ATTR(DTRACE_STABILITY_STABLE,
175
+ DTRACE_STABILITY_STABLE,
176
+ DTRACE_STABILITY_STABLE);
177
+ p.dofpv_nameattr = DOF_ATTR(DTRACE_STABILITY_STABLE,
178
+ DTRACE_STABILITY_STABLE,
179
+ DTRACE_STABILITY_STABLE);
180
+ p.dofpv_argsattr = DOF_ATTR(DTRACE_STABILITY_STABLE,
181
+ DTRACE_STABILITY_STABLE,
182
+ DTRACE_STABILITY_STABLE);
183
+
184
+ if ((usdt_dof_section_add_data(provider_s, &p, sizeof(p))) < 0) {
185
+ usdt_error(provider, USDT_ERROR_MALLOC);
186
+ return (-1);
187
+ }
188
+
189
+ return (0);
190
+ }