fbt.c revision 1.20 1 /* $NetBSD: fbt.c,v 1.20 2016/09/16 03:10:45 pgoyette 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 (at) freebsd.org
24 * Portions Copyright 2010 Darran Hunt darran (at) 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/limits.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