6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
26 */
27
28 #include <libdisasm.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "dis_tables.h"
33 #include "libdisasm_impl.h"
34
35 typedef struct dis_handle_i386 {
36 int dhx_mode;
37 dis86_t dhx_dis;
38 uint64_t dhx_end;
39 } dis_handle_i386_t;
40
41 /*
42 * Returns true if we are near the end of a function. This is a cheap hack at
43 * detecting NULL padding between functions. If we're within a few bytes of the
44 * next function, or past the start, then return true.
45 */
46 static int
47 check_func(void *data)
48 {
49 dis_handle_t *dhp = data;
50 uint64_t start;
109 */
110 if ((dhx = dis_zalloc(sizeof (dis_handle_i386_t))) == NULL) {
111 (void) dis_seterrno(E_DIS_NOMEM);
112 return (-1);
113 }
114 dhp->dh_arch_private = dhx;
115
116 /*
117 * Initialize x86-specific architecture structure
118 */
119 if (dhp->dh_flags & DIS_X86_SIZE16)
120 dhx->dhx_mode = SIZE16;
121 else if (dhp->dh_flags & DIS_X86_SIZE64)
122 dhx->dhx_mode = SIZE64;
123 else
124 dhx->dhx_mode = SIZE32;
125
126 if (dhp->dh_flags & DIS_OCTAL)
127 dhx->dhx_dis.d86_flags = DIS_F_OCTAL;
128
129 dhx->dhx_dis.d86_sprintf_func = snprintf;
130 dhx->dhx_dis.d86_get_byte = get_byte;
131 dhx->dhx_dis.d86_sym_lookup = do_lookup;
132 dhx->dhx_dis.d86_check_func = check_func;
133
134 dhx->dhx_dis.d86_data = dhp;
135
136 return (0);
137 }
138
139 static int
140 dis_i386_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
141 size_t buflen)
142 {
143 dis_handle_i386_t *dhx = dhp->dh_arch_private;
144 dhp->dh_addr = addr;
145
146 /* DIS_NOIMMSYM might not be set until now, so update */
147 if (dhp->dh_flags & DIS_NOIMMSYM)
148 dhx->dhx_dis.d86_flags |= DIS_F_NOIMMSYM;
149 else
156 dtrace_disx86_str(&dhx->dhx_dis, dhx->dhx_mode, addr, buf,
157 buflen);
158
159 return (0);
160 }
161
162 /* ARGSUSED */
163 static int
164 dis_i386_max_instrlen(dis_handle_t *dhp)
165 {
166 return (15);
167 }
168
169 /* ARGSUSED */
170 static int
171 dis_i386_min_instrlen(dis_handle_t *dhp)
172 {
173 return (1);
174 }
175
176 #define MIN(a, b) ((a) < (b) ? (a) : (b))
177
178 /*
179 * Return the previous instruction. On x86, we have no choice except to
180 * disassemble everything from the start of the symbol, and stop when we have
181 * reached our instruction address. If we're not in the middle of a known
182 * symbol, then we return the same address to indicate failure.
183 */
184 static uint64_t
185 dis_i386_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
186 {
187 uint64_t *hist, addr, start;
188 int cur, nseen;
189 uint64_t res = pc;
190
191 if (n <= 0)
192 return (pc);
193
194 if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 ||
195 start == pc)
196 return (res);
197
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
26 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 #include <libdisasm.h>
30
31 #include "dis_tables.h"
32 #include "libdisasm_impl.h"
33
34 typedef struct dis_handle_i386 {
35 int dhx_mode;
36 dis86_t dhx_dis;
37 uint64_t dhx_end;
38 } dis_handle_i386_t;
39
40 /*
41 * Returns true if we are near the end of a function. This is a cheap hack at
42 * detecting NULL padding between functions. If we're within a few bytes of the
43 * next function, or past the start, then return true.
44 */
45 static int
46 check_func(void *data)
47 {
48 dis_handle_t *dhp = data;
49 uint64_t start;
108 */
109 if ((dhx = dis_zalloc(sizeof (dis_handle_i386_t))) == NULL) {
110 (void) dis_seterrno(E_DIS_NOMEM);
111 return (-1);
112 }
113 dhp->dh_arch_private = dhx;
114
115 /*
116 * Initialize x86-specific architecture structure
117 */
118 if (dhp->dh_flags & DIS_X86_SIZE16)
119 dhx->dhx_mode = SIZE16;
120 else if (dhp->dh_flags & DIS_X86_SIZE64)
121 dhx->dhx_mode = SIZE64;
122 else
123 dhx->dhx_mode = SIZE32;
124
125 if (dhp->dh_flags & DIS_OCTAL)
126 dhx->dhx_dis.d86_flags = DIS_F_OCTAL;
127
128 dhx->dhx_dis.d86_sprintf_func = dis_snprintf;
129 dhx->dhx_dis.d86_get_byte = get_byte;
130 dhx->dhx_dis.d86_sym_lookup = do_lookup;
131 dhx->dhx_dis.d86_check_func = check_func;
132
133 dhx->dhx_dis.d86_data = dhp;
134
135 return (0);
136 }
137
138 static int
139 dis_i386_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
140 size_t buflen)
141 {
142 dis_handle_i386_t *dhx = dhp->dh_arch_private;
143 dhp->dh_addr = addr;
144
145 /* DIS_NOIMMSYM might not be set until now, so update */
146 if (dhp->dh_flags & DIS_NOIMMSYM)
147 dhx->dhx_dis.d86_flags |= DIS_F_NOIMMSYM;
148 else
155 dtrace_disx86_str(&dhx->dhx_dis, dhx->dhx_mode, addr, buf,
156 buflen);
157
158 return (0);
159 }
160
161 /* ARGSUSED */
162 static int
163 dis_i386_max_instrlen(dis_handle_t *dhp)
164 {
165 return (15);
166 }
167
168 /* ARGSUSED */
169 static int
170 dis_i386_min_instrlen(dis_handle_t *dhp)
171 {
172 return (1);
173 }
174
175 /*
176 * Return the previous instruction. On x86, we have no choice except to
177 * disassemble everything from the start of the symbol, and stop when we have
178 * reached our instruction address. If we're not in the middle of a known
179 * symbol, then we return the same address to indicate failure.
180 */
181 static uint64_t
182 dis_i386_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
183 {
184 uint64_t *hist, addr, start;
185 int cur, nseen;
186 uint64_t res = pc;
187
188 if (n <= 0)
189 return (pc);
190
191 if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 ||
192 start == pc)
193 return (res);
194
|