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