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 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 2015 Nexenta Systems, Inc. All rights reserved.
29 #include <libdisasm.h>
31 #include "dis_tables.h"
32 #include "libdisasm_impl.h"
34 typedef struct dis_handle_i386
{
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.
46 check_func(void *data
)
48 dis_handle_t
*dhp
= data
;
52 if (dhp
->dh_lookup(dhp
->dh_data
, dhp
->dh_addr
, NULL
, 0, &start
, &len
)
56 if (start
< dhp
->dh_addr
)
57 return (dhp
->dh_addr
> start
+ len
- 0x10);
66 dis_handle_t
*dhp
= data
;
68 if (dhp
->dh_read(dhp
->dh_data
, dhp
->dh_addr
, &byte
, sizeof (byte
)) !=
78 do_lookup(void *data
, uint64_t addr
, char *buf
, size_t buflen
)
80 dis_handle_t
*dhp
= data
;
82 return (dhp
->dh_lookup(dhp
->dh_data
, addr
, buf
, buflen
, NULL
, NULL
));
86 dis_i386_handle_detach(dis_handle_t
*dhp
)
88 dis_free(dhp
->dh_arch_private
, sizeof (dis_handle_i386_t
));
89 dhp
->dh_arch_private
= NULL
;
93 dis_i386_handle_attach(dis_handle_t
*dhp
)
95 dis_handle_i386_t
*dhx
;
98 * Validate architecture flags
100 if (dhp
->dh_flags
& ~(DIS_X86
|
101 DIS_SIZE_16
| DIS_SIZE_32
| DIS_SIZE_64
|
102 DIS_OCTAL
| DIS_NOIMMSYM
)) {
103 (void) dis_seterrno(E_DIS_INVALFLAG
);
108 * Create and initialize the internal structure
110 if ((dhx
= dis_zalloc(sizeof (dis_handle_i386_t
))) == NULL
) {
111 (void) dis_seterrno(E_DIS_NOMEM
);
114 dhp
->dh_arch_private
= dhx
;
117 * Initialize x86-specific architecture structure
119 if (dhp
->dh_flags
& DIS_SIZE_16
)
120 dhx
->dhx_mode
= SIZE16
;
121 else if (dhp
->dh_flags
& DIS_SIZE_64
)
122 dhx
->dhx_mode
= SIZE64
;
124 dhx
->dhx_mode
= SIZE32
;
126 if (dhp
->dh_flags
& DIS_OCTAL
)
127 dhx
->dhx_dis
.d86_flags
= DIS_F_OCTAL
;
129 dhx
->dhx_dis
.d86_sprintf_func
= dis_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
;
134 dhx
->dhx_dis
.d86_data
= dhp
;
140 dis_i386_disassemble(dis_handle_t
*dhp
, uint64_t addr
, char *buf
,
143 dis_handle_i386_t
*dhx
= dhp
->dh_arch_private
;
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
;
150 dhx
->dhx_dis
.d86_flags
&= ~DIS_F_NOIMMSYM
;
152 if (dtrace_disx86(&dhx
->dhx_dis
, dhx
->dhx_mode
) != 0)
156 dtrace_disx86_str(&dhx
->dhx_dis
, dhx
->dhx_mode
, addr
, buf
,
164 dis_i386_max_instrlen(dis_handle_t
*dhp
)
171 dis_i386_min_instrlen(dis_handle_t
*dhp
)
177 dis_i386_supports_flags(int flags
)
179 if ((flags
& DIS_ARCH_MASK
) == DIS_X86
&&
180 DIS_SIZE_CHECK(flags
, DIS_SIZE_16
| DIS_SIZE_32
| DIS_SIZE_64
))
186 dis_arch_t dis_arch_i386
= {
187 .da_supports_flags
= dis_i386_supports_flags
,
188 .da_handle_attach
= dis_i386_handle_attach
,
189 .da_handle_detach
= dis_i386_handle_detach
,
190 .da_disassemble
= dis_i386_disassemble
,
191 .da_min_instrlen
= dis_i386_min_instrlen
,
192 .da_max_instrlen
= dis_i386_max_instrlen
,