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