ruby-static-tracing 0.0.4 → 0.0.5

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