Print this page
OS-7095 Want risc-v disassembler
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libdisasm/common/libdisasm.c
+++ new/usr/src/lib/libdisasm/common/libdisasm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
26 26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 + * Copyright 2018, Joyent, Inc.
27 28 */
28 29
29 30 #include <libdisasm.h>
30 31 #include <stdlib.h>
31 32 #ifdef DIS_STANDALONE
32 33 #include <mdb/mdb_modapi.h>
33 34 #define _MDB
34 35 #include <mdb/mdb_io.h>
35 36 #else
36 37 #include <stdio.h>
37 38 #endif
38 39
39 40 #include "libdisasm_impl.h"
40 41
41 42 static int _dis_errno;
42 43
43 44 /*
44 45 * If we're building the standalone library, then we only want to
45 46 * include support for disassembly of the native architecture.
46 47 * The regular shared library should include support for all
47 48 * architectures.
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
48 49 */
49 50 #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64)
50 51 extern dis_arch_t dis_arch_i386;
51 52 #endif
52 53 #if !defined(DIS_STANDALONE) || defined(__sparc)
53 54 extern dis_arch_t dis_arch_sparc;
54 55 #endif
55 56 #if !defined(DIS_STANDALONE) || defined(__s390) || defined(__s390x)
56 57 extern dis_arch_t dis_arch_s390;
57 58 #endif
59 +#if !defined(DIS_STANDALONE) || defined(__riscv)
60 +extern dis_arch_t dis_arch_riscv;
61 +#endif
58 62
59 63 static dis_arch_t *dis_archs[] = {
60 64 #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64)
61 65 &dis_arch_i386,
62 66 #endif
63 67 #if !defined(DIS_STANDALONE) || defined(__sparc)
64 68 &dis_arch_sparc,
65 69 #endif
66 70 #if !defined(DIS_STANDALONE) || defined(__s390) || defined(__s390x)
67 71 &dis_arch_s390,
68 72 #endif
73 +#if !defined(DIS_STANDALONE) || defined(__riscv)
74 + &dis_arch_riscv,
75 +#endif
69 76 NULL
70 77 };
71 78
72 79 /*
73 80 * For the standalone library, we need to link against mdb's malloc/free.
74 81 * Otherwise, use the standard malloc/free.
75 82 */
76 83 #ifdef DIS_STANDALONE
77 84 void *
78 85 dis_zalloc(size_t bytes)
79 86 {
80 87 return (mdb_zalloc(bytes, UM_SLEEP));
81 88 }
82 89
83 90 void
84 91 dis_free(void *ptr, size_t bytes)
85 92 {
86 93 mdb_free(ptr, bytes);
87 94 }
88 95 #else
89 96 void *
90 97 dis_zalloc(size_t bytes)
91 98 {
92 99 return (calloc(1, bytes));
93 100 }
94 101
95 102 /*ARGSUSED*/
96 103 void
97 104 dis_free(void *ptr, size_t bytes)
98 105 {
99 106 free(ptr);
100 107 }
101 108 #endif
102 109
103 110 int
104 111 dis_seterrno(int error)
105 112 {
106 113 _dis_errno = error;
107 114 return (-1);
108 115 }
109 116
110 117 int
111 118 dis_errno(void)
112 119 {
113 120 return (_dis_errno);
114 121 }
115 122
116 123 const char *
117 124 dis_strerror(int error)
118 125 {
119 126 switch (error) {
120 127 case E_DIS_NOMEM:
121 128 return ("out of memory");
122 129 case E_DIS_INVALFLAG:
123 130 return ("invalid flags for this architecture");
124 131 case E_DIS_UNSUPARCH:
125 132 return ("unsupported machine architecture");
126 133 default:
127 134 return ("unknown error");
128 135 }
129 136 }
130 137
131 138 void
132 139 dis_set_data(dis_handle_t *dhp, void *data)
133 140 {
134 141 dhp->dh_data = data;
135 142 }
136 143
137 144 void
138 145 dis_flags_set(dis_handle_t *dhp, int f)
139 146 {
140 147 dhp->dh_flags |= f;
141 148 }
142 149
143 150 void
144 151 dis_flags_clear(dis_handle_t *dhp, int f)
145 152 {
146 153 dhp->dh_flags &= ~f;
147 154 }
148 155
149 156 void
150 157 dis_handle_destroy(dis_handle_t *dhp)
151 158 {
152 159 if (dhp->dh_arch->da_handle_detach != NULL)
153 160 dhp->dh_arch->da_handle_detach(dhp);
154 161
155 162 dis_free(dhp, sizeof (dis_handle_t));
156 163 }
157 164
158 165 dis_handle_t *
159 166 dis_handle_create(int flags, void *data, dis_lookup_f lookup_func,
160 167 dis_read_f read_func)
161 168 {
162 169 dis_handle_t *dhp;
163 170 dis_arch_t *arch = NULL;
164 171 int i;
165 172
166 173 /* Select an architecture based on flags */
167 174 for (i = 0; dis_archs[i] != NULL; i++) {
168 175 if (dis_archs[i]->da_supports_flags(flags)) {
169 176 arch = dis_archs[i];
170 177 break;
171 178 }
172 179 }
173 180 if (arch == NULL) {
174 181 (void) dis_seterrno(E_DIS_UNSUPARCH);
175 182 return (NULL);
176 183 }
177 184
178 185 if ((dhp = dis_zalloc(sizeof (dis_handle_t))) == NULL) {
179 186 (void) dis_seterrno(E_DIS_NOMEM);
180 187 return (NULL);
181 188 }
182 189 dhp->dh_arch = arch;
183 190 dhp->dh_lookup = lookup_func;
184 191 dhp->dh_read = read_func;
185 192 dhp->dh_flags = flags;
186 193 dhp->dh_data = data;
187 194
188 195 /*
189 196 * Allow the architecture-specific code to allocate
190 197 * its private data.
191 198 */
192 199 if (arch->da_handle_attach != NULL &&
193 200 arch->da_handle_attach(dhp) != 0) {
194 201 dis_free(dhp, sizeof (dis_handle_t));
195 202 /* dis errno already set */
196 203 return (NULL);
197 204 }
198 205
199 206 return (dhp);
200 207 }
201 208
202 209 int
203 210 dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
204 211 {
205 212 return (dhp->dh_arch->da_disassemble(dhp, addr, buf, buflen));
206 213 }
207 214
208 215 /*
209 216 * On some instruction sets (e.g., x86), we have no choice except to
210 217 * disassemble everything from the start of the symbol, and stop when we
211 218 * have reached our instruction address. If we're not in the middle of a
212 219 * known symbol, then we return the same address to indicate failure.
213 220 */
214 221 static uint64_t
215 222 dis_generic_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
216 223 {
217 224 uint64_t *hist, addr, start;
218 225 int cur, nseen;
219 226 uint64_t res = pc;
220 227
221 228 if (n <= 0)
222 229 return (pc);
223 230
224 231 if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 ||
225 232 start == pc)
226 233 return (res);
227 234
228 235 hist = dis_zalloc(sizeof (uint64_t) * n);
229 236
230 237 for (cur = 0, nseen = 0, addr = start; addr < pc; addr = dhp->dh_addr) {
231 238 hist[cur] = addr;
232 239 cur = (cur + 1) % n;
233 240 nseen++;
234 241
235 242 /* if we cannot make forward progress, give up */
236 243 if (dis_disassemble(dhp, addr, NULL, 0) != 0)
237 244 goto done;
238 245 }
239 246
240 247 if (addr != pc) {
241 248 /*
242 249 * We scanned past %pc, but didn't find an instruction that
243 250 * started at %pc. This means that either the caller specified
244 251 * an invalid address, or we ran into something other than code
245 252 * during our scan. Virtually any combination of bytes can be
246 253 * construed as a valid Intel instruction, so any non-code bytes
247 254 * we encounter will have thrown off the scan.
248 255 */
249 256 goto done;
250 257 }
251 258
252 259 res = hist[(cur + n - MIN(n, nseen)) % n];
253 260
254 261 done:
255 262 dis_free(hist, sizeof (uint64_t) * n);
256 263 return (res);
257 264 }
258 265
259 266 /*
260 267 * Return the nth previous instruction's address. Return the same address
261 268 * to indicate failure.
262 269 */
263 270 uint64_t
264 271 dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
265 272 {
266 273 if (dhp->dh_arch->da_previnstr == NULL)
267 274 return (dis_generic_previnstr(dhp, pc, n));
268 275
269 276 return (dhp->dh_arch->da_previnstr(dhp, pc, n));
270 277 }
271 278
272 279 int
273 280 dis_min_instrlen(dis_handle_t *dhp)
274 281 {
275 282 return (dhp->dh_arch->da_min_instrlen(dhp));
276 283 }
277 284
278 285 int
279 286 dis_max_instrlen(dis_handle_t *dhp)
280 287 {
281 288 return (dhp->dh_arch->da_max_instrlen(dhp));
282 289 }
283 290
284 291 static int
285 292 dis_generic_instrlen(dis_handle_t *dhp, uint64_t pc)
286 293 {
287 294 if (dis_disassemble(dhp, pc, NULL, 0) != 0)
288 295 return (-1);
289 296
290 297 return (dhp->dh_addr - pc);
291 298 }
292 299
293 300 int
294 301 dis_instrlen(dis_handle_t *dhp, uint64_t pc)
295 302 {
296 303 if (dhp->dh_arch->da_instrlen == NULL)
297 304 return (dis_generic_instrlen(dhp, pc));
298 305
299 306 return (dhp->dh_arch->da_instrlen(dhp, pc));
300 307 }
301 308
302 309 int
303 310 dis_vsnprintf(char *restrict s, size_t n, const char *restrict format,
304 311 va_list args)
305 312 {
306 313 #ifdef DIS_STANDALONE
307 314 return (mdb_iob_vsnprintf(s, n, format, args));
308 315 #else
309 316 return (vsnprintf(s, n, format, args));
310 317 #endif
311 318 }
312 319
313 320 int
314 321 dis_snprintf(char *restrict s, size_t n, const char *restrict format, ...)
315 322 {
316 323 va_list args;
317 324
318 325 va_start(args, format);
319 326 n = dis_vsnprintf(s, n, format, args);
320 327 va_end(args);
321 328
322 329 return (n);
323 330 }
|
↓ open down ↓ |
245 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX