1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* Portions Copyright 2013 Justin Hibbits */
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/fasttrap_isa.h>
28 #include <sys/fasttrap_impl.h>
29 #include <sys/dtrace.h>
30 #include <sys/dtrace_impl.h>
31 #include <cddl/dev/dtrace/dtrace_cddl.h>
32 #include <sys/proc.h>
33 #include <sys/types.h>
34 #include <sys/uio.h>
35 #include <sys/ptrace.h>
36 #include <sys/rmlock.h>
37 #include <sys/sysent.h>
38
39 #define OP(x) ((x) >> 26)
40 #define OPX(x) (((x) >> 2) & 0x3FF)
41 #define OP_BO(x) (((x) & 0x03E00000) >> 21)
42 #define OP_BI(x) (((x) & 0x001F0000) >> 16)
43 #define OP_RS(x) (((x) & 0x03E00000) >> 21)
44 #define OP_RA(x) (((x) & 0x001F0000) >> 16)
45 #define OP_RB(x) (((x) & 0x0000F100) >> 11)
46
47 int
fasttrap_tracepoint_install(proc_t * p,fasttrap_tracepoint_t * tp)48 fasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp)
49 {
50 fasttrap_instr_t instr = FASTTRAP_INSTR;
51
52 if (uwrite(p, &instr, 4, tp->ftt_pc) != 0)
53 return (-1);
54
55 return (0);
56 }
57
58 int
fasttrap_tracepoint_remove(proc_t * p,fasttrap_tracepoint_t * tp)59 fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp)
60 {
61 uint32_t instr;
62
63 /*
64 * Distinguish between read or write failures and a changed
65 * instruction.
66 */
67 if (uread(p, &instr, 4, tp->ftt_pc) != 0)
68 return (0);
69 if (instr != FASTTRAP_INSTR)
70 return (0);
71 if (uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0)
72 return (-1);
73
74 return (0);
75 }
76
77 int
fasttrap_tracepoint_init(proc_t * p,fasttrap_tracepoint_t * tp,uintptr_t pc,fasttrap_probe_type_t type)78 fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc,
79 fasttrap_probe_type_t type)
80 {
81 uint32_t instr;
82 //int32_t disp;
83
84 /*
85 * Read the instruction at the given address out of the process's
86 * address space. We don't have to worry about a debugger
87 * changing this instruction before we overwrite it with our trap
88 * instruction since P_PR_LOCK is set.
89 */
90 if (uread(p, &instr, 4, pc) != 0)
91 return (-1);
92
93 /*
94 * Decode the instruction to fill in the probe flags. We can have
95 * the process execute most instructions on its own using a pc/npc
96 * trick, but pc-relative control transfer present a problem since
97 * we're relocating the instruction. We emulate these instructions
98 * in the kernel. We assume a default type and over-write that as
99 * needed.
100 *
101 * pc-relative instructions must be emulated for correctness;
102 * other instructions (which represent a large set of commonly traced
103 * instructions) are emulated or otherwise optimized for performance.
104 */
105 tp->ftt_type = FASTTRAP_T_COMMON;
106 tp->ftt_instr = instr;
107
108 switch (OP(instr)) {
109 /* The following are invalid for trapping (invalid opcodes, tw/twi). */
110 case 0:
111 case 1:
112 case 2:
113 case 4:
114 case 5:
115 case 6:
116 case 30:
117 case 39:
118 case 58:
119 case 62:
120 case 3: /* twi */
121 return (-1);
122 case 31: /* tw */
123 if (OPX(instr) == 4)
124 return (-1);
125 else if (OPX(instr) == 444 && OP_RS(instr) == OP_RA(instr) &&
126 OP_RS(instr) == OP_RB(instr))
127 tp->ftt_type = FASTTRAP_T_NOP;
128 break;
129 case 16:
130 tp->ftt_type = FASTTRAP_T_BC;
131 tp->ftt_dest = instr & 0x0000FFFC; /* Extract target address */
132 if (instr & 0x00008000)
133 tp->ftt_dest |= 0xFFFF0000;
134 /* Use as offset if not absolute address. */
135 if (!(instr & 0x02))
136 tp->ftt_dest += pc;
137 tp->ftt_bo = OP_BO(instr);
138 tp->ftt_bi = OP_BI(instr);
139 break;
140 case 18:
141 tp->ftt_type = FASTTRAP_T_B;
142 tp->ftt_dest = instr & 0x03FFFFFC; /* Extract target address */
143 if (instr & 0x02000000)
144 tp->ftt_dest |= 0xFC000000;
145 /* Use as offset if not absolute address. */
146 if (!(instr & 0x02))
147 tp->ftt_dest += pc;
148 break;
149 case 19:
150 switch (OPX(instr)) {
151 case 528: /* bcctr */
152 tp->ftt_type = FASTTRAP_T_BCTR;
153 tp->ftt_bo = OP_BO(instr);
154 tp->ftt_bi = OP_BI(instr);
155 break;
156 case 16: /* bclr */
157 tp->ftt_type = FASTTRAP_T_BCTR;
158 tp->ftt_bo = OP_BO(instr);
159 tp->ftt_bi = OP_BI(instr);
160 break;
161 };
162 break;
163 case 24:
164 if (OP_RS(instr) == OP_RA(instr) &&
165 (instr & 0x0000FFFF) == 0)
166 tp->ftt_type = FASTTRAP_T_NOP;
167 break;
168 };
169
170 /*
171 * We don't know how this tracepoint is going to be used, but in case
172 * it's used as part of a function return probe, we need to indicate
173 * whether it's always a return site or only potentially a return
174 * site. If it's part of a return probe, it's always going to be a
175 * return from that function if it's a restore instruction or if
176 * the previous instruction was a return. If we could reliably
177 * distinguish jump tables from return sites, this wouldn't be
178 * necessary.
179 */
180 #if 0
181 if (tp->ftt_type != FASTTRAP_T_RESTORE &&
182 (uread(p, &instr, 4, pc - sizeof (instr)) != 0 ||
183 !(OP(instr) == 2 && OP3(instr) == OP3_RETURN)))
184 tp->ftt_flags |= FASTTRAP_F_RETMAYBE;
185 #endif
186
187 return (0);
188 }
189
190 static uint64_t
fasttrap_anarg(struct reg * rp,int argno)191 fasttrap_anarg(struct reg *rp, int argno)
192 {
193 uint64_t value;
194 proc_t *p = curproc;
195
196 /* The first 8 arguments are in registers. */
197 if (argno < 8)
198 return rp->fixreg[argno + 3];
199
200 /* Arguments on stack start after SP+LR (2 register slots). */
201 if (SV_PROC_FLAG(p, SV_ILP32)) {
202 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
203 value = dtrace_fuword32((void *)(rp->fixreg[1] + 8 +
204 ((argno - 8) * sizeof(uint32_t))));
205 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR);
206 } else {
207 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
208 value = dtrace_fuword64((void *)(rp->fixreg[1] + 48 +
209 ((argno - 8) * sizeof(uint64_t))));
210 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR);
211 }
212 return value;
213 }
214
215 uint64_t
fasttrap_pid_getarg(void * arg,dtrace_id_t id,void * parg,int argno,int aframes)216 fasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
217 int aframes)
218 {
219 struct reg r;
220
221 fill_regs(curthread, &r);
222
223 return (fasttrap_anarg(&r, argno));
224 }
225
226 uint64_t
fasttrap_usdt_getarg(void * arg,dtrace_id_t id,void * parg,int argno,int aframes)227 fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
228 int aframes)
229 {
230 struct reg r;
231
232 fill_regs(curthread, &r);
233
234 return (fasttrap_anarg(&r, argno));
235 }
236
237 static void
fasttrap_usdt_args(fasttrap_probe_t * probe,struct reg * rp,int argc,uintptr_t * argv)238 fasttrap_usdt_args(fasttrap_probe_t *probe, struct reg *rp, int argc,
239 uintptr_t *argv)
240 {
241 int i, x, cap = MIN(argc, probe->ftp_nargs);
242
243 for (i = 0; i < cap; i++) {
244 x = probe->ftp_argmap[i];
245
246 if (x < 8)
247 argv[i] = rp->fixreg[x];
248 else
249 if (SV_PROC_FLAG(curproc, SV_ILP32))
250 argv[i] = fuword32((void *)(rp->fixreg[1] + 8 +
251 (x * sizeof(uint32_t))));
252 else
253 argv[i] = fuword64((void *)(rp->fixreg[1] + 48 +
254 (x * sizeof(uint64_t))));
255 }
256
257 for (; i < argc; i++) {
258 argv[i] = 0;
259 }
260 }
261
262 static void
fasttrap_return_common(struct reg * rp,uintptr_t pc,pid_t pid,uintptr_t new_pc)263 fasttrap_return_common(struct reg *rp, uintptr_t pc, pid_t pid,
264 uintptr_t new_pc)
265 {
266 struct rm_priotracker tracker;
267 fasttrap_tracepoint_t *tp;
268 fasttrap_bucket_t *bucket;
269 fasttrap_id_t *id;
270
271 rm_rlock(&fasttrap_tp_lock, &tracker);
272 bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
273
274 for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
275 if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
276 tp->ftt_proc->ftpc_acount != 0)
277 break;
278 }
279
280 /*
281 * Don't sweat it if we can't find the tracepoint again; unlike
282 * when we're in fasttrap_pid_probe(), finding the tracepoint here
283 * is not essential to the correct execution of the process.
284 */
285 if (tp == NULL) {
286 rm_runlock(&fasttrap_tp_lock, &tracker);
287 return;
288 }
289
290 for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
291 /*
292 * If there's a branch that could act as a return site, we
293 * need to trace it, and check here if the program counter is
294 * external to the function.
295 */
296 /* Skip function-local branches. */
297 if ((new_pc - id->fti_probe->ftp_faddr) < id->fti_probe->ftp_fsize)
298 continue;
299
300 dtrace_probe(id->fti_probe->ftp_id,
301 pc - id->fti_probe->ftp_faddr,
302 rp->fixreg[3], rp->fixreg[4], 0, 0);
303 }
304 rm_runlock(&fasttrap_tp_lock, &tracker);
305 }
306
307
308 static int
fasttrap_branch_taken(int bo,int bi,struct reg * regs)309 fasttrap_branch_taken(int bo, int bi, struct reg *regs)
310 {
311 int crzero = 0;
312
313 /* Branch always? */
314 if ((bo & 0x14) == 0x14)
315 return 1;
316
317 /* Handle decrementing ctr */
318 if (!(bo & 0x04)) {
319 --regs->ctr;
320 crzero = (regs->ctr == 0);
321 if (bo & 0x10) {
322 return (!(crzero ^ (bo >> 1)));
323 }
324 }
325
326 return (crzero | (((regs->cr >> (31 - bi)) ^ (bo >> 3)) ^ 1));
327 }
328
329
330 int
fasttrap_pid_probe(struct trapframe * frame)331 fasttrap_pid_probe(struct trapframe *frame)
332 {
333 struct reg reg, *rp;
334 struct rm_priotracker tracker;
335 proc_t *p = curproc;
336 uintptr_t pc;
337 uintptr_t new_pc = 0;
338 fasttrap_bucket_t *bucket;
339 fasttrap_tracepoint_t *tp, tp_local;
340 pid_t pid;
341 dtrace_icookie_t cookie;
342 uint_t is_enabled = 0;
343
344 fill_regs(curthread, ®);
345 rp = ®
346 pc = rp->pc;
347
348 /*
349 * It's possible that a user (in a veritable orgy of bad planning)
350 * could redirect this thread's flow of control before it reached the
351 * return probe fasttrap. In this case we need to kill the process
352 * since it's in a unrecoverable state.
353 */
354 if (curthread->t_dtrace_step) {
355 ASSERT(curthread->t_dtrace_on);
356 fasttrap_sigtrap(p, curthread, pc);
357 return (0);
358 }
359
360 /*
361 * Clear all user tracing flags.
362 */
363 curthread->t_dtrace_ft = 0;
364 curthread->t_dtrace_pc = 0;
365 curthread->t_dtrace_npc = 0;
366 curthread->t_dtrace_scrpc = 0;
367 curthread->t_dtrace_astpc = 0;
368
369 rm_rlock(&fasttrap_tp_lock, &tracker);
370 pid = p->p_pid;
371 bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
372
373 /*
374 * Lookup the tracepoint that the process just hit.
375 */
376 for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
377 if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
378 tp->ftt_proc->ftpc_acount != 0)
379 break;
380 }
381
382 /*
383 * If we couldn't find a matching tracepoint, either a tracepoint has
384 * been inserted without using the pid<pid> ioctl interface (see
385 * fasttrap_ioctl), or somehow we have mislaid this tracepoint.
386 */
387 if (tp == NULL) {
388 rm_runlock(&fasttrap_tp_lock, &tracker);
389 return (-1);
390 }
391
392 if (tp->ftt_ids != NULL) {
393 fasttrap_id_t *id;
394
395 for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
396 fasttrap_probe_t *probe = id->fti_probe;
397
398 if (id->fti_ptype == DTFTP_ENTRY) {
399 /*
400 * We note that this was an entry
401 * probe to help ustack() find the
402 * first caller.
403 */
404 cookie = dtrace_interrupt_disable();
405 DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
406 dtrace_probe(probe->ftp_id, rp->fixreg[3],
407 rp->fixreg[4], rp->fixreg[5], rp->fixreg[6],
408 rp->fixreg[7]);
409 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
410 dtrace_interrupt_enable(cookie);
411 } else if (id->fti_ptype == DTFTP_IS_ENABLED) {
412 /*
413 * Note that in this case, we don't
414 * call dtrace_probe() since it's only
415 * an artificial probe meant to change
416 * the flow of control so that it
417 * encounters the true probe.
418 */
419 is_enabled = 1;
420 } else if (probe->ftp_argmap == NULL) {
421 dtrace_probe(probe->ftp_id, rp->fixreg[3],
422 rp->fixreg[4], rp->fixreg[5], rp->fixreg[6],
423 rp->fixreg[7]);
424 } else {
425 uintptr_t t[5];
426
427 fasttrap_usdt_args(probe, rp,
428 sizeof (t) / sizeof (t[0]), t);
429
430 dtrace_probe(probe->ftp_id, t[0], t[1],
431 t[2], t[3], t[4]);
432 }
433 }
434 }
435
436 /*
437 * We're about to do a bunch of work so we cache a local copy of
438 * the tracepoint to emulate the instruction, and then find the
439 * tracepoint again later if we need to light up any return probes.
440 */
441 tp_local = *tp;
442 rm_runlock(&fasttrap_tp_lock, &tracker);
443 tp = &tp_local;
444
445 /*
446 * If there's an is-enabled probe connected to this tracepoint it
447 * means that there was a 'xor r3, r3, r3'
448 * instruction that was placed there by DTrace when the binary was
449 * linked. As this probe is, in fact, enabled, we need to stuff 1
450 * into R3. Accordingly, we can bypass all the instruction
451 * emulation logic since we know the inevitable result. It's possible
452 * that a user could construct a scenario where the 'is-enabled'
453 * probe was on some other instruction, but that would be a rather
454 * exotic way to shoot oneself in the foot.
455 */
456 if (is_enabled) {
457 rp->fixreg[3] = 1;
458 new_pc = rp->pc + 4;
459 goto done;
460 }
461
462
463 switch (tp->ftt_type) {
464 case FASTTRAP_T_NOP:
465 new_pc = rp->pc + 4;
466 break;
467 case FASTTRAP_T_BC:
468 if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp))
469 break;
470 /* FALLTHROUGH */
471 case FASTTRAP_T_B:
472 if (tp->ftt_instr & 0x01)
473 rp->lr = rp->pc + 4;
474 new_pc = tp->ftt_dest;
475 break;
476 case FASTTRAP_T_BLR:
477 case FASTTRAP_T_BCTR:
478 if (!fasttrap_branch_taken(tp->ftt_bo, tp->ftt_bi, rp))
479 break;
480 /* FALLTHROUGH */
481 if (tp->ftt_type == FASTTRAP_T_BCTR)
482 new_pc = rp->ctr;
483 else
484 new_pc = rp->lr;
485 if (tp->ftt_instr & 0x01)
486 rp->lr = rp->pc + 4;
487 break;
488 case FASTTRAP_T_COMMON:
489 break;
490 };
491 done:
492 /*
493 * If there were no return probes when we first found the tracepoint,
494 * we should feel no obligation to honor any return probes that were
495 * subsequently enabled -- they'll just have to wait until the next
496 * time around.
497 */
498 if (tp->ftt_retids != NULL) {
499 /*
500 * We need to wait until the results of the instruction are
501 * apparent before invoking any return probes. If this
502 * instruction was emulated we can just call
503 * fasttrap_return_common(); if it needs to be executed, we
504 * need to wait until the user thread returns to the kernel.
505 */
506 if (tp->ftt_type != FASTTRAP_T_COMMON) {
507 fasttrap_return_common(rp, pc, pid, new_pc);
508 } else {
509 ASSERT(curthread->t_dtrace_ret != 0);
510 ASSERT(curthread->t_dtrace_pc == pc);
511 ASSERT(curthread->t_dtrace_scrpc != 0);
512 ASSERT(new_pc == curthread->t_dtrace_astpc);
513 }
514 }
515
516 rp->pc = new_pc;
517 set_regs(curthread, rp);
518
519 return (0);
520 }
521
522 int
fasttrap_return_probe(struct trapframe * tf)523 fasttrap_return_probe(struct trapframe *tf)
524 {
525 struct reg reg, *rp;
526 proc_t *p = curproc;
527 uintptr_t pc = curthread->t_dtrace_pc;
528 uintptr_t npc = curthread->t_dtrace_npc;
529
530 curthread->t_dtrace_pc = 0;
531 curthread->t_dtrace_npc = 0;
532 curthread->t_dtrace_scrpc = 0;
533 curthread->t_dtrace_astpc = 0;
534
535 fill_regs(curthread, ®);
536 rp = ®
537
538 /*
539 * We set rp->pc to the address of the traced instruction so
540 * that it appears to dtrace_probe() that we're on the original
541 * instruction.
542 */
543 rp->pc = pc;
544
545 fasttrap_return_common(rp, pc, p->p_pid, npc);
546
547 return (0);
548 }
549