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 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/dtrace_impl.h> 30 #include <sys/stack.h> 31 #include <sys/frame.h> 32 #include <sys/cmn_err.h> 33 #include <sys/privregs.h> 34 #include <sys/sysmacros.h> 35 36 /* 37 * This is gross knowledge to have to encode here... 38 */ 39 extern void _interrupt(); 40 extern void _cmntrap(); 41 extern void _allsyscalls(); 42 43 extern size_t _interrupt_size; 44 extern size_t _cmntrap_size; 45 extern size_t _allsyscalls_size; 46 47 extern uintptr_t kernelbase; 48 49 void 50 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 51 uint32_t *intrpc) 52 { 53 struct frame *fp = (struct frame *)dtrace_getfp(); 54 struct frame *nextfp, *minfp, *stacktop; 55 int depth = 0; 56 int on_intr, last = 0; 57 uintptr_t pc; 58 uintptr_t caller = CPU->cpu_dtrace_caller; 59 60 if ((on_intr = CPU_ON_INTR(CPU)) != 0) 61 stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME)); 62 else 63 stacktop = (struct frame *)curthread->t_stk; 64 minfp = fp; 65 66 aframes++; 67 68 if (intrpc != NULL && depth < pcstack_limit) 69 pcstack[depth++] = (pc_t)intrpc; 70 71 while (depth < pcstack_limit) { 72 nextfp = (struct frame *)fp->fr_savfp; 73 pc = fp->fr_savpc; 74 75 if (nextfp <= minfp || nextfp >= stacktop) { 76 if (on_intr) { 77 /* 78 * Hop from interrupt stack to thread stack. 79 */ 80 stacktop = (struct frame *)curthread->t_stk; 81 minfp = (struct frame *)curthread->t_stkbase; 82 on_intr = 0; 83 continue; 84 } 85 86 /* 87 * This is the last frame we can process; indicate 88 * that we should return after processing this frame. 89 */ 90 last = 1; 91 } 92 93 if (aframes > 0) { 94 if (--aframes == 0 && caller != NULL) { 95 /* 96 * We've just run out of artificial frames, 97 * and we have a valid caller -- fill it in 98 * now. 99 */ 100 ASSERT(depth < pcstack_limit); 101 pcstack[depth++] = (pc_t)caller; 102 caller = NULL; 103 } 104 } else { 105 if (depth < pcstack_limit) 106 pcstack[depth++] = (pc_t)pc; 107 } 108 109 if (last) { 110 while (depth < pcstack_limit) 111 pcstack[depth++] = NULL; 112 return; 113 } 114 115 fp = nextfp; 116 minfp = fp; 117 } 118 } 119 120 static int 121 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 122 uintptr_t sp) 123 { 124 klwp_t *lwp = ttolwp(curthread); 125 proc_t *p = curproc; 126 uintptr_t oldcontext = lwp->lwp_oldcontext; 127 volatile uint16_t *flags = 128 (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; 129 size_t s1, s2; 130 int ret = 0; 131 132 ASSERT(pcstack == NULL || pcstack_limit > 0); 133 134 if (p->p_model == DATAMODEL_NATIVE) { 135 s1 = sizeof (struct frame) + 2 * sizeof (long); 136 s2 = s1 + sizeof (siginfo_t); 137 } else { 138 s1 = sizeof (struct frame32) + 3 * sizeof (int); 139 s2 = s1 + sizeof (siginfo32_t); 140 } 141 142 while (pc != 0) { 143 ret++; 144 if (pcstack != NULL) { 145 *pcstack++ = (uint64_t)pc; 146 pcstack_limit--; 147 if (pcstack_limit <= 0) 148 break; 149 } 150 151 if (sp == 0) 152 break; 153 154 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 155 if (p->p_model == DATAMODEL_NATIVE) { 156 ucontext_t *ucp = (ucontext_t *)oldcontext; 157 greg_t *gregs = ucp->uc_mcontext.gregs; 158 159 sp = dtrace_fulword(&gregs[REG_FP]); 160 pc = dtrace_fulword(&gregs[REG_PC]); 161 162 oldcontext = dtrace_fulword(&ucp->uc_link); 163 } else { 164 ucontext32_t *ucp = (ucontext32_t *)oldcontext; 165 greg32_t *gregs = ucp->uc_mcontext.gregs; 166 167 sp = dtrace_fuword32(&gregs[EBP]); 168 pc = dtrace_fuword32(&gregs[EIP]); 169 170 oldcontext = dtrace_fuword32(&ucp->uc_link); 171 } 172 } else { 173 if (p->p_model == DATAMODEL_NATIVE) { 174 struct frame *fr = (struct frame *)sp; 175 176 pc = dtrace_fulword(&fr->fr_savpc); 177 sp = dtrace_fulword(&fr->fr_savfp); 178 } else { 179 struct frame32 *fr = (struct frame32 *)sp; 180 181 pc = dtrace_fuword32(&fr->fr_savpc); 182 sp = dtrace_fuword32(&fr->fr_savfp); 183 } 184 } 185 186 /* 187 * This is totally bogus: if we faulted, we're going to clear 188 * the fault and break. This is to deal with the apparently 189 * broken Java stacks on x86. 190 */ 191 if (*flags & CPU_DTRACE_FAULT) { 192 *flags &= ~CPU_DTRACE_FAULT; 193 break; 194 } 195 } 196 197 return (ret); 198 } 199 200 void 201 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 202 { 203 klwp_t *lwp = ttolwp(curthread); 204 proc_t *p = curproc; 205 struct regs *rp; 206 uintptr_t pc, sp; 207 volatile uint16_t *flags = 208 (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; 209 int n; 210 211 if (*flags & CPU_DTRACE_FAULT) 212 return; 213 214 if (pcstack_limit <= 0) 215 return; 216 217 /* 218 * If there's no user context we still need to zero the stack. 219 */ 220 if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) 221 goto zero; 222 223 *pcstack++ = (uint64_t)p->p_pid; 224 pcstack_limit--; 225 226 if (pcstack_limit <= 0) 227 return; 228 229 pc = rp->r_pc; 230 sp = rp->r_fp; 231 232 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 233 *pcstack++ = (uint64_t)pc; 234 pcstack_limit--; 235 if (pcstack_limit <= 0) 236 return; 237 238 if (p->p_model == DATAMODEL_NATIVE) 239 pc = dtrace_fulword((void *)rp->r_sp); 240 else 241 pc = dtrace_fuword32((void *)rp->r_sp); 242 } 243 244 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); 245 ASSERT(n >= 0); 246 ASSERT(n <= pcstack_limit); 247 248 pcstack += n; 249 pcstack_limit -= n; 250 251 zero: 252 while (pcstack_limit-- > 0) 253 *pcstack++ = NULL; 254 } 255 256 int 257 dtrace_getustackdepth(void) 258 { 259 klwp_t *lwp = ttolwp(curthread); 260 proc_t *p = curproc; 261 struct regs *rp; 262 uintptr_t pc, sp; 263 int n = 0; 264 265 if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) 266 return (0); 267 268 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 269 return (-1); 270 271 pc = rp->r_pc; 272 sp = rp->r_fp; 273 274 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 275 n++; 276 277 if (p->p_model == DATAMODEL_NATIVE) 278 pc = dtrace_fulword((void *)rp->r_sp); 279 else 280 pc = dtrace_fuword32((void *)rp->r_sp); 281 } 282 283 n += dtrace_getustack_common(NULL, 0, pc, sp); 284 285 return (n); 286 } 287 288 void 289 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 290 { 291 klwp_t *lwp = ttolwp(curthread); 292 proc_t *p = curproc; 293 struct regs *rp; 294 uintptr_t pc, sp, oldcontext; 295 volatile uint16_t *flags = 296 (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; 297 size_t s1, s2; 298 299 if (*flags & CPU_DTRACE_FAULT) 300 return; 301 302 if (pcstack_limit <= 0) 303 return; 304 305 /* 306 * If there's no user context we still need to zero the stack. 307 */ 308 if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL) 309 goto zero; 310 311 *pcstack++ = (uint64_t)p->p_pid; 312 pcstack_limit--; 313 314 if (pcstack_limit <= 0) 315 return; 316 317 pc = rp->r_pc; 318 sp = rp->r_fp; 319 oldcontext = lwp->lwp_oldcontext; 320 321 if (p->p_model == DATAMODEL_NATIVE) { 322 s1 = sizeof (struct frame) + 2 * sizeof (long); 323 s2 = s1 + sizeof (siginfo_t); 324 } else { 325 s1 = sizeof (struct frame32) + 3 * sizeof (int); 326 s2 = s1 + sizeof (siginfo32_t); 327 } 328 329 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 330 *pcstack++ = (uint64_t)pc; 331 *fpstack++ = 0; 332 pcstack_limit--; 333 if (pcstack_limit <= 0) 334 return; 335 336 if (p->p_model == DATAMODEL_NATIVE) 337 pc = dtrace_fulword((void *)rp->r_sp); 338 else 339 pc = dtrace_fuword32((void *)rp->r_sp); 340 } 341 342 while (pc != 0) { 343 *pcstack++ = (uint64_t)pc; 344 *fpstack++ = sp; 345 pcstack_limit--; 346 if (pcstack_limit <= 0) 347 break; 348 349 if (sp == 0) 350 break; 351 352 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 353 if (p->p_model == DATAMODEL_NATIVE) { 354 ucontext_t *ucp = (ucontext_t *)oldcontext; 355 greg_t *gregs = ucp->uc_mcontext.gregs; 356 357 sp = dtrace_fulword(&gregs[REG_FP]); 358 pc = dtrace_fulword(&gregs[REG_PC]); 359 360 oldcontext = dtrace_fulword(&ucp->uc_link); 361 } else { 362 ucontext_t *ucp = (ucontext_t *)oldcontext; 363 greg_t *gregs = ucp->uc_mcontext.gregs; 364 365 sp = dtrace_fuword32(&gregs[EBP]); 366 pc = dtrace_fuword32(&gregs[EIP]); 367 368 oldcontext = dtrace_fuword32(&ucp->uc_link); 369 } 370 } else { 371 if (p->p_model == DATAMODEL_NATIVE) { 372 struct frame *fr = (struct frame *)sp; 373 374 pc = dtrace_fulword(&fr->fr_savpc); 375 sp = dtrace_fulword(&fr->fr_savfp); 376 } else { 377 struct frame32 *fr = (struct frame32 *)sp; 378 379 pc = dtrace_fuword32(&fr->fr_savpc); 380 sp = dtrace_fuword32(&fr->fr_savfp); 381 } 382 } 383 384 /* 385 * This is totally bogus: if we faulted, we're going to clear 386 * the fault and break. This is to deal with the apparently 387 * broken Java stacks on x86. 388 */ 389 if (*flags & CPU_DTRACE_FAULT) { 390 *flags &= ~CPU_DTRACE_FAULT; 391 break; 392 } 393 } 394 395 zero: 396 while (pcstack_limit-- > 0) 397 *pcstack++ = NULL; 398 } 399 400 /*ARGSUSED*/ 401 uint64_t 402 dtrace_getarg(int arg, int aframes) 403 { 404 uintptr_t val; 405 struct frame *fp = (struct frame *)dtrace_getfp(); 406 uintptr_t *stack; 407 int i; 408 #if defined(__amd64) 409 /* 410 * A total of 6 arguments are passed via registers; any argument with 411 * index of 5 or lower is therefore in a register. 412 */ 413 int inreg = 5; 414 #endif 415 416 for (i = 1; i <= aframes; i++) { 417 fp = (struct frame *)(fp->fr_savfp); 418 419 if (fp->fr_savpc == (pc_t)dtrace_invop_callsite) { 420 #if !defined(__amd64) 421 /* 422 * If we pass through the invalid op handler, we will 423 * use the pointer that it passed to the stack as the 424 * second argument to dtrace_invop() as the pointer to 425 * the stack. When using this stack, we must step 426 * beyond the EIP/RIP that was pushed when the trap was 427 * taken -- hence the "+ 1" below. 428 */ 429 stack = ((uintptr_t **)&fp[1])[1] + 1; 430 #else 431 /* 432 * In the case of amd64, we will use the pointer to the 433 * regs structure that was pushed when we took the 434 * trap. To get this structure, we must increment 435 * beyond the frame structure, and then again beyond 436 * the calling RIP stored in dtrace_invop(). If the 437 * argument that we're seeking is passed on the stack, 438 * we'll pull the true stack pointer out of the saved 439 * registers and decrement our argument by the number 440 * of arguments passed in registers; if the argument 441 * we're seeking is passed in regsiters, we can just 442 * load it directly. 443 */ 444 struct regs *rp = (struct regs *)((uintptr_t)&fp[1] + 445 sizeof (uintptr_t)); 446 447 if (arg <= inreg) { 448 stack = (uintptr_t *)&rp->r_rdi; 449 } else { 450 stack = (uintptr_t *)(rp->r_rsp); 451 arg -= inreg; 452 } 453 #endif 454 goto load; 455 } 456 457 } 458 459 /* 460 * We know that we did not come through a trap to get into 461 * dtrace_probe() -- the provider simply called dtrace_probe() 462 * directly. As this is the case, we need to shift the argument 463 * that we're looking for: the probe ID is the first argument to 464 * dtrace_probe(), so the argument n will actually be found where 465 * one would expect to find argument (n + 1). 466 */ 467 arg++; 468 469 #if defined(__amd64) 470 if (arg <= inreg) { 471 /* 472 * This shouldn't happen. If the argument is passed in a 473 * register then it should have been, well, passed in a 474 * register... 475 */ 476 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 477 return (0); 478 } 479 480 arg -= (inreg + 1); 481 #endif 482 stack = (uintptr_t *)&fp[1]; 483 484 load: 485 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 486 val = stack[arg]; 487 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); 488 489 return (val); 490 } 491 492 /*ARGSUSED*/ 493 int 494 dtrace_getstackdepth(int aframes) 495 { 496 struct frame *fp = (struct frame *)dtrace_getfp(); 497 struct frame *nextfp, *minfp, *stacktop; 498 int depth = 0; 499 int on_intr; 500 501 if ((on_intr = CPU_ON_INTR(CPU)) != 0) 502 stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME)); 503 else 504 stacktop = (struct frame *)curthread->t_stk; 505 minfp = fp; 506 507 aframes++; 508 509 for (;;) { 510 depth++; 511 512 nextfp = (struct frame *)fp->fr_savfp; 513 514 if (nextfp <= minfp || nextfp >= stacktop) { 515 if (on_intr) { 516 /* 517 * Hop from interrupt stack to thread stack. 518 */ 519 stacktop = (struct frame *)curthread->t_stk; 520 minfp = (struct frame *)curthread->t_stkbase; 521 on_intr = 0; 522 continue; 523 } 524 break; 525 } 526 527 fp = nextfp; 528 minfp = fp; 529 } 530 531 if (depth <= aframes) 532 return (0); 533 534 return (depth - aframes); 535 } 536 537 ulong_t 538 dtrace_getreg(struct regs *rp, uint_t reg) 539 { 540 #if defined(__amd64) 541 int regmap[] = { 542 REG_GS, /* GS */ 543 REG_FS, /* FS */ 544 REG_ES, /* ES */ 545 REG_DS, /* DS */ 546 REG_RDI, /* EDI */ 547 REG_RSI, /* ESI */ 548 REG_RBP, /* EBP */ 549 REG_RSP, /* ESP */ 550 REG_RBX, /* EBX */ 551 REG_RDX, /* EDX */ 552 REG_RCX, /* ECX */ 553 REG_RAX, /* EAX */ 554 REG_TRAPNO, /* TRAPNO */ 555 REG_ERR, /* ERR */ 556 REG_RIP, /* EIP */ 557 REG_CS, /* CS */ 558 REG_RFL, /* EFL */ 559 REG_RSP, /* UESP */ 560 REG_SS /* SS */ 561 }; 562 563 if (reg <= SS) { 564 if (reg >= sizeof (regmap) / sizeof (int)) { 565 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 566 return (0); 567 } 568 569 reg = regmap[reg]; 570 } else { 571 reg -= SS + 1; 572 } 573 574 switch (reg) { 575 case REG_RDI: 576 return (rp->r_rdi); 577 case REG_RSI: 578 return (rp->r_rsi); 579 case REG_RDX: 580 return (rp->r_rdx); 581 case REG_RCX: 582 return (rp->r_rcx); 583 case REG_R8: 584 return (rp->r_r8); 585 case REG_R9: 586 return (rp->r_r9); 587 case REG_RAX: 588 return (rp->r_rax); 589 case REG_RBX: 590 return (rp->r_rbx); 591 case REG_RBP: 592 return (rp->r_rbp); 593 case REG_R10: 594 return (rp->r_r10); 595 case REG_R11: 596 return (rp->r_r11); 597 case REG_R12: 598 return (rp->r_r12); 599 case REG_R13: 600 return (rp->r_r13); 601 case REG_R14: 602 return (rp->r_r14); 603 case REG_R15: 604 return (rp->r_r15); 605 case REG_DS: 606 return (rp->r_ds); 607 case REG_ES: 608 return (rp->r_es); 609 case REG_FS: 610 return (rp->r_fs); 611 case REG_GS: 612 return (rp->r_gs); 613 case REG_TRAPNO: 614 return (rp->r_trapno); 615 case REG_ERR: 616 return (rp->r_err); 617 case REG_RIP: 618 return (rp->r_rip); 619 case REG_CS: 620 return (rp->r_cs); 621 case REG_SS: 622 return (rp->r_ss); 623 case REG_RFL: 624 return (rp->r_rfl); 625 case REG_RSP: 626 return (rp->r_rsp); 627 default: 628 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 629 return (0); 630 } 631 632 #else 633 if (reg > SS) { 634 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 635 return (0); 636 } 637 638 return ((&rp->r_gs)[reg]); 639 #endif 640 } 641 642 static int 643 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 644 { 645 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr); 646 647 if (uaddr + size >= kernelbase || uaddr + size < uaddr) { 648 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 649 cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr; 650 return (0); 651 } 652 653 return (1); 654 } 655 656 void 657 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size) 658 { 659 if (dtrace_copycheck(uaddr, kaddr, size)) 660 dtrace_copy(uaddr, kaddr, size); 661 } 662 663 void 664 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size) 665 { 666 if (dtrace_copycheck(uaddr, kaddr, size)) 667 dtrace_copy(kaddr, uaddr, size); 668 } 669 670 void 671 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size) 672 { 673 if (dtrace_copycheck(uaddr, kaddr, size)) 674 dtrace_copystr(uaddr, kaddr, size); 675 } 676 677 void 678 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size) 679 { 680 if (dtrace_copycheck(uaddr, kaddr, size)) 681 dtrace_copystr(kaddr, uaddr, size); 682 } 683 684 uint8_t 685 dtrace_fuword8(void *uaddr) 686 { 687 extern uint8_t dtrace_fuword8_nocheck(void *); 688 if ((uintptr_t)uaddr >= _userlimit) { 689 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 690 cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr; 691 return (0); 692 } 693 return (dtrace_fuword8_nocheck(uaddr)); 694 } 695 696 uint16_t 697 dtrace_fuword16(void *uaddr) 698 { 699 extern uint16_t dtrace_fuword16_nocheck(void *); 700 if ((uintptr_t)uaddr >= _userlimit) { 701 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 702 cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr; 703 return (0); 704 } 705 return (dtrace_fuword16_nocheck(uaddr)); 706 } 707 708 uint32_t 709 dtrace_fuword32(void *uaddr) 710 { 711 extern uint32_t dtrace_fuword32_nocheck(void *); 712 if ((uintptr_t)uaddr >= _userlimit) { 713 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 714 cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr; 715 return (0); 716 } 717 return (dtrace_fuword32_nocheck(uaddr)); 718 } 719 720 uint64_t 721 dtrace_fuword64(void *uaddr) 722 { 723 extern uint64_t dtrace_fuword64_nocheck(void *); 724 if ((uintptr_t)uaddr >= _userlimit) { 725 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 726 cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr; 727 return (0); 728 } 729 return (dtrace_fuword64_nocheck(uaddr)); 730 } 731