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