1193326Sed/* 2193326Sed * CDDL HEADER START 3193326Sed * 4193326Sed * The contents of this file are subject to the terms of the 5193326Sed * Common Development and Distribution License, Version 1.0 only 6193326Sed * (the "License"). You may not use this file except in compliance 7193326Sed * with the License. 8193326Sed * 9193326Sed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10193326Sed * or http://www.opensolaris.org/os/licensing. 11193326Sed * See the License for the specific language governing permissions 12193326Sed * and limitations under the License. 13193326Sed * 14218893Sdim * When distributing Covered Code, include this CDDL HEADER in each 15193326Sed * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16193326Sed * If applicable, add the following below this CDDL HEADER, with the 17193326Sed * fields enclosed by brackets "[]" replaced with your own identifying 18193326Sed * information: Portions Copyright [yyyy] [name of copyright owner] 19193326Sed * 20193326Sed * CDDL HEADER END 21193326Sed * 22193326Sed * $FreeBSD: releng/11.0/sys/cddl/dev/dtrace/amd64/instr_size.c 277300 2015-01-17 14:44:59Z smh $ 23193326Sed */ 24193326Sed/* 25193326Sed * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26193326Sed * Use is subject to license terms. 27193326Sed */ 28198092Srdivacky 29193326Sed/* Copyright (c) 1988 AT&T */ 30202879Srdivacky/* All Rights Reserved */ 31202879Srdivacky 32193326Sed 33193326Sed#ifdef illumos 34193326Sed#pragma ident "@(#)instr_size.c 1.14 05/07/08 SMI" 35193326Sed#endif 36193326Sed 37193326Sed#include <sys/types.h> 38193326Sed#include <sys/param.h> 39193326Sed#include <sys/proc.h> 40193326Sed#ifdef illumos 41193326Sed#include <sys/cmn_err.h> 42193326Sed#include <sys/archsystm.h> 43193326Sed#include <sys/copyops.h> 44193326Sed#include <vm/seg_enum.h> 45193326Sed#include <sys/privregs.h> 46193326Sed#else 47193326Sedtypedef u_int model_t; 48193326Sed#define DATAMODEL_NATIVE 0 49193326Sedint dtrace_instr_size(uchar_t *); 50223017Sdimint dtrace_instr_size_isa(uchar_t *, model_t, int *); 51223017Sdim#endif 52223017Sdim 53223017Sdim#include <dis_tables.h> 54223017Sdim 55223017Sdim/* 56223017Sdim * This subsystem (with the minor exception of the instr_size() function) is 57223017Sdim * is called from DTrace probe context. This imposes several requirements on 58223017Sdim * the implementation: 59223017Sdim * 60223017Sdim * 1. External subsystems and functions may not be referenced. The one current 61223017Sdim * exception is for cmn_err, but only to signal the detection of table 62223017Sdim * errors. Assuming the tables are correct, no combination of input is to 63223017Sdim * trigger a cmn_err call. 64223017Sdim * 65223017Sdim * 2. These functions can't be allowed to be traced. To prevent this, 66223017Sdim * all functions in the probe path (everything except instr_size()) must 67193326Sed * have names that begin with "dtrace_". 68208600Srdivacky */ 69208600Srdivacky 70193326Sedtypedef enum dis_isize { 71193326Sed DIS_ISIZE_INSTR, 72193326Sed DIS_ISIZE_OPERAND 73198092Srdivacky} dis_isize_t; 74193326Sed 75193326Sed 76193326Sed/* 77207619Srdivacky * get a byte from instruction stream 78193326Sed */ 79223017Sdimstatic int 80207619Srdivackydtrace_dis_get_byte(void *p) 81207619Srdivacky{ 82207619Srdivacky int ret; 83207619Srdivacky uchar_t **instr = p; 84223017Sdim 85207619Srdivacky ret = **instr; 86193326Sed *instr += 1; 87207619Srdivacky 88223017Sdim return (ret); 89223017Sdim} 90208600Srdivacky 91208600Srdivacky/* 92208600Srdivacky * Returns either the size of a given instruction, in bytes, or the size of that 93207619Srdivacky * instruction's memory access (if any), depending on the value of `which'. 94207619Srdivacky * If a programming error in the tables is detected, the system will panic to 95207619Srdivacky * ease diagnosis. Invalid instructions will not be flagged. They will appear 96207619Srdivacky * to have an instruction size between 1 and the actual size, and will be 97198092Srdivacky * reported as having no memory impact. 98207619Srdivacky */ 99223017Sdim/* ARGSUSED2 */ 100207619Srdivackystatic int 101193326Seddtrace_dis_isize(uchar_t *instr, dis_isize_t which, model_t model, int *rmindex) 102207619Srdivacky{ 103207619Srdivacky int sz; 104207619Srdivacky dis86_t x; 105223017Sdim uint_t mode = SIZE64; 106193326Sed 107207619Srdivacky#ifdef illumos 108207619Srdivacky mode = (model == DATAMODEL_LP64) ? SIZE64 : SIZE32; 109207619Srdivacky#endif 110193326Sed 111193326Sed x.d86_data = (void **)&instr; 112193326Sed x.d86_get_byte = dtrace_dis_get_byte; 113193326Sed x.d86_check_func = NULL; 114198092Srdivacky 115210299Sed if (dtrace_disx86(&x, mode) != 0) 116210299Sed return (-1); 117210299Sed 118223017Sdim if (which == DIS_ISIZE_INSTR) 119193326Sed sz = x.d86_len; /* length of the instruction */ 120193326Sed else 121193326Sed sz = x.d86_memsize; /* length of memory operand */ 122193326Sed 123223017Sdim if (rmindex != NULL) 124223017Sdim *rmindex = x.d86_rmindex; 125223017Sdim return (sz); 126223017Sdim} 127223017Sdim 128223017Sdimint 129223017Sdimdtrace_instr_size_isa(uchar_t *instr, model_t model, int *rmindex) 130223017Sdim{ 131223017Sdim return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, model, rmindex)); 132223017Sdim} 133223017Sdim 134223017Sdimint 135223017Sdimdtrace_instr_size(uchar_t *instr) 136193326Sed{ 137223017Sdim return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, DATAMODEL_NATIVE, 138223017Sdim NULL)); 139193326Sed} 140193326Sed