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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * $FreeBSD$ 23 */ 24 /* 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 #include <sys/cdefs.h> 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/stack.h> 34 #include <sys/pcpu.h> 35 36 #include <machine/frame.h> 37 #include <machine/md_var.h> 38 #include <machine/pcb.h> 39 #include <machine/stack.h> 40 41 #include <vm/vm.h> 42 #include <vm/vm_param.h> 43 #include <vm/pmap.h> 44 45 #include "regset.h" 46 47 extern uintptr_t kernbase; 48 uintptr_t kernelbase = (uintptr_t) &kernbase; 49 50 uint8_t dtrace_fuword8_nocheck(void *); 51 uint16_t dtrace_fuword16_nocheck(void *); 52 uint32_t dtrace_fuword32_nocheck(void *); 53 uint64_t dtrace_fuword64_nocheck(void *); 54 55 int dtrace_ustackdepth_max = 2048; 56 57 void 58 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 59 uint32_t *intrpc) 60 { 61 int depth = 0; 62 register_t ebp; 63 struct i386_frame *frame; 64 vm_offset_t callpc; 65 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 66 67 if (intrpc != 0) 68 pcstack[depth++] = (pc_t) intrpc; 69 70 aframes++; 71 72 __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); 73 74 frame = (struct i386_frame *)ebp; 75 while (depth < pcstack_limit) { 76 if (!INKERNEL(frame)) 77 break; 78 79 callpc = frame->f_retaddr; 80 81 if (!INKERNEL(callpc)) 82 break; 83 84 if (aframes > 0) { 85 aframes--; 86 if ((aframes == 0) && (caller != 0)) { 87 pcstack[depth++] = caller; 88 } 89 } 90 else { 91 pcstack[depth++] = callpc; 92 } 93 94 if (frame->f_frame <= frame || 95 (vm_offset_t)frame->f_frame >= curthread->td_kstack + 96 curthread->td_kstack_pages * PAGE_SIZE) 97 break; 98 frame = frame->f_frame; 99 } 100 101 for (; depth < pcstack_limit; depth++) { 102 pcstack[depth] = 0; 103 } 104 } 105 106 static int 107 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 108 uintptr_t sp) 109 { 110 #ifdef notyet 111 proc_t *p = curproc; 112 uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */ 113 size_t s1, s2; 114 #endif 115 uintptr_t oldsp; 116 volatile uint16_t *flags = 117 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 118 int ret = 0; 119 120 ASSERT(pcstack == NULL || pcstack_limit > 0); 121 ASSERT(dtrace_ustackdepth_max > 0); 122 123 #ifdef notyet /* XXX signal stack. */ 124 if (p->p_model == DATAMODEL_NATIVE) { 125 s1 = sizeof (struct frame) + 2 * sizeof (long); 126 s2 = s1 + sizeof (siginfo_t); 127 } else { 128 s1 = sizeof (struct frame32) + 3 * sizeof (int); 129 s2 = s1 + sizeof (siginfo32_t); 130 } 131 #endif 132 133 while (pc != 0) { 134 /* 135 * We limit the number of times we can go around this 136 * loop to account for a circular stack. 137 */ 138 if (ret++ >= dtrace_ustackdepth_max) { 139 *flags |= CPU_DTRACE_BADSTACK; 140 cpu_core[curcpu].cpuc_dtrace_illval = sp; 141 break; 142 } 143 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 oldsp = sp; 155 156 #ifdef notyet /* XXX signal stack. */ 157 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 158 if (p->p_model == DATAMODEL_NATIVE) { 159 ucontext_t *ucp = (ucontext_t *)oldcontext; 160 greg_t *gregs = ucp->uc_mcontext.gregs; 161 162 sp = dtrace_fulword(&gregs[REG_FP]); 163 pc = dtrace_fulword(&gregs[REG_PC]); 164 165 oldcontext = dtrace_fulword(&ucp->uc_link); 166 } else { 167 ucontext32_t *ucp = (ucontext32_t *)oldcontext; 168 greg32_t *gregs = ucp->uc_mcontext.gregs; 169 170 sp = dtrace_fuword32(&gregs[EBP]); 171 pc = dtrace_fuword32(&gregs[EIP]); 172 173 oldcontext = dtrace_fuword32(&ucp->uc_link); 174 } 175 } else { 176 if (p->p_model == DATAMODEL_NATIVE) { 177 struct frame *fr = (struct frame *)sp; 178 179 pc = dtrace_fulword(&fr->fr_savpc); 180 sp = dtrace_fulword(&fr->fr_savfp); 181 } else { 182 struct frame32 *fr = (struct frame32 *)sp; 183 184 pc = dtrace_fuword32(&fr->fr_savpc); 185 sp = dtrace_fuword32(&fr->fr_savfp); 186 } 187 } 188 #else 189 pc = dtrace_fuword32((void *)(sp + 190 offsetof(struct i386_frame, f_retaddr))); 191 sp = dtrace_fuword32((void *)sp); 192 #endif /* ! notyet */ 193 194 if (sp == oldsp) { 195 *flags |= CPU_DTRACE_BADSTACK; 196 cpu_core[curcpu].cpuc_dtrace_illval = sp; 197 break; 198 } 199 200 /* 201 * This is totally bogus: if we faulted, we're going to clear 202 * the fault and break. This is to deal with the apparently 203 * broken Java stacks on x86. 204 */ 205 if (*flags & CPU_DTRACE_FAULT) { 206 *flags &= ~CPU_DTRACE_FAULT; 207 break; 208 } 209 } 210 211 return (ret); 212 } 213 214 void 215 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 216 { 217 proc_t *p = curproc; 218 struct trapframe *tf; 219 uintptr_t pc, sp, fp; 220 volatile uint16_t *flags = 221 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 222 int n; 223 224 if (*flags & CPU_DTRACE_FAULT) 225 return; 226 227 if (pcstack_limit <= 0) 228 return; 229 230 /* 231 * If there's no user context we still need to zero the stack. 232 */ 233 if (p == NULL || (tf = curthread->td_frame) == NULL) 234 goto zero; 235 236 *pcstack++ = (uint64_t)p->p_pid; 237 pcstack_limit--; 238 239 if (pcstack_limit <= 0) 240 return; 241 242 pc = tf->tf_eip; 243 fp = tf->tf_ebp; 244 sp = tf->tf_esp; 245 246 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 247 /* 248 * In an entry probe. The frame pointer has not yet been 249 * pushed (that happens in the function prologue). The 250 * best approach is to add the current pc as a missing top 251 * of stack and back the pc up to the caller, which is stored 252 * at the current stack pointer address since the call 253 * instruction puts it there right before the branch. 254 */ 255 256 *pcstack++ = (uint64_t)pc; 257 pcstack_limit--; 258 if (pcstack_limit <= 0) 259 return; 260 261 pc = dtrace_fuword32((void *) sp); 262 } 263 264 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); 265 ASSERT(n >= 0); 266 ASSERT(n <= pcstack_limit); 267 268 pcstack += n; 269 pcstack_limit -= n; 270 271 zero: 272 while (pcstack_limit-- > 0) 273 *pcstack++ = 0; 274 } 275 276 int 277 dtrace_getustackdepth(void) 278 { 279 proc_t *p = curproc; 280 struct trapframe *tf; 281 uintptr_t pc, fp, sp; 282 int n = 0; 283 284 if (p == NULL || (tf = curthread->td_frame) == NULL) 285 return (0); 286 287 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 288 return (-1); 289 290 pc = tf->tf_eip; 291 fp = tf->tf_ebp; 292 sp = tf->tf_esp; 293 294 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 295 /* 296 * In an entry probe. The frame pointer has not yet been 297 * pushed (that happens in the function prologue). The 298 * best approach is to add the current pc as a missing top 299 * of stack and back the pc up to the caller, which is stored 300 * at the current stack pointer address since the call 301 * instruction puts it there right before the branch. 302 */ 303 304 pc = dtrace_fuword32((void *) sp); 305 n++; 306 } 307 308 n += dtrace_getustack_common(NULL, 0, pc, fp); 309 310 return (n); 311 } 312 313 void 314 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 315 { 316 proc_t *p = curproc; 317 struct trapframe *tf; 318 uintptr_t pc, sp, fp; 319 volatile uint16_t *flags = 320 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 321 #ifdef notyet /* XXX signal stack */ 322 uintptr_t oldcontext; 323 size_t s1, s2; 324 #endif 325 326 if (*flags & CPU_DTRACE_FAULT) 327 return; 328 329 if (pcstack_limit <= 0) 330 return; 331 332 /* 333 * If there's no user context we still need to zero the stack. 334 */ 335 if (p == NULL || (tf = curthread->td_frame) == NULL) 336 goto zero; 337 338 *pcstack++ = (uint64_t)p->p_pid; 339 pcstack_limit--; 340 341 if (pcstack_limit <= 0) 342 return; 343 344 pc = tf->tf_eip; 345 fp = tf->tf_ebp; 346 sp = tf->tf_esp; 347 348 #ifdef notyet /* XXX signal stack */ 349 oldcontext = lwp->lwp_oldcontext; 350 351 if (p->p_model == DATAMODEL_NATIVE) { 352 s1 = sizeof (struct frame) + 2 * sizeof (long); 353 s2 = s1 + sizeof (siginfo_t); 354 } else { 355 s1 = sizeof (struct frame32) + 3 * sizeof (int); 356 s2 = s1 + sizeof (siginfo32_t); 357 } 358 #endif 359 360 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 361 *pcstack++ = (uint64_t)pc; 362 *fpstack++ = 0; 363 pcstack_limit--; 364 if (pcstack_limit <= 0) 365 return; 366 367 pc = dtrace_fuword32((void *)sp); 368 } 369 370 while (pc != 0) { 371 *pcstack++ = (uint64_t)pc; 372 *fpstack++ = fp; 373 pcstack_limit--; 374 if (pcstack_limit <= 0) 375 break; 376 377 if (fp == 0) 378 break; 379 380 #ifdef notyet /* XXX signal stack */ 381 if (oldcontext == sp + s1 || oldcontext == sp + s2) { 382 if (p->p_model == DATAMODEL_NATIVE) { 383 ucontext_t *ucp = (ucontext_t *)oldcontext; 384 greg_t *gregs = ucp->uc_mcontext.gregs; 385 386 sp = dtrace_fulword(&gregs[REG_FP]); 387 pc = dtrace_fulword(&gregs[REG_PC]); 388 389 oldcontext = dtrace_fulword(&ucp->uc_link); 390 } else { 391 ucontext_t *ucp = (ucontext_t *)oldcontext; 392 greg_t *gregs = ucp->uc_mcontext.gregs; 393 394 sp = dtrace_fuword32(&gregs[EBP]); 395 pc = dtrace_fuword32(&gregs[EIP]); 396 397 oldcontext = dtrace_fuword32(&ucp->uc_link); 398 } 399 } else 400 #endif /* XXX */ 401 { 402 pc = dtrace_fuword32((void *)(fp + 403 offsetof(struct i386_frame, f_retaddr))); 404 fp = dtrace_fuword32((void *)fp); 405 } 406 407 /* 408 * This is totally bogus: if we faulted, we're going to clear 409 * the fault and break. This is to deal with the apparently 410 * broken Java stacks on x86. 411 */ 412 if (*flags & CPU_DTRACE_FAULT) { 413 *flags &= ~CPU_DTRACE_FAULT; 414 break; 415 } 416 } 417 418 zero: 419 while (pcstack_limit-- > 0) 420 *pcstack++ = 0; 421 } 422 423 uint64_t 424 dtrace_getarg(int arg, int aframes) 425 { 426 uintptr_t val; 427 struct i386_frame *fp = (struct i386_frame *)dtrace_getfp(); 428 uintptr_t *stack; 429 int i; 430 431 for (i = 1; i <= aframes; i++) { 432 fp = fp->f_frame; 433 434 if (P2ROUNDUP(fp->f_retaddr, 4) == 435 (long)dtrace_invop_callsite) { 436 /* 437 * If we pass through the invalid op handler, we will 438 * use the pointer that it passed to the stack as the 439 * second argument to dtrace_invop() as the pointer to 440 * the stack. When using this stack, we must step 441 * beyond the EIP/RIP that was pushed when the trap was 442 * taken -- hence the "+ 1" below. 443 */ 444 stack = ((uintptr_t **)&fp[1])[0] + 1; 445 goto load; 446 } 447 448 } 449 450 /* 451 * We know that we did not come through a trap to get into 452 * dtrace_probe() -- the provider simply called dtrace_probe() 453 * directly. As this is the case, we need to shift the argument 454 * that we're looking for: the probe ID is the first argument to 455 * dtrace_probe(), so the argument n will actually be found where 456 * one would expect to find argument (n + 1). 457 */ 458 arg++; 459 460 stack = (uintptr_t *)fp + 2; 461 462 load: 463 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 464 val = stack[arg]; 465 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); 466 467 return (val); 468 } 469 470 int 471 dtrace_getstackdepth(int aframes) 472 { 473 int depth = 0; 474 struct i386_frame *frame; 475 vm_offset_t ebp; 476 477 aframes++; 478 ebp = dtrace_getfp(); 479 frame = (struct i386_frame *)ebp; 480 depth++; 481 for(;;) { 482 if (!INKERNEL((long) frame)) 483 break; 484 if (!INKERNEL((long) frame->f_frame)) 485 break; 486 depth++; 487 if (frame->f_frame <= frame || 488 (vm_offset_t)frame->f_frame >= curthread->td_kstack + 489 curthread->td_kstack_pages * PAGE_SIZE) 490 break; 491 frame = frame->f_frame; 492 } 493 if (depth < aframes) 494 return 0; 495 else 496 return depth - aframes; 497 } 498 499 ulong_t 500 dtrace_getreg(struct trapframe *rp, uint_t reg) 501 { 502 struct pcb *pcb; 503 int regmap[] = { /* Order is dependent on reg.d */ 504 REG_GS, /* 0 GS */ 505 REG_FS, /* 1 FS */ 506 REG_ES, /* 2 ES */ 507 REG_DS, /* 3 DS */ 508 REG_RDI, /* 4 EDI */ 509 REG_RSI, /* 5 ESI */ 510 REG_RBP, /* 6 EBP, REG_FP */ 511 REG_RSP, /* 7 ESP */ 512 REG_RBX, /* 8 EBX */ 513 REG_RDX, /* 9 EDX, REG_R1 */ 514 REG_RCX, /* 10 ECX */ 515 REG_RAX, /* 11 EAX, REG_R0 */ 516 REG_TRAPNO, /* 12 TRAPNO */ 517 REG_ERR, /* 13 ERR */ 518 REG_RIP, /* 14 EIP, REG_PC */ 519 REG_CS, /* 15 CS */ 520 REG_RFL, /* 16 EFL, REG_PS */ 521 REG_RSP, /* 17 UESP, REG_SP */ 522 REG_SS /* 18 SS */ 523 }; 524 525 if (reg > SS) { 526 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 527 return (0); 528 } 529 530 if (reg >= sizeof (regmap) / sizeof (int)) { 531 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 532 return (0); 533 } 534 535 reg = regmap[reg]; 536 537 switch(reg) { 538 case REG_GS: 539 if ((pcb = curthread->td_pcb) == NULL) { 540 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 541 return (0); 542 } 543 return (pcb->pcb_gs); 544 case REG_FS: 545 return (rp->tf_fs); 546 case REG_ES: 547 return (rp->tf_es); 548 case REG_DS: 549 return (rp->tf_ds); 550 case REG_RDI: 551 return (rp->tf_edi); 552 case REG_RSI: 553 return (rp->tf_esi); 554 case REG_RBP: 555 return (rp->tf_ebp); 556 case REG_RSP: 557 return (rp->tf_isp); 558 case REG_RBX: 559 return (rp->tf_ebx); 560 case REG_RCX: 561 return (rp->tf_ecx); 562 case REG_RAX: 563 return (rp->tf_eax); 564 case REG_TRAPNO: 565 return (rp->tf_trapno); 566 case REG_ERR: 567 return (rp->tf_err); 568 case REG_RIP: 569 return (rp->tf_eip); 570 case REG_CS: 571 return (rp->tf_cs); 572 case REG_RFL: 573 return (rp->tf_eflags); 574 #if 0 575 case REG_RSP: 576 return (rp->tf_esp); 577 #endif 578 case REG_SS: 579 return (rp->tf_ss); 580 default: 581 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 582 return (0); 583 } 584 } 585 586 static int 587 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 588 { 589 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr); 590 591 if (uaddr + size >= kernelbase || uaddr + size < uaddr) { 592 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 593 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 594 return (0); 595 } 596 597 return (1); 598 } 599 600 void 601 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 602 volatile uint16_t *flags) 603 { 604 if (dtrace_copycheck(uaddr, kaddr, size)) 605 dtrace_copy(uaddr, kaddr, size); 606 } 607 608 void 609 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 610 volatile uint16_t *flags) 611 { 612 if (dtrace_copycheck(uaddr, kaddr, size)) 613 dtrace_copy(kaddr, uaddr, size); 614 } 615 616 void 617 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 618 volatile uint16_t *flags) 619 { 620 if (dtrace_copycheck(uaddr, kaddr, size)) 621 dtrace_copystr(uaddr, kaddr, size, flags); 622 } 623 624 void 625 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 626 volatile uint16_t *flags) 627 { 628 if (dtrace_copycheck(uaddr, kaddr, size)) 629 dtrace_copystr(kaddr, uaddr, size, flags); 630 } 631 632 uint8_t 633 dtrace_fuword8(void *uaddr) 634 { 635 if ((uintptr_t)uaddr >= kernelbase) { 636 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 637 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 638 return (0); 639 } 640 return (dtrace_fuword8_nocheck(uaddr)); 641 } 642 643 uint16_t 644 dtrace_fuword16(void *uaddr) 645 { 646 if ((uintptr_t)uaddr >= kernelbase) { 647 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 648 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 649 return (0); 650 } 651 return (dtrace_fuword16_nocheck(uaddr)); 652 } 653 654 uint32_t 655 dtrace_fuword32(void *uaddr) 656 { 657 if ((uintptr_t)uaddr >= kernelbase) { 658 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 659 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 660 return (0); 661 } 662 return (dtrace_fuword32_nocheck(uaddr)); 663 } 664 665 uint64_t 666 dtrace_fuword64(void *uaddr) 667 { 668 if ((uintptr_t)uaddr >= kernelbase) { 669 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 670 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 671 return (0); 672 } 673 return (dtrace_fuword64_nocheck(uaddr)); 674 } 675