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