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
;
55 #if !defined(DIS_STANDALONE) || defined(__s390) || defined(__s390x)
56 extern dis_arch_t dis_arch_s390
;
59 static dis_arch_t
*dis_archs
[] = {
60 #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64)
63 #if !defined(DIS_STANDALONE) || defined(__sparc)
66 #if !defined(DIS_STANDALONE) || defined(__s390) || defined(__s390x)
73 * For the standalone library, we need to link against mdb's malloc/free.
74 * Otherwise, use the standard malloc/free.
78 dis_zalloc(size_t bytes
)
80 return (mdb_zalloc(bytes
, UM_SLEEP
));
84 dis_free(void *ptr
, size_t bytes
)
90 dis_zalloc(size_t bytes
)
92 return (calloc(1, bytes
));
97 dis_free(void *ptr
, size_t bytes
)
104 dis_seterrno(int error
)
117 dis_strerror(int error
)
121 return ("out of memory");
122 case E_DIS_INVALFLAG
:
123 return ("invalid flags for this architecture");
124 case E_DIS_UNSUPARCH
:
125 return ("unsupported machine architecture");
127 return ("unknown error");
132 dis_set_data(dis_handle_t
*dhp
, void *data
)
138 dis_flags_set(dis_handle_t
*dhp
, int f
)
144 dis_flags_clear(dis_handle_t
*dhp
, int f
)
150 dis_handle_destroy(dis_handle_t
*dhp
)
152 if (dhp
->dh_arch
->da_handle_detach
!= NULL
)
153 dhp
->dh_arch
->da_handle_detach(dhp
);
155 dis_free(dhp
, sizeof (dis_handle_t
));
159 dis_handle_create(int flags
, void *data
, dis_lookup_f lookup_func
,
160 dis_read_f read_func
)
163 dis_arch_t
*arch
= NULL
;
166 /* Select an architecture based on flags */
167 for (i
= 0; dis_archs
[i
] != NULL
; i
++) {
168 if (dis_archs
[i
]->da_supports_flags(flags
)) {
174 (void) dis_seterrno(E_DIS_UNSUPARCH
);
178 if ((dhp
= dis_zalloc(sizeof (dis_handle_t
))) == NULL
) {
179 (void) dis_seterrno(E_DIS_NOMEM
);
183 dhp
->dh_lookup
= lookup_func
;
184 dhp
->dh_read
= read_func
;
185 dhp
->dh_flags
= flags
;
189 * Allow the architecture-specific code to allocate
192 if (arch
->da_handle_attach
!= NULL
&&
193 arch
->da_handle_attach(dhp
) != 0) {
194 dis_free(dhp
, sizeof (dis_handle_t
));
195 /* dis errno already set */
203 dis_disassemble(dis_handle_t
*dhp
, uint64_t addr
, char *buf
, size_t buflen
)
205 return (dhp
->dh_arch
->da_disassemble(dhp
, addr
, buf
, buflen
));
209 * On some instruction sets (e.g., x86), we have no choice except to
210 * disassemble everything from the start of the symbol, and stop when we
211 * have reached our instruction address. If we're not in the middle of a
212 * known symbol, then we return the same address to indicate failure.
215 dis_generic_previnstr(dis_handle_t
*dhp
, uint64_t pc
, int n
)
217 uint64_t *hist
, addr
, start
;
224 if (dhp
->dh_lookup(dhp
->dh_data
, pc
, NULL
, 0, &start
, NULL
) != 0 ||
228 hist
= dis_zalloc(sizeof (uint64_t) * n
);
230 for (cur
= 0, nseen
= 0, addr
= start
; addr
< pc
; addr
= dhp
->dh_addr
) {
235 /* if we cannot make forward progress, give up */
236 if (dis_disassemble(dhp
, addr
, NULL
, 0) != 0)
242 * We scanned past %pc, but didn't find an instruction that
243 * started at %pc. This means that either the caller specified
244 * an invalid address, or we ran into something other than code
245 * during our scan. Virtually any combination of bytes can be
246 * construed as a valid Intel instruction, so any non-code bytes
247 * we encounter will have thrown off the scan.
252 res
= hist
[(cur
+ n
- MIN(n
, nseen
)) % n
];
255 dis_free(hist
, sizeof (uint64_t) * n
);
260 * Return the nth previous instruction's address. Return the same address
261 * to indicate failure.
264 dis_previnstr(dis_handle_t
*dhp
, uint64_t pc
, int n
)
266 if (dhp
->dh_arch
->da_previnstr
== NULL
)
267 return (dis_generic_previnstr(dhp
, pc
, n
));
269 return (dhp
->dh_arch
->da_previnstr(dhp
, pc
, n
));
273 dis_min_instrlen(dis_handle_t
*dhp
)
275 return (dhp
->dh_arch
->da_min_instrlen(dhp
));
279 dis_max_instrlen(dis_handle_t
*dhp
)
281 return (dhp
->dh_arch
->da_max_instrlen(dhp
));
285 dis_generic_instrlen(dis_handle_t
*dhp
, uint64_t pc
)
287 if (dis_disassemble(dhp
, pc
, NULL
, 0) != 0)
290 return (dhp
->dh_addr
- pc
);
294 dis_instrlen(dis_handle_t
*dhp
, uint64_t pc
)
296 if (dhp
->dh_arch
->da_instrlen
== NULL
)
297 return (dis_generic_instrlen(dhp
, pc
));
299 return (dhp
->dh_arch
->da_instrlen(dhp
, pc
));
303 dis_vsnprintf(char *restrict s
, size_t n
, const char *restrict format
,
306 #ifdef DIS_STANDALONE
307 return (mdb_iob_vsnprintf(s
, n
, format
, args
));
309 return (vsnprintf(s
, n
, format
, args
));
314 dis_snprintf(char *restrict s
, size_t n
, const char *restrict format
, ...)
318 va_start(args
, format
);
319 n
= dis_vsnprintf(s
, n
, format
, args
);