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 | /* |
23 | * Copyright 2005 Sun Microsystems, Inc. All rights reserved. |
24 | * Use is subject to license terms. |
25 | */ |
26 | |
27 | /* Copyright (c) 1988 AT&T */ |
28 | /* All Rights Reserved */ |
29 | |
30 | |
31 | /* |
32 | * #pragma ident "@(#)instr_size.c 1.14 05/07/08 SMI" |
33 | */ |
34 | |
35 | #include <sys/dtrace.h> |
36 | #include <sys/dtrace_glue.h> |
37 | |
38 | #include <sys/dis_tables.h> |
39 | |
40 | /* |
41 | * This subsystem (with the minor exception of the instr_size() function) is |
42 | * is called from DTrace probe context. This imposes several requirements on |
43 | * the implementation: |
44 | * |
45 | * 1. External subsystems and functions may not be referenced. The one current |
46 | * exception is for cmn_err, but only to signal the detection of table |
47 | * errors. Assuming the tables are correct, no combination of input is to |
48 | * trigger a cmn_err call. |
49 | * |
50 | * 2. These functions can't be allowed to be traced. To prevent this, |
51 | * all functions in the probe path (everything except instr_size()) must |
52 | * have names that begin with "dtrace_". |
53 | */ |
54 | |
55 | typedef enum dis_isize { |
56 | DIS_ISIZE_INSTR, |
57 | DIS_ISIZE_OPERAND |
58 | } dis_isize_t; |
59 | |
60 | |
61 | /* |
62 | * get a byte from instruction stream |
63 | */ |
64 | static int |
65 | dtrace_dis_get_byte(void *p) |
66 | { |
67 | int ret; |
68 | uchar_t **instr = p; |
69 | |
70 | ret = **instr; |
71 | *instr += 1; |
72 | |
73 | return (ret); |
74 | } |
75 | |
76 | /* |
77 | * Returns either the size of a given instruction, in bytes, or the size of that |
78 | * instruction's memory access (if any), depending on the value of `which'. |
79 | * If a programming error in the tables is detected, the system will panic to |
80 | * ease diagnosis. Invalid instructions will not be flagged. They will appear |
81 | * to have an instruction size between 1 and the actual size, and will be |
82 | * reported as having no memory impact. |
83 | */ |
84 | /* ARGSUSED2 */ |
85 | static int |
86 | dtrace_dis_isize(uchar_t *instr, dis_isize_t which, model_t model, int *rmindex) |
87 | { |
88 | int sz; |
89 | dis86_t x; |
90 | uint_t mode = SIZE32; |
91 | |
92 | mode = (model == DATAMODEL_LP64) ? SIZE64 : SIZE32; |
93 | |
94 | x.d86_data = (void **)&instr; |
95 | x.d86_get_byte = dtrace_dis_get_byte; |
96 | x.d86_check_func = NULL; |
97 | |
98 | if (dtrace_disx86(&x, mode) != 0) |
99 | return (-1); |
100 | |
101 | if (which == DIS_ISIZE_INSTR) |
102 | sz = x.d86_len; /* length of the instruction */ |
103 | else |
104 | sz = x.d86_memsize; /* length of memory operand */ |
105 | |
106 | if (rmindex != NULL) |
107 | *rmindex = x.d86_rmindex; |
108 | return (sz); |
109 | } |
110 | |
111 | int |
112 | dtrace_instr_size_isa(uchar_t *instr, model_t model, int *rmindex) |
113 | { |
114 | return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, model, rmindex)); |
115 | } |
116 | |
117 | int |
118 | dtrace_instr_size(uchar_t *instr) |
119 | { |
120 | return (dtrace_dis_isize(instr, DIS_ISIZE_INSTR, DATAMODEL_NATIVE, |
121 | NULL)); |
122 | } |
123 | |