1139749Simp/* 267314Sjon * CDDL HEADER START 367314Sjon * 467314Sjon * The contents of this file are subject to the terms of the 567314Sjon * Common Development and Distribution License, Version 1.0 only 667314Sjon * (the "License"). You may not use this file except in compliance 767314Sjon * with the License. 867314Sjon * 967314Sjon * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1067314Sjon * or http://www.opensolaris.org/os/licensing. 1167314Sjon * See the License for the specific language governing permissions 1267314Sjon * and limitations under the License. 1367314Sjon * 1467314Sjon * When distributing Covered Code, include this CDDL HEADER in each 1567314Sjon * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1667314Sjon * If applicable, add the following below this CDDL HEADER, with the 1767314Sjon * fields enclosed by brackets "[]" replaced with your own identifying 1867314Sjon * information: Portions Copyright [yyyy] [name of copyright owner] 1967314Sjon * 2067314Sjon * CDDL HEADER END 2167314Sjon */ 2267314Sjon/* 2367314Sjon * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2467314Sjon * Use is subject to license terms. 2567314Sjon */ 2667314Sjon 2767314Sjon/* Copyright (c) 1988 AT&T */ 2867314Sjon/* All Rights Reserved */ 29119418Sobrien 30119418Sobrien#include <sys/types.h> 31119418Sobrien#include <sys/param.h> 3267314Sjon#include <sys/proc.h> 3367314Sjon#ifdef illumos 3467314Sjon#include <sys/cmn_err.h> 3567314Sjon#include <sys/archsystm.h> 3667314Sjon#include <sys/copyops.h> 3767314Sjon#include <vm/seg_enum.h> 3867314Sjon#include <sys/privregs.h> 3967314Sjon#else 4067314Sjon#include <sys/cred.h> 41201453Simp#include <cddl/dev/dtrace/dtrace_cddl.h> 42150762Simp 43150762Simptypedef u_int model_t; 4467314Sjon#define DATAMODEL_NATIVE 0 4567314Sjonint dtrace_dis_get_byte(void *); 4667314Sjonint dtrace_instr_size(uint8_t *); 4767314Sjonint dtrace_instr_size_isa(uint8_t *, model_t, int *); 4867314Sjon#endif 4967314Sjon 5067314Sjon#include <dis_tables.h> 5167314Sjon 5267314Sjon/* 5367314Sjon * This subsystem (with the minor exception of the instr_size() function) is 5467314Sjon * is called from DTrace probe context. This imposes several requirements on 5567314Sjon * the implementation: 5667314Sjon * 5767314Sjon * 1. External subsystems and functions may not be referenced. The one current 5867314Sjon * exception is for cmn_err, but only to signal the detection of table 59109514Sobrien * errors. Assuming the tables are correct, no combination of input is to 6067314Sjon * trigger a cmn_err call. 6167314Sjon * 6267314Sjon * 2. These functions can't be allowed to be traced. To prevent this, 6367314Sjon * all functions in the probe path (everything except instr_size()) must 6467314Sjon * have names that begin with "dtrace_". 65105135Salfred */ 66105135Salfred 6767314Sjontypedef enum dis_isize { 6867314Sjon DIS_ISIZE_INSTR, 6967314Sjon DIS_ISIZE_OPERAND 7067314Sjon} dis_isize_t; 7167314Sjon 7295722Sphk 7367314Sjon/* 74227908Smarius * get a byte from instruction stream 7567314Sjon */ 7667314Sjonint 7767314Sjondtrace_dis_get_byte(void *p) 7867314Sjon{ 7967314Sjon int ret; 8067314Sjon uint8_t **instr = p; 8167314Sjon 8267314Sjon ret = **instr; 8367314Sjon *instr += 1; 8467314Sjon 8567314Sjon return (ret); 8667314Sjon} 8792739Salfred 8892739Salfred/* 8967314Sjon * Returns either the size of a given instruction, in bytes, or the size of that 90164827Smarius * instruction's memory access (if any), depending on the value of `which'. 91221407Smarius * If a programming error in the tables is detected, the system will panic to 92164827Smarius * ease diagnosis. Invalid instructions will not be flagged. They will appear 93164827Smarius * to have an instruction size between 1 and the actual size, and will be 94164827Smarius * reported as having no memory impact. 95221407Smarius */ 96221407Smarius/* ARGSUSED2 */ 97221407Smariusstatic int 98221407Smariusdtrace_dis_isize(uint8_t *instr, dis_isize_t which, model_t model, int *rmindex) 99221407Smarius{ 100221407Smarius int sz; 10167314Sjon dis86_t x; 10267314Sjon uint_t mode = SIZE32; 10367314Sjon 10467314Sjon mode = (model == DATAMODEL_LP64) ? SIZE64 : SIZE32; 105164827Smarius 10667314Sjon x.d86_data = (void **)&instr; 10767314Sjon x.d86_get_byte = dtrace_dis_get_byte; 10867314Sjon x.d86_check_func = NULL; 10967314Sjon 11067314Sjon if (dtrace_disx86(&x, mode) != 0) 11167314Sjon return (-1); 112221407Smarius 113164830Smarius if (which == DIS_ISIZE_INSTR) 11467314Sjon sz = x.d86_len; /* length of the instruction */ 11567314Sjon else 11684145Sjlemon sz = x.d86_memsize; /* length of memory operand */ 11767314Sjon 11867314Sjon if (rmindex != NULL) 11967314Sjon *rmindex = x.d86_rmindex; 12067314Sjon return (sz); 12167314Sjon} 12267314Sjon 12367314Sjonint 12467314Sjondtrace_instr_size_isa(uint8_t *instr, model_t model, int *rmindex) 12567314Sjon{ 12667314Sjon return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, model, rmindex)); 12767314Sjon} 12867314Sjon 12967314Sjonint 13067314Sjondtrace_instr_size(uint8_t *instr) 131164832Smarius{ 13267314Sjon return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, DATAMODEL_NATIVE, 13367314Sjon NULL)); 13467314Sjon} 13584145Sjlemon