xref: /netbsd-src/external/cddl/osnet/dev/fbt/fbt.c (revision 501cd18a74d52bfcca7d9e7e3b0d472bbc870558)
1 /*	$NetBSD: fbt.c,v 1.21 2017/01/07 21:39:52 christos Exp $	*/
2 
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License (the "License").
8  * You may not use this file except in compliance with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
24  * Portions Copyright 2010 Darran Hunt darran@NetBSD.org
25  *
26  * $FreeBSD: src/sys/cddl/dev/fbt/fbt.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
27  *
28  */
29 
30 /*
31  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
32  * Use is subject to license terms.
33  */
34 
35 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/conf.h>
39 #include <sys/cpuvar.h>
40 #include <sys/fcntl.h>
41 #include <sys/filio.h>
42 #include <sys/kernel.h>
43 #include <sys/kmem.h>
44 #include <sys/ksyms.h>
45 #include <sys/cpu.h>
46 #include <sys/kthread.h>
47 #include <sys/syslimits.h>
48 #include <sys/linker.h>
49 #include <sys/lock.h>
50 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
53 #include <sys/poll.h>
54 #include <sys/proc.h>
55 #include <sys/selinfo.h>
56 #include <sys/syscall.h>
57 #include <sys/uio.h>
58 #include <sys/unistd.h>
59 
60 #include <machine/cpu.h>
61 #if defined(__i386__) || defined(__amd64__)
62 #include <machine/cpufunc.h>
63 #include <machine/specialreg.h>
64 #if 0
65 #include <x86/cpuvar.h>
66 #endif
67 #include <x86/cputypes.h>
68 #elif __arm__
69 #include <machine/trap.h>
70 #include <arm/cpufunc.h>
71 #include <arm/armreg.h>
72 #include <arm/frame.h>
73 #endif
74 
75 #define ELFSIZE ARCH_ELFSIZE
76 #include <sys/exec_elf.h>
77 
78 #include <sys/dtrace.h>
79 #include <sys/dtrace_bsd.h>
80 #include <sys/kern_ctf.h>
81 #include <sys/dtrace_impl.h>
82 
83 mod_ctf_t *modptr;
84 
85 MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
86 
87 #if defined(__i386__) || defined(__amd64__)
88 #define	FBT_PUSHL_EBP		0x55
89 #define	FBT_MOVL_ESP_EBP0_V0	0x8b
90 #define	FBT_MOVL_ESP_EBP1_V0	0xec
91 #define	FBT_MOVL_ESP_EBP0_V1	0x89
92 #define	FBT_MOVL_ESP_EBP1_V1	0xe5
93 #define	FBT_REX_RSP_RBP		0x48
94 
95 #define	FBT_POPL_EBP		0x5d
96 #define	FBT_RET			0xc3
97 #define	FBT_RET_IMM16		0xc2
98 #define	FBT_LEAVE		0xc9
99 #endif
100 
101 #ifdef __amd64__
102 #define	FBT_PATCHVAL		0xcc
103 #elif defined(__i386__)
104 #define	FBT_PATCHVAL		0xf0
105 
106 #elif defined(__arm__)
107 #define	FBT_PATCHVAL		DTRACE_BREAKPOINT
108 
109 /* entry and return */
110 #define	FBT_BX_LR_P(insn)	(((insn) & ~INSN_COND_MASK) == 0x012fff1e)
111 #define	FBT_B_LABEL_P(insn)	(((insn) & 0xff000000) == 0xea000000)
112 /* entry */
113 #define	FBT_MOV_IP_SP_P(insn)	((insn) == 0xe1a0c00d)
114 /* index=1, add=1, wback=0 */
115 #define	FBT_LDR_IMM_P(insn)	(((insn) & 0xfff00000) == 0xe5900000)
116 #define	FBT_MOVW_P(insn)	(((insn) & 0xfff00000) == 0xe3000000)
117 #define	FBT_MOV_IMM_P(insn)	(((insn) & 0xffff0000) == 0xe3a00000)
118 #define	FBT_CMP_IMM_P(insn)	(((insn) & 0xfff00000) == 0xe3500000)
119 #define	FBT_PUSH_P(insn)	(((insn) & 0xffff0000) == 0xe92d0000)
120 /* return */
121 /* cond=always, writeback=no, rn=sp and register_list includes pc */
122 #define	FBT_LDM_P(insn)	(((insn) & 0x0fff8000) == 0x089d8000)
123 #define	FBT_LDMIB_P(insn)	(((insn) & 0x0fff8000) == 0x099d8000)
124 #define	FBT_MOV_PC_LR_P(insn)	(((insn) & ~INSN_COND_MASK) == 0x01a0f00e)
125 /* cond=always, writeback=no, rn=sp and register_list includes lr, but not pc */
126 #define	FBT_LDM_LR_P(insn)	(((insn) & 0xffffc000) == 0xe89d4000)
127 #define	FBT_LDMIB_LR_P(insn)	(((insn) & 0xffffc000) == 0xe99d4000)
128 
129 /* rval = insn | invop_id (overwriting cond with invop ID) */
130 #define	BUILD_RVAL(insn, id)	(((insn) & ~INSN_COND_MASK) | __SHIFTIN((id), INSN_COND_MASK))
131 /* encode cond in the first byte */
132 #define	PATCHVAL_ENCODE_COND(insn)	(FBT_PATCHVAL | __SHIFTOUT((insn), INSN_COND_MASK))
133 
134 #else
135 #error "architecture not supported"
136 #endif
137 
138 static dev_type_open(fbt_open);
139 static int	fbt_unload(void);
140 static void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
141 static void	fbt_provide_module(void *, dtrace_modctl_t *);
142 static void	fbt_destroy(void *, dtrace_id_t, void *);
143 static int	fbt_enable(void *, dtrace_id_t, void *);
144 static void	fbt_disable(void *, dtrace_id_t, void *);
145 static void	fbt_load(void);
146 static void	fbt_suspend(void *, dtrace_id_t, void *);
147 static void	fbt_resume(void *, dtrace_id_t, void *);
148 
149 #define	FBT_ENTRY	"entry"
150 #define	FBT_RETURN	"return"
151 #define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
152 #define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
153 
154 static const struct cdevsw fbt_cdevsw = {
155 	.d_open		= fbt_open,
156 	.d_close	= noclose,
157 	.d_read		= noread,
158 	.d_write	= nowrite,
159 	.d_ioctl	= noioctl,
160 	.d_stop		= nostop,
161 	.d_tty		= notty,
162 	.d_poll		= nopoll,
163 	.d_mmap		= nommap,
164 	.d_kqfilter	= nokqfilter,
165 	.d_discard	= nodiscard,
166 	.d_flag		= D_OTHER
167 };
168 
169 static dtrace_pattr_t fbt_attr = {
170 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
171 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
172 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
173 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
174 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
175 };
176 
177 static dtrace_pops_t fbt_pops = {
178 	NULL,
179 	fbt_provide_module,
180 	fbt_enable,
181 	fbt_disable,
182 	fbt_suspend,
183 	fbt_resume,
184 	fbt_getargdesc,
185 	NULL,
186 	NULL,
187 	fbt_destroy
188 };
189 
190 typedef struct fbt_probe {
191 	struct fbt_probe *fbtp_hashnext;
192 #if defined(__i386__) || defined(__amd64__)
193 	uint8_t		*fbtp_patchpoint;
194 	int8_t		fbtp_rval;
195 	uint8_t		fbtp_patchval;
196 	uint8_t		fbtp_savedval;
197 #elif __arm__
198 	uint32_t	*fbtp_patchpoint;
199 	int32_t		fbtp_rval;
200 	uint32_t	fbtp_patchval;
201 	uint32_t	fbtp_savedval;
202 #endif
203 	uintptr_t	fbtp_roffset;
204 	dtrace_id_t	fbtp_id;
205 	const char	*fbtp_name;
206 	dtrace_modctl_t	*fbtp_ctl;
207 	int		fbtp_loadcnt;
208 	int		fbtp_primary;
209 	int		fbtp_invop_cnt;
210 	int		fbtp_symindx;
211 	struct fbt_probe *fbtp_next;
212 } fbt_probe_t;
213 
214 #ifdef notyet
215 static struct cdev		*fbt_cdev;
216 static int			fbt_verbose = 0;
217 #endif
218 static dtrace_provider_id_t	fbt_id;
219 static fbt_probe_t		**fbt_probetab;
220 static int			fbt_probetab_size;
221 static int			fbt_probetab_mask;
222 
223 #ifdef __arm__
224 extern void (* dtrace_emulation_jump_addr)(int, struct trapframe *);
225 
226 static uint32_t
227 expand_imm(uint32_t imm12)
228 {
229 	uint32_t unrot = imm12 & 0xff;
230 	int amount = 2 * (imm12 >> 8);
231 
232 	if (amount)
233 		return (unrot >> amount) | (unrot << (32 - amount));
234 	else
235 		return unrot;
236 }
237 
238 static uint32_t
239 add_with_carry(uint32_t x, uint32_t y, int carry_in,
240 	int *carry_out, int *overflow)
241 {
242 	uint32_t result;
243 	uint64_t unsigned_sum = x + y + (uint32_t)carry_in;
244 	int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
245 	KASSERT(carry_in == 1);
246 
247 	result = (uint32_t)(unsigned_sum & 0xffffffff);
248 	*carry_out = ((uint64_t)result == unsigned_sum) ? 1 : 0;
249 	*overflow = ((int64_t)result == signed_sum) ? 0 : 1;
250 
251 	return result;
252 }
253 
254 static void
255 fbt_emulate(int _op, struct trapframe *frame)
256 {
257 	uint32_t op = _op;
258 
259 	switch (op >> 28) {
260 	case DTRACE_INVOP_MOV_IP_SP:
261 		/* mov ip, sp */
262 		frame->tf_ip = frame->tf_svc_sp;
263 		frame->tf_pc += 4;
264 		break;
265 	case DTRACE_INVOP_BX_LR:
266 		/* bx lr */
267 		frame->tf_pc = frame->tf_svc_lr;
268 		break;
269 	case DTRACE_INVOP_MOV_PC_LR:
270 		/* mov pc, lr */
271 		frame->tf_pc = frame->tf_svc_lr;
272 		break;
273 	case DTRACE_INVOP_LDM:
274 		/* ldm sp, {..., pc} */
275 		/* FALLTHRU */
276 	case DTRACE_INVOP_LDMIB: {
277 		/* ldmib sp, {..., pc} */
278 		uint32_t register_list = (op & 0xffff);
279 		uint32_t *sp = (uint32_t *)(intptr_t)frame->tf_svc_sp;
280 		uint32_t *regs = &frame->tf_r0;
281 		int i;
282 
283 		/* IDMIB */
284 		if ((op >> 28) == 5)
285 			sp++;
286 
287 		for (i=0; i <= 12; i++) {
288 			if (register_list & (1 << i))
289 				regs[i] = *sp++;
290 		}
291 		if (register_list & (1 << 13))
292 			frame->tf_svc_sp = *sp++;
293 		if (register_list & (1 << 14))
294 			frame->tf_svc_lr = *sp++;
295 		frame->tf_pc = *sp;
296 		break;
297 	}
298 	case DTRACE_INVOP_LDR_IMM: {
299 		/* ldr r?, [{pc,r?}, #?] */
300 		uint32_t rt = (op >> 12) & 0xf;
301 		uint32_t rn = (op >> 16) & 0xf;
302 		uint32_t imm = op & 0xfff;
303 		uint32_t *regs = &frame->tf_r0;
304 		KDASSERT(rt <= 12);
305 		KDASSERT(rn == 15 || rn =< 12);
306 		if (rn == 15)
307 			regs[rt] = *((uint32_t *)(intptr_t)(frame->tf_pc + 8 + imm));
308 		else
309 			regs[rt] = *((uint32_t *)(intptr_t)(regs[rn] + imm));
310 		frame->tf_pc += 4;
311 		break;
312 	}
313 	case DTRACE_INVOP_MOVW: {
314 		/* movw r?, #? */
315 		uint32_t rd = (op >> 12) & 0xf;
316 		uint32_t imm = (op & 0xfff) | ((op & 0xf0000) >> 4);
317 		uint32_t *regs = &frame->tf_r0;
318 		KDASSERT(rd <= 12);
319 		regs[rd] = imm;
320 		frame->tf_pc += 4;
321 		break;
322 	}
323 	case DTRACE_INVOP_MOV_IMM: {
324 		/* mov r?, #? */
325 		uint32_t rd = (op >> 12) & 0xf;
326 		uint32_t imm = expand_imm(op & 0xfff);
327 		uint32_t *regs = &frame->tf_r0;
328 		KDASSERT(rd <= 12);
329 		regs[rd] = imm;
330 		frame->tf_pc += 4;
331 		break;
332 	}
333 	case DTRACE_INVOP_CMP_IMM: {
334 		/* cmp r?, #? */
335 		uint32_t rn = (op >> 16) & 0xf;
336 		uint32_t *regs = &frame->tf_r0;
337 		uint32_t imm = expand_imm(op & 0xfff);
338 		uint32_t spsr = frame->tf_spsr;
339 		uint32_t result;
340 		int carry;
341 		int overflow;
342 		/*
343 		 * (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), ’1’);
344 		 * APSR.N = result<31>;
345 		 * APSR.Z = IsZeroBit(result);
346 		 * APSR.C = carry;
347 		 * APSR.V = overflow;
348 		 */
349 		KDASSERT(rn <= 12);
350 		result = add_with_carry(regs[rn], ~imm, 1, &carry, &overflow);
351 		if (result & 0x80000000)
352 			spsr |= PSR_N_bit;
353 		else
354 			spsr &= ~PSR_N_bit;
355 		if (result == 0)
356 			spsr |= PSR_Z_bit;
357 		else
358 			spsr &= ~PSR_Z_bit;
359 		if (carry)
360 			spsr |= PSR_C_bit;
361 		else
362 			spsr &= ~PSR_C_bit;
363 		if (overflow)
364 			spsr |= PSR_V_bit;
365 		else
366 			spsr &= ~PSR_V_bit;
367 
368 #if 0
369 		aprint_normal("pc=%x Rn=%x imm=%x %c%c%c%c\n", frame->tf_pc, regs[rn], imm,
370 		    (spsr & PSR_N_bit) ? 'N' : 'n',
371 		    (spsr & PSR_Z_bit) ? 'Z' : 'z',
372 		    (spsr & PSR_C_bit) ? 'C' : 'c',
373 		    (spsr & PSR_V_bit) ? 'V' : 'v');
374 #endif
375 		frame->tf_spsr = spsr;
376 		frame->tf_pc += 4;
377 		break;
378 	}
379 	case DTRACE_INVOP_B_LABEL: {
380 		/* b ??? */
381 		uint32_t imm = (op & 0x00ffffff) << 2;
382 		int32_t diff;
383 		/* SignExtend(imm26, 32) */
384 		if (imm & 0x02000000)
385 			imm |= 0xfc000000;
386 		diff = (int32_t)imm;
387 		frame->tf_pc += 8 + diff;
388 		break;
389 	}
390 	/* FIXME: push will overwrite trapframe... */
391 	case DTRACE_INVOP_PUSH: {
392 		/* push {...} */
393 		uint32_t register_list = (op & 0xffff);
394 		uint32_t *sp = (uint32_t *)(intptr_t)frame->tf_svc_sp;
395 		uint32_t *regs = &frame->tf_r0;
396 		int i;
397 		int count = 0;
398 
399 #if 0
400 		if ((op & 0x0fff0fff) == 0x052d0004) {
401 			/* A2: str r4, [sp, #-4]! */
402 			*(sp - 1) = regs[4];
403 			frame->tf_pc += 4;
404 			break;
405 		}
406 #endif
407 
408 		for (i=0; i < 16; i++) {
409 			if (register_list & (1 << i))
410 				count++;
411 		}
412 		sp -= count;
413 
414 		for (i=0; i <= 12; i++) {
415 			if (register_list & (1 << i))
416 				*sp++ = regs[i];
417 		}
418 		if (register_list & (1 << 13))
419 			*sp++ = frame->tf_svc_sp;
420 		if (register_list & (1 << 14))
421 			*sp++ = frame->tf_svc_lr;
422 		if (register_list & (1 << 15))
423 			*sp = frame->tf_pc + 8;
424 
425 		/* make sure the caches and memory are in sync */
426 		cpu_dcache_wbinv_range(frame->tf_svc_sp, count * 4);
427 
428 		/* In case the current page tables have been modified ... */
429 		cpu_tlb_flushID();
430 		cpu_cpwait();
431 
432 		frame->tf_svc_sp -= count * 4;
433 		frame->tf_pc += 4;
434 
435 		break;
436 	}
437 	default:
438 		KDASSERTMSG(0, "op=%u\n", op >> 28);
439 	}
440 }
441 #endif
442 
443 static void
444 fbt_doubletrap(void)
445 {
446 	fbt_probe_t *fbt;
447 	int i;
448 
449 	for (i = 0; i < fbt_probetab_size; i++) {
450 		fbt = fbt_probetab[i];
451 
452 		for (; fbt != NULL; fbt = fbt->fbtp_next)
453 			*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
454 	}
455 }
456 
457 
458 static int
459 fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
460 {
461 	solaris_cpu_t *cpu = &solaris_cpu[cpu_number()];
462 	uintptr_t stack0, stack1, stack2, stack3, stack4;
463 	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
464 
465 	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
466 		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
467 			fbt->fbtp_invop_cnt++;
468 			if (fbt->fbtp_roffset == 0) {
469 				int i = 0;
470 				/*
471 				 * When accessing the arguments on the stack,
472 				 * we must protect against accessing beyond
473 				 * the stack.  We can safely set NOFAULT here
474 				 * -- we know that interrupts are already
475 				 * disabled.
476 				 */
477 				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
478 				cpu->cpu_dtrace_caller = stack[i++];
479 				stack0 = stack[i++];
480 				stack1 = stack[i++];
481 				stack2 = stack[i++];
482 				stack3 = stack[i++];
483 				stack4 = stack[i++];
484 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
485 				    CPU_DTRACE_BADADDR);
486 
487 				dtrace_probe(fbt->fbtp_id, stack0, stack1,
488 				    stack2, stack3, stack4);
489 
490 				cpu->cpu_dtrace_caller = 0;
491 			} else {
492 #ifdef __amd64__
493 				/*
494 				 * On amd64, we instrument the ret, not the
495 				 * leave.  We therefore need to set the caller
496 				 * to assure that the top frame of a stack()
497 				 * action is correct.
498 				 */
499 				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
500 				cpu->cpu_dtrace_caller = stack[0];
501 				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
502 				    CPU_DTRACE_BADADDR);
503 #endif
504 
505 				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
506 				    rval, 0, 0, 0);
507 				cpu->cpu_dtrace_caller = 0;
508 			}
509 
510 			return (fbt->fbtp_rval);
511 		}
512 	}
513 
514 	return (0);
515 }
516 
517 #if defined(__i386__) || defined(__amd64__)
518 static int
519 fbt_provide_module_cb(const char *name, int symindx, void *value,
520 	uint32_t symsize, int type, void *opaque)
521 {
522 	fbt_probe_t *fbt, *retfbt;
523 	u_int8_t *instr, *limit;
524 	dtrace_modctl_t *mod = opaque;
525 	const char *modname = mod->mod_info->mi_name;
526 	int j;
527 	int size;
528 
529 	/* got a function? */
530 	if (ELF_ST_TYPE(type) != STT_FUNC) {
531 	    return 0;
532 	}
533 
534 	if (strncmp(name, "dtrace_", 7) == 0 &&
535 	    strncmp(name, "dtrace_safe_", 12) != 0) {
536 		/*
537 		 * Anything beginning with "dtrace_" may be called
538 		 * from probe context unless it explicitly indicates
539 		 * that it won't be called from probe context by
540 		 * using the prefix "dtrace_safe_".
541 		 */
542 		return (0);
543 	}
544 
545 	if (name[0] == '_' && name[1] == '_')
546 		return (0);
547 
548 	/*
549 	 * Exclude some more symbols which can be called from probe context.
550 	 */
551 	if (strcmp(name, "x86_curcpu") == 0 /* CPU */
552 	    || strcmp(name, "x86_curlwp") == 0 /* curproc, curlwp, curthread */
553 	    || strcmp(name, "cpu_index") == 0 /* cpu_number, curcpu_id */
554 	    || strncmp(name, "db_", 3) == 0 /* debugger */
555 	    || strncmp(name, "ddb_", 4) == 0 /* debugger */
556 	    || strncmp(name, "kdb_", 4) == 0 /* debugger */
557 	    || strncmp(name, "lockdebug_", 10) == 0 /* lockdebug XXX for now */
558 	    || strncmp(name, "kauth_", 5) == 0 /* CRED XXX for now */
559 	    ) {
560 		return 0;
561 	}
562 
563 	instr = (u_int8_t *) value;
564 	limit = (u_int8_t *) value + symsize;
565 
566 #ifdef __amd64__
567 	while (instr < limit) {
568 		if (*instr == FBT_PUSHL_EBP)
569 			break;
570 
571 		if ((size = dtrace_instr_size(instr)) <= 0)
572 			break;
573 
574 		instr += size;
575 	}
576 
577 	if (instr >= limit || *instr != FBT_PUSHL_EBP) {
578 		/*
579 		 * We either don't save the frame pointer in this
580 		 * function, or we ran into some disassembly
581 		 * screw-up.  Either way, we bail.
582 		 */
583 		return (0);
584 	}
585 #else
586 	if (instr[0] != FBT_PUSHL_EBP) {
587 		return (0);
588 	}
589 
590 	if (!(instr[1] == FBT_MOVL_ESP_EBP0_V0 &&
591 	    instr[2] == FBT_MOVL_ESP_EBP1_V0) &&
592 	    !(instr[1] == FBT_MOVL_ESP_EBP0_V1 &&
593 	    instr[2] == FBT_MOVL_ESP_EBP1_V1)) {
594 		return (0);
595 	}
596 #endif
597 	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
598 	fbt->fbtp_name = name;
599 	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
600 	    name, FBT_ENTRY, 3, fbt);
601 	fbt->fbtp_patchpoint = instr;
602 	fbt->fbtp_ctl = mod;
603 	/* fbt->fbtp_loadcnt = lf->loadcnt; */
604 	fbt->fbtp_rval = DTRACE_INVOP_PUSHL_EBP;
605 	fbt->fbtp_savedval = *instr;
606 	fbt->fbtp_patchval = FBT_PATCHVAL;
607 	fbt->fbtp_symindx = symindx;
608 
609 	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
610 	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
611 	mod->mod_fbtentries++;
612 
613 	retfbt = NULL;
614 
615 	while (instr < limit) {
616 		if (instr >= limit)
617 			return (0);
618 
619 		/*
620 		 * If this disassembly fails, then we've likely walked off into
621 		 * a jump table or some other unsuitable area.  Bail out of the
622 		 * disassembly now.
623 		 */
624 		if ((size = dtrace_instr_size(instr)) <= 0)
625 			return (0);
626 
627 #ifdef __amd64__
628 		/*
629 		 * We only instrument "ret" on amd64 -- we don't yet instrument
630 		 * ret imm16, largely because the compiler doesn't seem to
631 		 * (yet) emit them in the kernel...
632 		 */
633 		if (*instr != FBT_RET) {
634 			instr += size;
635 			continue;
636 		}
637 #else
638 		if (!(size == 1 &&
639 		    (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) &&
640 		    (*(instr + 1) == FBT_RET ||
641 		    *(instr + 1) == FBT_RET_IMM16))) {
642 			instr += size;
643 			continue;
644 		}
645 #endif
646 
647 		/*
648 		 * We (desperately) want to avoid erroneously instrumenting a
649 		 * jump table, especially given that our markers are pretty
650 		 * short:  two bytes on x86, and just one byte on amd64.  To
651 		 * determine if we're looking at a true instruction sequence
652 		 * or an inline jump table that happens to contain the same
653 		 * byte sequences, we resort to some heuristic sleeze:  we
654 		 * treat this instruction as being contained within a pointer,
655 		 * and see if that pointer points to within the body of the
656 		 * function.  If it does, we refuse to instrument it.
657 		 */
658 		for (j = 0; j < sizeof (uintptr_t); j++) {
659 			caddr_t check = (caddr_t) instr - j;
660 			uint8_t *ptr;
661 
662 			if (check < (caddr_t)value)
663 				break;
664 
665 			if (check + sizeof (caddr_t) > (caddr_t)limit)
666 				continue;
667 
668 			ptr = *(uint8_t **)check;
669 
670 			if (ptr >= (uint8_t *) value && ptr < limit) {
671 				instr += size;
672 				continue;
673 			}
674 		}
675 
676 		/*
677 		 * We have a winner!
678 		 */
679 		fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
680 		fbt->fbtp_name = name;
681 
682 		if (retfbt == NULL) {
683 			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
684 			    name, FBT_RETURN, 3, fbt);
685 		} else {
686 			retfbt->fbtp_next = fbt;
687 			fbt->fbtp_id = retfbt->fbtp_id;
688 		}
689 
690 		retfbt = fbt;
691 		fbt->fbtp_patchpoint = instr;
692 		fbt->fbtp_ctl = mod;
693 		/* fbt->fbtp_loadcnt = lf->loadcnt; */
694 		fbt->fbtp_symindx = symindx;
695 
696 #ifndef __amd64__
697 		if (*instr == FBT_POPL_EBP) {
698 			fbt->fbtp_rval = DTRACE_INVOP_POPL_EBP;
699 		} else {
700 			ASSERT(*instr == FBT_LEAVE);
701 			fbt->fbtp_rval = DTRACE_INVOP_LEAVE;
702 		}
703 		fbt->fbtp_roffset =
704 		    (uintptr_t)(instr - (uint8_t *) value) + 1;
705 
706 #else
707 		ASSERT(*instr == FBT_RET);
708 		fbt->fbtp_rval = DTRACE_INVOP_RET;
709 		fbt->fbtp_roffset =
710 		    (uintptr_t)(instr - (uint8_t *) value);
711 #endif
712 
713 		fbt->fbtp_savedval = *instr;
714 		fbt->fbtp_patchval = FBT_PATCHVAL;
715 		fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
716 		fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
717 
718 		mod->mod_fbtentries++;
719 
720 		instr += size;
721 	}
722 
723 	return 0;
724 }
725 
726 #elif defined(__arm__)
727 
728 static int
729 fbt_provide_module_cb(const char *name, int symindx, void *value,
730 	uint32_t symsize, int type, void *opaque)
731 {
732 	fbt_probe_t *fbt, *retfbt;
733 	uint32_t *instr, *limit;
734 	bool was_ldm_lr = false;
735 	dtrace_modctl_t *mod = opaque;
736 	const char *modname = mod->mod_info->mi_name;
737 	int size;
738 
739 	/* got a function? */
740 	if (ELF_ST_TYPE(type) != STT_FUNC) {
741 	    return 0;
742 	}
743 
744 	if (strncmp(name, "dtrace_", 7) == 0 &&
745 	    strncmp(name, "dtrace_safe_", 12) != 0) {
746 		/*
747 		 * Anything beginning with "dtrace_" may be called
748 		 * from probe context unless it explicitly indicates
749 		 * that it won't be called from probe context by
750 		 * using the prefix "dtrace_safe_".
751 		 */
752 		return (0);
753 	}
754 
755 	if (name[0] == '_' && name[1] == '_')
756 		return (0);
757 
758 	/*
759 	 * Exclude some more symbols which can be called from probe context.
760 	 */
761 	if (strncmp(name, "db_", 3) == 0 /* debugger */
762 	    || strncmp(name, "ddb_", 4) == 0 /* debugger */
763 	    || strncmp(name, "kdb_", 4) == 0 /* debugger */
764 	    || strncmp(name, "lockdebug_", 10) == 0 /* lockdebug XXX for now */
765 	    || strncmp(name, "kauth_", 5) == 0 /* CRED XXX for now */
766 	    /* Sensitive functions on ARM */
767 	    || strncmp(name, "_spl", 4) == 0
768 	    || strcmp(name, "binuptime") == 0
769 	    || strcmp(name, "dosoftints") == 0
770 	    || strcmp(name, "fbt_emulate") == 0
771 	    || strcmp(name, "nanouptime") == 0
772 	    || strcmp(name, "undefinedinstruction") == 0
773 	    || strncmp(name, "dmt_", 4) == 0 /* omap */
774 	    || strncmp(name, "mvsoctmr_", 9) == 0 /* marvell */
775 	    ) {
776 		return 0;
777 	}
778 
779 	instr = (uint32_t *) value;
780 	limit = (uint32_t *)((uintptr_t)value + symsize);
781 
782 	if (!FBT_MOV_IP_SP_P(*instr)
783 	    && !FBT_BX_LR_P(*instr)
784 	    && !FBT_MOVW_P(*instr)
785 	    && !FBT_MOV_IMM_P(*instr)
786 	    && !FBT_B_LABEL_P(*instr)
787 	    && !FBT_LDR_IMM_P(*instr)
788 	    && !FBT_CMP_IMM_P(*instr)
789 	    /* && !FBT_PUSH_P(*instr) */
790 	    ) {
791 		return 0;
792 	}
793 
794 	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
795 	fbt->fbtp_name = name;
796 	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
797 	    name, FBT_ENTRY, 3, fbt);
798 	fbt->fbtp_patchpoint = instr;
799 	fbt->fbtp_ctl = mod;
800 	/* fbt->fbtp_loadcnt = lf->loadcnt; */
801 	if (FBT_MOV_IP_SP_P(*instr))
802 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_IP_SP);
803 	else if (FBT_LDR_IMM_P(*instr))
804 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_LDR_IMM);
805 	else if (FBT_MOVW_P(*instr))
806 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOVW);
807 	else if (FBT_MOV_IMM_P(*instr))
808 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_IMM);
809 	else if (FBT_CMP_IMM_P(*instr))
810 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_CMP_IMM);
811 	else if (FBT_BX_LR_P(*instr))
812 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_BX_LR);
813 	else if (FBT_PUSH_P(*instr))
814 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_PUSH);
815 	else if (FBT_B_LABEL_P(*instr))
816 		fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_B_LABEL);
817 
818 	fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(*instr);
819 	fbt->fbtp_savedval = *instr;
820 	fbt->fbtp_symindx = symindx;
821 
822 	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
823 	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
824 	mod->mod_fbtentries++;
825 
826 	retfbt = NULL;
827 
828 	while (instr < limit) {
829 		if (instr >= limit)
830 			return (0);
831 
832 		size = 1;
833 
834 		if (!FBT_BX_LR_P(*instr)
835 		    && !FBT_MOV_PC_LR_P(*instr)
836 		    && !FBT_LDM_P(*instr)
837 		    && !FBT_LDMIB_P(*instr)
838 		    && !(was_ldm_lr && FBT_B_LABEL_P(*instr))
839 		    ) {
840 			if (FBT_LDM_LR_P(*instr) || FBT_LDMIB_LR_P(*instr))
841 				was_ldm_lr = true;
842 			else
843 				was_ldm_lr = false;
844 			instr += size;
845 			continue;
846 		}
847 
848 		/*
849 		 * We have a winner!
850 		 */
851 		fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
852 		fbt->fbtp_name = name;
853 
854 		if (retfbt == NULL) {
855 			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
856 			    name, FBT_RETURN, 3, fbt);
857 		} else {
858 			retfbt->fbtp_next = fbt;
859 			fbt->fbtp_id = retfbt->fbtp_id;
860 		}
861 
862 		retfbt = fbt;
863 		fbt->fbtp_patchpoint = instr;
864 		fbt->fbtp_ctl = mod;
865 		/* fbt->fbtp_loadcnt = lf->loadcnt; */
866 		fbt->fbtp_symindx = symindx;
867 
868 		if (FBT_BX_LR_P(*instr))
869 			fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_BX_LR);
870 		else if (FBT_MOV_PC_LR_P(*instr))
871 			fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_MOV_PC_LR);
872 		else if (FBT_LDM_P(*instr))
873 			fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_LDM);
874 		else if (FBT_LDMIB_P(*instr))
875 			fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_LDMIB);
876 		else if (FBT_B_LABEL_P(*instr))
877 			fbt->fbtp_rval = BUILD_RVAL(*instr, DTRACE_INVOP_B_LABEL);
878 
879 		fbt->fbtp_roffset = (uintptr_t)(instr - (uint32_t *) value);
880 		fbt->fbtp_patchval = PATCHVAL_ENCODE_COND(*instr);
881 
882 		fbt->fbtp_savedval = *instr;
883 		fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
884 		fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
885 
886 		mod->mod_fbtentries++;
887 
888 		instr += size;
889 		was_ldm_lr = false;
890 	}
891 
892 	return 0;
893 }
894 #else
895 #error "architecture not supported"
896 #endif
897 
898 
899 static void
900 fbt_provide_module(void *arg, dtrace_modctl_t *mod)
901 {
902 	char modname[MAXPATHLEN];
903 	int i;
904 	size_t len;
905 
906 	strlcpy(modname, mod->mod_info->mi_name, sizeof(modname));
907 	len = strlen(modname);
908 	if (len > 5 && strcmp(modname + len - 3, ".kmod") == 0)
909 		modname[len - 4] = '\0';
910 
911 	/*
912 	 * Employees of dtrace and their families are ineligible.  Void
913 	 * where prohibited.
914 	 */
915 	if (strcmp(modname, "dtrace") == 0)
916 		return;
917 
918 	/*
919 	 * The cyclic timer subsystem can be built as a module and DTrace
920 	 * depends on that, so it is ineligible too.
921 	 */
922 	if (strcmp(modname, "cyclic") == 0)
923 		return;
924 
925 	/*
926 	 * To register with DTrace, a module must list 'dtrace' as a
927 	 * dependency in order for the kernel linker to resolve
928 	 * symbols like dtrace_register(). All modules with such a
929 	 * dependency are ineligible for FBT tracing.
930 	 */
931 	for (i = 0; i < mod->mod_nrequired; i++) {
932 		if (strncmp(mod->mod_required[i]->mod_info->mi_name,
933 			    "dtrace", 6) == 0)
934 			return;
935 	}
936 
937 	if (mod->mod_fbtentries) {
938 		/*
939 		 * This module has some FBT entries allocated; we're afraid
940 		 * to screw with it.
941 		 */
942 		return;
943 	}
944 
945 	/*
946 	 * List the functions in the module and the symbol values.
947 	 */
948 	ksyms_mod_foreach(modname, fbt_provide_module_cb, mod);
949 }
950 
951 static void
952 fbt_destroy(void *arg, dtrace_id_t id, void *parg)
953 {
954 	fbt_probe_t *fbt = parg, *next, *hash, *last;
955 	dtrace_modctl_t *ctl;
956 	int ndx;
957 
958 	do {
959 		ctl = fbt->fbtp_ctl;
960 
961 		ctl->mod_fbtentries--;
962 
963 		/*
964 		 * Now we need to remove this probe from the fbt_probetab.
965 		 */
966 		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
967 		last = NULL;
968 		hash = fbt_probetab[ndx];
969 
970 		while (hash != fbt) {
971 			ASSERT(hash != NULL);
972 			last = hash;
973 			hash = hash->fbtp_hashnext;
974 		}
975 
976 		if (last != NULL) {
977 			last->fbtp_hashnext = fbt->fbtp_hashnext;
978 		} else {
979 			fbt_probetab[ndx] = fbt->fbtp_hashnext;
980 		}
981 
982 		next = fbt->fbtp_next;
983 		free(fbt, M_FBT);
984 
985 		fbt = next;
986 	} while (fbt != NULL);
987 }
988 
989 #if defined(__i386__) || defined(__amd64__)
990 
991 static int
992 fbt_enable(void *arg, dtrace_id_t id, void *parg)
993 {
994 	fbt_probe_t *fbt = parg;
995 #if 0
996 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
997 #endif
998 	u_long psl;
999 	u_long cr0;
1000 
1001 
1002 #if 0	/* XXX TBD */
1003 	ctl->nenabled++;
1004 
1005 	/*
1006 	 * Now check that our modctl has the expected load count.  If it
1007 	 * doesn't, this module must have been unloaded and reloaded -- and
1008 	 * we're not going to touch it.
1009 	 */
1010 	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
1011 		if (fbt_verbose) {
1012 			printf("fbt is failing for probe %s "
1013 			    "(module %s reloaded)",
1014 			    fbt->fbtp_name, ctl->filename);
1015 		}
1016 
1017 		return;
1018 	}
1019 #endif
1020 
1021 	/* Disable interrupts. */
1022 	psl = x86_read_psl();
1023 	x86_disable_intr();
1024 
1025 	/* Disable write protection in supervisor mode. */
1026 	cr0 = rcr0();
1027 	lcr0(cr0 & ~CR0_WP);
1028 
1029 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
1030 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
1031 	}
1032 
1033 	/* Write back and invalidate cache, flush pipelines. */
1034 	wbinvd();
1035 	x86_flush();
1036 	x86_write_psl(psl);
1037 
1038 	/* Re-enable write protection. */
1039 	lcr0(cr0);
1040 
1041 	return 0;
1042 }
1043 
1044 static void
1045 fbt_disable(void *arg, dtrace_id_t id, void *parg)
1046 {
1047 	fbt_probe_t *fbt = parg;
1048 #if 0
1049 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1050 #endif
1051 	u_long psl;
1052 	u_long cr0;
1053 
1054 #if 0	/* XXX TBD */
1055 	ASSERT(ctl->nenabled > 0);
1056 	ctl->nenabled--;
1057 
1058 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1059 		return;
1060 #endif
1061 	/* Disable interrupts. */
1062 	psl = x86_read_psl();
1063 	x86_disable_intr();
1064 
1065 	/* Disable write protection in supervisor mode. */
1066 	cr0 = rcr0();
1067 	lcr0(cr0 & ~CR0_WP);
1068 
1069 	for (; fbt != NULL; fbt = fbt->fbtp_next)
1070 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
1071 
1072 	/* Write back and invalidate cache, flush pipelines. */
1073 	wbinvd();
1074 	x86_flush();
1075 	x86_write_psl(psl);
1076 
1077 	/* Re-enable write protection. */
1078 	lcr0(cr0);
1079 }
1080 
1081 static void
1082 fbt_suspend(void *arg, dtrace_id_t id, void *parg)
1083 {
1084 	fbt_probe_t *fbt = parg;
1085 #if 0
1086 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1087 #endif
1088 	u_long psl;
1089 	u_long cr0;
1090 
1091 #if 0	/* XXX TBD */
1092 	ASSERT(ctl->nenabled > 0);
1093 
1094 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1095 		return;
1096 #endif
1097 
1098 	/* Disable interrupts. */
1099 	psl = x86_read_psl();
1100 	x86_disable_intr();
1101 
1102 	/* Disable write protection in supervisor mode. */
1103 	cr0 = rcr0();
1104 	lcr0(cr0 & ~CR0_WP);
1105 
1106 	for (; fbt != NULL; fbt = fbt->fbtp_next)
1107 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
1108 
1109 	/* Write back and invalidate cache, flush pipelines. */
1110 	wbinvd();
1111 	x86_flush();
1112 	x86_write_psl(psl);
1113 
1114 	/* Re-enable write protection. */
1115 	lcr0(cr0);
1116 }
1117 
1118 static void
1119 fbt_resume(void *arg, dtrace_id_t id, void *parg)
1120 {
1121 	fbt_probe_t *fbt = parg;
1122 #if 0
1123 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1124 #endif
1125 	u_long psl;
1126 	u_long cr0;
1127 
1128 #if 0	/* XXX TBD */
1129 	ASSERT(ctl->nenabled > 0);
1130 
1131 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1132 		return;
1133 #endif
1134 	/* Disable interrupts. */
1135 	psl = x86_read_psl();
1136 	x86_disable_intr();
1137 
1138 	/* Disable write protection in supervisor mode. */
1139 	cr0 = rcr0();
1140 	lcr0(cr0 & ~CR0_WP);
1141 
1142 	for (; fbt != NULL; fbt = fbt->fbtp_next)
1143 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
1144 
1145 	/* Write back and invalidate cache, flush pipelines. */
1146 	wbinvd();
1147 	x86_flush();
1148 	x86_write_psl(psl);
1149 
1150 	/* Re-enable write protection. */
1151 	lcr0(cr0);
1152 }
1153 
1154 #elif defined(__arm__)
1155 
1156 static int
1157 fbt_enable(void *arg, dtrace_id_t id, void *parg)
1158 {
1159 	fbt_probe_t *fbt = parg;
1160 #if 0
1161 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1162 #endif
1163 	dtrace_icookie_t c;
1164 
1165 
1166 #if 0	/* XXX TBD */
1167 	ctl->nenabled++;
1168 
1169 	/*
1170 	 * Now check that our modctl has the expected load count.  If it
1171 	 * doesn't, this module must have been unloaded and reloaded -- and
1172 	 * we're not going to touch it.
1173 	 */
1174 	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
1175 		if (fbt_verbose) {
1176 			printf("fbt is failing for probe %s "
1177 			    "(module %s reloaded)",
1178 			    fbt->fbtp_name, ctl->filename);
1179 		}
1180 
1181 		return;
1182 	}
1183 #endif
1184 
1185 	c = dtrace_interrupt_disable();
1186 
1187 	for (fbt = parg; fbt != NULL; fbt = fbt->fbtp_next) {
1188 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
1189 		cpu_idcache_wbinv_range((vaddr_t)fbt->fbtp_patchpoint, 4);
1190 	}
1191 
1192 	dtrace_interrupt_enable(c);
1193 
1194 	return 0;
1195 }
1196 
1197 static void
1198 fbt_disable(void *arg, dtrace_id_t id, void *parg)
1199 {
1200 	fbt_probe_t *fbt = parg;
1201 #if 0
1202 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1203 #endif
1204 	dtrace_icookie_t c;
1205 
1206 #if 0	/* XXX TBD */
1207 	ASSERT(ctl->nenabled > 0);
1208 	ctl->nenabled--;
1209 
1210 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1211 		return;
1212 #endif
1213 
1214 	c = dtrace_interrupt_disable();
1215 
1216 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
1217 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
1218 		cpu_idcache_wbinv_range((vaddr_t)fbt->fbtp_patchpoint, 4);
1219 	}
1220 
1221 	dtrace_interrupt_enable(c);
1222 }
1223 
1224 static void
1225 fbt_suspend(void *arg, dtrace_id_t id, void *parg)
1226 {
1227 	fbt_probe_t *fbt = parg;
1228 #if 0
1229 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1230 #endif
1231 	dtrace_icookie_t c;
1232 
1233 #if 0	/* XXX TBD */
1234 	ASSERT(ctl->nenabled > 0);
1235 
1236 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1237 		return;
1238 #endif
1239 
1240 	c = dtrace_interrupt_disable();
1241 
1242 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
1243 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
1244 		cpu_idcache_wbinv_range((vaddr_t)fbt->fbtp_patchpoint, 4);
1245 	}
1246 
1247 	dtrace_interrupt_enable(c);
1248 }
1249 
1250 static void
1251 fbt_resume(void *arg, dtrace_id_t id, void *parg)
1252 {
1253 	fbt_probe_t *fbt = parg;
1254 #if 0
1255 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1256 #endif
1257 	dtrace_icookie_t c;
1258 
1259 #if 0	/* XXX TBD */
1260 	ASSERT(ctl->nenabled > 0);
1261 
1262 	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
1263 		return;
1264 #endif
1265 
1266 	c = dtrace_interrupt_disable();
1267 
1268 	for (; fbt != NULL; fbt = fbt->fbtp_next) {
1269 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
1270 		cpu_idcache_wbinv_range((vaddr_t)fbt->fbtp_patchpoint, 4);
1271 	}
1272 
1273 	dtrace_interrupt_enable(c);
1274 }
1275 
1276 #else
1277 #error "architecture not supported"
1278 #endif
1279 
1280 static int
1281 fbt_ctfoff_init(dtrace_modctl_t *mod, mod_ctf_t *mc)
1282 {
1283 	const Elf_Sym *symp = mc->symtab;
1284 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
1285 	const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
1286 	int i;
1287 	uint32_t *ctfoff;
1288 	uint32_t objtoff = hp->cth_objtoff;
1289 	uint32_t funcoff = hp->cth_funcoff;
1290 	ushort_t info;
1291 	ushort_t vlen;
1292 	int nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
1293 
1294 	/* Sanity check. */
1295 	if (hp->cth_magic != CTF_MAGIC) {
1296 		printf("Bad magic value in CTF data of '%s'\n",
1297 			mod->mod_info->mi_name);
1298 		return (EINVAL);
1299 	}
1300 
1301 	if (mc->symtab == NULL) {
1302 		printf("No symbol table in '%s'\n",
1303 			mod->mod_info->mi_name);
1304 		return (EINVAL);
1305 	}
1306 
1307 	if ((ctfoff = malloc(sizeof(uint32_t) * nsyms, M_FBT, M_WAITOK)) == NULL)
1308 		return (ENOMEM);
1309 
1310 	mc->ctfoffp = ctfoff;
1311 
1312 	for (i = 0; i < nsyms; i++, ctfoff++, symp++) {
1313 	   	if (mc->nmap != NULL) {
1314 			if (mc->nmap[i] == 0) {
1315 				printf("%s.%d: Error! Got zero nmap!\n",
1316 					__func__, __LINE__);
1317 				continue;
1318 			}
1319 
1320 			/* CTF expects the pre-sorted symbol ordering,
1321 			 * so map it from that to the current sorted
1322 			 * and trimmed symbol table.
1323 			 * ctfoff[new-ind] = oldind symbol info.
1324 			 */
1325 
1326 			/* map old index to new symbol table */
1327 			symp = &mc->symtab[mc->nmap[i] - 1];
1328 
1329 			/* map old index to new ctfoff index */
1330 			ctfoff = &mc->ctfoffp[mc->nmap[i]-1];
1331 		}
1332 
1333 		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
1334 			*ctfoff = 0xffffffff;
1335 			continue;
1336 		}
1337 
1338 		switch (ELF_ST_TYPE(symp->st_info)) {
1339 		case STT_OBJECT:
1340 			if (objtoff >= hp->cth_funcoff ||
1341                             (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
1342 				*ctfoff = 0xffffffff;
1343                                 break;
1344                         }
1345 
1346                         *ctfoff = objtoff;
1347                         objtoff += sizeof (ushort_t);
1348 			break;
1349 
1350 		case STT_FUNC:
1351 			if (funcoff >= hp->cth_typeoff) {
1352 				*ctfoff = 0xffffffff;
1353 				break;
1354 			}
1355 
1356 			*ctfoff = funcoff;
1357 
1358 			info = *((const ushort_t *)(ctfdata + funcoff));
1359 			vlen = CTF_INFO_VLEN(info);
1360 
1361 			/*
1362 			 * If we encounter a zero pad at the end, just skip it.
1363 			 * Otherwise skip over the function and its return type
1364 			 * (+2) and the argument list (vlen).
1365 			 */
1366 			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
1367 				funcoff += sizeof (ushort_t); /* skip pad */
1368 			else
1369 				funcoff += sizeof (ushort_t) * (vlen + 2);
1370 			break;
1371 
1372 		default:
1373 			*ctfoff = 0xffffffff;
1374 			break;
1375 		}
1376 	}
1377 
1378 	return (0);
1379 }
1380 
1381 static ssize_t
1382 fbt_get_ctt_size(uint8_t xversion, const ctf_type_t *tp, ssize_t *sizep,
1383     ssize_t *incrementp)
1384 {
1385 	ssize_t size, increment;
1386 
1387 	if (xversion > CTF_VERSION_1 &&
1388 	    tp->ctt_size == CTF_LSIZE_SENT) {
1389 		size = CTF_TYPE_LSIZE(tp);
1390 		increment = sizeof (ctf_type_t);
1391 	} else {
1392 		size = tp->ctt_size;
1393 		increment = sizeof (ctf_stype_t);
1394 	}
1395 
1396 	if (sizep)
1397 		*sizep = size;
1398 	if (incrementp)
1399 		*incrementp = increment;
1400 
1401 	return (size);
1402 }
1403 
1404 static int
1405 fbt_typoff_init(mod_ctf_t *mc)
1406 {
1407 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
1408 	const ctf_type_t *tbuf;
1409 	const ctf_type_t *tend;
1410 	const ctf_type_t *tp;
1411 	const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
1412 	int ctf_typemax = 0;
1413 	uint32_t *xp;
1414 	ulong_t pop[CTF_K_MAX + 1] = { 0 };
1415 
1416 	/* Sanity check. */
1417 	if (hp->cth_magic != CTF_MAGIC)
1418 		return (EINVAL);
1419 
1420 	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
1421 	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
1422 
1423 	int child = hp->cth_parname != 0;
1424 
1425 	/*
1426 	 * We make two passes through the entire type section.  In this first
1427 	 * pass, we count the number of each type and the total number of types.
1428 	 */
1429 	for (tp = tbuf; tp < tend; ctf_typemax++) {
1430 		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
1431 		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
1432 		ssize_t size, increment;
1433 
1434 		size_t vbytes;
1435 		uint_t n;
1436 
1437 		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
1438 
1439 		switch (kind) {
1440 		case CTF_K_INTEGER:
1441 		case CTF_K_FLOAT:
1442 			vbytes = sizeof (uint_t);
1443 			break;
1444 		case CTF_K_ARRAY:
1445 			vbytes = sizeof (ctf_array_t);
1446 			break;
1447 		case CTF_K_FUNCTION:
1448 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
1449 			break;
1450 		case CTF_K_STRUCT:
1451 		case CTF_K_UNION:
1452 			if (size < CTF_LSTRUCT_THRESH) {
1453 				ctf_member_t *mp = (ctf_member_t *)
1454 				    ((uintptr_t)tp + increment);
1455 
1456 				vbytes = sizeof (ctf_member_t) * vlen;
1457 				for (n = vlen; n != 0; n--, mp++)
1458 					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
1459 			} else {
1460 				ctf_lmember_t *lmp = (ctf_lmember_t *)
1461 				    ((uintptr_t)tp + increment);
1462 
1463 				vbytes = sizeof (ctf_lmember_t) * vlen;
1464 				for (n = vlen; n != 0; n--, lmp++)
1465 					child |=
1466 					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
1467 			}
1468 			break;
1469 		case CTF_K_ENUM:
1470 			vbytes = sizeof (ctf_enum_t) * vlen;
1471 			break;
1472 		case CTF_K_FORWARD:
1473 			/*
1474 			 * For forward declarations, ctt_type is the CTF_K_*
1475 			 * kind for the tag, so bump that population count too.
1476 			 * If ctt_type is unknown, treat the tag as a struct.
1477 			 */
1478 			if (tp->ctt_type == CTF_K_UNKNOWN ||
1479 			    tp->ctt_type >= CTF_K_MAX)
1480 				pop[CTF_K_STRUCT]++;
1481 			else
1482 				pop[tp->ctt_type]++;
1483 			/*FALLTHRU*/
1484 		case CTF_K_UNKNOWN:
1485 			vbytes = 0;
1486 			break;
1487 		case CTF_K_POINTER:
1488 		case CTF_K_TYPEDEF:
1489 		case CTF_K_VOLATILE:
1490 		case CTF_K_CONST:
1491 		case CTF_K_RESTRICT:
1492 			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
1493 			vbytes = 0;
1494 			break;
1495 		default:
1496 			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
1497 			return (EIO);
1498 		}
1499 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
1500 		pop[kind]++;
1501 	}
1502 
1503 	mc->typlen = ctf_typemax;
1504 
1505 	if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_FBT, M_ZERO | M_WAITOK)) == NULL)
1506 		return (ENOMEM);
1507 
1508 	mc->typoffp = xp;
1509 
1510 	/* type id 0 is used as a sentinel value */
1511 	*xp++ = 0;
1512 
1513 	/*
1514 	 * In the second pass, fill in the type offset.
1515 	 */
1516 	for (tp = tbuf; tp < tend; xp++) {
1517 		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
1518 		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
1519 		ssize_t size, increment;
1520 
1521 		size_t vbytes;
1522 		uint_t n;
1523 
1524 		(void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
1525 
1526 		switch (kind) {
1527 		case CTF_K_INTEGER:
1528 		case CTF_K_FLOAT:
1529 			vbytes = sizeof (uint_t);
1530 			break;
1531 		case CTF_K_ARRAY:
1532 			vbytes = sizeof (ctf_array_t);
1533 			break;
1534 		case CTF_K_FUNCTION:
1535 			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
1536 			break;
1537 		case CTF_K_STRUCT:
1538 		case CTF_K_UNION:
1539 			if (size < CTF_LSTRUCT_THRESH) {
1540 				ctf_member_t *mp = (ctf_member_t *)
1541 				    ((uintptr_t)tp + increment);
1542 
1543 				vbytes = sizeof (ctf_member_t) * vlen;
1544 				for (n = vlen; n != 0; n--, mp++)
1545 					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
1546 			} else {
1547 				ctf_lmember_t *lmp = (ctf_lmember_t *)
1548 				    ((uintptr_t)tp + increment);
1549 
1550 				vbytes = sizeof (ctf_lmember_t) * vlen;
1551 				for (n = vlen; n != 0; n--, lmp++)
1552 					child |=
1553 					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
1554 			}
1555 			break;
1556 		case CTF_K_ENUM:
1557 			vbytes = sizeof (ctf_enum_t) * vlen;
1558 			break;
1559 		case CTF_K_FORWARD:
1560 		case CTF_K_UNKNOWN:
1561 			vbytes = 0;
1562 			break;
1563 		case CTF_K_POINTER:
1564 		case CTF_K_TYPEDEF:
1565 		case CTF_K_VOLATILE:
1566 		case CTF_K_CONST:
1567 		case CTF_K_RESTRICT:
1568 			vbytes = 0;
1569 			break;
1570 		default:
1571 			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
1572 			return (EIO);
1573 		}
1574 		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
1575 		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
1576 	}
1577 
1578 	return (0);
1579 }
1580 
1581 /*
1582  * CTF Declaration Stack
1583  *
1584  * In order to implement ctf_type_name(), we must convert a type graph back
1585  * into a C type declaration.  Unfortunately, a type graph represents a storage
1586  * class ordering of the type whereas a type declaration must obey the C rules
1587  * for operator precedence, and the two orderings are frequently in conflict.
1588  * For example, consider these CTF type graphs and their C declarations:
1589  *
1590  * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
1591  * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
1592  *
1593  * In each case, parentheses are used to raise operator * to higher lexical
1594  * precedence, so the string form of the C declaration cannot be constructed by
1595  * walking the type graph links and forming the string from left to right.
1596  *
1597  * The functions in this file build a set of stacks from the type graph nodes
1598  * corresponding to the C operator precedence levels in the appropriate order.
1599  * The code in ctf_type_name() can then iterate over the levels and nodes in
1600  * lexical precedence order and construct the final C declaration string.
1601  */
1602 typedef struct ctf_list {
1603 	struct ctf_list *l_prev; /* previous pointer or tail pointer */
1604 	struct ctf_list *l_next; /* next pointer or head pointer */
1605 } ctf_list_t;
1606 
1607 #define	ctf_list_prev(elem)	((void *)(((ctf_list_t *)(elem))->l_prev))
1608 #define	ctf_list_next(elem)	((void *)(((ctf_list_t *)(elem))->l_next))
1609 
1610 typedef enum {
1611 	CTF_PREC_BASE,
1612 	CTF_PREC_POINTER,
1613 	CTF_PREC_ARRAY,
1614 	CTF_PREC_FUNCTION,
1615 	CTF_PREC_MAX
1616 } ctf_decl_prec_t;
1617 
1618 typedef struct ctf_decl_node {
1619 	ctf_list_t cd_list;			/* linked list pointers */
1620 	ctf_id_t cd_type;			/* type identifier */
1621 	uint_t cd_kind;				/* type kind */
1622 	uint_t cd_n;				/* type dimension if array */
1623 } ctf_decl_node_t;
1624 
1625 typedef struct ctf_decl {
1626 	ctf_list_t cd_nodes[CTF_PREC_MAX];	/* declaration node stacks */
1627 	int cd_order[CTF_PREC_MAX];		/* storage order of decls */
1628 	ctf_decl_prec_t cd_qualp;		/* qualifier precision */
1629 	ctf_decl_prec_t cd_ordp;		/* ordered precision */
1630 	char *cd_buf;				/* buffer for output */
1631 	char *cd_ptr;				/* buffer location */
1632 	char *cd_end;				/* buffer limit */
1633 	size_t cd_len;				/* buffer space required */
1634 	int cd_err;				/* saved error value */
1635 } ctf_decl_t;
1636 
1637 /*
1638  * Simple doubly-linked list append routine.  This implementation assumes that
1639  * each list element contains an embedded ctf_list_t as the first member.
1640  * An additional ctf_list_t is used to store the head (l_next) and tail
1641  * (l_prev) pointers.  The current head and tail list elements have their
1642  * previous and next pointers set to NULL, respectively.
1643  */
1644 static void
1645 ctf_list_append(ctf_list_t *lp, void *new)
1646 {
1647 	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
1648 	ctf_list_t *q = new;		/* q = new list element */
1649 
1650 	lp->l_prev = q;
1651 	q->l_prev = p;
1652 	q->l_next = NULL;
1653 
1654 	if (p != NULL)
1655 		p->l_next = q;
1656 	else
1657 		lp->l_next = q;
1658 }
1659 
1660 /*
1661  * Prepend the specified existing element to the given ctf_list_t.  The
1662  * existing pointer should be pointing at a struct with embedded ctf_list_t.
1663  */
1664 static void
1665 ctf_list_prepend(ctf_list_t *lp, void *new)
1666 {
1667 	ctf_list_t *p = new;		/* p = new list element */
1668 	ctf_list_t *q = lp->l_next;	/* q = head list element */
1669 
1670 	lp->l_next = p;
1671 	p->l_prev = NULL;
1672 	p->l_next = q;
1673 
1674 	if (q != NULL)
1675 		q->l_prev = p;
1676 	else
1677 		lp->l_prev = p;
1678 }
1679 
1680 static void
1681 ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
1682 {
1683 	int i;
1684 
1685 	bzero(cd, sizeof (ctf_decl_t));
1686 
1687 	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
1688 		cd->cd_order[i] = CTF_PREC_BASE - 1;
1689 
1690 	cd->cd_qualp = CTF_PREC_BASE;
1691 	cd->cd_ordp = CTF_PREC_BASE;
1692 
1693 	cd->cd_buf = buf;
1694 	cd->cd_ptr = buf;
1695 	cd->cd_end = buf + len;
1696 }
1697 
1698 static void
1699 ctf_decl_fini(ctf_decl_t *cd)
1700 {
1701 	ctf_decl_node_t *cdp, *ndp;
1702 	int i;
1703 
1704 	for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
1705 		for (cdp = ctf_list_next(&cd->cd_nodes[i]);
1706 		    cdp != NULL; cdp = ndp) {
1707 			ndp = ctf_list_next(cdp);
1708 			free(cdp, M_FBT);
1709 		}
1710 	}
1711 }
1712 
1713 static const ctf_type_t *
1714 ctf_lookup_by_id(mod_ctf_t *mc, ctf_id_t type)
1715 {
1716 	const ctf_type_t *tp;
1717 	uint32_t offset;
1718 	uint32_t *typoff = mc->typoffp;
1719 
1720 	if (type >= mc->typlen) {
1721 		printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,mc->typlen);
1722 		return(NULL);
1723 	}
1724 
1725 	/* Check if the type isn't cross-referenced. */
1726 	if ((offset = typoff[type]) == 0) {
1727 		printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
1728 		return(NULL);
1729 	}
1730 
1731 	tp = (const ctf_type_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
1732 
1733 	return (tp);
1734 }
1735 
1736 static void
1737 fbt_array_info(mod_ctf_t *mc, ctf_id_t type, ctf_arinfo_t *arp)
1738 {
1739 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
1740 	const ctf_type_t *tp;
1741 	const ctf_array_t *ap;
1742 	ssize_t increment;
1743 
1744 	bzero(arp, sizeof(*arp));
1745 
1746 	if ((tp = ctf_lookup_by_id(mc, type)) == NULL)
1747 		return;
1748 
1749 	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
1750 		return;
1751 
1752 	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
1753 
1754 	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
1755 	arp->ctr_contents = ap->cta_contents;
1756 	arp->ctr_index = ap->cta_index;
1757 	arp->ctr_nelems = ap->cta_nelems;
1758 }
1759 
1760 static const char *
1761 ctf_strptr(mod_ctf_t *mc, int name)
1762 {
1763 	const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;;
1764 	const char *strp = "";
1765 
1766 	if (name < 0 || name >= hp->cth_strlen)
1767 		return(strp);
1768 
1769 	strp = (const char *)(mc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
1770 
1771 	return (strp);
1772 }
1773 
1774 static void
1775 ctf_decl_push(ctf_decl_t *cd, mod_ctf_t *mc, ctf_id_t type)
1776 {
1777 	ctf_decl_node_t *cdp;
1778 	ctf_decl_prec_t prec;
1779 	uint_t kind, n = 1;
1780 	int is_qual = 0;
1781 
1782 	const ctf_type_t *tp;
1783 	ctf_arinfo_t ar;
1784 
1785 	if ((tp = ctf_lookup_by_id(mc, type)) == NULL) {
1786 		cd->cd_err = ENOENT;
1787 		return;
1788 	}
1789 
1790 	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
1791 	case CTF_K_ARRAY:
1792 		fbt_array_info(mc, type, &ar);
1793 		ctf_decl_push(cd, mc, ar.ctr_contents);
1794 		n = ar.ctr_nelems;
1795 		prec = CTF_PREC_ARRAY;
1796 		break;
1797 
1798 	case CTF_K_TYPEDEF:
1799 		if (ctf_strptr(mc, tp->ctt_name)[0] == '\0') {
1800 			ctf_decl_push(cd, mc, tp->ctt_type);
1801 			return;
1802 		}
1803 		prec = CTF_PREC_BASE;
1804 		break;
1805 
1806 	case CTF_K_FUNCTION:
1807 		ctf_decl_push(cd, mc, tp->ctt_type);
1808 		prec = CTF_PREC_FUNCTION;
1809 		break;
1810 
1811 	case CTF_K_POINTER:
1812 		ctf_decl_push(cd, mc, tp->ctt_type);
1813 		prec = CTF_PREC_POINTER;
1814 		break;
1815 
1816 	case CTF_K_VOLATILE:
1817 	case CTF_K_CONST:
1818 	case CTF_K_RESTRICT:
1819 		ctf_decl_push(cd, mc, tp->ctt_type);
1820 		prec = cd->cd_qualp;
1821 		is_qual++;
1822 		break;
1823 
1824 	default:
1825 		prec = CTF_PREC_BASE;
1826 	}
1827 
1828 	if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) {
1829 		cd->cd_err = EAGAIN;
1830 		return;
1831 	}
1832 
1833 	cdp->cd_type = type;
1834 	cdp->cd_kind = kind;
1835 	cdp->cd_n = n;
1836 
1837 	if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
1838 		cd->cd_order[prec] = cd->cd_ordp++;
1839 
1840 	/*
1841 	 * Reset cd_qualp to the highest precedence level that we've seen so
1842 	 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
1843 	 */
1844 	if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
1845 		cd->cd_qualp = prec;
1846 
1847 	/*
1848 	 * C array declarators are ordered inside out so prepend them.  Also by
1849 	 * convention qualifiers of base types precede the type specifier (e.g.
1850 	 * const int vs. int const) even though the two forms are equivalent.
1851 	 */
1852 	if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1853 		ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1854 	else
1855 		ctf_list_append(&cd->cd_nodes[prec], cdp);
1856 }
1857 
1858 static void
1859 ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1860 {
1861 	size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1862 	va_list ap;
1863 	size_t n;
1864 
1865 	va_start(ap, format);
1866 	n = vsnprintf(cd->cd_ptr, len, format, ap);
1867 	va_end(ap);
1868 
1869 	cd->cd_ptr += MIN(n, len);
1870 	cd->cd_len += n;
1871 }
1872 
1873 static ssize_t
1874 fbt_type_name(mod_ctf_t *mc, ctf_id_t type, char *buf, size_t len)
1875 {
1876 	ctf_decl_t cd;
1877 	ctf_decl_node_t *cdp;
1878 	ctf_decl_prec_t prec, lp, rp;
1879 	int ptr, arr;
1880 	uint_t k;
1881 
1882 	if (mc == NULL && type == CTF_ERR)
1883 		return (-1); /* simplify caller code by permitting CTF_ERR */
1884 
1885 	ctf_decl_init(&cd, buf, len);
1886 	ctf_decl_push(&cd, mc, type);
1887 
1888 	if (cd.cd_err != 0) {
1889 		ctf_decl_fini(&cd);
1890 		return (-1);
1891 	}
1892 
1893 	/*
1894 	 * If the type graph's order conflicts with lexical precedence order
1895 	 * for pointers or arrays, then we need to surround the declarations at
1896 	 * the corresponding lexical precedence with parentheses.  This can
1897 	 * result in either a parenthesized pointer (*) as in int (*)() or
1898 	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1899 	 */
1900 	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1901 	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1902 
1903 	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1904 	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1905 
1906 	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1907 
1908 	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1909 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1910 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
1911 
1912 			const ctf_type_t *tp =
1913 			    ctf_lookup_by_id(mc, cdp->cd_type);
1914 			const char *name = ctf_strptr(mc, tp->ctt_name);
1915 
1916 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1917 				ctf_decl_sprintf(&cd, " ");
1918 
1919 			if (lp == prec) {
1920 				ctf_decl_sprintf(&cd, "(");
1921 				lp = -1;
1922 			}
1923 
1924 			switch (cdp->cd_kind) {
1925 			case CTF_K_INTEGER:
1926 			case CTF_K_FLOAT:
1927 			case CTF_K_TYPEDEF:
1928 				ctf_decl_sprintf(&cd, "%s", name);
1929 				break;
1930 			case CTF_K_POINTER:
1931 				ctf_decl_sprintf(&cd, "*");
1932 				break;
1933 			case CTF_K_ARRAY:
1934 				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1935 				break;
1936 			case CTF_K_FUNCTION:
1937 				ctf_decl_sprintf(&cd, "()");
1938 				break;
1939 			case CTF_K_STRUCT:
1940 			case CTF_K_FORWARD:
1941 				ctf_decl_sprintf(&cd, "struct %s", name);
1942 				break;
1943 			case CTF_K_UNION:
1944 				ctf_decl_sprintf(&cd, "union %s", name);
1945 				break;
1946 			case CTF_K_ENUM:
1947 				ctf_decl_sprintf(&cd, "enum %s", name);
1948 				break;
1949 			case CTF_K_VOLATILE:
1950 				ctf_decl_sprintf(&cd, "volatile");
1951 				break;
1952 			case CTF_K_CONST:
1953 				ctf_decl_sprintf(&cd, "const");
1954 				break;
1955 			case CTF_K_RESTRICT:
1956 				ctf_decl_sprintf(&cd, "restrict");
1957 				break;
1958 			}
1959 
1960 			k = cdp->cd_kind;
1961 		}
1962 
1963 		if (rp == prec)
1964 			ctf_decl_sprintf(&cd, ")");
1965 	}
1966 
1967 	ctf_decl_fini(&cd);
1968 	return (cd.cd_len);
1969 }
1970 
1971 static void
1972 fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1973 {
1974 	const ushort_t *dp;
1975 	fbt_probe_t *fbt = parg;
1976 	mod_ctf_t mc;
1977 	dtrace_modctl_t *ctl = fbt->fbtp_ctl;
1978 	int ndx = desc->dtargd_ndx;
1979 	int symindx = fbt->fbtp_symindx;
1980 	uint32_t *ctfoff;
1981 	uint32_t offset;
1982 	ushort_t info, kind, n;
1983 	int nsyms;
1984 
1985 	desc->dtargd_ndx = DTRACE_ARGNONE;
1986 
1987 	/* Get a pointer to the CTF data and it's length. */
1988 	if (mod_ctf_get(ctl, &mc) != 0) {
1989 		static int report=0;
1990 		if (report < 1) {
1991 		    report++;
1992 		    printf("FBT: Error no CTF section found in module \"%s\"\n",
1993 			    ctl->mod_info->mi_name);
1994 		}
1995 		/* No CTF data? Something wrong? *shrug* */
1996 		return;
1997 	}
1998 
1999 	nsyms = (mc.nmap != NULL) ? mc.nmapsize : mc.nsym;
2000 
2001 	/* Check if this module hasn't been initialised yet. */
2002 	if (mc.ctfoffp == NULL) {
2003 		/*
2004 		 * Initialise the CTF object and function symindx to
2005 		 * byte offset array.
2006 		 */
2007 		if (fbt_ctfoff_init(ctl, &mc) != 0) {
2008 			return;
2009 		}
2010 
2011 		/* Initialise the CTF type to byte offset array. */
2012 		if (fbt_typoff_init(&mc) != 0) {
2013 			return;
2014 		}
2015 	}
2016 
2017 	ctfoff = mc.ctfoffp;
2018 
2019 	if (ctfoff == NULL || mc.typoffp == NULL) {
2020 		return;
2021 	}
2022 
2023 	/* Check if the symbol index is out of range. */
2024 	if (symindx >= nsyms)
2025 		return;
2026 
2027 	/* Check if the symbol isn't cross-referenced. */
2028 	if ((offset = ctfoff[symindx]) == 0xffffffff)
2029 		return;
2030 
2031 	dp = (const ushort_t *)(mc.ctftab + offset + sizeof(ctf_header_t));
2032 
2033 	info = *dp++;
2034 	kind = CTF_INFO_KIND(info);
2035 	n = CTF_INFO_VLEN(info);
2036 
2037 	if (kind == CTF_K_UNKNOWN && n == 0) {
2038 		printf("%s(%d): Unknown function %s!\n",__func__,__LINE__,
2039 		    fbt->fbtp_name);
2040 		return;
2041 	}
2042 
2043 	if (kind != CTF_K_FUNCTION) {
2044 		printf("%s(%d): Expected a function %s!\n",__func__,__LINE__,
2045 		    fbt->fbtp_name);
2046 		return;
2047 	}
2048 
2049 	/* Check if the requested argument doesn't exist. */
2050 	if (ndx >= n)
2051 		return;
2052 
2053 	/* Skip the return type and arguments up to the one requested. */
2054 	dp += ndx + 1;
2055 
2056 	if (fbt_type_name(&mc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0) {
2057 		desc->dtargd_ndx = ndx;
2058 	}
2059 
2060 	return;
2061 }
2062 
2063 static void
2064 fbt_load(void)
2065 {
2066 	/* Default the probe table size if not specified. */
2067 	if (fbt_probetab_size == 0)
2068 		fbt_probetab_size = FBT_PROBETAB_SIZE;
2069 
2070 	/* Choose the hash mask for the probe table. */
2071 	fbt_probetab_mask = fbt_probetab_size - 1;
2072 
2073 	/* Allocate memory for the probe table. */
2074 	fbt_probetab =
2075 	    malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
2076 
2077 	dtrace_doubletrap_func = fbt_doubletrap;
2078 	dtrace_invop_add(fbt_invop);
2079 #ifdef __arm__
2080 	dtrace_emulation_jump_addr = fbt_emulate;
2081 #endif
2082 
2083 	if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
2084 	    NULL, &fbt_pops, NULL, &fbt_id) != 0)
2085 		return;
2086 }
2087 
2088 
2089 static int
2090 fbt_unload(void)
2091 {
2092 	int error = 0;
2093 
2094 #ifdef __arm__
2095 	dtrace_emulation_jump_addr = NULL;
2096 #endif
2097 	/* De-register the invalid opcode handler. */
2098 	dtrace_invop_remove(fbt_invop);
2099 
2100 	dtrace_doubletrap_func = NULL;
2101 
2102 	/* De-register this DTrace provider. */
2103 	if ((error = dtrace_unregister(fbt_id)) != 0)
2104 		return (error);
2105 
2106 	/* Free the probe table. */
2107 	free(fbt_probetab, M_FBT);
2108 	fbt_probetab = NULL;
2109 	fbt_probetab_mask = 0;
2110 
2111 	return (error);
2112 }
2113 
2114 
2115 static int
2116 dtrace_fbt_modcmd(modcmd_t cmd, void *data)
2117 {
2118 	int bmajor = -1, cmajor = -1;
2119 	int error;
2120 
2121 	switch (cmd) {
2122 	case MODULE_CMD_INIT:
2123 		fbt_load();
2124 		return devsw_attach("fbt", NULL, &bmajor,
2125 		    &fbt_cdevsw, &cmajor);
2126 	case MODULE_CMD_FINI:
2127 		error = fbt_unload();
2128 		if (error != 0)
2129 			return error;
2130 		return devsw_detach(NULL, &fbt_cdevsw);
2131 	case MODULE_CMD_AUTOUNLOAD:
2132 		return EBUSY;
2133 	default:
2134 		return ENOTTY;
2135 	}
2136 }
2137 
2138 static int
2139 fbt_open(dev_t dev, int flags, int mode, struct lwp *l)
2140 {
2141 	return (0);
2142 }
2143 
2144 MODULE(MODULE_CLASS_MISC, dtrace_fbt, "dtrace,zlib");
2145