4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
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.
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]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
29 #include <libdisasm.h>
32 #include <mdb/mdb_modapi.h>
34 #include <mdb/mdb_io.h>
39 #include "libdisasm_impl.h"
41 static int _dis_errno
;
44 * If we're building the standalone library, then we only want to
45 * include support for disassembly of the native architecture.
46 * The regular shared library should include support for all
49 #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64)
50 extern dis_arch_t dis_arch_i386
;
52 #if !defined(DIS_STANDALONE) || defined(__sparc)
53 extern dis_arch_t dis_arch_sparc
;
56 static dis_arch_t
*dis_archs
[] = {
57 #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64)
60 #if !defined(DIS_STANDALONE) || defined(__sparc)
67 * For the standalone library, we need to link against mdb's malloc/free.
68 * Otherwise, use the standard malloc/free.
72 dis_zalloc(size_t bytes
)
74 return (mdb_zalloc(bytes
, UM_SLEEP
));
78 dis_free(void *ptr
, size_t bytes
)
84 dis_zalloc(size_t bytes
)
86 return (calloc(1, bytes
));
91 dis_free(void *ptr
, size_t bytes
)
98 dis_seterrno(int error
)
111 dis_strerror(int error
)
115 return ("out of memory");
116 case E_DIS_INVALFLAG
:
117 return ("invalid flags for this architecture");
118 case E_DIS_UNSUPARCH
:
119 return ("unsupported machine architecture");
121 return ("unknown error");
126 dis_set_data(dis_handle_t
*dhp
, void *data
)
132 dis_flags_set(dis_handle_t
*dhp
, int f
)
138 dis_flags_clear(dis_handle_t
*dhp
, int f
)
144 dis_handle_destroy(dis_handle_t
*dhp
)
146 dhp
->dh_arch
->da_handle_detach(dhp
);
147 dis_free(dhp
, sizeof (dis_handle_t
));
151 dis_handle_create(int flags
, void *data
, dis_lookup_f lookup_func
,
152 dis_read_f read_func
)
155 dis_arch_t
*arch
= NULL
;
158 /* Select an architecture based on flags */
159 for (i
= 0; dis_archs
[i
] != NULL
; i
++) {
160 if (dis_archs
[i
]->da_supports_flags(flags
)) {
166 (void) dis_seterrno(E_DIS_UNSUPARCH
);
170 if ((dhp
= dis_zalloc(sizeof (dis_handle_t
))) == NULL
) {
171 (void) dis_seterrno(E_DIS_NOMEM
);
175 dhp
->dh_lookup
= lookup_func
;
176 dhp
->dh_read
= read_func
;
177 dhp
->dh_flags
= flags
;
181 * Allow the architecture-specific code to allocate
184 if (arch
->da_handle_attach(dhp
) != 0) {
185 dis_free(dhp
, sizeof (dis_handle_t
));
186 /* dis errno already set */
194 dis_disassemble(dis_handle_t
*dhp
, uint64_t addr
, char *buf
, size_t buflen
)
196 return (dhp
->dh_arch
->da_disassemble(dhp
, addr
, buf
, buflen
));
200 * On some instruction sets (e.g., x86), we have no choice except to
201 * disassemble everything from the start of the symbol, and stop when we
202 * have reached our instruction address. If we're not in the middle of a
203 * known symbol, then we return the same address to indicate failure.
206 dis_generic_previnstr(dis_handle_t
*dhp
, uint64_t pc
, int n
)
208 uint64_t *hist
, addr
, start
;
215 if (dhp
->dh_lookup(dhp
->dh_data
, pc
, NULL
, 0, &start
, NULL
) != 0 ||
219 hist
= dis_zalloc(sizeof (uint64_t) * n
);
221 for (cur
= 0, nseen
= 0, addr
= start
; addr
< pc
; addr
= dhp
->dh_addr
) {
226 /* if we cannot make forward progress, give up */
227 if (dis_disassemble(dhp
, addr
, NULL
, 0) != 0)
233 * We scanned past %pc, but didn't find an instruction that
234 * started at %pc. This means that either the caller specified
235 * an invalid address, or we ran into something other than code
236 * during our scan. Virtually any combination of bytes can be
237 * construed as a valid Intel instruction, so any non-code bytes
238 * we encounter will have thrown off the scan.
243 res
= hist
[(cur
+ n
- MIN(n
, nseen
)) % n
];
246 dis_free(hist
, sizeof (uint64_t) * n
);
251 * Return the nth previous instruction's address. Return the same address
252 * to indicate failure.
255 dis_previnstr(dis_handle_t
*dhp
, uint64_t pc
, int n
)
257 if (dhp
->dh_arch
->da_previnstr
== NULL
)
258 return (dis_generic_previnstr(dhp
, pc
, n
));
260 return (dhp
->dh_arch
->da_previnstr(dhp
, pc
, n
));
264 dis_min_instrlen(dis_handle_t
*dhp
)
266 return (dhp
->dh_arch
->da_min_instrlen(dhp
));
270 dis_max_instrlen(dis_handle_t
*dhp
)
272 return (dhp
->dh_arch
->da_max_instrlen(dhp
));
276 dis_generic_instrlen(dis_handle_t
*dhp
, uint64_t pc
)
278 if (dis_disassemble(dhp
, pc
, NULL
, 0) != 0)
281 return (dhp
->dh_addr
- pc
);
285 dis_instrlen(dis_handle_t
*dhp
, uint64_t pc
)
287 if (dhp
->dh_arch
->da_instrlen
== NULL
)
288 return (dis_generic_instrlen(dhp
, pc
));
290 return (dhp
->dh_arch
->da_instrlen(dhp
, pc
));
294 dis_vsnprintf(char *restrict s
, size_t n
, const char *restrict format
,
297 #ifdef DIS_STANDALONE
298 return (mdb_iob_vsnprintf(s
, n
, format
, args
));
300 return (vsnprintf(s
, n
, format
, args
));
305 dis_snprintf(char *restrict s
, size_t n
, const char *restrict format
, ...)
309 va_start(args
, format
);
310 n
= dis_vsnprintf(s
, n
, format
, args
);