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