fbt.c revision 1.29 1 1.29 riastrad /* $NetBSD: fbt.c,v 1.29 2022/09/02 11:03:50 riastradh Exp $ */
2 1.2 darran
3 1.1 darran /*
4 1.1 darran * CDDL HEADER START
5 1.1 darran *
6 1.1 darran * The contents of this file are subject to the terms of the
7 1.1 darran * Common Development and Distribution License (the "License").
8 1.1 darran * You may not use this file except in compliance with the License.
9 1.1 darran *
10 1.1 darran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 1.1 darran * or http://www.opensolaris.org/os/licensing.
12 1.1 darran * See the License for the specific language governing permissions
13 1.1 darran * and limitations under the License.
14 1.1 darran *
15 1.1 darran * When distributing Covered Code, include this CDDL HEADER in each
16 1.1 darran * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 1.1 darran * If applicable, add the following below this CDDL HEADER, with the
18 1.1 darran * fields enclosed by brackets "[]" replaced with your own identifying
19 1.1 darran * information: Portions Copyright [yyyy] [name of copyright owner]
20 1.1 darran *
21 1.1 darran * CDDL HEADER END
22 1.1 darran *
23 1.1 darran * Portions Copyright 2006-2008 John Birrell jb (at) freebsd.org
24 1.3 darran * Portions Copyright 2010 Darran Hunt darran (at) NetBSD.org
25 1.1 darran *
26 1.24 chs * $FreeBSD: head/sys/cddl/dev/fbt/fbt.c 309786 2016-12-10 03:13:11Z markj $
27 1.1 darran *
28 1.1 darran */
29 1.1 darran
30 1.1 darran /*
31 1.1 darran * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
32 1.1 darran * Use is subject to license terms.
33 1.1 darran */
34 1.1 darran
35 1.1 darran #include <sys/cdefs.h>
36 1.24 chs #include <sys/proc.h>
37 1.1 darran #include <sys/param.h>
38 1.1 darran #include <sys/systm.h>
39 1.1 darran #include <sys/conf.h>
40 1.1 darran #include <sys/cpuvar.h>
41 1.1 darran #include <sys/fcntl.h>
42 1.1 darran #include <sys/filio.h>
43 1.1 darran #include <sys/kernel.h>
44 1.1 darran #include <sys/kmem.h>
45 1.5 christos #include <sys/ksyms.h>
46 1.3 darran #include <sys/cpu.h>
47 1.1 darran #include <sys/kthread.h>
48 1.21 christos #include <sys/syslimits.h>
49 1.1 darran #include <sys/linker.h>
50 1.1 darran #include <sys/lock.h>
51 1.1 darran #include <sys/malloc.h>
52 1.1 darran #include <sys/module.h>
53 1.1 darran #include <sys/mutex.h>
54 1.1 darran #include <sys/poll.h>
55 1.1 darran #include <sys/proc.h>
56 1.1 darran #include <sys/selinfo.h>
57 1.1 darran #include <sys/syscall.h>
58 1.1 darran #include <sys/uio.h>
59 1.1 darran #include <sys/unistd.h>
60 1.3 darran #include <sys/exec_elf.h>
61 1.3 darran
62 1.1 darran #include <sys/dtrace.h>
63 1.1 darran #include <sys/dtrace_bsd.h>
64 1.3 darran #include <sys/kern_ctf.h>
65 1.7 tron #include <sys/dtrace_impl.h>
66 1.3 darran
67 1.24 chs #include "fbt.h"
68 1.24 chs
69 1.3 darran mod_ctf_t *modptr;
70 1.1 darran
71 1.24 chs dtrace_provider_id_t fbt_id;
72 1.24 chs fbt_probe_t **fbt_probetab;
73 1.24 chs int fbt_probetab_mask;
74 1.24 chs static int fbt_probetab_size;
75 1.1 darran
76 1.3 darran static dev_type_open(fbt_open);
77 1.1 darran static int fbt_unload(void);
78 1.1 darran static void fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
79 1.24 chs static void fbt_provide_module(void *, modctl_t *);
80 1.1 darran static void fbt_destroy(void *, dtrace_id_t, void *);
81 1.3 darran static int fbt_enable(void *, dtrace_id_t, void *);
82 1.1 darran static void fbt_disable(void *, dtrace_id_t, void *);
83 1.3 darran static void fbt_load(void);
84 1.1 darran static void fbt_suspend(void *, dtrace_id_t, void *);
85 1.1 darran static void fbt_resume(void *, dtrace_id_t, void *);
86 1.1 darran
87 1.3 darran static const struct cdevsw fbt_cdevsw = {
88 1.19 pgoyette .d_open = fbt_open,
89 1.19 pgoyette .d_close = noclose,
90 1.19 pgoyette .d_read = noread,
91 1.19 pgoyette .d_write = nowrite,
92 1.19 pgoyette .d_ioctl = noioctl,
93 1.19 pgoyette .d_stop = nostop,
94 1.19 pgoyette .d_tty = notty,
95 1.19 pgoyette .d_poll = nopoll,
96 1.19 pgoyette .d_mmap = nommap,
97 1.19 pgoyette .d_kqfilter = nokqfilter,
98 1.19 pgoyette .d_discard = nodiscard,
99 1.19 pgoyette .d_flag = D_OTHER
100 1.1 darran };
101 1.1 darran
102 1.1 darran static dtrace_pattr_t fbt_attr = {
103 1.1 darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
104 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
105 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
106 1.1 darran { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
107 1.1 darran { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
108 1.1 darran };
109 1.1 darran
110 1.1 darran static dtrace_pops_t fbt_pops = {
111 1.1 darran NULL,
112 1.1 darran fbt_provide_module,
113 1.1 darran fbt_enable,
114 1.1 darran fbt_disable,
115 1.1 darran fbt_suspend,
116 1.1 darran fbt_resume,
117 1.1 darran fbt_getargdesc,
118 1.1 darran NULL,
119 1.1 darran NULL,
120 1.1 darran fbt_destroy
121 1.1 darran };
122 1.1 darran
123 1.24 chs #ifdef __FreeBSD__
124 1.24 chs static int fbt_verbose = 0;
125 1.1 darran
126 1.1 darran static struct cdev *fbt_cdev;
127 1.24 chs #endif /* __FreeBSD__ */
128 1.1 darran
129 1.24 chs #ifdef __NetBSD__
130 1.24 chs specificdata_key_t fbt_module_key;
131 1.14 ozaki
132 1.24 chs #define version xversion
133 1.24 chs #endif /* __NetBSD__ */
134 1.14 ozaki
135 1.24 chs int
136 1.24 chs fbt_excluded(const char *name)
137 1.14 ozaki {
138 1.14 ozaki
139 1.24 chs if (strncmp(name, "dtrace_", 7) == 0 &&
140 1.24 chs strncmp(name, "dtrace_safe_", 12) != 0) {
141 1.14 ozaki /*
142 1.24 chs * Anything beginning with "dtrace_" may be called
143 1.24 chs * from probe context unless it explicitly indicates
144 1.24 chs * that it won't be called from probe context by
145 1.24 chs * using the prefix "dtrace_safe_".
146 1.14 ozaki */
147 1.24 chs return (1);
148 1.14 ozaki }
149 1.14 ozaki
150 1.24 chs #ifdef __FreeBSD__
151 1.24 chs /*
152 1.24 chs * Lock owner methods may be called from probe context.
153 1.24 chs */
154 1.24 chs if (strcmp(name, "owner_mtx") == 0 ||
155 1.24 chs strcmp(name, "owner_rm") == 0 ||
156 1.24 chs strcmp(name, "owner_rw") == 0 ||
157 1.24 chs strcmp(name, "owner_sx") == 0)
158 1.24 chs return (1);
159 1.14 ozaki
160 1.24 chs /*
161 1.24 chs * When DTrace is built into the kernel we need to exclude
162 1.24 chs * the FBT functions from instrumentation.
163 1.24 chs */
164 1.24 chs #ifndef _KLD_MODULE
165 1.24 chs if (strncmp(name, "fbt_", 4) == 0)
166 1.24 chs return (1);
167 1.24 chs #endif
168 1.24 chs #endif
169 1.14 ozaki
170 1.24 chs #ifdef __NetBSD__
171 1.24 chs if (strcmp(name, "cpu_index") == 0 ||
172 1.24 chs strncmp(name, "db_", 3) == 0 ||
173 1.24 chs strncmp(name, "ddb_", 4) == 0 ||
174 1.24 chs strncmp(name, "kdb_", 4) == 0 ||
175 1.24 chs strncmp(name, "lockdebug_", 10) == 0 ||
176 1.24 chs strncmp(name, "kauth_", 5) == 0 ||
177 1.27 hannken strncmp(name, "ktext_write", 11) == 0 ||
178 1.27 hannken strncmp(name, "fbt_", 4) == 0) {
179 1.24 chs return (1);
180 1.14 ozaki }
181 1.24 chs #endif
182 1.24 chs
183 1.24 chs return (0);
184 1.14 ozaki }
185 1.14 ozaki
186 1.1 darran static void
187 1.1 darran fbt_doubletrap(void)
188 1.1 darran {
189 1.1 darran fbt_probe_t *fbt;
190 1.1 darran int i;
191 1.1 darran
192 1.1 darran for (i = 0; i < fbt_probetab_size; i++) {
193 1.1 darran fbt = fbt_probetab[i];
194 1.1 darran
195 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next)
196 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
197 1.1 darran }
198 1.1 darran }
199 1.1 darran
200 1.24 chs #ifdef __FreeBSD__
201 1.24 chs static void
202 1.24 chs fbt_provide_module(void *arg, modctl_t *lf)
203 1.1 darran {
204 1.24 chs char modname[MAXPATHLEN];
205 1.24 chs int i;
206 1.24 chs size_t len;
207 1.22 chs
208 1.24 chs strlcpy(modname, lf->filename, sizeof(modname));
209 1.24 chs len = strlen(modname);
210 1.24 chs if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
211 1.24 chs modname[len - 3] = '\0';
212 1.1 darran
213 1.24 chs /*
214 1.24 chs * Employees of dtrace and their families are ineligible. Void
215 1.24 chs * where prohibited.
216 1.24 chs */
217 1.24 chs if (strcmp(modname, "dtrace") == 0)
218 1.24 chs return;
219 1.1 darran
220 1.10 yamt /*
221 1.24 chs * To register with DTrace, a module must list 'dtrace' as a
222 1.24 chs * dependency in order for the kernel linker to resolve
223 1.24 chs * symbols like dtrace_register(). All modules with such a
224 1.24 chs * dependency are ineligible for FBT tracing.
225 1.10 yamt */
226 1.24 chs for (i = 0; i < lf->ndeps; i++)
227 1.24 chs if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
228 1.24 chs return;
229 1.10 yamt
230 1.24 chs if (lf->fbt_nentries) {
231 1.1 darran /*
232 1.24 chs * This module has some FBT entries allocated; we're afraid
233 1.24 chs * to screw with it.
234 1.1 darran */
235 1.24 chs return;
236 1.14 ozaki }
237 1.14 ozaki
238 1.14 ozaki /*
239 1.24 chs * List the functions in the module and the symbol values.
240 1.14 ozaki */
241 1.24 chs (void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
242 1.14 ozaki }
243 1.14 ozaki #endif
244 1.24 chs #ifdef __NetBSD__
245 1.1 darran static void
246 1.24 chs fbt_provide_module(void *arg, modctl_t *mod)
247 1.1 darran {
248 1.24 chs struct fbt_ksyms_arg fka;
249 1.24 chs struct mod_ctf *mc;
250 1.1 darran char modname[MAXPATHLEN];
251 1.1 darran int i;
252 1.1 darran size_t len;
253 1.1 darran
254 1.24 chs if (mod_ctf_get(mod, &mc)) {
255 1.24 chs printf("fbt: no CTF data for module %s\n", module_name(mod));
256 1.24 chs return;
257 1.24 chs }
258 1.24 chs
259 1.24 chs strlcpy(modname, module_name(mod), sizeof(modname));
260 1.1 darran len = strlen(modname);
261 1.3 darran if (len > 5 && strcmp(modname + len - 3, ".kmod") == 0)
262 1.3 darran modname[len - 4] = '\0';
263 1.1 darran
264 1.1 darran /*
265 1.1 darran * Employees of dtrace and their families are ineligible. Void
266 1.1 darran * where prohibited.
267 1.1 darran */
268 1.1 darran if (strcmp(modname, "dtrace") == 0)
269 1.1 darran return;
270 1.1 darran
271 1.1 darran /*
272 1.1 darran * The cyclic timer subsystem can be built as a module and DTrace
273 1.1 darran * depends on that, so it is ineligible too.
274 1.1 darran */
275 1.1 darran if (strcmp(modname, "cyclic") == 0)
276 1.1 darran return;
277 1.1 darran
278 1.1 darran /*
279 1.1 darran * To register with DTrace, a module must list 'dtrace' as a
280 1.1 darran * dependency in order for the kernel linker to resolve
281 1.1 darran * symbols like dtrace_register(). All modules with such a
282 1.1 darran * dependency are ineligible for FBT tracing.
283 1.1 darran */
284 1.3 darran for (i = 0; i < mod->mod_nrequired; i++) {
285 1.25 pgoyette if (strncmp(module_name((*mod->mod_required)[i]),
286 1.3 darran "dtrace", 6) == 0)
287 1.1 darran return;
288 1.3 darran }
289 1.24 chs if (mc->fbt_provided) {
290 1.1 darran return;
291 1.1 darran }
292 1.1 darran
293 1.1 darran /*
294 1.1 darran * List the functions in the module and the symbol values.
295 1.1 darran */
296 1.24 chs memset(&fka, 0, sizeof(fka));
297 1.24 chs fka.fka_mod = mod;
298 1.24 chs fka.fka_mc = mc;
299 1.24 chs ksyms_mod_foreach(modname, fbt_provide_module_cb, &fka);
300 1.24 chs mc->fbt_provided = true;
301 1.1 darran }
302 1.1 darran
303 1.1 darran static void
304 1.24 chs fbt_module_dtor(void *arg)
305 1.24 chs {
306 1.24 chs mod_ctf_t *mc = arg;
307 1.24 chs
308 1.24 chs if (mc->ctfalloc)
309 1.24 chs free(mc->ctftab, M_TEMP);
310 1.24 chs kmem_free(mc, sizeof(*mc));
311 1.24 chs }
312 1.24 chs #endif
313 1.24 chs
314 1.24 chs static void
315 1.1 darran fbt_destroy(void *arg, dtrace_id_t id, void *parg)
316 1.1 darran {
317 1.1 darran fbt_probe_t *fbt = parg, *next, *hash, *last;
318 1.24 chs modctl_t *ctl;
319 1.1 darran int ndx;
320 1.1 darran
321 1.1 darran do {
322 1.1 darran ctl = fbt->fbtp_ctl;
323 1.1 darran
324 1.24 chs #ifdef __FreeBSD__
325 1.3 darran ctl->mod_fbtentries--;
326 1.24 chs #endif
327 1.24 chs #ifdef __NetBSD__
328 1.24 chs mod_ctf_t *mc = module_getspecific(ctl, fbt_module_key);
329 1.24 chs mc->fbt_provided = false;
330 1.24 chs #endif
331 1.1 darran
332 1.1 darran /*
333 1.1 darran * Now we need to remove this probe from the fbt_probetab.
334 1.1 darran */
335 1.1 darran ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
336 1.1 darran last = NULL;
337 1.1 darran hash = fbt_probetab[ndx];
338 1.1 darran
339 1.1 darran while (hash != fbt) {
340 1.1 darran ASSERT(hash != NULL);
341 1.1 darran last = hash;
342 1.1 darran hash = hash->fbtp_hashnext;
343 1.1 darran }
344 1.1 darran
345 1.1 darran if (last != NULL) {
346 1.1 darran last->fbtp_hashnext = fbt->fbtp_hashnext;
347 1.1 darran } else {
348 1.1 darran fbt_probetab[ndx] = fbt->fbtp_hashnext;
349 1.1 darran }
350 1.1 darran
351 1.1 darran next = fbt->fbtp_next;
352 1.24 chs kmem_free(fbt, sizeof(*fbt));
353 1.1 darran
354 1.1 darran fbt = next;
355 1.1 darran } while (fbt != NULL);
356 1.1 darran }
357 1.1 darran
358 1.3 darran static int
359 1.1 darran fbt_enable(void *arg, dtrace_id_t id, void *parg)
360 1.1 darran {
361 1.1 darran fbt_probe_t *fbt = parg;
362 1.24 chs modctl_t *ctl = fbt->fbtp_ctl;
363 1.3 darran
364 1.24 chs #ifdef __NetBSD__
365 1.24 chs module_hold(ctl);
366 1.24 chs #else
367 1.1 darran ctl->nenabled++;
368 1.1 darran
369 1.1 darran /*
370 1.1 darran * Now check that our modctl has the expected load count. If it
371 1.1 darran * doesn't, this module must have been unloaded and reloaded -- and
372 1.1 darran * we're not going to touch it.
373 1.1 darran */
374 1.1 darran if (ctl->loadcnt != fbt->fbtp_loadcnt) {
375 1.1 darran if (fbt_verbose) {
376 1.1 darran printf("fbt is failing for probe %s "
377 1.1 darran "(module %s reloaded)",
378 1.24 chs fbt->fbtp_name, module_name(ctl));
379 1.1 darran }
380 1.1 darran
381 1.24 chs return 0;
382 1.1 darran }
383 1.3 darran #endif
384 1.3 darran
385 1.24 chs for (; fbt != NULL; fbt = fbt->fbtp_next)
386 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_patchval);
387 1.3 darran return 0;
388 1.1 darran }
389 1.1 darran
390 1.1 darran static void
391 1.1 darran fbt_disable(void *arg, dtrace_id_t id, void *parg)
392 1.1 darran {
393 1.1 darran fbt_probe_t *fbt = parg;
394 1.24 chs modctl_t *ctl = fbt->fbtp_ctl;
395 1.1 darran
396 1.24 chs #ifndef __NetBSD__
397 1.1 darran ASSERT(ctl->nenabled > 0);
398 1.1 darran ctl->nenabled--;
399 1.1 darran
400 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt))
401 1.1 darran return;
402 1.3 darran #endif
403 1.1 darran
404 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next)
405 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
406 1.3 darran
407 1.24 chs #ifdef __NetBSD__
408 1.24 chs module_rele(ctl);
409 1.24 chs #endif
410 1.1 darran }
411 1.1 darran
412 1.1 darran static void
413 1.1 darran fbt_suspend(void *arg, dtrace_id_t id, void *parg)
414 1.1 darran {
415 1.1 darran fbt_probe_t *fbt = parg;
416 1.24 chs #ifndef __NetBSD__
417 1.24 chs modctl_t *ctl = fbt->fbtp_ctl;
418 1.1 darran
419 1.1 darran ASSERT(ctl->nenabled > 0);
420 1.1 darran
421 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt))
422 1.1 darran return;
423 1.3 darran #endif
424 1.3 darran
425 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next)
426 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
427 1.1 darran }
428 1.1 darran
429 1.1 darran static void
430 1.1 darran fbt_resume(void *arg, dtrace_id_t id, void *parg)
431 1.1 darran {
432 1.1 darran fbt_probe_t *fbt = parg;
433 1.24 chs #ifndef __NetBSD__
434 1.24 chs modctl_t *ctl = fbt->fbtp_ctl;
435 1.1 darran
436 1.1 darran ASSERT(ctl->nenabled > 0);
437 1.1 darran
438 1.1 darran if ((ctl->loadcnt != fbt->fbtp_loadcnt))
439 1.1 darran return;
440 1.3 darran #endif
441 1.1 darran
442 1.1 darran for (; fbt != NULL; fbt = fbt->fbtp_next)
443 1.24 chs fbt_patch_tracepoint(fbt, fbt->fbtp_patchval);
444 1.14 ozaki }
445 1.14 ozaki
446 1.1 darran static int
447 1.24 chs fbt_ctfoff_init(modctl_t *mod, mod_ctf_t *mc)
448 1.1 darran {
449 1.3 darran const Elf_Sym *symp = mc->symtab;
450 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
451 1.3 darran const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
452 1.1 darran int i;
453 1.1 darran uint32_t *ctfoff;
454 1.1 darran uint32_t objtoff = hp->cth_objtoff;
455 1.1 darran uint32_t funcoff = hp->cth_funcoff;
456 1.1 darran ushort_t info;
457 1.1 darran ushort_t vlen;
458 1.3 darran int nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
459 1.1 darran
460 1.1 darran /* Sanity check. */
461 1.1 darran if (hp->cth_magic != CTF_MAGIC) {
462 1.3 darran printf("Bad magic value in CTF data of '%s'\n",
463 1.24 chs module_name(mod));
464 1.1 darran return (EINVAL);
465 1.1 darran }
466 1.1 darran
467 1.3 darran if (mc->symtab == NULL) {
468 1.24 chs printf("No symbol table in '%s'\n", module_name(mod));
469 1.1 darran return (EINVAL);
470 1.1 darran }
471 1.1 darran
472 1.24 chs ctfoff = malloc(sizeof(uint32_t) * nsyms, M_FBT, M_WAITOK);
473 1.3 darran mc->ctfoffp = ctfoff;
474 1.3 darran
475 1.3 darran for (i = 0; i < nsyms; i++, ctfoff++, symp++) {
476 1.3 darran if (mc->nmap != NULL) {
477 1.3 darran if (mc->nmap[i] == 0) {
478 1.3 darran printf("%s.%d: Error! Got zero nmap!\n",
479 1.3 darran __func__, __LINE__);
480 1.3 darran continue;
481 1.3 darran }
482 1.3 darran
483 1.24 chs /*
484 1.24 chs * CTF expects the unsorted symbol ordering,
485 1.3 darran * so map it from that to the current sorted
486 1.24 chs * symbol table.
487 1.3 darran * ctfoff[new-ind] = oldind symbol info.
488 1.3 darran */
489 1.3 darran
490 1.3 darran /* map old index to new symbol table */
491 1.3 darran symp = &mc->symtab[mc->nmap[i] - 1];
492 1.3 darran
493 1.3 darran /* map old index to new ctfoff index */
494 1.3 darran ctfoff = &mc->ctfoffp[mc->nmap[i]-1];
495 1.3 darran }
496 1.1 darran
497 1.24 chs /*
498 1.24 chs * Note that due to how kern_ksyms.c adjusts st_name
499 1.24 chs * to be the offset into a virtual combined strtab,
500 1.24 chs * st_name will never be 0 for loaded modules.
501 1.24 chs */
502 1.24 chs
503 1.1 darran if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
504 1.1 darran *ctfoff = 0xffffffff;
505 1.1 darran continue;
506 1.1 darran }
507 1.1 darran
508 1.1 darran switch (ELF_ST_TYPE(symp->st_info)) {
509 1.1 darran case STT_OBJECT:
510 1.1 darran if (objtoff >= hp->cth_funcoff ||
511 1.1 darran (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
512 1.1 darran *ctfoff = 0xffffffff;
513 1.1 darran break;
514 1.1 darran }
515 1.1 darran
516 1.1 darran *ctfoff = objtoff;
517 1.1 darran objtoff += sizeof (ushort_t);
518 1.1 darran break;
519 1.1 darran
520 1.1 darran case STT_FUNC:
521 1.1 darran if (funcoff >= hp->cth_typeoff) {
522 1.1 darran *ctfoff = 0xffffffff;
523 1.1 darran break;
524 1.1 darran }
525 1.1 darran
526 1.1 darran *ctfoff = funcoff;
527 1.1 darran
528 1.1 darran info = *((const ushort_t *)(ctfdata + funcoff));
529 1.1 darran vlen = CTF_INFO_VLEN(info);
530 1.1 darran
531 1.1 darran /*
532 1.1 darran * If we encounter a zero pad at the end, just skip it.
533 1.1 darran * Otherwise skip over the function and its return type
534 1.1 darran * (+2) and the argument list (vlen).
535 1.1 darran */
536 1.1 darran if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
537 1.1 darran funcoff += sizeof (ushort_t); /* skip pad */
538 1.1 darran else
539 1.1 darran funcoff += sizeof (ushort_t) * (vlen + 2);
540 1.1 darran break;
541 1.1 darran
542 1.1 darran default:
543 1.1 darran *ctfoff = 0xffffffff;
544 1.1 darran break;
545 1.1 darran }
546 1.1 darran }
547 1.1 darran
548 1.1 darran return (0);
549 1.1 darran }
550 1.1 darran
551 1.1 darran static ssize_t
552 1.24 chs fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
553 1.1 darran ssize_t *incrementp)
554 1.1 darran {
555 1.1 darran ssize_t size, increment;
556 1.1 darran
557 1.24 chs if (version > CTF_VERSION_1 &&
558 1.1 darran tp->ctt_size == CTF_LSIZE_SENT) {
559 1.1 darran size = CTF_TYPE_LSIZE(tp);
560 1.1 darran increment = sizeof (ctf_type_t);
561 1.1 darran } else {
562 1.1 darran size = tp->ctt_size;
563 1.1 darran increment = sizeof (ctf_stype_t);
564 1.1 darran }
565 1.1 darran
566 1.1 darran if (sizep)
567 1.1 darran *sizep = size;
568 1.1 darran if (incrementp)
569 1.1 darran *incrementp = increment;
570 1.1 darran
571 1.1 darran return (size);
572 1.1 darran }
573 1.1 darran
574 1.1 darran static int
575 1.3 darran fbt_typoff_init(mod_ctf_t *mc)
576 1.1 darran {
577 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
578 1.1 darran const ctf_type_t *tbuf;
579 1.1 darran const ctf_type_t *tend;
580 1.1 darran const ctf_type_t *tp;
581 1.3 darran const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
582 1.1 darran int ctf_typemax = 0;
583 1.1 darran uint32_t *xp;
584 1.1 darran ulong_t pop[CTF_K_MAX + 1] = { 0 };
585 1.1 darran
586 1.24 chs
587 1.1 darran /* Sanity check. */
588 1.1 darran if (hp->cth_magic != CTF_MAGIC)
589 1.1 darran return (EINVAL);
590 1.1 darran
591 1.1 darran tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
592 1.1 darran tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
593 1.1 darran
594 1.1 darran int child = hp->cth_parname != 0;
595 1.1 darran
596 1.1 darran /*
597 1.1 darran * We make two passes through the entire type section. In this first
598 1.1 darran * pass, we count the number of each type and the total number of types.
599 1.1 darran */
600 1.1 darran for (tp = tbuf; tp < tend; ctf_typemax++) {
601 1.1 darran ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
602 1.1 darran ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
603 1.1 darran ssize_t size, increment;
604 1.1 darran
605 1.1 darran size_t vbytes;
606 1.1 darran uint_t n;
607 1.1 darran
608 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
609 1.1 darran
610 1.1 darran switch (kind) {
611 1.1 darran case CTF_K_INTEGER:
612 1.1 darran case CTF_K_FLOAT:
613 1.1 darran vbytes = sizeof (uint_t);
614 1.1 darran break;
615 1.1 darran case CTF_K_ARRAY:
616 1.1 darran vbytes = sizeof (ctf_array_t);
617 1.1 darran break;
618 1.1 darran case CTF_K_FUNCTION:
619 1.1 darran vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
620 1.1 darran break;
621 1.1 darran case CTF_K_STRUCT:
622 1.1 darran case CTF_K_UNION:
623 1.1 darran if (size < CTF_LSTRUCT_THRESH) {
624 1.1 darran ctf_member_t *mp = (ctf_member_t *)
625 1.1 darran ((uintptr_t)tp + increment);
626 1.1 darran
627 1.1 darran vbytes = sizeof (ctf_member_t) * vlen;
628 1.1 darran for (n = vlen; n != 0; n--, mp++)
629 1.1 darran child |= CTF_TYPE_ISCHILD(mp->ctm_type);
630 1.1 darran } else {
631 1.1 darran ctf_lmember_t *lmp = (ctf_lmember_t *)
632 1.1 darran ((uintptr_t)tp + increment);
633 1.1 darran
634 1.1 darran vbytes = sizeof (ctf_lmember_t) * vlen;
635 1.1 darran for (n = vlen; n != 0; n--, lmp++)
636 1.1 darran child |=
637 1.1 darran CTF_TYPE_ISCHILD(lmp->ctlm_type);
638 1.1 darran }
639 1.1 darran break;
640 1.1 darran case CTF_K_ENUM:
641 1.1 darran vbytes = sizeof (ctf_enum_t) * vlen;
642 1.1 darran break;
643 1.1 darran case CTF_K_FORWARD:
644 1.1 darran /*
645 1.1 darran * For forward declarations, ctt_type is the CTF_K_*
646 1.1 darran * kind for the tag, so bump that population count too.
647 1.1 darran * If ctt_type is unknown, treat the tag as a struct.
648 1.1 darran */
649 1.1 darran if (tp->ctt_type == CTF_K_UNKNOWN ||
650 1.1 darran tp->ctt_type >= CTF_K_MAX)
651 1.1 darran pop[CTF_K_STRUCT]++;
652 1.1 darran else
653 1.1 darran pop[tp->ctt_type]++;
654 1.1 darran /*FALLTHRU*/
655 1.1 darran case CTF_K_UNKNOWN:
656 1.1 darran vbytes = 0;
657 1.1 darran break;
658 1.1 darran case CTF_K_POINTER:
659 1.1 darran case CTF_K_TYPEDEF:
660 1.1 darran case CTF_K_VOLATILE:
661 1.1 darran case CTF_K_CONST:
662 1.1 darran case CTF_K_RESTRICT:
663 1.1 darran child |= CTF_TYPE_ISCHILD(tp->ctt_type);
664 1.1 darran vbytes = 0;
665 1.1 darran break;
666 1.1 darran default:
667 1.24 chs printf("%s(%d): detected invalid CTF kind -- %u\n",
668 1.24 chs __func__, __LINE__, kind);
669 1.1 darran return (EIO);
670 1.1 darran }
671 1.1 darran tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
672 1.1 darran pop[kind]++;
673 1.1 darran }
674 1.1 darran
675 1.24 chs /* account for a sentinel value below */
676 1.24 chs ctf_typemax++;
677 1.3 darran mc->typlen = ctf_typemax;
678 1.1 darran
679 1.24 chs xp = malloc(sizeof(uint32_t) * ctf_typemax, M_FBT, M_ZERO | M_WAITOK);
680 1.1 darran
681 1.3 darran mc->typoffp = xp;
682 1.1 darran
683 1.1 darran /* type id 0 is used as a sentinel value */
684 1.1 darran *xp++ = 0;
685 1.1 darran
686 1.1 darran /*
687 1.1 darran * In the second pass, fill in the type offset.
688 1.1 darran */
689 1.1 darran for (tp = tbuf; tp < tend; xp++) {
690 1.1 darran ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
691 1.1 darran ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
692 1.1 darran ssize_t size, increment;
693 1.1 darran
694 1.1 darran size_t vbytes;
695 1.1 darran uint_t n;
696 1.1 darran
697 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
698 1.1 darran
699 1.1 darran switch (kind) {
700 1.1 darran case CTF_K_INTEGER:
701 1.1 darran case CTF_K_FLOAT:
702 1.1 darran vbytes = sizeof (uint_t);
703 1.1 darran break;
704 1.1 darran case CTF_K_ARRAY:
705 1.1 darran vbytes = sizeof (ctf_array_t);
706 1.1 darran break;
707 1.1 darran case CTF_K_FUNCTION:
708 1.1 darran vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
709 1.1 darran break;
710 1.1 darran case CTF_K_STRUCT:
711 1.1 darran case CTF_K_UNION:
712 1.1 darran if (size < CTF_LSTRUCT_THRESH) {
713 1.1 darran ctf_member_t *mp = (ctf_member_t *)
714 1.1 darran ((uintptr_t)tp + increment);
715 1.1 darran
716 1.1 darran vbytes = sizeof (ctf_member_t) * vlen;
717 1.1 darran for (n = vlen; n != 0; n--, mp++)
718 1.1 darran child |= CTF_TYPE_ISCHILD(mp->ctm_type);
719 1.1 darran } else {
720 1.1 darran ctf_lmember_t *lmp = (ctf_lmember_t *)
721 1.1 darran ((uintptr_t)tp + increment);
722 1.1 darran
723 1.1 darran vbytes = sizeof (ctf_lmember_t) * vlen;
724 1.1 darran for (n = vlen; n != 0; n--, lmp++)
725 1.1 darran child |=
726 1.1 darran CTF_TYPE_ISCHILD(lmp->ctlm_type);
727 1.1 darran }
728 1.1 darran break;
729 1.1 darran case CTF_K_ENUM:
730 1.1 darran vbytes = sizeof (ctf_enum_t) * vlen;
731 1.1 darran break;
732 1.1 darran case CTF_K_FORWARD:
733 1.1 darran case CTF_K_UNKNOWN:
734 1.1 darran vbytes = 0;
735 1.1 darran break;
736 1.1 darran case CTF_K_POINTER:
737 1.1 darran case CTF_K_TYPEDEF:
738 1.1 darran case CTF_K_VOLATILE:
739 1.1 darran case CTF_K_CONST:
740 1.1 darran case CTF_K_RESTRICT:
741 1.1 darran vbytes = 0;
742 1.1 darran break;
743 1.1 darran default:
744 1.1 darran printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
745 1.1 darran return (EIO);
746 1.1 darran }
747 1.1 darran *xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
748 1.1 darran tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
749 1.1 darran }
750 1.1 darran
751 1.1 darran return (0);
752 1.1 darran }
753 1.1 darran
754 1.1 darran /*
755 1.1 darran * CTF Declaration Stack
756 1.1 darran *
757 1.1 darran * In order to implement ctf_type_name(), we must convert a type graph back
758 1.1 darran * into a C type declaration. Unfortunately, a type graph represents a storage
759 1.1 darran * class ordering of the type whereas a type declaration must obey the C rules
760 1.1 darran * for operator precedence, and the two orderings are frequently in conflict.
761 1.1 darran * For example, consider these CTF type graphs and their C declarations:
762 1.1 darran *
763 1.1 darran * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER : int (*)()
764 1.1 darran * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER : int (*)[]
765 1.1 darran *
766 1.1 darran * In each case, parentheses are used to raise operator * to higher lexical
767 1.1 darran * precedence, so the string form of the C declaration cannot be constructed by
768 1.1 darran * walking the type graph links and forming the string from left to right.
769 1.1 darran *
770 1.1 darran * The functions in this file build a set of stacks from the type graph nodes
771 1.1 darran * corresponding to the C operator precedence levels in the appropriate order.
772 1.1 darran * The code in ctf_type_name() can then iterate over the levels and nodes in
773 1.1 darran * lexical precedence order and construct the final C declaration string.
774 1.1 darran */
775 1.1 darran typedef struct ctf_list {
776 1.1 darran struct ctf_list *l_prev; /* previous pointer or tail pointer */
777 1.1 darran struct ctf_list *l_next; /* next pointer or head pointer */
778 1.1 darran } ctf_list_t;
779 1.1 darran
780 1.1 darran #define ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev))
781 1.1 darran #define ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next))
782 1.1 darran
783 1.1 darran typedef enum {
784 1.1 darran CTF_PREC_BASE,
785 1.1 darran CTF_PREC_POINTER,
786 1.1 darran CTF_PREC_ARRAY,
787 1.1 darran CTF_PREC_FUNCTION,
788 1.1 darran CTF_PREC_MAX
789 1.1 darran } ctf_decl_prec_t;
790 1.1 darran
791 1.1 darran typedef struct ctf_decl_node {
792 1.1 darran ctf_list_t cd_list; /* linked list pointers */
793 1.1 darran ctf_id_t cd_type; /* type identifier */
794 1.1 darran uint_t cd_kind; /* type kind */
795 1.1 darran uint_t cd_n; /* type dimension if array */
796 1.1 darran } ctf_decl_node_t;
797 1.1 darran
798 1.1 darran typedef struct ctf_decl {
799 1.1 darran ctf_list_t cd_nodes[CTF_PREC_MAX]; /* declaration node stacks */
800 1.1 darran int cd_order[CTF_PREC_MAX]; /* storage order of decls */
801 1.1 darran ctf_decl_prec_t cd_qualp; /* qualifier precision */
802 1.1 darran ctf_decl_prec_t cd_ordp; /* ordered precision */
803 1.1 darran char *cd_buf; /* buffer for output */
804 1.1 darran char *cd_ptr; /* buffer location */
805 1.1 darran char *cd_end; /* buffer limit */
806 1.1 darran size_t cd_len; /* buffer space required */
807 1.1 darran int cd_err; /* saved error value */
808 1.1 darran } ctf_decl_t;
809 1.1 darran
810 1.1 darran /*
811 1.1 darran * Simple doubly-linked list append routine. This implementation assumes that
812 1.1 darran * each list element contains an embedded ctf_list_t as the first member.
813 1.1 darran * An additional ctf_list_t is used to store the head (l_next) and tail
814 1.1 darran * (l_prev) pointers. The current head and tail list elements have their
815 1.1 darran * previous and next pointers set to NULL, respectively.
816 1.1 darran */
817 1.1 darran static void
818 1.1 darran ctf_list_append(ctf_list_t *lp, void *new)
819 1.1 darran {
820 1.1 darran ctf_list_t *p = lp->l_prev; /* p = tail list element */
821 1.1 darran ctf_list_t *q = new; /* q = new list element */
822 1.1 darran
823 1.1 darran lp->l_prev = q;
824 1.1 darran q->l_prev = p;
825 1.1 darran q->l_next = NULL;
826 1.1 darran
827 1.1 darran if (p != NULL)
828 1.1 darran p->l_next = q;
829 1.1 darran else
830 1.1 darran lp->l_next = q;
831 1.1 darran }
832 1.1 darran
833 1.1 darran /*
834 1.1 darran * Prepend the specified existing element to the given ctf_list_t. The
835 1.1 darran * existing pointer should be pointing at a struct with embedded ctf_list_t.
836 1.1 darran */
837 1.1 darran static void
838 1.1 darran ctf_list_prepend(ctf_list_t *lp, void *new)
839 1.1 darran {
840 1.1 darran ctf_list_t *p = new; /* p = new list element */
841 1.1 darran ctf_list_t *q = lp->l_next; /* q = head list element */
842 1.1 darran
843 1.1 darran lp->l_next = p;
844 1.1 darran p->l_prev = NULL;
845 1.1 darran p->l_next = q;
846 1.1 darran
847 1.1 darran if (q != NULL)
848 1.1 darran q->l_prev = p;
849 1.1 darran else
850 1.1 darran lp->l_prev = p;
851 1.1 darran }
852 1.1 darran
853 1.1 darran static void
854 1.1 darran ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
855 1.1 darran {
856 1.1 darran int i;
857 1.1 darran
858 1.1 darran bzero(cd, sizeof (ctf_decl_t));
859 1.1 darran
860 1.1 darran for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
861 1.1 darran cd->cd_order[i] = CTF_PREC_BASE - 1;
862 1.1 darran
863 1.1 darran cd->cd_qualp = CTF_PREC_BASE;
864 1.1 darran cd->cd_ordp = CTF_PREC_BASE;
865 1.1 darran
866 1.1 darran cd->cd_buf = buf;
867 1.1 darran cd->cd_ptr = buf;
868 1.1 darran cd->cd_end = buf + len;
869 1.1 darran }
870 1.1 darran
871 1.1 darran static void
872 1.1 darran ctf_decl_fini(ctf_decl_t *cd)
873 1.1 darran {
874 1.1 darran ctf_decl_node_t *cdp, *ndp;
875 1.1 darran int i;
876 1.1 darran
877 1.1 darran for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
878 1.1 darran for (cdp = ctf_list_next(&cd->cd_nodes[i]);
879 1.1 darran cdp != NULL; cdp = ndp) {
880 1.1 darran ndp = ctf_list_next(cdp);
881 1.1 darran free(cdp, M_FBT);
882 1.1 darran }
883 1.1 darran }
884 1.1 darran }
885 1.1 darran
886 1.1 darran static const ctf_type_t *
887 1.3 darran ctf_lookup_by_id(mod_ctf_t *mc, ctf_id_t type)
888 1.1 darran {
889 1.1 darran const ctf_type_t *tp;
890 1.1 darran uint32_t offset;
891 1.3 darran uint32_t *typoff = mc->typoffp;
892 1.1 darran
893 1.3 darran if (type >= mc->typlen) {
894 1.3 darran printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,mc->typlen);
895 1.1 darran return(NULL);
896 1.1 darran }
897 1.1 darran
898 1.1 darran /* Check if the type isn't cross-referenced. */
899 1.1 darran if ((offset = typoff[type]) == 0) {
900 1.1 darran printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
901 1.1 darran return(NULL);
902 1.1 darran }
903 1.1 darran
904 1.3 darran tp = (const ctf_type_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
905 1.1 darran
906 1.1 darran return (tp);
907 1.1 darran }
908 1.1 darran
909 1.1 darran static void
910 1.3 darran fbt_array_info(mod_ctf_t *mc, ctf_id_t type, ctf_arinfo_t *arp)
911 1.1 darran {
912 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
913 1.1 darran const ctf_type_t *tp;
914 1.1 darran const ctf_array_t *ap;
915 1.1 darran ssize_t increment;
916 1.1 darran
917 1.1 darran bzero(arp, sizeof(*arp));
918 1.1 darran
919 1.3 darran if ((tp = ctf_lookup_by_id(mc, type)) == NULL)
920 1.1 darran return;
921 1.1 darran
922 1.1 darran if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
923 1.1 darran return;
924 1.1 darran
925 1.1 darran (void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
926 1.1 darran
927 1.1 darran ap = (const ctf_array_t *)((uintptr_t)tp + increment);
928 1.1 darran arp->ctr_contents = ap->cta_contents;
929 1.1 darran arp->ctr_index = ap->cta_index;
930 1.1 darran arp->ctr_nelems = ap->cta_nelems;
931 1.1 darran }
932 1.1 darran
933 1.1 darran static const char *
934 1.3 darran ctf_strptr(mod_ctf_t *mc, int name)
935 1.1 darran {
936 1.3 darran const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;;
937 1.1 darran const char *strp = "";
938 1.1 darran
939 1.1 darran if (name < 0 || name >= hp->cth_strlen)
940 1.1 darran return(strp);
941 1.1 darran
942 1.3 darran strp = (const char *)(mc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
943 1.1 darran
944 1.1 darran return (strp);
945 1.1 darran }
946 1.1 darran
947 1.1 darran static void
948 1.3 darran ctf_decl_push(ctf_decl_t *cd, mod_ctf_t *mc, ctf_id_t type)
949 1.1 darran {
950 1.1 darran ctf_decl_node_t *cdp;
951 1.1 darran ctf_decl_prec_t prec;
952 1.1 darran uint_t kind, n = 1;
953 1.1 darran int is_qual = 0;
954 1.1 darran
955 1.1 darran const ctf_type_t *tp;
956 1.1 darran ctf_arinfo_t ar;
957 1.1 darran
958 1.3 darran if ((tp = ctf_lookup_by_id(mc, type)) == NULL) {
959 1.1 darran cd->cd_err = ENOENT;
960 1.1 darran return;
961 1.1 darran }
962 1.1 darran
963 1.1 darran switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
964 1.1 darran case CTF_K_ARRAY:
965 1.3 darran fbt_array_info(mc, type, &ar);
966 1.3 darran ctf_decl_push(cd, mc, ar.ctr_contents);
967 1.1 darran n = ar.ctr_nelems;
968 1.1 darran prec = CTF_PREC_ARRAY;
969 1.1 darran break;
970 1.1 darran
971 1.1 darran case CTF_K_TYPEDEF:
972 1.3 darran if (ctf_strptr(mc, tp->ctt_name)[0] == '\0') {
973 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type);
974 1.1 darran return;
975 1.1 darran }
976 1.1 darran prec = CTF_PREC_BASE;
977 1.1 darran break;
978 1.1 darran
979 1.1 darran case CTF_K_FUNCTION:
980 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type);
981 1.1 darran prec = CTF_PREC_FUNCTION;
982 1.1 darran break;
983 1.1 darran
984 1.1 darran case CTF_K_POINTER:
985 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type);
986 1.1 darran prec = CTF_PREC_POINTER;
987 1.1 darran break;
988 1.1 darran
989 1.1 darran case CTF_K_VOLATILE:
990 1.1 darran case CTF_K_CONST:
991 1.1 darran case CTF_K_RESTRICT:
992 1.3 darran ctf_decl_push(cd, mc, tp->ctt_type);
993 1.1 darran prec = cd->cd_qualp;
994 1.1 darran is_qual++;
995 1.1 darran break;
996 1.1 darran
997 1.1 darran default:
998 1.1 darran prec = CTF_PREC_BASE;
999 1.1 darran }
1000 1.1 darran
1001 1.24 chs cdp = malloc(sizeof(*cdp), M_FBT, M_WAITOK);
1002 1.1 darran cdp->cd_type = type;
1003 1.1 darran cdp->cd_kind = kind;
1004 1.1 darran cdp->cd_n = n;
1005 1.1 darran
1006 1.1 darran if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
1007 1.1 darran cd->cd_order[prec] = cd->cd_ordp++;
1008 1.1 darran
1009 1.1 darran /*
1010 1.1 darran * Reset cd_qualp to the highest precedence level that we've seen so
1011 1.1 darran * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
1012 1.1 darran */
1013 1.1 darran if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
1014 1.1 darran cd->cd_qualp = prec;
1015 1.1 darran
1016 1.1 darran /*
1017 1.1 darran * C array declarators are ordered inside out so prepend them. Also by
1018 1.1 darran * convention qualifiers of base types precede the type specifier (e.g.
1019 1.1 darran * const int vs. int const) even though the two forms are equivalent.
1020 1.1 darran */
1021 1.1 darran if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1022 1.1 darran ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1023 1.1 darran else
1024 1.1 darran ctf_list_append(&cd->cd_nodes[prec], cdp);
1025 1.1 darran }
1026 1.1 darran
1027 1.1 darran static void
1028 1.1 darran ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1029 1.1 darran {
1030 1.1 darran size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1031 1.1 darran va_list ap;
1032 1.1 darran size_t n;
1033 1.1 darran
1034 1.1 darran va_start(ap, format);
1035 1.1 darran n = vsnprintf(cd->cd_ptr, len, format, ap);
1036 1.1 darran va_end(ap);
1037 1.1 darran
1038 1.1 darran cd->cd_ptr += MIN(n, len);
1039 1.1 darran cd->cd_len += n;
1040 1.1 darran }
1041 1.1 darran
1042 1.1 darran static ssize_t
1043 1.3 darran fbt_type_name(mod_ctf_t *mc, ctf_id_t type, char *buf, size_t len)
1044 1.1 darran {
1045 1.1 darran ctf_decl_t cd;
1046 1.1 darran ctf_decl_node_t *cdp;
1047 1.1 darran ctf_decl_prec_t prec, lp, rp;
1048 1.1 darran int ptr, arr;
1049 1.1 darran uint_t k;
1050 1.1 darran
1051 1.3 darran if (mc == NULL && type == CTF_ERR)
1052 1.1 darran return (-1); /* simplify caller code by permitting CTF_ERR */
1053 1.1 darran
1054 1.1 darran ctf_decl_init(&cd, buf, len);
1055 1.3 darran ctf_decl_push(&cd, mc, type);
1056 1.1 darran
1057 1.1 darran if (cd.cd_err != 0) {
1058 1.1 darran ctf_decl_fini(&cd);
1059 1.1 darran return (-1);
1060 1.1 darran }
1061 1.1 darran
1062 1.1 darran /*
1063 1.1 darran * If the type graph's order conflicts with lexical precedence order
1064 1.1 darran * for pointers or arrays, then we need to surround the declarations at
1065 1.1 darran * the corresponding lexical precedence with parentheses. This can
1066 1.1 darran * result in either a parenthesized pointer (*) as in int (*)() or
1067 1.1 darran * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1068 1.1 darran */
1069 1.1 darran ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1070 1.1 darran arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1071 1.1 darran
1072 1.1 darran rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1073 1.1 darran lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1074 1.1 darran
1075 1.1 darran k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1076 1.1 darran
1077 1.1 darran for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1078 1.1 darran for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1079 1.1 darran cdp != NULL; cdp = ctf_list_next(cdp)) {
1080 1.1 darran
1081 1.1 darran const ctf_type_t *tp =
1082 1.3 darran ctf_lookup_by_id(mc, cdp->cd_type);
1083 1.3 darran const char *name = ctf_strptr(mc, tp->ctt_name);
1084 1.1 darran
1085 1.1 darran if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1086 1.1 darran ctf_decl_sprintf(&cd, " ");
1087 1.1 darran
1088 1.1 darran if (lp == prec) {
1089 1.1 darran ctf_decl_sprintf(&cd, "(");
1090 1.1 darran lp = -1;
1091 1.1 darran }
1092 1.1 darran
1093 1.1 darran switch (cdp->cd_kind) {
1094 1.1 darran case CTF_K_INTEGER:
1095 1.1 darran case CTF_K_FLOAT:
1096 1.1 darran case CTF_K_TYPEDEF:
1097 1.1 darran ctf_decl_sprintf(&cd, "%s", name);
1098 1.1 darran break;
1099 1.1 darran case CTF_K_POINTER:
1100 1.1 darran ctf_decl_sprintf(&cd, "*");
1101 1.1 darran break;
1102 1.1 darran case CTF_K_ARRAY:
1103 1.1 darran ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1104 1.1 darran break;
1105 1.1 darran case CTF_K_FUNCTION:
1106 1.1 darran ctf_decl_sprintf(&cd, "()");
1107 1.1 darran break;
1108 1.1 darran case CTF_K_STRUCT:
1109 1.1 darran case CTF_K_FORWARD:
1110 1.1 darran ctf_decl_sprintf(&cd, "struct %s", name);
1111 1.1 darran break;
1112 1.1 darran case CTF_K_UNION:
1113 1.1 darran ctf_decl_sprintf(&cd, "union %s", name);
1114 1.1 darran break;
1115 1.1 darran case CTF_K_ENUM:
1116 1.1 darran ctf_decl_sprintf(&cd, "enum %s", name);
1117 1.1 darran break;
1118 1.1 darran case CTF_K_VOLATILE:
1119 1.1 darran ctf_decl_sprintf(&cd, "volatile");
1120 1.1 darran break;
1121 1.1 darran case CTF_K_CONST:
1122 1.1 darran ctf_decl_sprintf(&cd, "const");
1123 1.1 darran break;
1124 1.1 darran case CTF_K_RESTRICT:
1125 1.1 darran ctf_decl_sprintf(&cd, "restrict");
1126 1.1 darran break;
1127 1.1 darran }
1128 1.1 darran
1129 1.1 darran k = cdp->cd_kind;
1130 1.1 darran }
1131 1.1 darran
1132 1.1 darran if (rp == prec)
1133 1.1 darran ctf_decl_sprintf(&cd, ")");
1134 1.1 darran }
1135 1.1 darran
1136 1.1 darran ctf_decl_fini(&cd);
1137 1.1 darran return (cd.cd_len);
1138 1.1 darran }
1139 1.1 darran
1140 1.1 darran static void
1141 1.1 darran fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1142 1.1 darran {
1143 1.1 darran const ushort_t *dp;
1144 1.1 darran fbt_probe_t *fbt = parg;
1145 1.24 chs mod_ctf_t *mc;
1146 1.24 chs modctl_t *ctl = fbt->fbtp_ctl;
1147 1.1 darran int ndx = desc->dtargd_ndx;
1148 1.1 darran int symindx = fbt->fbtp_symindx;
1149 1.1 darran uint32_t *ctfoff;
1150 1.1 darran uint32_t offset;
1151 1.1 darran ushort_t info, kind, n;
1152 1.3 darran int nsyms;
1153 1.1 darran
1154 1.24 chs if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
1155 1.24 chs (void) strcpy(desc->dtargd_native, "int");
1156 1.24 chs return;
1157 1.24 chs }
1158 1.24 chs
1159 1.1 darran desc->dtargd_ndx = DTRACE_ARGNONE;
1160 1.1 darran
1161 1.24 chs /* Get a pointer to the CTF data and its length. */
1162 1.3 darran if (mod_ctf_get(ctl, &mc) != 0) {
1163 1.24 chs static int report = 0;
1164 1.6 darran if (report < 1) {
1165 1.24 chs report++;
1166 1.24 chs printf("FBT: Error no CTF section found in module \"%s\"\n",
1167 1.24 chs module_name(ctl));
1168 1.6 darran }
1169 1.1 darran /* No CTF data? Something wrong? *shrug* */
1170 1.1 darran return;
1171 1.3 darran }
1172 1.3 darran
1173 1.24 chs nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
1174 1.1 darran
1175 1.1 darran /* Check if this module hasn't been initialised yet. */
1176 1.24 chs if (mc->ctfoffp == NULL) {
1177 1.1 darran /*
1178 1.1 darran * Initialise the CTF object and function symindx to
1179 1.1 darran * byte offset array.
1180 1.1 darran */
1181 1.24 chs if (fbt_ctfoff_init(ctl, mc) != 0)
1182 1.1 darran return;
1183 1.1 darran
1184 1.1 darran /* Initialise the CTF type to byte offset array. */
1185 1.24 chs if (fbt_typoff_init(mc) != 0)
1186 1.1 darran return;
1187 1.1 darran }
1188 1.1 darran
1189 1.24 chs ctfoff = mc->ctfoffp;
1190 1.1 darran
1191 1.24 chs if (ctfoff == NULL || mc->typoffp == NULL) {
1192 1.1 darran return;
1193 1.3 darran }
1194 1.1 darran
1195 1.1 darran /* Check if the symbol index is out of range. */
1196 1.3 darran if (symindx >= nsyms)
1197 1.1 darran return;
1198 1.1 darran
1199 1.1 darran /* Check if the symbol isn't cross-referenced. */
1200 1.1 darran if ((offset = ctfoff[symindx]) == 0xffffffff)
1201 1.1 darran return;
1202 1.1 darran
1203 1.24 chs dp = (const ushort_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
1204 1.1 darran
1205 1.1 darran info = *dp++;
1206 1.1 darran kind = CTF_INFO_KIND(info);
1207 1.1 darran n = CTF_INFO_VLEN(info);
1208 1.1 darran
1209 1.1 darran if (kind == CTF_K_UNKNOWN && n == 0) {
1210 1.12 christos printf("%s(%d): Unknown function %s!\n",__func__,__LINE__,
1211 1.12 christos fbt->fbtp_name);
1212 1.1 darran return;
1213 1.1 darran }
1214 1.1 darran
1215 1.1 darran if (kind != CTF_K_FUNCTION) {
1216 1.12 christos printf("%s(%d): Expected a function %s!\n",__func__,__LINE__,
1217 1.12 christos fbt->fbtp_name);
1218 1.1 darran return;
1219 1.1 darran }
1220 1.1 darran
1221 1.24 chs if (fbt->fbtp_roffset != 0) {
1222 1.24 chs /* Only return type is available for args[1] in return probe. */
1223 1.24 chs if (ndx > 1)
1224 1.24 chs return;
1225 1.24 chs ASSERT(ndx == 1);
1226 1.24 chs } else {
1227 1.24 chs /* Check if the requested argument doesn't exist. */
1228 1.24 chs if (ndx >= n)
1229 1.24 chs return;
1230 1.1 darran
1231 1.24 chs /* Skip the return type and arguments up to the one requested. */
1232 1.24 chs dp += ndx + 1;
1233 1.24 chs }
1234 1.1 darran
1235 1.24 chs if (fbt_type_name(mc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
1236 1.1 darran desc->dtargd_ndx = ndx;
1237 1.1 darran
1238 1.1 darran return;
1239 1.1 darran }
1240 1.1 darran
1241 1.24 chs #ifdef __FreeBSD__
1242 1.24 chs static int
1243 1.24 chs fbt_linker_file_cb(linker_file_t lf, void *arg)
1244 1.24 chs {
1245 1.24 chs
1246 1.24 chs fbt_provide_module(arg, lf);
1247 1.24 chs
1248 1.24 chs return (0);
1249 1.24 chs }
1250 1.24 chs #endif
1251 1.24 chs
1252 1.1 darran static void
1253 1.3 darran fbt_load(void)
1254 1.1 darran {
1255 1.24 chs
1256 1.24 chs #ifdef __FreeBSD__
1257 1.24 chs /* Create the /dev/dtrace/fbt entry. */
1258 1.24 chs fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
1259 1.24 chs "dtrace/fbt");
1260 1.24 chs #endif
1261 1.24 chs #ifdef __NetBSD__
1262 1.24 chs (void) module_specific_key_create(&fbt_module_key, fbt_module_dtor);
1263 1.24 chs #endif
1264 1.24 chs
1265 1.1 darran /* Default the probe table size if not specified. */
1266 1.1 darran if (fbt_probetab_size == 0)
1267 1.1 darran fbt_probetab_size = FBT_PROBETAB_SIZE;
1268 1.1 darran
1269 1.1 darran /* Choose the hash mask for the probe table. */
1270 1.1 darran fbt_probetab_mask = fbt_probetab_size - 1;
1271 1.1 darran
1272 1.1 darran /* Allocate memory for the probe table. */
1273 1.1 darran fbt_probetab =
1274 1.1 darran malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
1275 1.1 darran
1276 1.1 darran dtrace_doubletrap_func = fbt_doubletrap;
1277 1.1 darran dtrace_invop_add(fbt_invop);
1278 1.1 darran
1279 1.1 darran if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
1280 1.1 darran NULL, &fbt_pops, NULL, &fbt_id) != 0)
1281 1.1 darran return;
1282 1.1 darran }
1283 1.1 darran
1284 1.1 darran
1285 1.1 darran static int
1286 1.3 darran fbt_unload(void)
1287 1.1 darran {
1288 1.1 darran int error = 0;
1289 1.1 darran
1290 1.1 darran /* De-register the invalid opcode handler. */
1291 1.1 darran dtrace_invop_remove(fbt_invop);
1292 1.1 darran
1293 1.1 darran dtrace_doubletrap_func = NULL;
1294 1.1 darran
1295 1.1 darran /* De-register this DTrace provider. */
1296 1.1 darran if ((error = dtrace_unregister(fbt_id)) != 0)
1297 1.1 darran return (error);
1298 1.1 darran
1299 1.1 darran /* Free the probe table. */
1300 1.1 darran free(fbt_probetab, M_FBT);
1301 1.1 darran fbt_probetab = NULL;
1302 1.1 darran fbt_probetab_mask = 0;
1303 1.1 darran
1304 1.24 chs #ifdef __FreeBSD__
1305 1.24 chs destroy_dev(fbt_cdev);
1306 1.24 chs #endif
1307 1.24 chs #ifdef __NetBSD__
1308 1.24 chs (void) module_specific_key_delete(fbt_module_key);
1309 1.24 chs #endif
1310 1.1 darran return (error);
1311 1.1 darran }
1312 1.1 darran
1313 1.3 darran
1314 1.1 darran static int
1315 1.18 ozaki dtrace_fbt_modcmd(modcmd_t cmd, void *data)
1316 1.1 darran {
1317 1.26 kamil int bmajor = -1, cmajor = 352;
1318 1.17 ozaki int error;
1319 1.1 darran
1320 1.3 darran switch (cmd) {
1321 1.3 darran case MODULE_CMD_INIT:
1322 1.3 darran fbt_load();
1323 1.3 darran return devsw_attach("fbt", NULL, &bmajor,
1324 1.3 darran &fbt_cdevsw, &cmajor);
1325 1.3 darran case MODULE_CMD_FINI:
1326 1.17 ozaki error = fbt_unload();
1327 1.17 ozaki if (error != 0)
1328 1.17 ozaki return error;
1329 1.28 riastrad devsw_detach(NULL, &fbt_cdevsw);
1330 1.28 riastrad return 0;
1331 1.17 ozaki case MODULE_CMD_AUTOUNLOAD:
1332 1.17 ozaki return EBUSY;
1333 1.1 darran default:
1334 1.3 darran return ENOTTY;
1335 1.1 darran }
1336 1.1 darran }
1337 1.1 darran
1338 1.1 darran static int
1339 1.3 darran fbt_open(dev_t dev, int flags, int mode, struct lwp *l)
1340 1.1 darran {
1341 1.1 darran return (0);
1342 1.1 darran }
1343 1.1 darran
1344 1.24 chs #ifdef __FreeBSD__
1345 1.24 chs SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL);
1346 1.24 chs SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL);
1347 1.24 chs
1348 1.24 chs DEV_MODULE(fbt, fbt_modevent, NULL);
1349 1.24 chs MODULE_VERSION(fbt, 1);
1350 1.24 chs MODULE_DEPEND(fbt, dtrace, 1, 1, 1);
1351 1.24 chs MODULE_DEPEND(fbt, opensolaris, 1, 1, 1);
1352 1.24 chs #endif
1353 1.24 chs #ifdef __NetBSD__
1354 1.20 pgoyette MODULE(MODULE_CLASS_MISC, dtrace_fbt, "dtrace,zlib");
1355 1.24 chs #endif
1356