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_SIZE16
| DIS_X86_SIZE32
| DIS_X86_SIZE64
|
101 DIS_OCTAL
| DIS_NOIMMSYM
)) {
102 (void) dis_seterrno(E_DIS_INVALFLAG
);
107 * Create and initialize the internal structure
109 if ((dhx
= dis_zalloc(sizeof (dis_handle_i386_t
))) == NULL
) {
110 (void) dis_seterrno(E_DIS_NOMEM
);
113 dhp
->dh_arch_private
= dhx
;
116 * Initialize x86-specific architecture structure
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
;
123 dhx
->dhx_mode
= SIZE32
;
125 if (dhp
->dh_flags
& DIS_OCTAL
)
126 dhx
->dhx_dis
.d86_flags
= DIS_F_OCTAL
;
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
;
133 dhx
->dhx_dis
.d86_data
= dhp
;
139 dis_i386_disassemble(dis_handle_t
*dhp
, uint64_t addr
, char *buf
,
142 dis_handle_i386_t
*dhx
= dhp
->dh_arch_private
;
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
;
149 dhx
->dhx_dis
.d86_flags
&= ~DIS_F_NOIMMSYM
;
151 if (dtrace_disx86(&dhx
->dhx_dis
, dhx
->dhx_mode
) != 0)
155 dtrace_disx86_str(&dhx
->dhx_dis
, dhx
->dhx_mode
, addr
, buf
,
163 dis_i386_max_instrlen(dis_handle_t
*dhp
)
170 dis_i386_min_instrlen(dis_handle_t
*dhp
)
176 dis_i386_supports_flags(int flags
)
178 int archflags
= flags
& DIS_ARCH_MASK
;
180 if (archflags
== DIS_X86_SIZE16
|| archflags
== DIS_X86_SIZE32
||
181 archflags
== DIS_X86_SIZE64
)
187 dis_arch_t dis_arch_i386
= {
188 .da_supports_flags
= dis_i386_supports_flags
,
189 .da_handle_attach
= dis_i386_handle_attach
,
190 .da_handle_detach
= dis_i386_handle_detach
,
191 .da_disassemble
= dis_i386_disassemble
,
192 .da_min_instrlen
= dis_i386_min_instrlen
,
193 .da_max_instrlen
= dis_i386_max_instrlen
,