1209720Srpaulo/* 2209720Srpaulo * CDDL HEADER START 3209720Srpaulo * 4209720Srpaulo * The contents of this file are subject to the terms of the 5209720Srpaulo * Common Development and Distribution License (the "License"). 6209720Srpaulo * You may not use this file except in compliance with the License. 7209720Srpaulo * 8209720Srpaulo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9209720Srpaulo * or http://www.opensolaris.org/os/licensing. 10209720Srpaulo * See the License for the specific language governing permissions 11209720Srpaulo * and limitations under the License. 12209720Srpaulo * 13209720Srpaulo * When distributing Covered Code, include this CDDL HEADER in each 14209720Srpaulo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15209720Srpaulo * If applicable, add the following below this CDDL HEADER, with the 16209720Srpaulo * fields enclosed by brackets "[]" replaced with your own identifying 17209720Srpaulo * information: Portions Copyright [yyyy] [name of copyright owner] 18209720Srpaulo * 19209720Srpaulo * CDDL HEADER END 20211744Srpaulo * 21211744Srpaulo * Portions Copyright 2010 The FreeBSD Foundation 22211744Srpaulo * 23211744Srpaulo * $FreeBSD$ 24209720Srpaulo */ 25209720Srpaulo 26209720Srpaulo/* 27209720Srpaulo * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 28209720Srpaulo * Use is subject to license terms. 29209720Srpaulo */ 30209720Srpaulo 31211744Srpaulo#if defined(sun) 32209720Srpaulo#pragma ident "%Z%%M% %I% %E% SMI" 33211744Srpaulo#endif 34209720Srpaulo 35209720Srpaulo#include <sys/fasttrap_isa.h> 36209720Srpaulo#include <sys/fasttrap_impl.h> 37209720Srpaulo#include <sys/dtrace.h> 38209720Srpaulo#include <sys/dtrace_impl.h> 39209720Srpaulo#include <sys/cmn_err.h> 40211744Srpaulo#if defined(sun) 41209720Srpaulo#include <sys/regset.h> 42209720Srpaulo#include <sys/privregs.h> 43209720Srpaulo#include <sys/segments.h> 44209720Srpaulo#include <sys/x86_archext.h> 45211744Srpaulo#else 46211744Srpaulo#include <cddl/dev/dtrace/dtrace_cddl.h> 47211744Srpaulo#include <sys/types.h> 48211744Srpaulo#include <sys/proc.h> 49211744Srpaulo#include <sys/dtrace_bsd.h> 50211744Srpaulo#include <cddl/dev/dtrace/i386/regset.h> 51211744Srpaulo#include <machine/segments.h> 52211744Srpaulo#include <machine/reg.h> 53211744Srpaulo#include <machine/pcb.h> 54211744Srpaulo#endif 55209720Srpaulo#include <sys/sysmacros.h> 56211744Srpaulo#if defined(sun) 57209720Srpaulo#include <sys/trap.h> 58209720Srpaulo#include <sys/archsystm.h> 59211744Srpaulo#else 60211744Srpaulo#include <sys/ptrace.h> 61209720Srpaulo 62211744Srpaulostatic int 63211744Srpauloproc_ops(int op, proc_t *p, void *kaddr, off_t uaddr, size_t len) 64211744Srpaulo{ 65211744Srpaulo struct iovec iov; 66211744Srpaulo struct uio uio; 67211744Srpaulo 68211744Srpaulo iov.iov_base = kaddr; 69211744Srpaulo iov.iov_len = len; 70211744Srpaulo uio.uio_offset = uaddr; 71211744Srpaulo uio.uio_iov = &iov; 72211744Srpaulo uio.uio_resid = len; 73211744Srpaulo uio.uio_iovcnt = 1; 74211744Srpaulo uio.uio_segflg = UIO_SYSSPACE; 75211744Srpaulo uio.uio_td = curthread; 76211744Srpaulo uio.uio_rw = op; 77212494Srpaulo PHOLD(p); 78211744Srpaulo if (proc_rwmem(p, &uio) < 0) { 79212494Srpaulo PRELE(p); 80211744Srpaulo return (-1); 81211744Srpaulo } 82212494Srpaulo PRELE(p); 83211744Srpaulo 84211744Srpaulo return (0); 85211744Srpaulo} 86211744Srpaulo 87211744Srpaulostatic int 88211744Srpaulouread(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr) 89211744Srpaulo{ 90211744Srpaulo 91211744Srpaulo return (proc_ops(UIO_READ, p, kaddr, uaddr, len)); 92211744Srpaulo} 93211744Srpaulo 94211744Srpaulostatic int 95211744Srpaulouwrite(proc_t *p, void *kaddr, size_t len, uintptr_t uaddr) 96211744Srpaulo{ 97211744Srpaulo 98211744Srpaulo return (proc_ops(UIO_WRITE, p, kaddr, uaddr, len)); 99211744Srpaulo} 100227291Srstone#endif /* sun */ 101211744Srpaulo#ifdef __i386__ 102211744Srpaulo#define r_rax r_eax 103211744Srpaulo#define r_rbx r_ebx 104211744Srpaulo#define r_rip r_eip 105211744Srpaulo#define r_rflags r_eflags 106211744Srpaulo#define r_rsp r_esp 107211744Srpaulo#endif 108211744Srpaulo 109209720Srpaulo/* 110209720Srpaulo * Lossless User-Land Tracing on x86 111209720Srpaulo * --------------------------------- 112209720Srpaulo * 113209720Srpaulo * The execution of most instructions is not dependent on the address; for 114209720Srpaulo * these instructions it is sufficient to copy them into the user process's 115209720Srpaulo * address space and execute them. To effectively single-step an instruction 116209720Srpaulo * in user-land, we copy out the following sequence of instructions to scratch 117209720Srpaulo * space in the user thread's ulwp_t structure. 118209720Srpaulo * 119209720Srpaulo * We then set the program counter (%eip or %rip) to point to this scratch 120209720Srpaulo * space. Once execution resumes, the original instruction is executed and 121209720Srpaulo * then control flow is redirected to what was originally the subsequent 122209720Srpaulo * instruction. If the kernel attemps to deliver a signal while single- 123209720Srpaulo * stepping, the signal is deferred and the program counter is moved into the 124209720Srpaulo * second sequence of instructions. The second sequence ends in a trap into 125209720Srpaulo * the kernel where the deferred signal is then properly handled and delivered. 126209720Srpaulo * 127209720Srpaulo * For instructions whose execute is position dependent, we perform simple 128209720Srpaulo * emulation. These instructions are limited to control transfer 129209720Srpaulo * instructions in 32-bit mode, but in 64-bit mode there's the added wrinkle 130209720Srpaulo * of %rip-relative addressing that means that almost any instruction can be 131209720Srpaulo * position dependent. For all the details on how we emulate generic 132209720Srpaulo * instructions included %rip-relative instructions, see the code in 133209720Srpaulo * fasttrap_pid_probe() below where we handle instructions of type 134209720Srpaulo * FASTTRAP_T_COMMON (under the header: Generic Instruction Tracing). 135209720Srpaulo */ 136209720Srpaulo 137209720Srpaulo#define FASTTRAP_MODRM_MOD(modrm) (((modrm) >> 6) & 0x3) 138209720Srpaulo#define FASTTRAP_MODRM_REG(modrm) (((modrm) >> 3) & 0x7) 139209720Srpaulo#define FASTTRAP_MODRM_RM(modrm) ((modrm) & 0x7) 140209720Srpaulo#define FASTTRAP_MODRM(mod, reg, rm) (((mod) << 6) | ((reg) << 3) | (rm)) 141209720Srpaulo 142209720Srpaulo#define FASTTRAP_SIB_SCALE(sib) (((sib) >> 6) & 0x3) 143209720Srpaulo#define FASTTRAP_SIB_INDEX(sib) (((sib) >> 3) & 0x7) 144209720Srpaulo#define FASTTRAP_SIB_BASE(sib) ((sib) & 0x7) 145209720Srpaulo 146209720Srpaulo#define FASTTRAP_REX_W(rex) (((rex) >> 3) & 1) 147209720Srpaulo#define FASTTRAP_REX_R(rex) (((rex) >> 2) & 1) 148209720Srpaulo#define FASTTRAP_REX_X(rex) (((rex) >> 1) & 1) 149209720Srpaulo#define FASTTRAP_REX_B(rex) ((rex) & 1) 150209720Srpaulo#define FASTTRAP_REX(w, r, x, b) \ 151209720Srpaulo (0x40 | ((w) << 3) | ((r) << 2) | ((x) << 1) | (b)) 152209720Srpaulo 153209720Srpaulo/* 154209720Srpaulo * Single-byte op-codes. 155209720Srpaulo */ 156209720Srpaulo#define FASTTRAP_PUSHL_EBP 0x55 157209720Srpaulo 158209720Srpaulo#define FASTTRAP_JO 0x70 159209720Srpaulo#define FASTTRAP_JNO 0x71 160209720Srpaulo#define FASTTRAP_JB 0x72 161209720Srpaulo#define FASTTRAP_JAE 0x73 162209720Srpaulo#define FASTTRAP_JE 0x74 163209720Srpaulo#define FASTTRAP_JNE 0x75 164209720Srpaulo#define FASTTRAP_JBE 0x76 165209720Srpaulo#define FASTTRAP_JA 0x77 166209720Srpaulo#define FASTTRAP_JS 0x78 167209720Srpaulo#define FASTTRAP_JNS 0x79 168209720Srpaulo#define FASTTRAP_JP 0x7a 169209720Srpaulo#define FASTTRAP_JNP 0x7b 170209720Srpaulo#define FASTTRAP_JL 0x7c 171209720Srpaulo#define FASTTRAP_JGE 0x7d 172209720Srpaulo#define FASTTRAP_JLE 0x7e 173209720Srpaulo#define FASTTRAP_JG 0x7f 174209720Srpaulo 175209720Srpaulo#define FASTTRAP_NOP 0x90 176209720Srpaulo 177209720Srpaulo#define FASTTRAP_MOV_EAX 0xb8 178209720Srpaulo#define FASTTRAP_MOV_ECX 0xb9 179209720Srpaulo 180209720Srpaulo#define FASTTRAP_RET16 0xc2 181209720Srpaulo#define FASTTRAP_RET 0xc3 182209720Srpaulo 183209720Srpaulo#define FASTTRAP_LOOPNZ 0xe0 184209720Srpaulo#define FASTTRAP_LOOPZ 0xe1 185209720Srpaulo#define FASTTRAP_LOOP 0xe2 186209720Srpaulo#define FASTTRAP_JCXZ 0xe3 187209720Srpaulo 188209720Srpaulo#define FASTTRAP_CALL 0xe8 189209720Srpaulo#define FASTTRAP_JMP32 0xe9 190209720Srpaulo#define FASTTRAP_JMP8 0xeb 191209720Srpaulo 192209720Srpaulo#define FASTTRAP_INT3 0xcc 193209720Srpaulo#define FASTTRAP_INT 0xcd 194209720Srpaulo 195209720Srpaulo#define FASTTRAP_2_BYTE_OP 0x0f 196209720Srpaulo#define FASTTRAP_GROUP5_OP 0xff 197209720Srpaulo 198209720Srpaulo/* 199209720Srpaulo * Two-byte op-codes (second byte only). 200209720Srpaulo */ 201209720Srpaulo#define FASTTRAP_0F_JO 0x80 202209720Srpaulo#define FASTTRAP_0F_JNO 0x81 203209720Srpaulo#define FASTTRAP_0F_JB 0x82 204209720Srpaulo#define FASTTRAP_0F_JAE 0x83 205209720Srpaulo#define FASTTRAP_0F_JE 0x84 206209720Srpaulo#define FASTTRAP_0F_JNE 0x85 207209720Srpaulo#define FASTTRAP_0F_JBE 0x86 208209720Srpaulo#define FASTTRAP_0F_JA 0x87 209209720Srpaulo#define FASTTRAP_0F_JS 0x88 210209720Srpaulo#define FASTTRAP_0F_JNS 0x89 211209720Srpaulo#define FASTTRAP_0F_JP 0x8a 212209720Srpaulo#define FASTTRAP_0F_JNP 0x8b 213209720Srpaulo#define FASTTRAP_0F_JL 0x8c 214209720Srpaulo#define FASTTRAP_0F_JGE 0x8d 215209720Srpaulo#define FASTTRAP_0F_JLE 0x8e 216209720Srpaulo#define FASTTRAP_0F_JG 0x8f 217209720Srpaulo 218209720Srpaulo#define FASTTRAP_EFLAGS_OF 0x800 219209720Srpaulo#define FASTTRAP_EFLAGS_DF 0x400 220209720Srpaulo#define FASTTRAP_EFLAGS_SF 0x080 221209720Srpaulo#define FASTTRAP_EFLAGS_ZF 0x040 222209720Srpaulo#define FASTTRAP_EFLAGS_AF 0x010 223209720Srpaulo#define FASTTRAP_EFLAGS_PF 0x004 224209720Srpaulo#define FASTTRAP_EFLAGS_CF 0x001 225209720Srpaulo 226209720Srpaulo/* 227209720Srpaulo * Instruction prefixes. 228209720Srpaulo */ 229209720Srpaulo#define FASTTRAP_PREFIX_OPERAND 0x66 230209720Srpaulo#define FASTTRAP_PREFIX_ADDRESS 0x67 231209720Srpaulo#define FASTTRAP_PREFIX_CS 0x2E 232209720Srpaulo#define FASTTRAP_PREFIX_DS 0x3E 233209720Srpaulo#define FASTTRAP_PREFIX_ES 0x26 234209720Srpaulo#define FASTTRAP_PREFIX_FS 0x64 235209720Srpaulo#define FASTTRAP_PREFIX_GS 0x65 236209720Srpaulo#define FASTTRAP_PREFIX_SS 0x36 237209720Srpaulo#define FASTTRAP_PREFIX_LOCK 0xF0 238209720Srpaulo#define FASTTRAP_PREFIX_REP 0xF3 239209720Srpaulo#define FASTTRAP_PREFIX_REPNE 0xF2 240209720Srpaulo 241209720Srpaulo#define FASTTRAP_NOREG 0xff 242209720Srpaulo 243209720Srpaulo/* 244209720Srpaulo * Map between instruction register encodings and the kernel constants which 245209720Srpaulo * correspond to indicies into struct regs. 246209720Srpaulo */ 247209720Srpaulo#ifdef __amd64 248209720Srpaulostatic const uint8_t regmap[16] = { 249209720Srpaulo REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI, 250209720Srpaulo REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, 251209720Srpaulo}; 252209720Srpaulo#else 253209720Srpaulostatic const uint8_t regmap[8] = { 254209720Srpaulo EAX, ECX, EDX, EBX, UESP, EBP, ESI, EDI 255209720Srpaulo}; 256209720Srpaulo#endif 257209720Srpaulo 258211744Srpaulostatic ulong_t fasttrap_getreg(struct reg *, uint_t); 259209720Srpaulo 260209720Srpaulostatic uint64_t 261211744Srpaulofasttrap_anarg(struct reg *rp, int function_entry, int argno) 262209720Srpaulo{ 263211744Srpaulo uint64_t value = 0; 264209720Srpaulo int shift = function_entry ? 1 : 0; 265209720Srpaulo 266209720Srpaulo#ifdef __amd64 267209720Srpaulo if (curproc->p_model == DATAMODEL_LP64) { 268209720Srpaulo uintptr_t *stack; 269209720Srpaulo 270209720Srpaulo /* 271209720Srpaulo * In 64-bit mode, the first six arguments are stored in 272209720Srpaulo * registers. 273209720Srpaulo */ 274209720Srpaulo if (argno < 6) 275209720Srpaulo return ((&rp->r_rdi)[argno]); 276209720Srpaulo 277211744Srpaulo stack = (uintptr_t *)rp->r_rsp; 278209720Srpaulo DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 279209720Srpaulo value = dtrace_fulword(&stack[argno - 6 + shift]); 280209720Srpaulo DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR); 281209720Srpaulo } else { 282209720Srpaulo#endif 283211744Srpaulo#ifdef __i386 284211744Srpaulo uint32_t *stack = (uint32_t *)rp->r_esp; 285209720Srpaulo DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 286209720Srpaulo value = dtrace_fuword32(&stack[argno + shift]); 287209720Srpaulo DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | CPU_DTRACE_BADADDR); 288211744Srpaulo#endif 289209720Srpaulo#ifdef __amd64 290209720Srpaulo } 291209720Srpaulo#endif 292209720Srpaulo 293209720Srpaulo return (value); 294209720Srpaulo} 295209720Srpaulo 296209720Srpaulo/*ARGSUSED*/ 297209720Srpauloint 298209720Srpaulofasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc, 299209720Srpaulo fasttrap_probe_type_t type) 300209720Srpaulo{ 301209720Srpaulo uint8_t instr[FASTTRAP_MAX_INSTR_SIZE + 10]; 302209720Srpaulo size_t len = FASTTRAP_MAX_INSTR_SIZE; 303209720Srpaulo size_t first = MIN(len, PAGESIZE - (pc & PAGEOFFSET)); 304209720Srpaulo uint_t start = 0; 305209720Srpaulo int rmindex, size; 306209720Srpaulo uint8_t seg, rex = 0; 307209720Srpaulo 308209720Srpaulo /* 309209720Srpaulo * Read the instruction at the given address out of the process's 310209720Srpaulo * address space. We don't have to worry about a debugger 311209720Srpaulo * changing this instruction before we overwrite it with our trap 312209720Srpaulo * instruction since P_PR_LOCK is set. Since instructions can span 313209720Srpaulo * pages, we potentially read the instruction in two parts. If the 314209720Srpaulo * second part fails, we just zero out that part of the instruction. 315209720Srpaulo */ 316209720Srpaulo if (uread(p, &instr[0], first, pc) != 0) 317209720Srpaulo return (-1); 318209720Srpaulo if (len > first && 319209720Srpaulo uread(p, &instr[first], len - first, pc + first) != 0) { 320209720Srpaulo bzero(&instr[first], len - first); 321209720Srpaulo len = first; 322209720Srpaulo } 323209720Srpaulo 324209720Srpaulo /* 325209720Srpaulo * If the disassembly fails, then we have a malformed instruction. 326209720Srpaulo */ 327209720Srpaulo if ((size = dtrace_instr_size_isa(instr, p->p_model, &rmindex)) <= 0) 328209720Srpaulo return (-1); 329209720Srpaulo 330209720Srpaulo /* 331209720Srpaulo * Make sure the disassembler isn't completely broken. 332209720Srpaulo */ 333209720Srpaulo ASSERT(-1 <= rmindex && rmindex < size); 334209720Srpaulo 335209720Srpaulo /* 336209720Srpaulo * If the computed size is greater than the number of bytes read, 337209720Srpaulo * then it was a malformed instruction possibly because it fell on a 338209720Srpaulo * page boundary and the subsequent page was missing or because of 339209720Srpaulo * some malicious user. 340209720Srpaulo */ 341209720Srpaulo if (size > len) 342209720Srpaulo return (-1); 343209720Srpaulo 344209720Srpaulo tp->ftt_size = (uint8_t)size; 345209720Srpaulo tp->ftt_segment = FASTTRAP_SEG_NONE; 346209720Srpaulo 347209720Srpaulo /* 348209720Srpaulo * Find the start of the instruction's opcode by processing any 349209720Srpaulo * legacy prefixes. 350209720Srpaulo */ 351209720Srpaulo for (;;) { 352209720Srpaulo seg = 0; 353209720Srpaulo switch (instr[start]) { 354209720Srpaulo case FASTTRAP_PREFIX_SS: 355209720Srpaulo seg++; 356209720Srpaulo /*FALLTHRU*/ 357209720Srpaulo case FASTTRAP_PREFIX_GS: 358209720Srpaulo seg++; 359209720Srpaulo /*FALLTHRU*/ 360209720Srpaulo case FASTTRAP_PREFIX_FS: 361209720Srpaulo seg++; 362209720Srpaulo /*FALLTHRU*/ 363209720Srpaulo case FASTTRAP_PREFIX_ES: 364209720Srpaulo seg++; 365209720Srpaulo /*FALLTHRU*/ 366209720Srpaulo case FASTTRAP_PREFIX_DS: 367209720Srpaulo seg++; 368209720Srpaulo /*FALLTHRU*/ 369209720Srpaulo case FASTTRAP_PREFIX_CS: 370209720Srpaulo seg++; 371209720Srpaulo /*FALLTHRU*/ 372209720Srpaulo case FASTTRAP_PREFIX_OPERAND: 373209720Srpaulo case FASTTRAP_PREFIX_ADDRESS: 374209720Srpaulo case FASTTRAP_PREFIX_LOCK: 375209720Srpaulo case FASTTRAP_PREFIX_REP: 376209720Srpaulo case FASTTRAP_PREFIX_REPNE: 377209720Srpaulo if (seg != 0) { 378209720Srpaulo /* 379209720Srpaulo * It's illegal for an instruction to specify 380209720Srpaulo * two segment prefixes -- give up on this 381209720Srpaulo * illegal instruction. 382209720Srpaulo */ 383209720Srpaulo if (tp->ftt_segment != FASTTRAP_SEG_NONE) 384209720Srpaulo return (-1); 385209720Srpaulo 386209720Srpaulo tp->ftt_segment = seg; 387209720Srpaulo } 388209720Srpaulo start++; 389209720Srpaulo continue; 390209720Srpaulo } 391209720Srpaulo break; 392209720Srpaulo } 393209720Srpaulo 394209720Srpaulo#ifdef __amd64 395209720Srpaulo /* 396209720Srpaulo * Identify the REX prefix on 64-bit processes. 397209720Srpaulo */ 398209720Srpaulo if (p->p_model == DATAMODEL_LP64 && (instr[start] & 0xf0) == 0x40) 399209720Srpaulo rex = instr[start++]; 400209720Srpaulo#endif 401209720Srpaulo 402209720Srpaulo /* 403209720Srpaulo * Now that we're pretty sure that the instruction is okay, copy the 404209720Srpaulo * valid part to the tracepoint. 405209720Srpaulo */ 406209720Srpaulo bcopy(instr, tp->ftt_instr, FASTTRAP_MAX_INSTR_SIZE); 407209720Srpaulo 408209720Srpaulo tp->ftt_type = FASTTRAP_T_COMMON; 409209720Srpaulo if (instr[start] == FASTTRAP_2_BYTE_OP) { 410209720Srpaulo switch (instr[start + 1]) { 411209720Srpaulo case FASTTRAP_0F_JO: 412209720Srpaulo case FASTTRAP_0F_JNO: 413209720Srpaulo case FASTTRAP_0F_JB: 414209720Srpaulo case FASTTRAP_0F_JAE: 415209720Srpaulo case FASTTRAP_0F_JE: 416209720Srpaulo case FASTTRAP_0F_JNE: 417209720Srpaulo case FASTTRAP_0F_JBE: 418209720Srpaulo case FASTTRAP_0F_JA: 419209720Srpaulo case FASTTRAP_0F_JS: 420209720Srpaulo case FASTTRAP_0F_JNS: 421209720Srpaulo case FASTTRAP_0F_JP: 422209720Srpaulo case FASTTRAP_0F_JNP: 423209720Srpaulo case FASTTRAP_0F_JL: 424209720Srpaulo case FASTTRAP_0F_JGE: 425209720Srpaulo case FASTTRAP_0F_JLE: 426209720Srpaulo case FASTTRAP_0F_JG: 427209720Srpaulo tp->ftt_type = FASTTRAP_T_JCC; 428209720Srpaulo tp->ftt_code = (instr[start + 1] & 0x0f) | FASTTRAP_JO; 429209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 430209720Srpaulo /* LINTED - alignment */ 431209720Srpaulo *(int32_t *)&instr[start + 2]; 432209720Srpaulo break; 433209720Srpaulo } 434209720Srpaulo } else if (instr[start] == FASTTRAP_GROUP5_OP) { 435209720Srpaulo uint_t mod = FASTTRAP_MODRM_MOD(instr[start + 1]); 436209720Srpaulo uint_t reg = FASTTRAP_MODRM_REG(instr[start + 1]); 437209720Srpaulo uint_t rm = FASTTRAP_MODRM_RM(instr[start + 1]); 438209720Srpaulo 439209720Srpaulo if (reg == 2 || reg == 4) { 440209720Srpaulo uint_t i, sz; 441209720Srpaulo 442209720Srpaulo if (reg == 2) 443209720Srpaulo tp->ftt_type = FASTTRAP_T_CALL; 444209720Srpaulo else 445209720Srpaulo tp->ftt_type = FASTTRAP_T_JMP; 446209720Srpaulo 447209720Srpaulo if (mod == 3) 448209720Srpaulo tp->ftt_code = 2; 449209720Srpaulo else 450209720Srpaulo tp->ftt_code = 1; 451209720Srpaulo 452209720Srpaulo ASSERT(p->p_model == DATAMODEL_LP64 || rex == 0); 453209720Srpaulo 454209720Srpaulo /* 455209720Srpaulo * See AMD x86-64 Architecture Programmer's Manual 456209720Srpaulo * Volume 3, Section 1.2.7, Table 1-12, and 457209720Srpaulo * Appendix A.3.1, Table A-15. 458209720Srpaulo */ 459209720Srpaulo if (mod != 3 && rm == 4) { 460209720Srpaulo uint8_t sib = instr[start + 2]; 461209720Srpaulo uint_t index = FASTTRAP_SIB_INDEX(sib); 462209720Srpaulo uint_t base = FASTTRAP_SIB_BASE(sib); 463209720Srpaulo 464209720Srpaulo tp->ftt_scale = FASTTRAP_SIB_SCALE(sib); 465209720Srpaulo 466209720Srpaulo tp->ftt_index = (index == 4) ? 467209720Srpaulo FASTTRAP_NOREG : 468209720Srpaulo regmap[index | (FASTTRAP_REX_X(rex) << 3)]; 469209720Srpaulo tp->ftt_base = (mod == 0 && base == 5) ? 470209720Srpaulo FASTTRAP_NOREG : 471209720Srpaulo regmap[base | (FASTTRAP_REX_B(rex) << 3)]; 472209720Srpaulo 473209720Srpaulo i = 3; 474209720Srpaulo sz = mod == 1 ? 1 : 4; 475209720Srpaulo } else { 476209720Srpaulo /* 477209720Srpaulo * In 64-bit mode, mod == 0 and r/m == 5 478209720Srpaulo * denotes %rip-relative addressing; in 32-bit 479209720Srpaulo * mode, the base register isn't used. In both 480209720Srpaulo * modes, there is a 32-bit operand. 481209720Srpaulo */ 482209720Srpaulo if (mod == 0 && rm == 5) { 483209720Srpaulo#ifdef __amd64 484209720Srpaulo if (p->p_model == DATAMODEL_LP64) 485209720Srpaulo tp->ftt_base = REG_RIP; 486209720Srpaulo else 487209720Srpaulo#endif 488209720Srpaulo tp->ftt_base = FASTTRAP_NOREG; 489209720Srpaulo sz = 4; 490209720Srpaulo } else { 491209720Srpaulo uint8_t base = rm | 492209720Srpaulo (FASTTRAP_REX_B(rex) << 3); 493209720Srpaulo 494209720Srpaulo tp->ftt_base = regmap[base]; 495209720Srpaulo sz = mod == 1 ? 1 : mod == 2 ? 4 : 0; 496209720Srpaulo } 497209720Srpaulo tp->ftt_index = FASTTRAP_NOREG; 498209720Srpaulo i = 2; 499209720Srpaulo } 500209720Srpaulo 501209720Srpaulo if (sz == 1) { 502209720Srpaulo tp->ftt_dest = *(int8_t *)&instr[start + i]; 503209720Srpaulo } else if (sz == 4) { 504209720Srpaulo /* LINTED - alignment */ 505209720Srpaulo tp->ftt_dest = *(int32_t *)&instr[start + i]; 506209720Srpaulo } else { 507209720Srpaulo tp->ftt_dest = 0; 508209720Srpaulo } 509209720Srpaulo } 510209720Srpaulo } else { 511209720Srpaulo switch (instr[start]) { 512209720Srpaulo case FASTTRAP_RET: 513209720Srpaulo tp->ftt_type = FASTTRAP_T_RET; 514209720Srpaulo break; 515209720Srpaulo 516209720Srpaulo case FASTTRAP_RET16: 517209720Srpaulo tp->ftt_type = FASTTRAP_T_RET16; 518209720Srpaulo /* LINTED - alignment */ 519209720Srpaulo tp->ftt_dest = *(uint16_t *)&instr[start + 1]; 520209720Srpaulo break; 521209720Srpaulo 522209720Srpaulo case FASTTRAP_JO: 523209720Srpaulo case FASTTRAP_JNO: 524209720Srpaulo case FASTTRAP_JB: 525209720Srpaulo case FASTTRAP_JAE: 526209720Srpaulo case FASTTRAP_JE: 527209720Srpaulo case FASTTRAP_JNE: 528209720Srpaulo case FASTTRAP_JBE: 529209720Srpaulo case FASTTRAP_JA: 530209720Srpaulo case FASTTRAP_JS: 531209720Srpaulo case FASTTRAP_JNS: 532209720Srpaulo case FASTTRAP_JP: 533209720Srpaulo case FASTTRAP_JNP: 534209720Srpaulo case FASTTRAP_JL: 535209720Srpaulo case FASTTRAP_JGE: 536209720Srpaulo case FASTTRAP_JLE: 537209720Srpaulo case FASTTRAP_JG: 538209720Srpaulo tp->ftt_type = FASTTRAP_T_JCC; 539209720Srpaulo tp->ftt_code = instr[start]; 540209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 541209720Srpaulo (int8_t)instr[start + 1]; 542209720Srpaulo break; 543209720Srpaulo 544209720Srpaulo case FASTTRAP_LOOPNZ: 545209720Srpaulo case FASTTRAP_LOOPZ: 546209720Srpaulo case FASTTRAP_LOOP: 547209720Srpaulo tp->ftt_type = FASTTRAP_T_LOOP; 548209720Srpaulo tp->ftt_code = instr[start]; 549209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 550209720Srpaulo (int8_t)instr[start + 1]; 551209720Srpaulo break; 552209720Srpaulo 553209720Srpaulo case FASTTRAP_JCXZ: 554209720Srpaulo tp->ftt_type = FASTTRAP_T_JCXZ; 555209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 556209720Srpaulo (int8_t)instr[start + 1]; 557209720Srpaulo break; 558209720Srpaulo 559209720Srpaulo case FASTTRAP_CALL: 560209720Srpaulo tp->ftt_type = FASTTRAP_T_CALL; 561209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 562209720Srpaulo /* LINTED - alignment */ 563209720Srpaulo *(int32_t *)&instr[start + 1]; 564209720Srpaulo tp->ftt_code = 0; 565209720Srpaulo break; 566209720Srpaulo 567209720Srpaulo case FASTTRAP_JMP32: 568209720Srpaulo tp->ftt_type = FASTTRAP_T_JMP; 569209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 570209720Srpaulo /* LINTED - alignment */ 571209720Srpaulo *(int32_t *)&instr[start + 1]; 572209720Srpaulo break; 573209720Srpaulo case FASTTRAP_JMP8: 574209720Srpaulo tp->ftt_type = FASTTRAP_T_JMP; 575209720Srpaulo tp->ftt_dest = pc + tp->ftt_size + 576209720Srpaulo (int8_t)instr[start + 1]; 577209720Srpaulo break; 578209720Srpaulo 579209720Srpaulo case FASTTRAP_PUSHL_EBP: 580209720Srpaulo if (start == 0) 581209720Srpaulo tp->ftt_type = FASTTRAP_T_PUSHL_EBP; 582209720Srpaulo break; 583209720Srpaulo 584209720Srpaulo case FASTTRAP_NOP: 585209720Srpaulo#ifdef __amd64 586209720Srpaulo ASSERT(p->p_model == DATAMODEL_LP64 || rex == 0); 587209720Srpaulo 588209720Srpaulo /* 589209720Srpaulo * On amd64 we have to be careful not to confuse a nop 590209720Srpaulo * (actually xchgl %eax, %eax) with an instruction using 591209720Srpaulo * the same opcode, but that does something different 592209720Srpaulo * (e.g. xchgl %r8d, %eax or xcghq %r8, %rax). 593209720Srpaulo */ 594209720Srpaulo if (FASTTRAP_REX_B(rex) == 0) 595209720Srpaulo#endif 596209720Srpaulo tp->ftt_type = FASTTRAP_T_NOP; 597209720Srpaulo break; 598209720Srpaulo 599209720Srpaulo case FASTTRAP_INT3: 600209720Srpaulo /* 601209720Srpaulo * The pid provider shares the int3 trap with debugger 602209720Srpaulo * breakpoints so we can't instrument them. 603209720Srpaulo */ 604209720Srpaulo ASSERT(instr[start] == FASTTRAP_INSTR); 605209720Srpaulo return (-1); 606209720Srpaulo 607209720Srpaulo case FASTTRAP_INT: 608209720Srpaulo /* 609209720Srpaulo * Interrupts seem like they could be traced with 610209720Srpaulo * no negative implications, but it's possible that 611209720Srpaulo * a thread could be redirected by the trap handling 612209720Srpaulo * code which would eventually return to the 613209720Srpaulo * instruction after the interrupt. If the interrupt 614209720Srpaulo * were in our scratch space, the subsequent 615209720Srpaulo * instruction might be overwritten before we return. 616209720Srpaulo * Accordingly we refuse to instrument any interrupt. 617209720Srpaulo */ 618209720Srpaulo return (-1); 619209720Srpaulo } 620209720Srpaulo } 621209720Srpaulo 622209720Srpaulo#ifdef __amd64 623209720Srpaulo if (p->p_model == DATAMODEL_LP64 && tp->ftt_type == FASTTRAP_T_COMMON) { 624209720Srpaulo /* 625209720Srpaulo * If the process is 64-bit and the instruction type is still 626209720Srpaulo * FASTTRAP_T_COMMON -- meaning we're going to copy it out an 627209720Srpaulo * execute it -- we need to watch for %rip-relative 628209720Srpaulo * addressing mode. See the portion of fasttrap_pid_probe() 629209720Srpaulo * below where we handle tracepoints with type 630209720Srpaulo * FASTTRAP_T_COMMON for how we emulate instructions that 631209720Srpaulo * employ %rip-relative addressing. 632209720Srpaulo */ 633209720Srpaulo if (rmindex != -1) { 634209720Srpaulo uint_t mod = FASTTRAP_MODRM_MOD(instr[rmindex]); 635209720Srpaulo uint_t reg = FASTTRAP_MODRM_REG(instr[rmindex]); 636209720Srpaulo uint_t rm = FASTTRAP_MODRM_RM(instr[rmindex]); 637209720Srpaulo 638209720Srpaulo ASSERT(rmindex > start); 639209720Srpaulo 640209720Srpaulo if (mod == 0 && rm == 5) { 641209720Srpaulo /* 642209720Srpaulo * We need to be sure to avoid other 643209720Srpaulo * registers used by this instruction. While 644209720Srpaulo * the reg field may determine the op code 645209720Srpaulo * rather than denoting a register, assuming 646209720Srpaulo * that it denotes a register is always safe. 647209720Srpaulo * We leave the REX field intact and use 648209720Srpaulo * whatever value's there for simplicity. 649209720Srpaulo */ 650209720Srpaulo if (reg != 0) { 651209720Srpaulo tp->ftt_ripmode = FASTTRAP_RIP_1 | 652209720Srpaulo (FASTTRAP_RIP_X * 653209720Srpaulo FASTTRAP_REX_B(rex)); 654209720Srpaulo rm = 0; 655209720Srpaulo } else { 656209720Srpaulo tp->ftt_ripmode = FASTTRAP_RIP_2 | 657209720Srpaulo (FASTTRAP_RIP_X * 658209720Srpaulo FASTTRAP_REX_B(rex)); 659209720Srpaulo rm = 1; 660209720Srpaulo } 661209720Srpaulo 662209720Srpaulo tp->ftt_modrm = tp->ftt_instr[rmindex]; 663209720Srpaulo tp->ftt_instr[rmindex] = 664209720Srpaulo FASTTRAP_MODRM(2, reg, rm); 665209720Srpaulo } 666209720Srpaulo } 667209720Srpaulo } 668209720Srpaulo#endif 669209720Srpaulo 670209720Srpaulo return (0); 671209720Srpaulo} 672209720Srpaulo 673209720Srpauloint 674209720Srpaulofasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp) 675209720Srpaulo{ 676209720Srpaulo fasttrap_instr_t instr = FASTTRAP_INSTR; 677209720Srpaulo 678209720Srpaulo if (uwrite(p, &instr, 1, tp->ftt_pc) != 0) 679209720Srpaulo return (-1); 680209720Srpaulo 681209720Srpaulo return (0); 682209720Srpaulo} 683209720Srpaulo 684209720Srpauloint 685209720Srpaulofasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp) 686209720Srpaulo{ 687209720Srpaulo uint8_t instr; 688209720Srpaulo 689209720Srpaulo /* 690209720Srpaulo * Distinguish between read or write failures and a changed 691209720Srpaulo * instruction. 692209720Srpaulo */ 693209720Srpaulo if (uread(p, &instr, 1, tp->ftt_pc) != 0) 694209720Srpaulo return (0); 695209720Srpaulo if (instr != FASTTRAP_INSTR) 696209720Srpaulo return (0); 697209720Srpaulo if (uwrite(p, &tp->ftt_instr[0], 1, tp->ftt_pc) != 0) 698209720Srpaulo return (-1); 699209720Srpaulo 700209720Srpaulo return (0); 701209720Srpaulo} 702209720Srpaulo 703209720Srpaulo#ifdef __amd64 704209720Srpaulostatic uintptr_t 705209720Srpaulofasttrap_fulword_noerr(const void *uaddr) 706209720Srpaulo{ 707209720Srpaulo uintptr_t ret; 708209720Srpaulo 709211744Srpaulo if ((ret = fasttrap_fulword(uaddr)) != -1) 710209720Srpaulo return (ret); 711209720Srpaulo 712209720Srpaulo return (0); 713209720Srpaulo} 714209720Srpaulo#endif 715209720Srpaulo 716211744Srpaulo#ifdef __i386__ 717209720Srpaulostatic uint32_t 718209720Srpaulofasttrap_fuword32_noerr(const void *uaddr) 719209720Srpaulo{ 720209720Srpaulo uint32_t ret; 721209720Srpaulo 722211744Srpaulo if ((ret = fasttrap_fuword32(uaddr)) != -1) 723209720Srpaulo return (ret); 724209720Srpaulo 725209720Srpaulo return (0); 726209720Srpaulo} 727211744Srpaulo#endif 728209720Srpaulo 729209720Srpaulostatic void 730211744Srpaulofasttrap_return_common(struct reg *rp, uintptr_t pc, pid_t pid, 731209720Srpaulo uintptr_t new_pc) 732209720Srpaulo{ 733209720Srpaulo fasttrap_tracepoint_t *tp; 734209720Srpaulo fasttrap_bucket_t *bucket; 735209720Srpaulo fasttrap_id_t *id; 736211744Srpaulo#if defined(sun) 737209720Srpaulo kmutex_t *pid_mtx; 738211744Srpaulo#endif 739209720Srpaulo 740211744Srpaulo#if defined(sun) 741209720Srpaulo pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; 742209720Srpaulo mutex_enter(pid_mtx); 743211744Srpaulo#endif 744209720Srpaulo bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 745209720Srpaulo 746209720Srpaulo for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 747209720Srpaulo if (pid == tp->ftt_pid && pc == tp->ftt_pc && 748209720Srpaulo tp->ftt_proc->ftpc_acount != 0) 749209720Srpaulo break; 750209720Srpaulo } 751209720Srpaulo 752209720Srpaulo /* 753209720Srpaulo * Don't sweat it if we can't find the tracepoint again; unlike 754209720Srpaulo * when we're in fasttrap_pid_probe(), finding the tracepoint here 755209720Srpaulo * is not essential to the correct execution of the process. 756209720Srpaulo */ 757209720Srpaulo if (tp == NULL) { 758211744Srpaulo#if defined(sun) 759209720Srpaulo mutex_exit(pid_mtx); 760211744Srpaulo#endif 761209720Srpaulo return; 762209720Srpaulo } 763209720Srpaulo 764209720Srpaulo for (id = tp->ftt_retids; id != NULL; id = id->fti_next) { 765209720Srpaulo /* 766209720Srpaulo * If there's a branch that could act as a return site, we 767209720Srpaulo * need to trace it, and check here if the program counter is 768209720Srpaulo * external to the function. 769209720Srpaulo */ 770209720Srpaulo if (tp->ftt_type != FASTTRAP_T_RET && 771209720Srpaulo tp->ftt_type != FASTTRAP_T_RET16 && 772209720Srpaulo new_pc - id->fti_probe->ftp_faddr < 773209720Srpaulo id->fti_probe->ftp_fsize) 774209720Srpaulo continue; 775209720Srpaulo 776209720Srpaulo dtrace_probe(id->fti_probe->ftp_id, 777209720Srpaulo pc - id->fti_probe->ftp_faddr, 778211744Srpaulo rp->r_rax, rp->r_rbx, 0, 0); 779209720Srpaulo } 780209720Srpaulo 781211744Srpaulo#if defined(sun) 782209720Srpaulo mutex_exit(pid_mtx); 783211744Srpaulo#endif 784209720Srpaulo} 785209720Srpaulo 786209720Srpaulostatic void 787209720Srpaulofasttrap_sigsegv(proc_t *p, kthread_t *t, uintptr_t addr) 788209720Srpaulo{ 789211744Srpaulo#if defined(sun) 790209720Srpaulo sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP); 791209720Srpaulo 792209720Srpaulo sqp->sq_info.si_signo = SIGSEGV; 793209720Srpaulo sqp->sq_info.si_code = SEGV_MAPERR; 794209720Srpaulo sqp->sq_info.si_addr = (caddr_t)addr; 795209720Srpaulo 796209720Srpaulo mutex_enter(&p->p_lock); 797209720Srpaulo sigaddqa(p, t, sqp); 798209720Srpaulo mutex_exit(&p->p_lock); 799209720Srpaulo 800209720Srpaulo if (t != NULL) 801209720Srpaulo aston(t); 802211744Srpaulo#else 803211744Srpaulo ksiginfo_t *ksi = kmem_zalloc(sizeof (ksiginfo_t), KM_SLEEP); 804211744Srpaulo 805211744Srpaulo ksiginfo_init(ksi); 806211744Srpaulo ksi->ksi_signo = SIGSEGV; 807211744Srpaulo ksi->ksi_code = SEGV_MAPERR; 808211744Srpaulo ksi->ksi_addr = (caddr_t)addr; 809211744Srpaulo (void) tdksignal(t, SIGSEGV, ksi); 810211744Srpaulo#endif 811209720Srpaulo} 812209720Srpaulo 813209720Srpaulo#ifdef __amd64 814209720Srpaulostatic void 815211744Srpaulofasttrap_usdt_args64(fasttrap_probe_t *probe, struct reg *rp, int argc, 816209720Srpaulo uintptr_t *argv) 817209720Srpaulo{ 818209720Srpaulo int i, x, cap = MIN(argc, probe->ftp_nargs); 819211744Srpaulo uintptr_t *stack = (uintptr_t *)rp->r_rsp; 820209720Srpaulo 821209720Srpaulo for (i = 0; i < cap; i++) { 822209720Srpaulo x = probe->ftp_argmap[i]; 823209720Srpaulo 824209720Srpaulo if (x < 6) 825209720Srpaulo argv[i] = (&rp->r_rdi)[x]; 826209720Srpaulo else 827209720Srpaulo argv[i] = fasttrap_fulword_noerr(&stack[x]); 828209720Srpaulo } 829209720Srpaulo 830209720Srpaulo for (; i < argc; i++) { 831209720Srpaulo argv[i] = 0; 832209720Srpaulo } 833209720Srpaulo} 834209720Srpaulo#endif 835209720Srpaulo 836211744Srpaulo#ifdef __i386__ 837209720Srpaulostatic void 838211744Srpaulofasttrap_usdt_args32(fasttrap_probe_t *probe, struct reg *rp, int argc, 839209720Srpaulo uint32_t *argv) 840209720Srpaulo{ 841209720Srpaulo int i, x, cap = MIN(argc, probe->ftp_nargs); 842211744Srpaulo uint32_t *stack = (uint32_t *)rp->r_rsp; 843209720Srpaulo 844209720Srpaulo for (i = 0; i < cap; i++) { 845209720Srpaulo x = probe->ftp_argmap[i]; 846209720Srpaulo 847209720Srpaulo argv[i] = fasttrap_fuword32_noerr(&stack[x]); 848209720Srpaulo } 849209720Srpaulo 850209720Srpaulo for (; i < argc; i++) { 851209720Srpaulo argv[i] = 0; 852209720Srpaulo } 853209720Srpaulo} 854211744Srpaulo#endif 855209720Srpaulo 856209720Srpaulostatic int 857211744Srpaulofasttrap_do_seg(fasttrap_tracepoint_t *tp, struct reg *rp, uintptr_t *addr) 858209720Srpaulo{ 859209720Srpaulo proc_t *p = curproc; 860211744Srpaulo#ifdef __i386__ 861211744Srpaulo struct segment_descriptor *desc; 862211744Srpaulo#else 863211744Srpaulo struct user_segment_descriptor *desc; 864211744Srpaulo#endif 865211744Srpaulo uint16_t sel = 0, ndx, type; 866209720Srpaulo uintptr_t limit; 867209720Srpaulo 868209720Srpaulo switch (tp->ftt_segment) { 869209720Srpaulo case FASTTRAP_SEG_CS: 870209720Srpaulo sel = rp->r_cs; 871209720Srpaulo break; 872209720Srpaulo case FASTTRAP_SEG_DS: 873209720Srpaulo sel = rp->r_ds; 874209720Srpaulo break; 875209720Srpaulo case FASTTRAP_SEG_ES: 876209720Srpaulo sel = rp->r_es; 877209720Srpaulo break; 878209720Srpaulo case FASTTRAP_SEG_FS: 879209720Srpaulo sel = rp->r_fs; 880209720Srpaulo break; 881209720Srpaulo case FASTTRAP_SEG_GS: 882209720Srpaulo sel = rp->r_gs; 883209720Srpaulo break; 884209720Srpaulo case FASTTRAP_SEG_SS: 885209720Srpaulo sel = rp->r_ss; 886209720Srpaulo break; 887209720Srpaulo } 888209720Srpaulo 889209720Srpaulo /* 890209720Srpaulo * Make sure the given segment register specifies a user priority 891209720Srpaulo * selector rather than a kernel selector. 892209720Srpaulo */ 893211744Srpaulo if (ISPL(sel) != SEL_UPL) 894209720Srpaulo return (-1); 895209720Srpaulo 896211744Srpaulo ndx = IDXSEL(sel); 897209720Srpaulo 898209720Srpaulo /* 899209720Srpaulo * Check the bounds and grab the descriptor out of the specified 900209720Srpaulo * descriptor table. 901209720Srpaulo */ 902211744Srpaulo if (ISLDT(sel)) { 903211744Srpaulo#ifdef __i386__ 904211744Srpaulo if (ndx > p->p_md.md_ldt->ldt_len) 905209720Srpaulo return (-1); 906209720Srpaulo 907211744Srpaulo desc = (struct segment_descriptor *) 908211744Srpaulo p->p_md.md_ldt[ndx].ldt_base; 909211744Srpaulo#else 910211744Srpaulo if (ndx > max_ldt_segment) 911211744Srpaulo return (-1); 912209720Srpaulo 913211744Srpaulo desc = (struct user_segment_descriptor *) 914211744Srpaulo p->p_md.md_ldt[ndx].ldt_base; 915211744Srpaulo#endif 916211744Srpaulo 917209720Srpaulo } else { 918209720Srpaulo if (ndx >= NGDT) 919209720Srpaulo return (-1); 920209720Srpaulo 921211744Srpaulo#ifdef __i386__ 922211744Srpaulo desc = &gdt[ndx].sd; 923211744Srpaulo#else 924211744Srpaulo desc = &gdt[ndx]; 925211744Srpaulo#endif 926209720Srpaulo } 927209720Srpaulo 928209720Srpaulo /* 929209720Srpaulo * The descriptor must have user privilege level and it must be 930209720Srpaulo * present in memory. 931209720Srpaulo */ 932211744Srpaulo if (desc->sd_dpl != SEL_UPL || desc->sd_p != 1) 933209720Srpaulo return (-1); 934209720Srpaulo 935211744Srpaulo type = desc->sd_type; 936209720Srpaulo 937209720Srpaulo /* 938209720Srpaulo * If the S bit in the type field is not set, this descriptor can 939209720Srpaulo * only be used in system context. 940209720Srpaulo */ 941209720Srpaulo if ((type & 0x10) != 0x10) 942209720Srpaulo return (-1); 943209720Srpaulo 944211744Srpaulo limit = USD_GETLIMIT(desc) * (desc->sd_gran ? PAGESIZE : 1); 945209720Srpaulo 946209720Srpaulo if (tp->ftt_segment == FASTTRAP_SEG_CS) { 947209720Srpaulo /* 948209720Srpaulo * The code/data bit and readable bit must both be set. 949209720Srpaulo */ 950209720Srpaulo if ((type & 0xa) != 0xa) 951209720Srpaulo return (-1); 952209720Srpaulo 953209720Srpaulo if (*addr > limit) 954209720Srpaulo return (-1); 955209720Srpaulo } else { 956209720Srpaulo /* 957209720Srpaulo * The code/data bit must be clear. 958209720Srpaulo */ 959209720Srpaulo if ((type & 0x8) != 0) 960209720Srpaulo return (-1); 961209720Srpaulo 962209720Srpaulo /* 963209720Srpaulo * If the expand-down bit is clear, we just check the limit as 964209720Srpaulo * it would naturally be applied. Otherwise, we need to check 965209720Srpaulo * that the address is the range [limit + 1 .. 0xffff] or 966209720Srpaulo * [limit + 1 ... 0xffffffff] depending on if the default 967209720Srpaulo * operand size bit is set. 968209720Srpaulo */ 969209720Srpaulo if ((type & 0x4) == 0) { 970209720Srpaulo if (*addr > limit) 971209720Srpaulo return (-1); 972211744Srpaulo } else if (desc->sd_def32) { 973209720Srpaulo if (*addr < limit + 1 || 0xffff < *addr) 974209720Srpaulo return (-1); 975209720Srpaulo } else { 976209720Srpaulo if (*addr < limit + 1 || 0xffffffff < *addr) 977209720Srpaulo return (-1); 978209720Srpaulo } 979209720Srpaulo } 980209720Srpaulo 981211744Srpaulo *addr += USD_GETBASE(desc); 982209720Srpaulo 983209720Srpaulo return (0); 984209720Srpaulo} 985209720Srpaulo 986209720Srpauloint 987211744Srpaulofasttrap_pid_probe(struct reg *rp) 988209720Srpaulo{ 989209720Srpaulo proc_t *p = curproc; 990211744Srpaulo uintptr_t pc = rp->r_rip - 1; 991211744Srpaulo uintptr_t new_pc = 0; 992209720Srpaulo fasttrap_bucket_t *bucket; 993211744Srpaulo#if defined(sun) 994209720Srpaulo kmutex_t *pid_mtx; 995211744Srpaulo#endif 996209720Srpaulo fasttrap_tracepoint_t *tp, tp_local; 997209720Srpaulo pid_t pid; 998209720Srpaulo dtrace_icookie_t cookie; 999209720Srpaulo uint_t is_enabled = 0; 1000209720Srpaulo 1001209720Srpaulo /* 1002209720Srpaulo * It's possible that a user (in a veritable orgy of bad planning) 1003209720Srpaulo * could redirect this thread's flow of control before it reached the 1004209720Srpaulo * return probe fasttrap. In this case we need to kill the process 1005209720Srpaulo * since it's in a unrecoverable state. 1006209720Srpaulo */ 1007209720Srpaulo if (curthread->t_dtrace_step) { 1008209720Srpaulo ASSERT(curthread->t_dtrace_on); 1009209720Srpaulo fasttrap_sigtrap(p, curthread, pc); 1010209720Srpaulo return (0); 1011209720Srpaulo } 1012209720Srpaulo 1013209720Srpaulo /* 1014209720Srpaulo * Clear all user tracing flags. 1015209720Srpaulo */ 1016209720Srpaulo curthread->t_dtrace_ft = 0; 1017209720Srpaulo curthread->t_dtrace_pc = 0; 1018209720Srpaulo curthread->t_dtrace_npc = 0; 1019209720Srpaulo curthread->t_dtrace_scrpc = 0; 1020209720Srpaulo curthread->t_dtrace_astpc = 0; 1021209720Srpaulo#ifdef __amd64 1022209720Srpaulo curthread->t_dtrace_regv = 0; 1023209720Srpaulo#endif 1024209720Srpaulo 1025211744Srpaulo#if defined(sun) 1026209720Srpaulo /* 1027209720Srpaulo * Treat a child created by a call to vfork(2) as if it were its 1028209720Srpaulo * parent. We know that there's only one thread of control in such a 1029209720Srpaulo * process: this one. 1030209720Srpaulo */ 1031209720Srpaulo while (p->p_flag & SVFORK) { 1032209720Srpaulo p = p->p_parent; 1033209720Srpaulo } 1034211744Srpaulo#endif 1035209720Srpaulo 1036211744Srpaulo PROC_LOCK(p); 1037247820Sgibbs _PHOLD(p); 1038209720Srpaulo pid = p->p_pid; 1039211744Srpaulo#if defined(sun) 1040209720Srpaulo pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock; 1041209720Srpaulo mutex_enter(pid_mtx); 1042211744Srpaulo#endif 1043209720Srpaulo bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; 1044209720Srpaulo 1045209720Srpaulo /* 1046209720Srpaulo * Lookup the tracepoint that the process just hit. 1047209720Srpaulo */ 1048209720Srpaulo for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { 1049209720Srpaulo if (pid == tp->ftt_pid && pc == tp->ftt_pc && 1050209720Srpaulo tp->ftt_proc->ftpc_acount != 0) 1051209720Srpaulo break; 1052209720Srpaulo } 1053209720Srpaulo 1054209720Srpaulo /* 1055209720Srpaulo * If we couldn't find a matching tracepoint, either a tracepoint has 1056209720Srpaulo * been inserted without using the pid<pid> ioctl interface (see 1057209720Srpaulo * fasttrap_ioctl), or somehow we have mislaid this tracepoint. 1058209720Srpaulo */ 1059209720Srpaulo if (tp == NULL) { 1060211744Srpaulo#if defined(sun) 1061209720Srpaulo mutex_exit(pid_mtx); 1062211744Srpaulo#endif 1063247820Sgibbs _PRELE(p); 1064211744Srpaulo PROC_UNLOCK(p); 1065209720Srpaulo return (-1); 1066209720Srpaulo } 1067209720Srpaulo 1068209720Srpaulo /* 1069209720Srpaulo * Set the program counter to the address of the traced instruction 1070209720Srpaulo * so that it looks right in ustack() output. 1071209720Srpaulo */ 1072211744Srpaulo rp->r_rip = pc; 1073209720Srpaulo 1074209720Srpaulo if (tp->ftt_ids != NULL) { 1075209720Srpaulo fasttrap_id_t *id; 1076209720Srpaulo 1077209720Srpaulo#ifdef __amd64 1078209720Srpaulo if (p->p_model == DATAMODEL_LP64) { 1079209720Srpaulo for (id = tp->ftt_ids; id != NULL; id = id->fti_next) { 1080209720Srpaulo fasttrap_probe_t *probe = id->fti_probe; 1081209720Srpaulo 1082209720Srpaulo if (id->fti_ptype == DTFTP_ENTRY) { 1083209720Srpaulo /* 1084209720Srpaulo * We note that this was an entry 1085209720Srpaulo * probe to help ustack() find the 1086209720Srpaulo * first caller. 1087209720Srpaulo */ 1088209720Srpaulo cookie = dtrace_interrupt_disable(); 1089209720Srpaulo DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY); 1090209720Srpaulo dtrace_probe(probe->ftp_id, rp->r_rdi, 1091209720Srpaulo rp->r_rsi, rp->r_rdx, rp->r_rcx, 1092209720Srpaulo rp->r_r8); 1093209720Srpaulo DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY); 1094209720Srpaulo dtrace_interrupt_enable(cookie); 1095209720Srpaulo } else if (id->fti_ptype == DTFTP_IS_ENABLED) { 1096209720Srpaulo /* 1097209720Srpaulo * Note that in this case, we don't 1098209720Srpaulo * call dtrace_probe() since it's only 1099209720Srpaulo * an artificial probe meant to change 1100209720Srpaulo * the flow of control so that it 1101209720Srpaulo * encounters the true probe. 1102209720Srpaulo */ 1103209720Srpaulo is_enabled = 1; 1104209720Srpaulo } else if (probe->ftp_argmap == NULL) { 1105209720Srpaulo dtrace_probe(probe->ftp_id, rp->r_rdi, 1106209720Srpaulo rp->r_rsi, rp->r_rdx, rp->r_rcx, 1107209720Srpaulo rp->r_r8); 1108209720Srpaulo } else { 1109209720Srpaulo uintptr_t t[5]; 1110209720Srpaulo 1111209720Srpaulo fasttrap_usdt_args64(probe, rp, 1112209720Srpaulo sizeof (t) / sizeof (t[0]), t); 1113209720Srpaulo 1114209720Srpaulo dtrace_probe(probe->ftp_id, t[0], t[1], 1115209720Srpaulo t[2], t[3], t[4]); 1116209720Srpaulo } 1117209720Srpaulo } 1118209720Srpaulo } else { 1119211744Srpaulo#else /* __amd64 */ 1120209720Srpaulo uintptr_t s0, s1, s2, s3, s4, s5; 1121211744Srpaulo uint32_t *stack = (uint32_t *)rp->r_esp; 1122209720Srpaulo 1123209720Srpaulo /* 1124209720Srpaulo * In 32-bit mode, all arguments are passed on the 1125209720Srpaulo * stack. If this is a function entry probe, we need 1126209720Srpaulo * to skip the first entry on the stack as it 1127209720Srpaulo * represents the return address rather than a 1128209720Srpaulo * parameter to the function. 1129209720Srpaulo */ 1130209720Srpaulo s0 = fasttrap_fuword32_noerr(&stack[0]); 1131209720Srpaulo s1 = fasttrap_fuword32_noerr(&stack[1]); 1132209720Srpaulo s2 = fasttrap_fuword32_noerr(&stack[2]); 1133209720Srpaulo s3 = fasttrap_fuword32_noerr(&stack[3]); 1134209720Srpaulo s4 = fasttrap_fuword32_noerr(&stack[4]); 1135209720Srpaulo s5 = fasttrap_fuword32_noerr(&stack[5]); 1136209720Srpaulo 1137209720Srpaulo for (id = tp->ftt_ids; id != NULL; id = id->fti_next) { 1138209720Srpaulo fasttrap_probe_t *probe = id->fti_probe; 1139209720Srpaulo 1140209720Srpaulo if (id->fti_ptype == DTFTP_ENTRY) { 1141209720Srpaulo /* 1142209720Srpaulo * We note that this was an entry 1143209720Srpaulo * probe to help ustack() find the 1144209720Srpaulo * first caller. 1145209720Srpaulo */ 1146209720Srpaulo cookie = dtrace_interrupt_disable(); 1147209720Srpaulo DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY); 1148209720Srpaulo dtrace_probe(probe->ftp_id, s1, s2, 1149209720Srpaulo s3, s4, s5); 1150209720Srpaulo DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY); 1151209720Srpaulo dtrace_interrupt_enable(cookie); 1152209720Srpaulo } else if (id->fti_ptype == DTFTP_IS_ENABLED) { 1153209720Srpaulo /* 1154209720Srpaulo * Note that in this case, we don't 1155209720Srpaulo * call dtrace_probe() since it's only 1156209720Srpaulo * an artificial probe meant to change 1157209720Srpaulo * the flow of control so that it 1158209720Srpaulo * encounters the true probe. 1159209720Srpaulo */ 1160209720Srpaulo is_enabled = 1; 1161209720Srpaulo } else if (probe->ftp_argmap == NULL) { 1162209720Srpaulo dtrace_probe(probe->ftp_id, s0, s1, 1163209720Srpaulo s2, s3, s4); 1164209720Srpaulo } else { 1165209720Srpaulo uint32_t t[5]; 1166209720Srpaulo 1167209720Srpaulo fasttrap_usdt_args32(probe, rp, 1168209720Srpaulo sizeof (t) / sizeof (t[0]), t); 1169209720Srpaulo 1170209720Srpaulo dtrace_probe(probe->ftp_id, t[0], t[1], 1171209720Srpaulo t[2], t[3], t[4]); 1172209720Srpaulo } 1173209720Srpaulo } 1174211744Srpaulo#endif /* __amd64 */ 1175209720Srpaulo#ifdef __amd64 1176209720Srpaulo } 1177209720Srpaulo#endif 1178209720Srpaulo } 1179209720Srpaulo 1180209720Srpaulo /* 1181209720Srpaulo * We're about to do a bunch of work so we cache a local copy of 1182209720Srpaulo * the tracepoint to emulate the instruction, and then find the 1183209720Srpaulo * tracepoint again later if we need to light up any return probes. 1184209720Srpaulo */ 1185209720Srpaulo tp_local = *tp; 1186211744Srpaulo PROC_UNLOCK(p); 1187211744Srpaulo#if defined(sun) 1188209720Srpaulo mutex_exit(pid_mtx); 1189211744Srpaulo#endif 1190209720Srpaulo tp = &tp_local; 1191209720Srpaulo 1192209720Srpaulo /* 1193209720Srpaulo * Set the program counter to appear as though the traced instruction 1194209720Srpaulo * had completely executed. This ensures that fasttrap_getreg() will 1195209720Srpaulo * report the expected value for REG_RIP. 1196209720Srpaulo */ 1197211744Srpaulo rp->r_rip = pc + tp->ftt_size; 1198209720Srpaulo 1199209720Srpaulo /* 1200209720Srpaulo * If there's an is-enabled probe connected to this tracepoint it 1201209720Srpaulo * means that there was a 'xorl %eax, %eax' or 'xorq %rax, %rax' 1202209720Srpaulo * instruction that was placed there by DTrace when the binary was 1203209720Srpaulo * linked. As this probe is, in fact, enabled, we need to stuff 1 1204209720Srpaulo * into %eax or %rax. Accordingly, we can bypass all the instruction 1205209720Srpaulo * emulation logic since we know the inevitable result. It's possible 1206209720Srpaulo * that a user could construct a scenario where the 'is-enabled' 1207209720Srpaulo * probe was on some other instruction, but that would be a rather 1208209720Srpaulo * exotic way to shoot oneself in the foot. 1209209720Srpaulo */ 1210209720Srpaulo if (is_enabled) { 1211211744Srpaulo rp->r_rax = 1; 1212211744Srpaulo new_pc = rp->r_rip; 1213209720Srpaulo goto done; 1214209720Srpaulo } 1215209720Srpaulo 1216209720Srpaulo /* 1217209720Srpaulo * We emulate certain types of instructions to ensure correctness 1218209720Srpaulo * (in the case of position dependent instructions) or optimize 1219209720Srpaulo * common cases. The rest we have the thread execute back in user- 1220209720Srpaulo * land. 1221209720Srpaulo */ 1222209720Srpaulo switch (tp->ftt_type) { 1223209720Srpaulo case FASTTRAP_T_RET: 1224209720Srpaulo case FASTTRAP_T_RET16: 1225209720Srpaulo { 1226211744Srpaulo uintptr_t dst = 0; 1227211744Srpaulo uintptr_t addr = 0; 1228211744Srpaulo int ret = 0; 1229209720Srpaulo 1230209720Srpaulo /* 1231209720Srpaulo * We have to emulate _every_ facet of the behavior of a ret 1232209720Srpaulo * instruction including what happens if the load from %esp 1233209720Srpaulo * fails; in that case, we send a SIGSEGV. 1234209720Srpaulo */ 1235209720Srpaulo#ifdef __amd64 1236209720Srpaulo if (p->p_model == DATAMODEL_NATIVE) { 1237211744Srpaulo ret = dst = fasttrap_fulword((void *)rp->r_rsp); 1238211744Srpaulo addr = rp->r_rsp + sizeof (uintptr_t); 1239211744Srpaulo } else { 1240209720Srpaulo#endif 1241211744Srpaulo#ifdef __i386__ 1242209720Srpaulo uint32_t dst32; 1243211744Srpaulo ret = dst32 = fasttrap_fuword32((void *)rp->r_esp); 1244209720Srpaulo dst = dst32; 1245211744Srpaulo addr = rp->r_esp + sizeof (uint32_t); 1246211744Srpaulo#endif 1247211744Srpaulo#ifdef __amd64 1248209720Srpaulo } 1249209720Srpaulo#endif 1250209720Srpaulo 1251209720Srpaulo if (ret == -1) { 1252211744Srpaulo fasttrap_sigsegv(p, curthread, rp->r_rsp); 1253209720Srpaulo new_pc = pc; 1254209720Srpaulo break; 1255209720Srpaulo } 1256209720Srpaulo 1257209720Srpaulo if (tp->ftt_type == FASTTRAP_T_RET16) 1258209720Srpaulo addr += tp->ftt_dest; 1259209720Srpaulo 1260211744Srpaulo rp->r_rsp = addr; 1261209720Srpaulo new_pc = dst; 1262209720Srpaulo break; 1263209720Srpaulo } 1264209720Srpaulo 1265209720Srpaulo case FASTTRAP_T_JCC: 1266209720Srpaulo { 1267211744Srpaulo uint_t taken = 0; 1268209720Srpaulo 1269209720Srpaulo switch (tp->ftt_code) { 1270209720Srpaulo case FASTTRAP_JO: 1271211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_OF) != 0; 1272209720Srpaulo break; 1273209720Srpaulo case FASTTRAP_JNO: 1274211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_OF) == 0; 1275209720Srpaulo break; 1276209720Srpaulo case FASTTRAP_JB: 1277211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_CF) != 0; 1278209720Srpaulo break; 1279209720Srpaulo case FASTTRAP_JAE: 1280211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_CF) == 0; 1281209720Srpaulo break; 1282209720Srpaulo case FASTTRAP_JE: 1283211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) != 0; 1284209720Srpaulo break; 1285209720Srpaulo case FASTTRAP_JNE: 1286211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) == 0; 1287209720Srpaulo break; 1288209720Srpaulo case FASTTRAP_JBE: 1289211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_CF) != 0 || 1290211744Srpaulo (rp->r_rflags & FASTTRAP_EFLAGS_ZF) != 0; 1291209720Srpaulo break; 1292209720Srpaulo case FASTTRAP_JA: 1293211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_CF) == 0 && 1294211744Srpaulo (rp->r_rflags & FASTTRAP_EFLAGS_ZF) == 0; 1295209720Srpaulo break; 1296209720Srpaulo case FASTTRAP_JS: 1297211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_SF) != 0; 1298209720Srpaulo break; 1299209720Srpaulo case FASTTRAP_JNS: 1300211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_SF) == 0; 1301209720Srpaulo break; 1302209720Srpaulo case FASTTRAP_JP: 1303211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_PF) != 0; 1304209720Srpaulo break; 1305209720Srpaulo case FASTTRAP_JNP: 1306211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_PF) == 0; 1307209720Srpaulo break; 1308209720Srpaulo case FASTTRAP_JL: 1309211744Srpaulo taken = ((rp->r_rflags & FASTTRAP_EFLAGS_SF) == 0) != 1310211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_OF) == 0); 1311209720Srpaulo break; 1312209720Srpaulo case FASTTRAP_JGE: 1313211744Srpaulo taken = ((rp->r_rflags & FASTTRAP_EFLAGS_SF) == 0) == 1314211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_OF) == 0); 1315209720Srpaulo break; 1316209720Srpaulo case FASTTRAP_JLE: 1317211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) != 0 || 1318211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_SF) == 0) != 1319211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_OF) == 0); 1320209720Srpaulo break; 1321209720Srpaulo case FASTTRAP_JG: 1322211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) == 0 && 1323211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_SF) == 0) == 1324211744Srpaulo ((rp->r_rflags & FASTTRAP_EFLAGS_OF) == 0); 1325209720Srpaulo break; 1326209720Srpaulo 1327209720Srpaulo } 1328209720Srpaulo 1329209720Srpaulo if (taken) 1330209720Srpaulo new_pc = tp->ftt_dest; 1331209720Srpaulo else 1332209720Srpaulo new_pc = pc + tp->ftt_size; 1333209720Srpaulo break; 1334209720Srpaulo } 1335209720Srpaulo 1336209720Srpaulo case FASTTRAP_T_LOOP: 1337209720Srpaulo { 1338211744Srpaulo uint_t taken = 0; 1339209720Srpaulo#ifdef __amd64 1340209720Srpaulo greg_t cx = rp->r_rcx--; 1341209720Srpaulo#else 1342209720Srpaulo greg_t cx = rp->r_ecx--; 1343209720Srpaulo#endif 1344209720Srpaulo 1345209720Srpaulo switch (tp->ftt_code) { 1346209720Srpaulo case FASTTRAP_LOOPNZ: 1347211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) == 0 && 1348209720Srpaulo cx != 0; 1349209720Srpaulo break; 1350209720Srpaulo case FASTTRAP_LOOPZ: 1351211744Srpaulo taken = (rp->r_rflags & FASTTRAP_EFLAGS_ZF) != 0 && 1352209720Srpaulo cx != 0; 1353209720Srpaulo break; 1354209720Srpaulo case FASTTRAP_LOOP: 1355209720Srpaulo taken = (cx != 0); 1356209720Srpaulo break; 1357209720Srpaulo } 1358209720Srpaulo 1359209720Srpaulo if (taken) 1360209720Srpaulo new_pc = tp->ftt_dest; 1361209720Srpaulo else 1362209720Srpaulo new_pc = pc + tp->ftt_size; 1363209720Srpaulo break; 1364209720Srpaulo } 1365209720Srpaulo 1366209720Srpaulo case FASTTRAP_T_JCXZ: 1367209720Srpaulo { 1368209720Srpaulo#ifdef __amd64 1369209720Srpaulo greg_t cx = rp->r_rcx; 1370209720Srpaulo#else 1371209720Srpaulo greg_t cx = rp->r_ecx; 1372209720Srpaulo#endif 1373209720Srpaulo 1374209720Srpaulo if (cx == 0) 1375209720Srpaulo new_pc = tp->ftt_dest; 1376209720Srpaulo else 1377209720Srpaulo new_pc = pc + tp->ftt_size; 1378209720Srpaulo break; 1379209720Srpaulo } 1380209720Srpaulo 1381209720Srpaulo case FASTTRAP_T_PUSHL_EBP: 1382209720Srpaulo { 1383211744Srpaulo int ret = 0; 1384211744Srpaulo uintptr_t addr = 0; 1385227291Srstone 1386209720Srpaulo#ifdef __amd64 1387209720Srpaulo if (p->p_model == DATAMODEL_NATIVE) { 1388211744Srpaulo addr = rp->r_rsp - sizeof (uintptr_t); 1389211744Srpaulo ret = fasttrap_sulword((void *)addr, &rp->r_rsp); 1390211744Srpaulo } else { 1391209720Srpaulo#endif 1392211744Srpaulo#ifdef __i386__ 1393211744Srpaulo addr = rp->r_rsp - sizeof (uint32_t); 1394211744Srpaulo ret = fasttrap_suword32((void *)addr, &rp->r_rsp); 1395211744Srpaulo#endif 1396209720Srpaulo#ifdef __amd64 1397209720Srpaulo } 1398209720Srpaulo#endif 1399209720Srpaulo 1400209720Srpaulo if (ret == -1) { 1401209720Srpaulo fasttrap_sigsegv(p, curthread, addr); 1402209720Srpaulo new_pc = pc; 1403209720Srpaulo break; 1404209720Srpaulo } 1405209720Srpaulo 1406211744Srpaulo rp->r_rsp = addr; 1407209720Srpaulo new_pc = pc + tp->ftt_size; 1408209720Srpaulo break; 1409209720Srpaulo } 1410209720Srpaulo 1411209720Srpaulo case FASTTRAP_T_NOP: 1412209720Srpaulo new_pc = pc + tp->ftt_size; 1413209720Srpaulo break; 1414209720Srpaulo 1415209720Srpaulo case FASTTRAP_T_JMP: 1416209720Srpaulo case FASTTRAP_T_CALL: 1417209720Srpaulo if (tp->ftt_code == 0) { 1418209720Srpaulo new_pc = tp->ftt_dest; 1419209720Srpaulo } else { 1420211744Srpaulo#ifdef __amd64 1421211744Srpaulo uintptr_t value; 1422211744Srpaulo#endif 1423211744Srpaulo uintptr_t addr = tp->ftt_dest; 1424209720Srpaulo 1425209720Srpaulo if (tp->ftt_base != FASTTRAP_NOREG) 1426209720Srpaulo addr += fasttrap_getreg(rp, tp->ftt_base); 1427209720Srpaulo if (tp->ftt_index != FASTTRAP_NOREG) 1428209720Srpaulo addr += fasttrap_getreg(rp, tp->ftt_index) << 1429209720Srpaulo tp->ftt_scale; 1430209720Srpaulo 1431209720Srpaulo if (tp->ftt_code == 1) { 1432209720Srpaulo /* 1433209720Srpaulo * If there's a segment prefix for this 1434209720Srpaulo * instruction, we'll need to check permissions 1435209720Srpaulo * and bounds on the given selector, and adjust 1436209720Srpaulo * the address accordingly. 1437209720Srpaulo */ 1438209720Srpaulo if (tp->ftt_segment != FASTTRAP_SEG_NONE && 1439209720Srpaulo fasttrap_do_seg(tp, rp, &addr) != 0) { 1440209720Srpaulo fasttrap_sigsegv(p, curthread, addr); 1441209720Srpaulo new_pc = pc; 1442209720Srpaulo break; 1443209720Srpaulo } 1444209720Srpaulo 1445209720Srpaulo#ifdef __amd64 1446209720Srpaulo if (p->p_model == DATAMODEL_NATIVE) { 1447211744Srpaulo if ((value = fasttrap_fulword((void *)addr)) 1448211744Srpaulo == -1) { 1449209720Srpaulo fasttrap_sigsegv(p, curthread, 1450209720Srpaulo addr); 1451209720Srpaulo new_pc = pc; 1452209720Srpaulo break; 1453209720Srpaulo } 1454209720Srpaulo new_pc = value; 1455209720Srpaulo } else { 1456211744Srpaulo#endif 1457211744Srpaulo#ifdef __i386__ 1458209720Srpaulo uint32_t value32; 1459209720Srpaulo addr = (uintptr_t)(uint32_t)addr; 1460211744Srpaulo if ((value32 = fasttrap_fuword32((void *)addr)) 1461211744Srpaulo == -1) { 1462209720Srpaulo fasttrap_sigsegv(p, curthread, 1463209720Srpaulo addr); 1464209720Srpaulo new_pc = pc; 1465209720Srpaulo break; 1466209720Srpaulo } 1467209720Srpaulo new_pc = value32; 1468211744Srpaulo#endif 1469209720Srpaulo } 1470211744Srpaulo#ifdef __amd64 1471209720Srpaulo } else { 1472209720Srpaulo new_pc = addr; 1473209720Srpaulo } 1474211744Srpaulo#endif 1475209720Srpaulo } 1476209720Srpaulo 1477209720Srpaulo /* 1478209720Srpaulo * If this is a call instruction, we need to push the return 1479209720Srpaulo * address onto the stack. If this fails, we send the process 1480209720Srpaulo * a SIGSEGV and reset the pc to emulate what would happen if 1481209720Srpaulo * this instruction weren't traced. 1482209720Srpaulo */ 1483209720Srpaulo if (tp->ftt_type == FASTTRAP_T_CALL) { 1484211744Srpaulo int ret = 0; 1485211744Srpaulo uintptr_t addr = 0, pcps; 1486209720Srpaulo#ifdef __amd64 1487209720Srpaulo if (p->p_model == DATAMODEL_NATIVE) { 1488211744Srpaulo addr = rp->r_rsp - sizeof (uintptr_t); 1489211744Srpaulo pcps = pc + tp->ftt_size; 1490211744Srpaulo ret = fasttrap_sulword((void *)addr, &pcps); 1491209720Srpaulo } else { 1492209720Srpaulo#endif 1493211744Srpaulo#ifdef __i386__ 1494211744Srpaulo addr = rp->r_rsp - sizeof (uint32_t); 1495211744Srpaulo pcps = (uint32_t)(pc + tp->ftt_size); 1496211744Srpaulo ret = fasttrap_suword32((void *)addr, &pcps); 1497211744Srpaulo#endif 1498209720Srpaulo#ifdef __amd64 1499209720Srpaulo } 1500209720Srpaulo#endif 1501209720Srpaulo 1502209720Srpaulo if (ret == -1) { 1503209720Srpaulo fasttrap_sigsegv(p, curthread, addr); 1504209720Srpaulo new_pc = pc; 1505209720Srpaulo break; 1506209720Srpaulo } 1507209720Srpaulo 1508211744Srpaulo rp->r_rsp = addr; 1509209720Srpaulo } 1510209720Srpaulo 1511209720Srpaulo break; 1512209720Srpaulo 1513209720Srpaulo case FASTTRAP_T_COMMON: 1514209720Srpaulo { 1515209720Srpaulo uintptr_t addr; 1516209720Srpaulo#if defined(__amd64) 1517209720Srpaulo uint8_t scratch[2 * FASTTRAP_MAX_INSTR_SIZE + 22]; 1518209720Srpaulo#else 1519209720Srpaulo uint8_t scratch[2 * FASTTRAP_MAX_INSTR_SIZE + 7]; 1520209720Srpaulo#endif 1521209720Srpaulo uint_t i = 0; 1522211744Srpaulo#if defined(sun) 1523209720Srpaulo klwp_t *lwp = ttolwp(curthread); 1524211744Srpaulo#endif 1525209720Srpaulo 1526209720Srpaulo /* 1527209720Srpaulo * Compute the address of the ulwp_t and step over the 1528209720Srpaulo * ul_self pointer. The method used to store the user-land 1529209720Srpaulo * thread pointer is very different on 32- and 64-bit 1530209720Srpaulo * kernels. 1531209720Srpaulo */ 1532211744Srpaulo#if defined(sun) 1533209720Srpaulo#if defined(__amd64) 1534209720Srpaulo if (p->p_model == DATAMODEL_LP64) { 1535209720Srpaulo addr = lwp->lwp_pcb.pcb_fsbase; 1536209720Srpaulo addr += sizeof (void *); 1537209720Srpaulo } else { 1538209720Srpaulo addr = lwp->lwp_pcb.pcb_gsbase; 1539209720Srpaulo addr += sizeof (caddr32_t); 1540209720Srpaulo } 1541209720Srpaulo#else 1542211744Srpaulo addr = USD_GETBASE(&lwp->lwp_pcb.pcb_gsdesc); 1543209720Srpaulo addr += sizeof (void *); 1544209720Srpaulo#endif 1545211744Srpaulo#endif /* sun */ 1546211744Srpaulo#ifdef __i386__ 1547211744Srpaulo addr = USD_GETBASE(&curthread->td_pcb->pcb_gsd); 1548211744Srpaulo#else 1549211744Srpaulo addr = curthread->td_pcb->pcb_gsbase; 1550211744Srpaulo#endif 1551211744Srpaulo addr += sizeof (void *); 1552209720Srpaulo 1553209720Srpaulo /* 1554209720Srpaulo * Generic Instruction Tracing 1555209720Srpaulo * --------------------------- 1556209720Srpaulo * 1557209720Srpaulo * This is the layout of the scratch space in the user-land 1558209720Srpaulo * thread structure for our generated instructions. 1559209720Srpaulo * 1560209720Srpaulo * 32-bit mode bytes 1561209720Srpaulo * ------------------------ ----- 1562209720Srpaulo * a: <original instruction> <= 15 1563209720Srpaulo * jmp <pc + tp->ftt_size> 5 1564227291Srstone * b: <original instruction> <= 15 1565209720Srpaulo * int T_DTRACE_RET 2 1566209720Srpaulo * ----- 1567209720Srpaulo * <= 37 1568209720Srpaulo * 1569209720Srpaulo * 64-bit mode bytes 1570209720Srpaulo * ------------------------ ----- 1571209720Srpaulo * a: <original instruction> <= 15 1572209720Srpaulo * jmp 0(%rip) 6 1573209720Srpaulo * <pc + tp->ftt_size> 8 1574209720Srpaulo * b: <original instruction> <= 15 1575209720Srpaulo * int T_DTRACE_RET 2 1576209720Srpaulo * ----- 1577209720Srpaulo * <= 46 1578209720Srpaulo * 1579209720Srpaulo * The %pc is set to a, and curthread->t_dtrace_astpc is set 1580209720Srpaulo * to b. If we encounter a signal on the way out of the 1581209720Srpaulo * kernel, trap() will set %pc to curthread->t_dtrace_astpc 1582209720Srpaulo * so that we execute the original instruction and re-enter 1583209720Srpaulo * the kernel rather than redirecting to the next instruction. 1584209720Srpaulo * 1585209720Srpaulo * If there are return probes (so we know that we're going to 1586209720Srpaulo * need to reenter the kernel after executing the original 1587209720Srpaulo * instruction), the scratch space will just contain the 1588209720Srpaulo * original instruction followed by an interrupt -- the same 1589209720Srpaulo * data as at b. 1590209720Srpaulo * 1591209720Srpaulo * %rip-relative Addressing 1592209720Srpaulo * ------------------------ 1593209720Srpaulo * 1594209720Srpaulo * There's a further complication in 64-bit mode due to %rip- 1595209720Srpaulo * relative addressing. While this is clearly a beneficial 1596209720Srpaulo * architectural decision for position independent code, it's 1597209720Srpaulo * hard not to see it as a personal attack against the pid 1598209720Srpaulo * provider since before there was a relatively small set of 1599209720Srpaulo * instructions to emulate; with %rip-relative addressing, 1600209720Srpaulo * almost every instruction can potentially depend on the 1601209720Srpaulo * address at which it's executed. Rather than emulating 1602209720Srpaulo * the broad spectrum of instructions that can now be 1603209720Srpaulo * position dependent, we emulate jumps and others as in 1604209720Srpaulo * 32-bit mode, and take a different tack for instructions 1605209720Srpaulo * using %rip-relative addressing. 1606209720Srpaulo * 1607209720Srpaulo * For every instruction that uses the ModRM byte, the 1608209720Srpaulo * in-kernel disassembler reports its location. We use the 1609209720Srpaulo * ModRM byte to identify that an instruction uses 1610209720Srpaulo * %rip-relative addressing and to see what other registers 1611209720Srpaulo * the instruction uses. To emulate those instructions, 1612209720Srpaulo * we modify the instruction to be %rax-relative rather than 1613209720Srpaulo * %rip-relative (or %rcx-relative if the instruction uses 1614209720Srpaulo * %rax; or %r8- or %r9-relative if the REX.B is present so 1615209720Srpaulo * we don't have to rewrite the REX prefix). We then load 1616209720Srpaulo * the value that %rip would have been into the scratch 1617209720Srpaulo * register and generate an instruction to reset the scratch 1618209720Srpaulo * register back to its original value. The instruction 1619209720Srpaulo * sequence looks like this: 1620209720Srpaulo * 1621209720Srpaulo * 64-mode %rip-relative bytes 1622209720Srpaulo * ------------------------ ----- 1623209720Srpaulo * a: <modified instruction> <= 15 1624209720Srpaulo * movq $<value>, %<scratch> 6 1625209720Srpaulo * jmp 0(%rip) 6 1626209720Srpaulo * <pc + tp->ftt_size> 8 1627209720Srpaulo * b: <modified instruction> <= 15 1628209720Srpaulo * int T_DTRACE_RET 2 1629209720Srpaulo * ----- 1630209720Srpaulo * 52 1631209720Srpaulo * 1632209720Srpaulo * We set curthread->t_dtrace_regv so that upon receiving 1633209720Srpaulo * a signal we can reset the value of the scratch register. 1634209720Srpaulo */ 1635209720Srpaulo 1636209720Srpaulo ASSERT(tp->ftt_size < FASTTRAP_MAX_INSTR_SIZE); 1637209720Srpaulo 1638209720Srpaulo curthread->t_dtrace_scrpc = addr; 1639209720Srpaulo bcopy(tp->ftt_instr, &scratch[i], tp->ftt_size); 1640209720Srpaulo i += tp->ftt_size; 1641209720Srpaulo 1642209720Srpaulo#ifdef __amd64 1643209720Srpaulo if (tp->ftt_ripmode != 0) { 1644211744Srpaulo greg_t *reg = NULL; 1645209720Srpaulo 1646209720Srpaulo ASSERT(p->p_model == DATAMODEL_LP64); 1647209720Srpaulo ASSERT(tp->ftt_ripmode & 1648209720Srpaulo (FASTTRAP_RIP_1 | FASTTRAP_RIP_2)); 1649209720Srpaulo 1650209720Srpaulo /* 1651209720Srpaulo * If this was a %rip-relative instruction, we change 1652209720Srpaulo * it to be either a %rax- or %rcx-relative 1653209720Srpaulo * instruction (depending on whether those registers 1654209720Srpaulo * are used as another operand; or %r8- or %r9- 1655209720Srpaulo * relative depending on the value of REX.B). We then 1656209720Srpaulo * set that register and generate a movq instruction 1657209720Srpaulo * to reset the value. 1658209720Srpaulo */ 1659209720Srpaulo if (tp->ftt_ripmode & FASTTRAP_RIP_X) 1660209720Srpaulo scratch[i++] = FASTTRAP_REX(1, 0, 0, 1); 1661209720Srpaulo else 1662209720Srpaulo scratch[i++] = FASTTRAP_REX(1, 0, 0, 0); 1663209720Srpaulo 1664209720Srpaulo if (tp->ftt_ripmode & FASTTRAP_RIP_1) 1665209720Srpaulo scratch[i++] = FASTTRAP_MOV_EAX; 1666209720Srpaulo else 1667209720Srpaulo scratch[i++] = FASTTRAP_MOV_ECX; 1668209720Srpaulo 1669209720Srpaulo switch (tp->ftt_ripmode) { 1670209720Srpaulo case FASTTRAP_RIP_1: 1671209720Srpaulo reg = &rp->r_rax; 1672209720Srpaulo curthread->t_dtrace_reg = REG_RAX; 1673209720Srpaulo break; 1674209720Srpaulo case FASTTRAP_RIP_2: 1675209720Srpaulo reg = &rp->r_rcx; 1676209720Srpaulo curthread->t_dtrace_reg = REG_RCX; 1677209720Srpaulo break; 1678209720Srpaulo case FASTTRAP_RIP_1 | FASTTRAP_RIP_X: 1679209720Srpaulo reg = &rp->r_r8; 1680209720Srpaulo curthread->t_dtrace_reg = REG_R8; 1681209720Srpaulo break; 1682209720Srpaulo case FASTTRAP_RIP_2 | FASTTRAP_RIP_X: 1683209720Srpaulo reg = &rp->r_r9; 1684209720Srpaulo curthread->t_dtrace_reg = REG_R9; 1685209720Srpaulo break; 1686209720Srpaulo } 1687209720Srpaulo 1688209720Srpaulo /* LINTED - alignment */ 1689209720Srpaulo *(uint64_t *)&scratch[i] = *reg; 1690209720Srpaulo curthread->t_dtrace_regv = *reg; 1691209720Srpaulo *reg = pc + tp->ftt_size; 1692209720Srpaulo i += sizeof (uint64_t); 1693209720Srpaulo } 1694209720Srpaulo#endif 1695209720Srpaulo 1696209720Srpaulo /* 1697209720Srpaulo * Generate the branch instruction to what would have 1698209720Srpaulo * normally been the subsequent instruction. In 32-bit mode, 1699209720Srpaulo * this is just a relative branch; in 64-bit mode this is a 1700209720Srpaulo * %rip-relative branch that loads the 64-bit pc value 1701209720Srpaulo * immediately after the jmp instruction. 1702209720Srpaulo */ 1703209720Srpaulo#ifdef __amd64 1704209720Srpaulo if (p->p_model == DATAMODEL_LP64) { 1705209720Srpaulo scratch[i++] = FASTTRAP_GROUP5_OP; 1706209720Srpaulo scratch[i++] = FASTTRAP_MODRM(0, 4, 5); 1707209720Srpaulo /* LINTED - alignment */ 1708209720Srpaulo *(uint32_t *)&scratch[i] = 0; 1709209720Srpaulo i += sizeof (uint32_t); 1710209720Srpaulo /* LINTED - alignment */ 1711209720Srpaulo *(uint64_t *)&scratch[i] = pc + tp->ftt_size; 1712209720Srpaulo i += sizeof (uint64_t); 1713209720Srpaulo } else { 1714209720Srpaulo#endif 1715211744Srpaulo#ifdef __i386__ 1716209720Srpaulo /* 1717209720Srpaulo * Set up the jmp to the next instruction; note that 1718209720Srpaulo * the size of the traced instruction cancels out. 1719209720Srpaulo */ 1720209720Srpaulo scratch[i++] = FASTTRAP_JMP32; 1721209720Srpaulo /* LINTED - alignment */ 1722209720Srpaulo *(uint32_t *)&scratch[i] = pc - addr - 5; 1723209720Srpaulo i += sizeof (uint32_t); 1724211744Srpaulo#endif 1725209720Srpaulo#ifdef __amd64 1726209720Srpaulo } 1727209720Srpaulo#endif 1728209720Srpaulo 1729209720Srpaulo curthread->t_dtrace_astpc = addr + i; 1730209720Srpaulo bcopy(tp->ftt_instr, &scratch[i], tp->ftt_size); 1731209720Srpaulo i += tp->ftt_size; 1732209720Srpaulo scratch[i++] = FASTTRAP_INT; 1733209720Srpaulo scratch[i++] = T_DTRACE_RET; 1734209720Srpaulo 1735209720Srpaulo ASSERT(i <= sizeof (scratch)); 1736209720Srpaulo 1737227291Srstone#if defined(sun) 1738209720Srpaulo if (fasttrap_copyout(scratch, (char *)addr, i)) { 1739227291Srstone#else 1740227291Srstone if (uwrite(curproc, scratch, i, addr)) { 1741227291Srstone#endif 1742209720Srpaulo fasttrap_sigtrap(p, curthread, pc); 1743209720Srpaulo new_pc = pc; 1744209720Srpaulo break; 1745209720Srpaulo } 1746209720Srpaulo if (tp->ftt_retids != NULL) { 1747209720Srpaulo curthread->t_dtrace_step = 1; 1748209720Srpaulo curthread->t_dtrace_ret = 1; 1749209720Srpaulo new_pc = curthread->t_dtrace_astpc; 1750209720Srpaulo } else { 1751209720Srpaulo new_pc = curthread->t_dtrace_scrpc; 1752209720Srpaulo } 1753209720Srpaulo 1754209720Srpaulo curthread->t_dtrace_pc = pc; 1755209720Srpaulo curthread->t_dtrace_npc = pc + tp->ftt_size; 1756209720Srpaulo curthread->t_dtrace_on = 1; 1757209720Srpaulo break; 1758209720Srpaulo } 1759209720Srpaulo 1760209720Srpaulo default: 1761209720Srpaulo panic("fasttrap: mishandled an instruction"); 1762209720Srpaulo } 1763209720Srpaulo 1764209720Srpaulodone: 1765209720Srpaulo /* 1766209720Srpaulo * If there were no return probes when we first found the tracepoint, 1767209720Srpaulo * we should feel no obligation to honor any return probes that were 1768209720Srpaulo * subsequently enabled -- they'll just have to wait until the next 1769209720Srpaulo * time around. 1770209720Srpaulo */ 1771209720Srpaulo if (tp->ftt_retids != NULL) { 1772209720Srpaulo /* 1773209720Srpaulo * We need to wait until the results of the instruction are 1774209720Srpaulo * apparent before invoking any return probes. If this 1775209720Srpaulo * instruction was emulated we can just call 1776209720Srpaulo * fasttrap_return_common(); if it needs to be executed, we 1777209720Srpaulo * need to wait until the user thread returns to the kernel. 1778209720Srpaulo */ 1779209720Srpaulo if (tp->ftt_type != FASTTRAP_T_COMMON) { 1780209720Srpaulo /* 1781209720Srpaulo * Set the program counter to the address of the traced 1782209720Srpaulo * instruction so that it looks right in ustack() 1783209720Srpaulo * output. We had previously set it to the end of the 1784209720Srpaulo * instruction to simplify %rip-relative addressing. 1785209720Srpaulo */ 1786211744Srpaulo rp->r_rip = pc; 1787209720Srpaulo 1788209720Srpaulo fasttrap_return_common(rp, pc, pid, new_pc); 1789209720Srpaulo } else { 1790209720Srpaulo ASSERT(curthread->t_dtrace_ret != 0); 1791209720Srpaulo ASSERT(curthread->t_dtrace_pc == pc); 1792209720Srpaulo ASSERT(curthread->t_dtrace_scrpc != 0); 1793209720Srpaulo ASSERT(new_pc == curthread->t_dtrace_astpc); 1794209720Srpaulo } 1795209720Srpaulo } 1796209720Srpaulo 1797211744Srpaulo rp->r_rip = new_pc; 1798209720Srpaulo 1799247820Sgibbs PROC_LOCK(p); 1800247820Sgibbs proc_write_regs(curthread, rp); 1801247820Sgibbs _PRELE(p); 1802247820Sgibbs PROC_UNLOCK(p); 1803247820Sgibbs 1804209720Srpaulo return (0); 1805209720Srpaulo} 1806209720Srpaulo 1807209720Srpauloint 1808211744Srpaulofasttrap_return_probe(struct reg *rp) 1809209720Srpaulo{ 1810209720Srpaulo proc_t *p = curproc; 1811209720Srpaulo uintptr_t pc = curthread->t_dtrace_pc; 1812209720Srpaulo uintptr_t npc = curthread->t_dtrace_npc; 1813209720Srpaulo 1814209720Srpaulo curthread->t_dtrace_pc = 0; 1815209720Srpaulo curthread->t_dtrace_npc = 0; 1816209720Srpaulo curthread->t_dtrace_scrpc = 0; 1817209720Srpaulo curthread->t_dtrace_astpc = 0; 1818209720Srpaulo 1819211744Srpaulo#if defined(sun) 1820209720Srpaulo /* 1821209720Srpaulo * Treat a child created by a call to vfork(2) as if it were its 1822209720Srpaulo * parent. We know that there's only one thread of control in such a 1823209720Srpaulo * process: this one. 1824209720Srpaulo */ 1825209720Srpaulo while (p->p_flag & SVFORK) { 1826209720Srpaulo p = p->p_parent; 1827209720Srpaulo } 1828211744Srpaulo#endif 1829209720Srpaulo 1830209720Srpaulo /* 1831211744Srpaulo * We set rp->r_rip to the address of the traced instruction so 1832209720Srpaulo * that it appears to dtrace_probe() that we're on the original 1833209720Srpaulo * instruction, and so that the user can't easily detect our 1834209720Srpaulo * complex web of lies. dtrace_return_probe() (our caller) 1835209720Srpaulo * will correctly set %pc after we return. 1836209720Srpaulo */ 1837211744Srpaulo rp->r_rip = pc; 1838209720Srpaulo 1839209720Srpaulo fasttrap_return_common(rp, pc, p->p_pid, npc); 1840209720Srpaulo 1841209720Srpaulo return (0); 1842209720Srpaulo} 1843209720Srpaulo 1844209720Srpaulo/*ARGSUSED*/ 1845209720Srpaulouint64_t 1846209720Srpaulofasttrap_pid_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 1847209720Srpaulo int aframes) 1848209720Srpaulo{ 1849211744Srpaulo struct reg r; 1850211744Srpaulo 1851211744Srpaulo fill_regs(curthread, &r); 1852211744Srpaulo 1853211744Srpaulo return (fasttrap_anarg(&r, 1, argno)); 1854209720Srpaulo} 1855209720Srpaulo 1856209720Srpaulo/*ARGSUSED*/ 1857209720Srpaulouint64_t 1858209720Srpaulofasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, 1859209720Srpaulo int aframes) 1860209720Srpaulo{ 1861211744Srpaulo struct reg r; 1862211744Srpaulo 1863211744Srpaulo fill_regs(curthread, &r); 1864211744Srpaulo 1865211744Srpaulo return (fasttrap_anarg(&r, 0, argno)); 1866209720Srpaulo} 1867209720Srpaulo 1868209720Srpaulostatic ulong_t 1869211744Srpaulofasttrap_getreg(struct reg *rp, uint_t reg) 1870209720Srpaulo{ 1871209720Srpaulo#ifdef __amd64 1872209720Srpaulo switch (reg) { 1873209720Srpaulo case REG_R15: return (rp->r_r15); 1874209720Srpaulo case REG_R14: return (rp->r_r14); 1875209720Srpaulo case REG_R13: return (rp->r_r13); 1876209720Srpaulo case REG_R12: return (rp->r_r12); 1877209720Srpaulo case REG_R11: return (rp->r_r11); 1878209720Srpaulo case REG_R10: return (rp->r_r10); 1879209720Srpaulo case REG_R9: return (rp->r_r9); 1880209720Srpaulo case REG_R8: return (rp->r_r8); 1881209720Srpaulo case REG_RDI: return (rp->r_rdi); 1882209720Srpaulo case REG_RSI: return (rp->r_rsi); 1883209720Srpaulo case REG_RBP: return (rp->r_rbp); 1884209720Srpaulo case REG_RBX: return (rp->r_rbx); 1885209720Srpaulo case REG_RDX: return (rp->r_rdx); 1886209720Srpaulo case REG_RCX: return (rp->r_rcx); 1887209720Srpaulo case REG_RAX: return (rp->r_rax); 1888209720Srpaulo case REG_TRAPNO: return (rp->r_trapno); 1889209720Srpaulo case REG_ERR: return (rp->r_err); 1890209720Srpaulo case REG_RIP: return (rp->r_rip); 1891209720Srpaulo case REG_CS: return (rp->r_cs); 1892211744Srpaulo#if defined(sun) 1893209720Srpaulo case REG_RFL: return (rp->r_rfl); 1894211744Srpaulo#endif 1895209720Srpaulo case REG_RSP: return (rp->r_rsp); 1896209720Srpaulo case REG_SS: return (rp->r_ss); 1897209720Srpaulo case REG_FS: return (rp->r_fs); 1898209720Srpaulo case REG_GS: return (rp->r_gs); 1899209720Srpaulo case REG_DS: return (rp->r_ds); 1900209720Srpaulo case REG_ES: return (rp->r_es); 1901211744Srpaulo case REG_FSBASE: return (rdmsr(MSR_FSBASE)); 1902211744Srpaulo case REG_GSBASE: return (rdmsr(MSR_GSBASE)); 1903209720Srpaulo } 1904209720Srpaulo 1905209720Srpaulo panic("dtrace: illegal register constant"); 1906209720Srpaulo /*NOTREACHED*/ 1907209720Srpaulo#else 1908211744Srpaulo#define _NGREG 19 1909209720Srpaulo if (reg >= _NGREG) 1910209720Srpaulo panic("dtrace: illegal register constant"); 1911209720Srpaulo 1912209720Srpaulo return (((greg_t *)&rp->r_gs)[reg]); 1913209720Srpaulo#endif 1914209720Srpaulo} 1915