fbt.c revision 254268
1245700Snwhitehorn/*
2245700Snwhitehorn * CDDL HEADER START
3245700Snwhitehorn *
4245700Snwhitehorn * The contents of this file are subject to the terms of the
5245700Snwhitehorn * Common Development and Distribution License (the "License").
6245700Snwhitehorn * You may not use this file except in compliance with the License.
7245700Snwhitehorn *
8245700Snwhitehorn * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9245700Snwhitehorn * or http://www.opensolaris.org/os/licensing.
10245700Snwhitehorn * See the License for the specific language governing permissions
11245700Snwhitehorn * and limitations under the License.
12245700Snwhitehorn *
13245700Snwhitehorn * When distributing Covered Code, include this CDDL HEADER in each
14245700Snwhitehorn * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15245700Snwhitehorn * If applicable, add the following below this CDDL HEADER, with the
16245700Snwhitehorn * fields enclosed by brackets "[]" replaced with your own identifying
17245700Snwhitehorn * information: Portions Copyright [yyyy] [name of copyright owner]
18245700Snwhitehorn *
19245700Snwhitehorn * CDDL HEADER END
20245700Snwhitehorn *
21245700Snwhitehorn * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
22245700Snwhitehorn *
23245700Snwhitehorn * $FreeBSD: head/sys/cddl/dev/fbt/fbt.c 254268 2013-08-13 03:10:39Z markj $
24245700Snwhitehorn *
25245700Snwhitehorn */
26245700Snwhitehorn
27245700Snwhitehorn/*
28245700Snwhitehorn * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
29245700Snwhitehorn * Use is subject to license terms.
30245700Snwhitehorn */
31245700Snwhitehorn
32245700Snwhitehorn#include <sys/cdefs.h>
33245700Snwhitehorn#include <sys/param.h>
34245700Snwhitehorn#include <sys/systm.h>
35245700Snwhitehorn#include <sys/conf.h>
36245700Snwhitehorn#include <sys/cpuvar.h>
37245700Snwhitehorn#include <sys/fcntl.h>
38245700Snwhitehorn#include <sys/filio.h>
39245700Snwhitehorn#include <sys/kdb.h>
40245700Snwhitehorn#include <sys/kernel.h>
41245700Snwhitehorn#include <sys/kmem.h>
42245700Snwhitehorn#include <sys/kthread.h>
43245700Snwhitehorn#include <sys/limits.h>
44245700Snwhitehorn#include <sys/linker.h>
45245700Snwhitehorn#include <sys/lock.h>
46245700Snwhitehorn#include <sys/malloc.h>
47245700Snwhitehorn#include <sys/module.h>
48245700Snwhitehorn#include <sys/mutex.h>
49245700Snwhitehorn#include <sys/pcpu.h>
50245700Snwhitehorn#include <sys/poll.h>
51245700Snwhitehorn#include <sys/proc.h>
52245700Snwhitehorn#include <sys/selinfo.h>
53245700Snwhitehorn#include <sys/smp.h>
54245700Snwhitehorn#include <sys/syscall.h>
55245700Snwhitehorn#include <sys/sysent.h>
56245700Snwhitehorn#include <sys/sysproto.h>
57245700Snwhitehorn#include <sys/uio.h>
58245700Snwhitehorn#include <sys/unistd.h>
59245700Snwhitehorn#include <machine/stdarg.h>
60245700Snwhitehorn
61245700Snwhitehorn#include <sys/dtrace.h>
62245700Snwhitehorn#include <sys/dtrace_bsd.h>
63245700Snwhitehorn
64245700Snwhitehornstatic MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
65245700Snwhitehorn
66245700Snwhitehorn#define	FBT_PUSHL_EBP		0x55
67245700Snwhitehorn#define	FBT_MOVL_ESP_EBP0_V0	0x8b
68245700Snwhitehorn#define	FBT_MOVL_ESP_EBP1_V0	0xec
69245700Snwhitehorn#define	FBT_MOVL_ESP_EBP0_V1	0x89
70245700Snwhitehorn#define	FBT_MOVL_ESP_EBP1_V1	0xe5
71245700Snwhitehorn#define	FBT_REX_RSP_RBP		0x48
72245700Snwhitehorn
73245700Snwhitehorn#define	FBT_POPL_EBP		0x5d
74245700Snwhitehorn#define	FBT_RET			0xc3
75245700Snwhitehorn#define	FBT_RET_IMM16		0xc2
76245700Snwhitehorn#define	FBT_LEAVE		0xc9
77245700Snwhitehorn
78245796Snwhitehorn#ifdef __amd64__
79245796Snwhitehorn#define	FBT_PATCHVAL		0xcc
80245796Snwhitehorn#else
81245796Snwhitehorn#define	FBT_PATCHVAL		0xf0
82245796Snwhitehorn#endif
83245700Snwhitehorn
84245700Snwhitehornstatic d_open_t	fbt_open;
85245700Snwhitehornstatic int	fbt_unload(void);
86245700Snwhitehornstatic void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
87245700Snwhitehornstatic void	fbt_provide_module(void *, modctl_t *);
88245700Snwhitehornstatic void	fbt_destroy(void *, dtrace_id_t, void *);
89245700Snwhitehornstatic void	fbt_enable(void *, dtrace_id_t, void *);
90245700Snwhitehornstatic void	fbt_disable(void *, dtrace_id_t, void *);
91245700Snwhitehornstatic void	fbt_load(void *);
92245700Snwhitehornstatic void	fbt_suspend(void *, dtrace_id_t, void *);
93245700Snwhitehornstatic void	fbt_resume(void *, dtrace_id_t, void *);
94245700Snwhitehorn
95245700Snwhitehorn#define	FBT_ENTRY	"entry"
96245700Snwhitehorn#define	FBT_RETURN	"return"
97245700Snwhitehorn#define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
98245700Snwhitehorn#define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
99245700Snwhitehorn
100245700Snwhitehornstatic struct cdevsw fbt_cdevsw = {
101245700Snwhitehorn	.d_version	= D_VERSION,
102245700Snwhitehorn	.d_open		= fbt_open,
103245700Snwhitehorn	.d_name		= "fbt",
104245700Snwhitehorn};
105245700Snwhitehorn
106245700Snwhitehornstatic dtrace_pattr_t fbt_attr = {
107245700Snwhitehorn{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
108245700Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
109245700Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
110245700Snwhitehorn{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
111245701Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
112273831Snwhitehorn};
113245701Snwhitehorn
114245701Snwhitehornstatic dtrace_pops_t fbt_pops = {
115245701Snwhitehorn	NULL,
116245700Snwhitehorn	fbt_provide_module,
117245700Snwhitehorn	fbt_enable,
118245700Snwhitehorn	fbt_disable,
119245700Snwhitehorn	fbt_suspend,
120245700Snwhitehorn	fbt_resume,
121245700Snwhitehorn	fbt_getargdesc,
122245700Snwhitehorn	NULL,
123245700Snwhitehorn	NULL,
124245700Snwhitehorn	fbt_destroy
125245700Snwhitehorn};
126245700Snwhitehorn
127245700Snwhitehorntypedef struct fbt_probe {
128245700Snwhitehorn	struct fbt_probe *fbtp_hashnext;
129245700Snwhitehorn	uint8_t		*fbtp_patchpoint;
130245700Snwhitehorn	int8_t		fbtp_rval;
131245700Snwhitehorn	uint8_t		fbtp_patchval;
132245700Snwhitehorn	uint8_t		fbtp_savedval;
133245700Snwhitehorn	uintptr_t	fbtp_roffset;
134245700Snwhitehorn	dtrace_id_t	fbtp_id;
135245700Snwhitehorn	const char	*fbtp_name;
136245700Snwhitehorn	modctl_t	*fbtp_ctl;
137245700Snwhitehorn	int		fbtp_loadcnt;
138245701Snwhitehorn	int		fbtp_primary;
139245700Snwhitehorn	int		fbtp_invop_cnt;
140245700Snwhitehorn	int		fbtp_symindx;
141245700Snwhitehorn	struct fbt_probe *fbtp_next;
142245700Snwhitehorn} fbt_probe_t;
143245700Snwhitehorn
144245700Snwhitehornstatic struct cdev		*fbt_cdev;
145245700Snwhitehornstatic dtrace_provider_id_t	fbt_id;
146245700Snwhitehornstatic fbt_probe_t		**fbt_probetab;
147245700Snwhitehornstatic int			fbt_probetab_size;
148245700Snwhitehornstatic int			fbt_probetab_mask;
149245700Snwhitehornstatic int			fbt_verbose = 0;
150245700Snwhitehorn
151245700Snwhitehornstatic void
152245700Snwhitehornfbt_doubletrap(void)
153245700Snwhitehorn{
154245700Snwhitehorn	fbt_probe_t *fbt;
155245700Snwhitehorn	int i;
156245700Snwhitehorn
157245700Snwhitehorn	for (i = 0; i < fbt_probetab_size; i++) {
158245700Snwhitehorn		fbt = fbt_probetab[i];
159245700Snwhitehorn
160245700Snwhitehorn		for (; fbt != NULL; fbt = fbt->fbtp_next)
161245700Snwhitehorn			*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
162245700Snwhitehorn	}
163245700Snwhitehorn}
164245700Snwhitehorn
165245700Snwhitehornstatic int
166245700Snwhitehornfbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
167245700Snwhitehorn{
168245700Snwhitehorn	solaris_cpu_t *cpu = &solaris_cpu[curcpu];
169245700Snwhitehorn	uintptr_t stack0, stack1, stack2, stack3, stack4;
170245700Snwhitehorn	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
171245700Snwhitehorn
172245700Snwhitehorn	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
173245700Snwhitehorn		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
174245700Snwhitehorn			fbt->fbtp_invop_cnt++;
175245700Snwhitehorn			if (fbt->fbtp_roffset == 0) {
176245700Snwhitehorn				int i = 0;
177245700Snwhitehorn				/*
178245700Snwhitehorn				 * When accessing the arguments on the stack,
179245700Snwhitehorn				 * we must protect against accessing beyond
180245700Snwhitehorn				 * the stack.  We can safely set NOFAULT here
181245700Snwhitehorn				 * -- we know that interrupts are already
182245700Snwhitehorn				 * disabled.
183245700Snwhitehorn				 */
184245700Snwhitehorn				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
185245796Snwhitehorn				cpu->cpu_dtrace_caller = stack[i++];
186245700Snwhitehorn				stack0 = stack[i++];
187245700Snwhitehorn				stack1 = stack[i++];
188245700Snwhitehorn				stack2 = stack[i++];
189245700Snwhitehorn				stack3 = stack[i++];
190245700Snwhitehorn				stack4 = stack[i++];
191245700Snwhitehorn				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
192245700Snwhitehorn				    CPU_DTRACE_BADADDR);
193245700Snwhitehorn
194245796Snwhitehorn				dtrace_probe(fbt->fbtp_id, stack0, stack1,
195245700Snwhitehorn				    stack2, stack3, stack4);
196245700Snwhitehorn
197245700Snwhitehorn				cpu->cpu_dtrace_caller = 0;
198245700Snwhitehorn			} else {
199245700Snwhitehorn#ifdef __amd64__
200245700Snwhitehorn				/*
201245700Snwhitehorn				 * On amd64, we instrument the ret, not the
202245700Snwhitehorn				 * leave.  We therefore need to set the caller
203245700Snwhitehorn				 * to assure that the top frame of a stack()
204245700Snwhitehorn				 * action is correct.
205245796Snwhitehorn				 */
206245796Snwhitehorn				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
207245796Snwhitehorn				cpu->cpu_dtrace_caller = stack[0];
208245796Snwhitehorn				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
209245796Snwhitehorn				    CPU_DTRACE_BADADDR);
210245700Snwhitehorn#endif
211245700Snwhitehorn
212245700Snwhitehorn				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
213245700Snwhitehorn				    rval, 0, 0, 0);
214				cpu->cpu_dtrace_caller = 0;
215			}
216
217			return (fbt->fbtp_rval);
218		}
219	}
220
221	return (0);
222}
223
224static int
225fbt_provide_module_function(linker_file_t lf, int symindx,
226    linker_symval_t *symval, void *opaque)
227{
228	char *modname = opaque;
229	const char *name = symval->name;
230	fbt_probe_t *fbt, *retfbt;
231	int j;
232	int size;
233	u_int8_t *instr, *limit;
234
235	if (strncmp(name, "dtrace_", 7) == 0 &&
236	    strncmp(name, "dtrace_safe_", 12) != 0) {
237		/*
238		 * Anything beginning with "dtrace_" may be called
239		 * from probe context unless it explicitly indicates
240		 * that it won't be called from probe context by
241		 * using the prefix "dtrace_safe_".
242		 */
243		return (0);
244	}
245
246	if (name[0] == '_' && name[1] == '_')
247		return (0);
248
249	size = symval->size;
250
251	instr = (u_int8_t *) symval->value;
252	limit = (u_int8_t *) symval->value + symval->size;
253
254#ifdef __amd64__
255	while (instr < limit) {
256		if (*instr == FBT_PUSHL_EBP)
257			break;
258
259		if ((size = dtrace_instr_size(instr)) <= 0)
260			break;
261
262		instr += size;
263	}
264
265	if (instr >= limit || *instr != FBT_PUSHL_EBP) {
266		/*
267		 * We either don't save the frame pointer in this
268		 * function, or we ran into some disassembly
269		 * screw-up.  Either way, we bail.
270		 */
271		return (0);
272	}
273#else
274	if (instr[0] != FBT_PUSHL_EBP)
275		return (0);
276
277	if (!(instr[1] == FBT_MOVL_ESP_EBP0_V0 &&
278	    instr[2] == FBT_MOVL_ESP_EBP1_V0) &&
279	    !(instr[1] == FBT_MOVL_ESP_EBP0_V1 &&
280	    instr[2] == FBT_MOVL_ESP_EBP1_V1))
281		return (0);
282#endif
283
284	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
285	fbt->fbtp_name = name;
286	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
287	    name, FBT_ENTRY, 3, fbt);
288	fbt->fbtp_patchpoint = instr;
289	fbt->fbtp_ctl = lf;
290	fbt->fbtp_loadcnt = lf->loadcnt;
291	fbt->fbtp_rval = DTRACE_INVOP_PUSHL_EBP;
292	fbt->fbtp_savedval = *instr;
293	fbt->fbtp_patchval = FBT_PATCHVAL;
294	fbt->fbtp_symindx = symindx;
295
296	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
297	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
298
299	lf->fbt_nentries++;
300
301	retfbt = NULL;
302again:
303	if (instr >= limit)
304		return (0);
305
306	/*
307	 * If this disassembly fails, then we've likely walked off into
308	 * a jump table or some other unsuitable area.  Bail out of the
309	 * disassembly now.
310	 */
311	if ((size = dtrace_instr_size(instr)) <= 0)
312		return (0);
313
314#ifdef __amd64__
315	/*
316	 * We only instrument "ret" on amd64 -- we don't yet instrument
317	 * ret imm16, largely because the compiler doesn't seem to
318	 * (yet) emit them in the kernel...
319	 */
320	if (*instr != FBT_RET) {
321		instr += size;
322		goto again;
323	}
324#else
325	if (!(size == 1 &&
326	    (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) &&
327	    (*(instr + 1) == FBT_RET ||
328	    *(instr + 1) == FBT_RET_IMM16))) {
329		instr += size;
330		goto again;
331	}
332#endif
333
334	/*
335	 * We (desperately) want to avoid erroneously instrumenting a
336	 * jump table, especially given that our markers are pretty
337	 * short:  two bytes on x86, and just one byte on amd64.  To
338	 * determine if we're looking at a true instruction sequence
339	 * or an inline jump table that happens to contain the same
340	 * byte sequences, we resort to some heuristic sleeze:  we
341	 * treat this instruction as being contained within a pointer,
342	 * and see if that pointer points to within the body of the
343	 * function.  If it does, we refuse to instrument it.
344	 */
345	for (j = 0; j < sizeof (uintptr_t); j++) {
346		caddr_t check = (caddr_t) instr - j;
347		uint8_t *ptr;
348
349		if (check < symval->value)
350			break;
351
352		if (check + sizeof (caddr_t) > (caddr_t)limit)
353			continue;
354
355		ptr = *(uint8_t **)check;
356
357		if (ptr >= (uint8_t *) symval->value && ptr < limit) {
358			instr += size;
359			goto again;
360		}
361	}
362
363	/*
364	 * We have a winner!
365	 */
366	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
367	fbt->fbtp_name = name;
368
369	if (retfbt == NULL) {
370		fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
371		    name, FBT_RETURN, 3, fbt);
372	} else {
373		retfbt->fbtp_next = fbt;
374		fbt->fbtp_id = retfbt->fbtp_id;
375	}
376
377	retfbt = fbt;
378	fbt->fbtp_patchpoint = instr;
379	fbt->fbtp_ctl = lf;
380	fbt->fbtp_loadcnt = lf->loadcnt;
381	fbt->fbtp_symindx = symindx;
382
383#ifndef __amd64__
384	if (*instr == FBT_POPL_EBP) {
385		fbt->fbtp_rval = DTRACE_INVOP_POPL_EBP;
386	} else {
387		ASSERT(*instr == FBT_LEAVE);
388		fbt->fbtp_rval = DTRACE_INVOP_LEAVE;
389	}
390	fbt->fbtp_roffset =
391	    (uintptr_t)(instr - (uint8_t *) symval->value) + 1;
392
393#else
394	ASSERT(*instr == FBT_RET);
395	fbt->fbtp_rval = DTRACE_INVOP_RET;
396	fbt->fbtp_roffset =
397	    (uintptr_t)(instr - (uint8_t *) symval->value);
398#endif
399
400	fbt->fbtp_savedval = *instr;
401	fbt->fbtp_patchval = FBT_PATCHVAL;
402	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
403	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
404
405	lf->fbt_nentries++;
406
407	instr += size;
408	goto again;
409}
410
411static void
412fbt_provide_module(void *arg, modctl_t *lf)
413{
414	char modname[MAXPATHLEN];
415	int i;
416	size_t len;
417
418	strlcpy(modname, lf->filename, sizeof(modname));
419	len = strlen(modname);
420	if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
421		modname[len - 3] = '\0';
422
423	/*
424	 * Employees of dtrace and their families are ineligible.  Void
425	 * where prohibited.
426	 */
427	if (strcmp(modname, "dtrace") == 0)
428		return;
429
430	/*
431	 * The cyclic timer subsystem can be built as a module and DTrace
432	 * depends on that, so it is ineligible too.
433	 */
434	if (strcmp(modname, "cyclic") == 0)
435		return;
436
437	/*
438	 * To register with DTrace, a module must list 'dtrace' as a
439	 * dependency in order for the kernel linker to resolve
440	 * symbols like dtrace_register(). All modules with such a
441	 * dependency are ineligible for FBT tracing.
442	 */
443	for (i = 0; i < lf->ndeps; i++)
444		if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
445			return;
446
447	if (lf->fbt_nentries) {
448		/*
449		 * This module has some FBT entries allocated; we're afraid
450		 * to screw with it.
451		 */
452		return;
453	}
454
455	/*
456	 * List the functions in the module and the symbol values.
457	 */
458	(void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
459}
460
461static void
462fbt_destroy(void *arg, dtrace_id_t id, void *parg)
463{
464	fbt_probe_t *fbt = parg, *next, *hash, *last;
465	modctl_t *ctl;
466	int ndx;
467
468	do {
469		ctl = fbt->fbtp_ctl;
470
471		ctl->fbt_nentries--;
472
473		/*
474		 * Now we need to remove this probe from the fbt_probetab.
475		 */
476		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
477		last = NULL;
478		hash = fbt_probetab[ndx];
479
480		while (hash != fbt) {
481			ASSERT(hash != NULL);
482			last = hash;
483			hash = hash->fbtp_hashnext;
484		}
485
486		if (last != NULL) {
487			last->fbtp_hashnext = fbt->fbtp_hashnext;
488		} else {
489			fbt_probetab[ndx] = fbt->fbtp_hashnext;
490		}
491
492		next = fbt->fbtp_next;
493		free(fbt, M_FBT);
494
495		fbt = next;
496	} while (fbt != NULL);
497}
498
499static void
500fbt_enable(void *arg, dtrace_id_t id, void *parg)
501{
502	fbt_probe_t *fbt = parg;
503	modctl_t *ctl = fbt->fbtp_ctl;
504
505	ctl->nenabled++;
506
507	/*
508	 * Now check that our modctl has the expected load count.  If it
509	 * doesn't, this module must have been unloaded and reloaded -- and
510	 * we're not going to touch it.
511	 */
512	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
513		if (fbt_verbose) {
514			printf("fbt is failing for probe %s "
515			    "(module %s reloaded)",
516			    fbt->fbtp_name, ctl->filename);
517		}
518
519		return;
520	}
521
522	for (; fbt != NULL; fbt = fbt->fbtp_next) {
523		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
524	}
525}
526
527static void
528fbt_disable(void *arg, dtrace_id_t id, void *parg)
529{
530	fbt_probe_t *fbt = parg;
531	modctl_t *ctl = fbt->fbtp_ctl;
532
533	ASSERT(ctl->nenabled > 0);
534	ctl->nenabled--;
535
536	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
537		return;
538
539	for (; fbt != NULL; fbt = fbt->fbtp_next)
540		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
541}
542
543static void
544fbt_suspend(void *arg, dtrace_id_t id, void *parg)
545{
546	fbt_probe_t *fbt = parg;
547	modctl_t *ctl = fbt->fbtp_ctl;
548
549	ASSERT(ctl->nenabled > 0);
550
551	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
552		return;
553
554	for (; fbt != NULL; fbt = fbt->fbtp_next)
555		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
556}
557
558static void
559fbt_resume(void *arg, dtrace_id_t id, void *parg)
560{
561	fbt_probe_t *fbt = parg;
562	modctl_t *ctl = fbt->fbtp_ctl;
563
564	ASSERT(ctl->nenabled > 0);
565
566	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
567		return;
568
569	for (; fbt != NULL; fbt = fbt->fbtp_next)
570		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
571}
572
573static int
574fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
575{
576	const Elf_Sym *symp = lc->symtab;;
577	const char *name;
578	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
579	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
580	int i;
581	uint32_t *ctfoff;
582	uint32_t objtoff = hp->cth_objtoff;
583	uint32_t funcoff = hp->cth_funcoff;
584	ushort_t info;
585	ushort_t vlen;
586
587	/* Sanity check. */
588	if (hp->cth_magic != CTF_MAGIC) {
589		printf("Bad magic value in CTF data of '%s'\n",lf->pathname);
590		return (EINVAL);
591	}
592
593	if (lc->symtab == NULL) {
594		printf("No symbol table in '%s'\n",lf->pathname);
595		return (EINVAL);
596	}
597
598	if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) == NULL)
599		return (ENOMEM);
600
601	*lc->ctfoffp = ctfoff;
602
603	for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
604		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
605			*ctfoff = 0xffffffff;
606			continue;
607		}
608
609		if (symp->st_name < lc->strcnt)
610			name = lc->strtab + symp->st_name;
611		else
612			name = "(?)";
613
614		switch (ELF_ST_TYPE(symp->st_info)) {
615		case STT_OBJECT:
616			if (objtoff >= hp->cth_funcoff ||
617                            (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
618				*ctfoff = 0xffffffff;
619                                break;
620                        }
621
622                        *ctfoff = objtoff;
623                        objtoff += sizeof (ushort_t);
624			break;
625
626		case STT_FUNC:
627			if (funcoff >= hp->cth_typeoff) {
628				*ctfoff = 0xffffffff;
629				break;
630			}
631
632			*ctfoff = funcoff;
633
634			info = *((const ushort_t *)(ctfdata + funcoff));
635			vlen = CTF_INFO_VLEN(info);
636
637			/*
638			 * If we encounter a zero pad at the end, just skip it.
639			 * Otherwise skip over the function and its return type
640			 * (+2) and the argument list (vlen).
641			 */
642			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
643				funcoff += sizeof (ushort_t); /* skip pad */
644			else
645				funcoff += sizeof (ushort_t) * (vlen + 2);
646			break;
647
648		default:
649			*ctfoff = 0xffffffff;
650			break;
651		}
652	}
653
654	return (0);
655}
656
657static ssize_t
658fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
659    ssize_t *incrementp)
660{
661	ssize_t size, increment;
662
663	if (version > CTF_VERSION_1 &&
664	    tp->ctt_size == CTF_LSIZE_SENT) {
665		size = CTF_TYPE_LSIZE(tp);
666		increment = sizeof (ctf_type_t);
667	} else {
668		size = tp->ctt_size;
669		increment = sizeof (ctf_stype_t);
670	}
671
672	if (sizep)
673		*sizep = size;
674	if (incrementp)
675		*incrementp = increment;
676
677	return (size);
678}
679
680static int
681fbt_typoff_init(linker_ctf_t *lc)
682{
683	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
684	const ctf_type_t *tbuf;
685	const ctf_type_t *tend;
686	const ctf_type_t *tp;
687	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
688	int ctf_typemax = 0;
689	uint32_t *xp;
690	ulong_t pop[CTF_K_MAX + 1] = { 0 };
691
692
693	/* Sanity check. */
694	if (hp->cth_magic != CTF_MAGIC)
695		return (EINVAL);
696
697	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
698	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
699
700	int child = hp->cth_parname != 0;
701
702	/*
703	 * We make two passes through the entire type section.  In this first
704	 * pass, we count the number of each type and the total number of types.
705	 */
706	for (tp = tbuf; tp < tend; ctf_typemax++) {
707		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
708		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
709		ssize_t size, increment;
710
711		size_t vbytes;
712		uint_t n;
713
714		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
715
716		switch (kind) {
717		case CTF_K_INTEGER:
718		case CTF_K_FLOAT:
719			vbytes = sizeof (uint_t);
720			break;
721		case CTF_K_ARRAY:
722			vbytes = sizeof (ctf_array_t);
723			break;
724		case CTF_K_FUNCTION:
725			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
726			break;
727		case CTF_K_STRUCT:
728		case CTF_K_UNION:
729			if (size < CTF_LSTRUCT_THRESH) {
730				ctf_member_t *mp = (ctf_member_t *)
731				    ((uintptr_t)tp + increment);
732
733				vbytes = sizeof (ctf_member_t) * vlen;
734				for (n = vlen; n != 0; n--, mp++)
735					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
736			} else {
737				ctf_lmember_t *lmp = (ctf_lmember_t *)
738				    ((uintptr_t)tp + increment);
739
740				vbytes = sizeof (ctf_lmember_t) * vlen;
741				for (n = vlen; n != 0; n--, lmp++)
742					child |=
743					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
744			}
745			break;
746		case CTF_K_ENUM:
747			vbytes = sizeof (ctf_enum_t) * vlen;
748			break;
749		case CTF_K_FORWARD:
750			/*
751			 * For forward declarations, ctt_type is the CTF_K_*
752			 * kind for the tag, so bump that population count too.
753			 * If ctt_type is unknown, treat the tag as a struct.
754			 */
755			if (tp->ctt_type == CTF_K_UNKNOWN ||
756			    tp->ctt_type >= CTF_K_MAX)
757				pop[CTF_K_STRUCT]++;
758			else
759				pop[tp->ctt_type]++;
760			/*FALLTHRU*/
761		case CTF_K_UNKNOWN:
762			vbytes = 0;
763			break;
764		case CTF_K_POINTER:
765		case CTF_K_TYPEDEF:
766		case CTF_K_VOLATILE:
767		case CTF_K_CONST:
768		case CTF_K_RESTRICT:
769			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
770			vbytes = 0;
771			break;
772		default:
773			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
774			return (EIO);
775		}
776		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
777		pop[kind]++;
778	}
779
780	/* account for a sentinel value below */
781	ctf_typemax++;
782	*lc->typlenp = ctf_typemax;
783
784	if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_LINKER, M_ZERO | M_WAITOK)) == NULL)
785		return (ENOMEM);
786
787	*lc->typoffp = xp;
788
789	/* type id 0 is used as a sentinel value */
790	*xp++ = 0;
791
792	/*
793	 * In the second pass, fill in the type offset.
794	 */
795	for (tp = tbuf; tp < tend; xp++) {
796		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
797		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
798		ssize_t size, increment;
799
800		size_t vbytes;
801		uint_t n;
802
803		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
804
805		switch (kind) {
806		case CTF_K_INTEGER:
807		case CTF_K_FLOAT:
808			vbytes = sizeof (uint_t);
809			break;
810		case CTF_K_ARRAY:
811			vbytes = sizeof (ctf_array_t);
812			break;
813		case CTF_K_FUNCTION:
814			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
815			break;
816		case CTF_K_STRUCT:
817		case CTF_K_UNION:
818			if (size < CTF_LSTRUCT_THRESH) {
819				ctf_member_t *mp = (ctf_member_t *)
820				    ((uintptr_t)tp + increment);
821
822				vbytes = sizeof (ctf_member_t) * vlen;
823				for (n = vlen; n != 0; n--, mp++)
824					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
825			} else {
826				ctf_lmember_t *lmp = (ctf_lmember_t *)
827				    ((uintptr_t)tp + increment);
828
829				vbytes = sizeof (ctf_lmember_t) * vlen;
830				for (n = vlen; n != 0; n--, lmp++)
831					child |=
832					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
833			}
834			break;
835		case CTF_K_ENUM:
836			vbytes = sizeof (ctf_enum_t) * vlen;
837			break;
838		case CTF_K_FORWARD:
839		case CTF_K_UNKNOWN:
840			vbytes = 0;
841			break;
842		case CTF_K_POINTER:
843		case CTF_K_TYPEDEF:
844		case CTF_K_VOLATILE:
845		case CTF_K_CONST:
846		case CTF_K_RESTRICT:
847			vbytes = 0;
848			break;
849		default:
850			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
851			return (EIO);
852		}
853		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
854		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
855	}
856
857	return (0);
858}
859
860/*
861 * CTF Declaration Stack
862 *
863 * In order to implement ctf_type_name(), we must convert a type graph back
864 * into a C type declaration.  Unfortunately, a type graph represents a storage
865 * class ordering of the type whereas a type declaration must obey the C rules
866 * for operator precedence, and the two orderings are frequently in conflict.
867 * For example, consider these CTF type graphs and their C declarations:
868 *
869 * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
870 * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
871 *
872 * In each case, parentheses are used to raise operator * to higher lexical
873 * precedence, so the string form of the C declaration cannot be constructed by
874 * walking the type graph links and forming the string from left to right.
875 *
876 * The functions in this file build a set of stacks from the type graph nodes
877 * corresponding to the C operator precedence levels in the appropriate order.
878 * The code in ctf_type_name() can then iterate over the levels and nodes in
879 * lexical precedence order and construct the final C declaration string.
880 */
881typedef struct ctf_list {
882	struct ctf_list *l_prev; /* previous pointer or tail pointer */
883	struct ctf_list *l_next; /* next pointer or head pointer */
884} ctf_list_t;
885
886#define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
887#define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
888
889typedef enum {
890	CTF_PREC_BASE,
891	CTF_PREC_POINTER,
892	CTF_PREC_ARRAY,
893	CTF_PREC_FUNCTION,
894	CTF_PREC_MAX
895} ctf_decl_prec_t;
896
897typedef struct ctf_decl_node {
898	ctf_list_t cd_list;			/* linked list pointers */
899	ctf_id_t cd_type;			/* type identifier */
900	uint_t cd_kind;				/* type kind */
901	uint_t cd_n;				/* type dimension if array */
902} ctf_decl_node_t;
903
904typedef struct ctf_decl {
905	ctf_list_t cd_nodes[CTF_PREC_MAX];	/* declaration node stacks */
906	int cd_order[CTF_PREC_MAX];		/* storage order of decls */
907	ctf_decl_prec_t cd_qualp;		/* qualifier precision */
908	ctf_decl_prec_t cd_ordp;		/* ordered precision */
909	char *cd_buf;				/* buffer for output */
910	char *cd_ptr;				/* buffer location */
911	char *cd_end;				/* buffer limit */
912	size_t cd_len;				/* buffer space required */
913	int cd_err;				/* saved error value */
914} ctf_decl_t;
915
916/*
917 * Simple doubly-linked list append routine.  This implementation assumes that
918 * each list element contains an embedded ctf_list_t as the first member.
919 * An additional ctf_list_t is used to store the head (l_next) and tail
920 * (l_prev) pointers.  The current head and tail list elements have their
921 * previous and next pointers set to NULL, respectively.
922 */
923static void
924ctf_list_append(ctf_list_t *lp, void *new)
925{
926	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
927	ctf_list_t *q = new;		/* q = new list element */
928
929	lp->l_prev = q;
930	q->l_prev = p;
931	q->l_next = NULL;
932
933	if (p != NULL)
934		p->l_next = q;
935	else
936		lp->l_next = q;
937}
938
939/*
940 * Prepend the specified existing element to the given ctf_list_t.  The
941 * existing pointer should be pointing at a struct with embedded ctf_list_t.
942 */
943static void
944ctf_list_prepend(ctf_list_t *lp, void *new)
945{
946	ctf_list_t *p = new;		/* p = new list element */
947	ctf_list_t *q = lp->l_next;	/* q = head list element */
948
949	lp->l_next = p;
950	p->l_prev = NULL;
951	p->l_next = q;
952
953	if (q != NULL)
954		q->l_prev = p;
955	else
956		lp->l_prev = p;
957}
958
959static void
960ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
961{
962	int i;
963
964	bzero(cd, sizeof (ctf_decl_t));
965
966	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
967		cd->cd_order[i] = CTF_PREC_BASE - 1;
968
969	cd->cd_qualp = CTF_PREC_BASE;
970	cd->cd_ordp = CTF_PREC_BASE;
971
972	cd->cd_buf = buf;
973	cd->cd_ptr = buf;
974	cd->cd_end = buf + len;
975}
976
977static void
978ctf_decl_fini(ctf_decl_t *cd)
979{
980	ctf_decl_node_t *cdp, *ndp;
981	int i;
982
983	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
984		for (cdp = ctf_list_next(&cd->cd_nodes[i]);
985		    cdp != NULL; cdp = ndp) {
986			ndp = ctf_list_next(cdp);
987			free(cdp, M_FBT);
988		}
989	}
990}
991
992static const ctf_type_t *
993ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
994{
995	const ctf_type_t *tp;
996	uint32_t offset;
997	uint32_t *typoff = *lc->typoffp;
998
999	if (type >= *lc->typlenp) {
1000		printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,*lc->typlenp);
1001		return(NULL);
1002	}
1003
1004	/* Check if the type isn't cross-referenced. */
1005	if ((offset = typoff[type]) == 0) {
1006		printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
1007		return(NULL);
1008	}
1009
1010	tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t));
1011
1012	return (tp);
1013}
1014
1015static void
1016fbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp)
1017{
1018	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
1019	const ctf_type_t *tp;
1020	const ctf_array_t *ap;
1021	ssize_t increment;
1022
1023	bzero(arp, sizeof(*arp));
1024
1025	if ((tp = ctf_lookup_by_id(lc, type)) == NULL)
1026		return;
1027
1028	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
1029		return;
1030
1031	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
1032
1033	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
1034	arp->ctr_contents = ap->cta_contents;
1035	arp->ctr_index = ap->cta_index;
1036	arp->ctr_nelems = ap->cta_nelems;
1037}
1038
1039static const char *
1040ctf_strptr(linker_ctf_t *lc, int name)
1041{
1042	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;;
1043	const char *strp = "";
1044
1045	if (name < 0 || name >= hp->cth_strlen)
1046		return(strp);
1047
1048	strp = (const char *)(lc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
1049
1050	return (strp);
1051}
1052
1053static void
1054ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
1055{
1056	ctf_decl_node_t *cdp;
1057	ctf_decl_prec_t prec;
1058	uint_t kind, n = 1;
1059	int is_qual = 0;
1060
1061	const ctf_type_t *tp;
1062	ctf_arinfo_t ar;
1063
1064	if ((tp = ctf_lookup_by_id(lc, type)) == NULL) {
1065		cd->cd_err = ENOENT;
1066		return;
1067	}
1068
1069	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
1070	case CTF_K_ARRAY:
1071		fbt_array_info(lc, type, &ar);
1072		ctf_decl_push(cd, lc, ar.ctr_contents);
1073		n = ar.ctr_nelems;
1074		prec = CTF_PREC_ARRAY;
1075		break;
1076
1077	case CTF_K_TYPEDEF:
1078		if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') {
1079			ctf_decl_push(cd, lc, tp->ctt_type);
1080			return;
1081		}
1082		prec = CTF_PREC_BASE;
1083		break;
1084
1085	case CTF_K_FUNCTION:
1086		ctf_decl_push(cd, lc, tp->ctt_type);
1087		prec = CTF_PREC_FUNCTION;
1088		break;
1089
1090	case CTF_K_POINTER:
1091		ctf_decl_push(cd, lc, tp->ctt_type);
1092		prec = CTF_PREC_POINTER;
1093		break;
1094
1095	case CTF_K_VOLATILE:
1096	case CTF_K_CONST:
1097	case CTF_K_RESTRICT:
1098		ctf_decl_push(cd, lc, tp->ctt_type);
1099		prec = cd->cd_qualp;
1100		is_qual++;
1101		break;
1102
1103	default:
1104		prec = CTF_PREC_BASE;
1105	}
1106
1107	if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
1108		cd->cd_err = EAGAIN;
1109		return;
1110	}
1111
1112	cdp->cd_type = type;
1113	cdp->cd_kind = kind;
1114	cdp->cd_n = n;
1115
1116	if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
1117		cd->cd_order[prec] = cd->cd_ordp++;
1118
1119	/*
1120	 * Reset cd_qualp to the highest precedence level that we've seen so
1121	 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
1122	 */
1123	if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
1124		cd->cd_qualp = prec;
1125
1126	/*
1127	 * C array declarators are ordered inside out so prepend them.  Also by
1128	 * convention qualifiers of base types precede the type specifier (e.g.
1129	 * const int vs. int const) even though the two forms are equivalent.
1130	 */
1131	if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1132		ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1133	else
1134		ctf_list_append(&cd->cd_nodes[prec], cdp);
1135}
1136
1137static void
1138ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1139{
1140	size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1141	va_list ap;
1142	size_t n;
1143
1144	va_start(ap, format);
1145	n = vsnprintf(cd->cd_ptr, len, format, ap);
1146	va_end(ap);
1147
1148	cd->cd_ptr += MIN(n, len);
1149	cd->cd_len += n;
1150}
1151
1152static ssize_t
1153fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
1154{
1155	ctf_decl_t cd;
1156	ctf_decl_node_t *cdp;
1157	ctf_decl_prec_t prec, lp, rp;
1158	int ptr, arr;
1159	uint_t k;
1160
1161	if (lc == NULL && type == CTF_ERR)
1162		return (-1); /* simplify caller code by permitting CTF_ERR */
1163
1164	ctf_decl_init(&cd, buf, len);
1165	ctf_decl_push(&cd, lc, type);
1166
1167	if (cd.cd_err != 0) {
1168		ctf_decl_fini(&cd);
1169		return (-1);
1170	}
1171
1172	/*
1173	 * If the type graph's order conflicts with lexical precedence order
1174	 * for pointers or arrays, then we need to surround the declarations at
1175	 * the corresponding lexical precedence with parentheses.  This can
1176	 * result in either a parenthesized pointer (*) as in int (*)() or
1177	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1178	 */
1179	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1180	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1181
1182	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1183	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1184
1185	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1186
1187	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1188		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1189		    cdp != NULL; cdp = ctf_list_next(cdp)) {
1190
1191			const ctf_type_t *tp =
1192			    ctf_lookup_by_id(lc, cdp->cd_type);
1193			const char *name = ctf_strptr(lc, tp->ctt_name);
1194
1195			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1196				ctf_decl_sprintf(&cd, " ");
1197
1198			if (lp == prec) {
1199				ctf_decl_sprintf(&cd, "(");
1200				lp = -1;
1201			}
1202
1203			switch (cdp->cd_kind) {
1204			case CTF_K_INTEGER:
1205			case CTF_K_FLOAT:
1206			case CTF_K_TYPEDEF:
1207				ctf_decl_sprintf(&cd, "%s", name);
1208				break;
1209			case CTF_K_POINTER:
1210				ctf_decl_sprintf(&cd, "*");
1211				break;
1212			case CTF_K_ARRAY:
1213				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1214				break;
1215			case CTF_K_FUNCTION:
1216				ctf_decl_sprintf(&cd, "()");
1217				break;
1218			case CTF_K_STRUCT:
1219			case CTF_K_FORWARD:
1220				ctf_decl_sprintf(&cd, "struct %s", name);
1221				break;
1222			case CTF_K_UNION:
1223				ctf_decl_sprintf(&cd, "union %s", name);
1224				break;
1225			case CTF_K_ENUM:
1226				ctf_decl_sprintf(&cd, "enum %s", name);
1227				break;
1228			case CTF_K_VOLATILE:
1229				ctf_decl_sprintf(&cd, "volatile");
1230				break;
1231			case CTF_K_CONST:
1232				ctf_decl_sprintf(&cd, "const");
1233				break;
1234			case CTF_K_RESTRICT:
1235				ctf_decl_sprintf(&cd, "restrict");
1236				break;
1237			}
1238
1239			k = cdp->cd_kind;
1240		}
1241
1242		if (rp == prec)
1243			ctf_decl_sprintf(&cd, ")");
1244	}
1245
1246	ctf_decl_fini(&cd);
1247	return (cd.cd_len);
1248}
1249
1250static void
1251fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1252{
1253	const ushort_t *dp;
1254	fbt_probe_t *fbt = parg;
1255	linker_ctf_t lc;
1256	modctl_t *ctl = fbt->fbtp_ctl;
1257	int ndx = desc->dtargd_ndx;
1258	int symindx = fbt->fbtp_symindx;
1259	uint32_t *ctfoff;
1260	uint32_t offset;
1261	ushort_t info, kind, n;
1262
1263	if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
1264		(void) strcpy(desc->dtargd_native, "int");
1265		return;
1266	}
1267
1268	desc->dtargd_ndx = DTRACE_ARGNONE;
1269
1270	/* Get a pointer to the CTF data and it's length. */
1271	if (linker_ctf_get(ctl, &lc) != 0)
1272		/* No CTF data? Something wrong? *shrug* */
1273		return;
1274
1275	/* Check if this module hasn't been initialised yet. */
1276	if (*lc.ctfoffp == NULL) {
1277		/*
1278		 * Initialise the CTF object and function symindx to
1279		 * byte offset array.
1280		 */
1281		if (fbt_ctfoff_init(ctl, &lc) != 0)
1282			return;
1283
1284		/* Initialise the CTF type to byte offset array. */
1285		if (fbt_typoff_init(&lc) != 0)
1286			return;
1287	}
1288
1289	ctfoff = *lc.ctfoffp;
1290
1291	if (ctfoff == NULL || *lc.typoffp == NULL)
1292		return;
1293
1294	/* Check if the symbol index is out of range. */
1295	if (symindx >= lc.nsym)
1296		return;
1297
1298	/* Check if the symbol isn't cross-referenced. */
1299	if ((offset = ctfoff[symindx]) == 0xffffffff)
1300		return;
1301
1302	dp = (const ushort_t *)(lc.ctftab + offset + sizeof(ctf_header_t));
1303
1304	info = *dp++;
1305	kind = CTF_INFO_KIND(info);
1306	n = CTF_INFO_VLEN(info);
1307
1308	if (kind == CTF_K_UNKNOWN && n == 0) {
1309		printf("%s(%d): Unknown function!\n",__func__,__LINE__);
1310		return;
1311	}
1312
1313	if (kind != CTF_K_FUNCTION) {
1314		printf("%s(%d): Expected a function!\n",__func__,__LINE__);
1315		return;
1316	}
1317
1318	if (fbt->fbtp_roffset != 0) {
1319		/* Only return type is available for args[1] in return probe. */
1320		if (ndx > 1)
1321			return;
1322		ASSERT(ndx == 1);
1323	} else {
1324		/* Check if the requested argument doesn't exist. */
1325		if (ndx >= n)
1326			return;
1327
1328		/* Skip the return type and arguments up to the one requested. */
1329		dp += ndx + 1;
1330	}
1331
1332	if (fbt_type_name(&lc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
1333		desc->dtargd_ndx = ndx;
1334
1335	return;
1336}
1337
1338static int
1339fbt_linker_file_cb(linker_file_t lf, void *arg)
1340{
1341
1342	fbt_provide_module(arg, lf);
1343
1344	return (0);
1345}
1346
1347static void
1348fbt_load(void *dummy)
1349{
1350	/* Create the /dev/dtrace/fbt entry. */
1351	fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
1352	    "dtrace/fbt");
1353
1354	/* Default the probe table size if not specified. */
1355	if (fbt_probetab_size == 0)
1356		fbt_probetab_size = FBT_PROBETAB_SIZE;
1357
1358	/* Choose the hash mask for the probe table. */
1359	fbt_probetab_mask = fbt_probetab_size - 1;
1360
1361	/* Allocate memory for the probe table. */
1362	fbt_probetab =
1363	    malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
1364
1365	dtrace_doubletrap_func = fbt_doubletrap;
1366	dtrace_invop_add(fbt_invop);
1367
1368	if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
1369	    NULL, &fbt_pops, NULL, &fbt_id) != 0)
1370		return;
1371
1372	/* Create probes for the kernel and already-loaded modules. */
1373	linker_file_foreach(fbt_linker_file_cb, NULL);
1374}
1375
1376static int
1377fbt_unload()
1378{
1379	int error = 0;
1380
1381	/* De-register the invalid opcode handler. */
1382	dtrace_invop_remove(fbt_invop);
1383
1384	dtrace_doubletrap_func = NULL;
1385
1386	/* De-register this DTrace provider. */
1387	if ((error = dtrace_unregister(fbt_id)) != 0)
1388		return (error);
1389
1390	/* Free the probe table. */
1391	free(fbt_probetab, M_FBT);
1392	fbt_probetab = NULL;
1393	fbt_probetab_mask = 0;
1394
1395	destroy_dev(fbt_cdev);
1396
1397	return (error);
1398}
1399
1400static int
1401fbt_modevent(module_t mod __unused, int type, void *data __unused)
1402{
1403	int error = 0;
1404
1405	switch (type) {
1406	case MOD_LOAD:
1407		break;
1408
1409	case MOD_UNLOAD:
1410		break;
1411
1412	case MOD_SHUTDOWN:
1413		break;
1414
1415	default:
1416		error = EOPNOTSUPP;
1417		break;
1418
1419	}
1420
1421	return (error);
1422}
1423
1424static int
1425fbt_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
1426{
1427	return (0);
1428}
1429
1430SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL);
1431SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL);
1432
1433DEV_MODULE(fbt, fbt_modevent, NULL);
1434MODULE_VERSION(fbt, 1);
1435MODULE_DEPEND(fbt, dtrace, 1, 1, 1);
1436MODULE_DEPEND(fbt, opensolaris, 1, 1, 1);
1437