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,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
+ }