1dc0093f4Seschrock /* 2dc0093f4Seschrock * CDDL HEADER START 3dc0093f4Seschrock * 4dc0093f4Seschrock * The contents of this file are subject to the terms of the 5dc0093f4Seschrock * Common Development and Distribution License (the "License"). 6dc0093f4Seschrock * You may not use this file except in compliance with the License. 7dc0093f4Seschrock * 8dc0093f4Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9dc0093f4Seschrock * or http://www.opensolaris.org/os/licensing. 10dc0093f4Seschrock * See the License for the specific language governing permissions 11dc0093f4Seschrock * and limitations under the License. 12dc0093f4Seschrock * 13dc0093f4Seschrock * When distributing Covered Code, include this CDDL HEADER in each 14dc0093f4Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15dc0093f4Seschrock * If applicable, add the following below this CDDL HEADER, with the 16dc0093f4Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 17dc0093f4Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 18dc0093f4Seschrock * 19dc0093f4Seschrock * CDDL HEADER END 20dc0093f4Seschrock */ 21dc0093f4Seschrock 22dc0093f4Seschrock /* 23dc0093f4Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24dc0093f4Seschrock * Use is subject to license terms. 25*f7184619SJoshua M. Clulow * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org> 26*f7184619SJoshua M. Clulow * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 27dc0093f4Seschrock */ 28dc0093f4Seschrock 29dc0093f4Seschrock #include <libdisasm.h> 30dc0093f4Seschrock #include <stdlib.h> 31dc0093f4Seschrock #ifdef DIS_STANDALONE 32dc0093f4Seschrock #include <mdb/mdb_modapi.h> 33*f7184619SJoshua M. Clulow #define _MDB 34*f7184619SJoshua M. Clulow #include <mdb/mdb_io.h> 35*f7184619SJoshua M. Clulow #else 36*f7184619SJoshua M. Clulow #include <stdio.h> 37dc0093f4Seschrock #endif 38dc0093f4Seschrock 39*f7184619SJoshua M. Clulow #include "libdisasm_impl.h" 40*f7184619SJoshua M. Clulow 41dc0093f4Seschrock static int _dis_errno; 42dc0093f4Seschrock 43dc0093f4Seschrock /* 44*f7184619SJoshua M. Clulow * If we're building the standalone library, then we only want to 45*f7184619SJoshua M. Clulow * include support for disassembly of the native architecture. 46*f7184619SJoshua M. Clulow * The regular shared library should include support for all 47*f7184619SJoshua M. Clulow * architectures. 48*f7184619SJoshua M. Clulow */ 49*f7184619SJoshua M. Clulow #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64) 50*f7184619SJoshua M. Clulow extern dis_arch_t dis_arch_i386; 51*f7184619SJoshua M. Clulow #endif 52*f7184619SJoshua M. Clulow #if !defined(DIS_STANDALONE) || defined(__sparc) 53*f7184619SJoshua M. Clulow extern dis_arch_t dis_arch_sparc; 54*f7184619SJoshua M. Clulow #endif 55*f7184619SJoshua M. Clulow 56*f7184619SJoshua M. Clulow static dis_arch_t *dis_archs[] = { 57*f7184619SJoshua M. Clulow #if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64) 58*f7184619SJoshua M. Clulow &dis_arch_i386, 59*f7184619SJoshua M. Clulow #endif 60*f7184619SJoshua M. Clulow #if !defined(DIS_STANDALONE) || defined(__sparc) 61*f7184619SJoshua M. Clulow &dis_arch_sparc, 62*f7184619SJoshua M. Clulow #endif 63*f7184619SJoshua M. Clulow NULL 64*f7184619SJoshua M. Clulow }; 65*f7184619SJoshua M. Clulow 66*f7184619SJoshua M. Clulow /* 67dc0093f4Seschrock * For the standalone library, we need to link against mdb's malloc/free. 68dc0093f4Seschrock * Otherwise, use the standard malloc/free. 69dc0093f4Seschrock */ 70dc0093f4Seschrock #ifdef DIS_STANDALONE 71dc0093f4Seschrock void * 72dc0093f4Seschrock dis_zalloc(size_t bytes) 73dc0093f4Seschrock { 74dc0093f4Seschrock return (mdb_zalloc(bytes, UM_SLEEP)); 75dc0093f4Seschrock } 76dc0093f4Seschrock 77dc0093f4Seschrock void 78dc0093f4Seschrock dis_free(void *ptr, size_t bytes) 79dc0093f4Seschrock { 80dc0093f4Seschrock mdb_free(ptr, bytes); 81dc0093f4Seschrock } 82dc0093f4Seschrock #else 83dc0093f4Seschrock void * 84dc0093f4Seschrock dis_zalloc(size_t bytes) 85dc0093f4Seschrock { 86dc0093f4Seschrock return (calloc(1, bytes)); 87dc0093f4Seschrock } 88dc0093f4Seschrock 89dc0093f4Seschrock /*ARGSUSED*/ 90dc0093f4Seschrock void 91dc0093f4Seschrock dis_free(void *ptr, size_t bytes) 92dc0093f4Seschrock { 93dc0093f4Seschrock free(ptr); 94dc0093f4Seschrock } 95dc0093f4Seschrock #endif 96dc0093f4Seschrock 97dc0093f4Seschrock int 98dc0093f4Seschrock dis_seterrno(int error) 99dc0093f4Seschrock { 100dc0093f4Seschrock _dis_errno = error; 101dc0093f4Seschrock return (-1); 102dc0093f4Seschrock } 103dc0093f4Seschrock 104dc0093f4Seschrock int 105dc0093f4Seschrock dis_errno(void) 106dc0093f4Seschrock { 107dc0093f4Seschrock return (_dis_errno); 108dc0093f4Seschrock } 109dc0093f4Seschrock 110dc0093f4Seschrock const char * 111dc0093f4Seschrock dis_strerror(int error) 112dc0093f4Seschrock { 113dc0093f4Seschrock switch (error) { 114dc0093f4Seschrock case E_DIS_NOMEM: 115dc0093f4Seschrock return ("out of memory"); 116dc0093f4Seschrock case E_DIS_INVALFLAG: 117dc0093f4Seschrock return ("invalid flags for this architecture"); 118*f7184619SJoshua M. Clulow case E_DIS_UNSUPARCH: 119*f7184619SJoshua M. Clulow return ("unsupported machine architecture"); 120dc0093f4Seschrock default: 121dc0093f4Seschrock return ("unknown error"); 122dc0093f4Seschrock } 123dc0093f4Seschrock } 124*f7184619SJoshua M. Clulow 125*f7184619SJoshua M. Clulow void 126*f7184619SJoshua M. Clulow dis_set_data(dis_handle_t *dhp, void *data) 127*f7184619SJoshua M. Clulow { 128*f7184619SJoshua M. Clulow dhp->dh_data = data; 129*f7184619SJoshua M. Clulow } 130*f7184619SJoshua M. Clulow 131*f7184619SJoshua M. Clulow void 132*f7184619SJoshua M. Clulow dis_flags_set(dis_handle_t *dhp, int f) 133*f7184619SJoshua M. Clulow { 134*f7184619SJoshua M. Clulow dhp->dh_flags |= f; 135*f7184619SJoshua M. Clulow } 136*f7184619SJoshua M. Clulow 137*f7184619SJoshua M. Clulow void 138*f7184619SJoshua M. Clulow dis_flags_clear(dis_handle_t *dhp, int f) 139*f7184619SJoshua M. Clulow { 140*f7184619SJoshua M. Clulow dhp->dh_flags &= ~f; 141*f7184619SJoshua M. Clulow } 142*f7184619SJoshua M. Clulow 143*f7184619SJoshua M. Clulow void 144*f7184619SJoshua M. Clulow dis_handle_destroy(dis_handle_t *dhp) 145*f7184619SJoshua M. Clulow { 146*f7184619SJoshua M. Clulow dhp->dh_arch->da_handle_detach(dhp); 147*f7184619SJoshua M. Clulow dis_free(dhp, sizeof (dis_handle_t)); 148*f7184619SJoshua M. Clulow } 149*f7184619SJoshua M. Clulow 150*f7184619SJoshua M. Clulow dis_handle_t * 151*f7184619SJoshua M. Clulow dis_handle_create(int flags, void *data, dis_lookup_f lookup_func, 152*f7184619SJoshua M. Clulow dis_read_f read_func) 153*f7184619SJoshua M. Clulow { 154*f7184619SJoshua M. Clulow dis_handle_t *dhp; 155*f7184619SJoshua M. Clulow dis_arch_t *arch = NULL; 156*f7184619SJoshua M. Clulow int i; 157*f7184619SJoshua M. Clulow 158*f7184619SJoshua M. Clulow /* Select an architecture based on flags */ 159*f7184619SJoshua M. Clulow for (i = 0; dis_archs[i] != NULL; i++) { 160*f7184619SJoshua M. Clulow if (dis_archs[i]->da_supports_flags(flags)) { 161*f7184619SJoshua M. Clulow arch = dis_archs[i]; 162*f7184619SJoshua M. Clulow break; 163*f7184619SJoshua M. Clulow } 164*f7184619SJoshua M. Clulow } 165*f7184619SJoshua M. Clulow if (arch == NULL) { 166*f7184619SJoshua M. Clulow (void) dis_seterrno(E_DIS_UNSUPARCH); 167*f7184619SJoshua M. Clulow return (NULL); 168*f7184619SJoshua M. Clulow } 169*f7184619SJoshua M. Clulow 170*f7184619SJoshua M. Clulow if ((dhp = dis_zalloc(sizeof (dis_handle_t))) == NULL) { 171*f7184619SJoshua M. Clulow (void) dis_seterrno(E_DIS_NOMEM); 172*f7184619SJoshua M. Clulow return (NULL); 173*f7184619SJoshua M. Clulow } 174*f7184619SJoshua M. Clulow dhp->dh_arch = arch; 175*f7184619SJoshua M. Clulow dhp->dh_lookup = lookup_func; 176*f7184619SJoshua M. Clulow dhp->dh_read = read_func; 177*f7184619SJoshua M. Clulow dhp->dh_flags = flags; 178*f7184619SJoshua M. Clulow dhp->dh_data = data; 179*f7184619SJoshua M. Clulow 180*f7184619SJoshua M. Clulow /* 181*f7184619SJoshua M. Clulow * Allow the architecture-specific code to allocate 182*f7184619SJoshua M. Clulow * its private data. 183*f7184619SJoshua M. Clulow */ 184*f7184619SJoshua M. Clulow if (arch->da_handle_attach(dhp) != 0) { 185*f7184619SJoshua M. Clulow dis_free(dhp, sizeof (dis_handle_t)); 186*f7184619SJoshua M. Clulow /* dis errno already set */ 187*f7184619SJoshua M. Clulow return (NULL); 188*f7184619SJoshua M. Clulow } 189*f7184619SJoshua M. Clulow 190*f7184619SJoshua M. Clulow return (dhp); 191*f7184619SJoshua M. Clulow } 192*f7184619SJoshua M. Clulow 193*f7184619SJoshua M. Clulow int 194*f7184619SJoshua M. Clulow dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen) 195*f7184619SJoshua M. Clulow { 196*f7184619SJoshua M. Clulow return (dhp->dh_arch->da_disassemble(dhp, addr, buf, buflen)); 197*f7184619SJoshua M. Clulow } 198*f7184619SJoshua M. Clulow 199*f7184619SJoshua M. Clulow uint64_t 200*f7184619SJoshua M. Clulow dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n) 201*f7184619SJoshua M. Clulow { 202*f7184619SJoshua M. Clulow return (dhp->dh_arch->da_previnstr(dhp, pc, n)); 203*f7184619SJoshua M. Clulow } 204*f7184619SJoshua M. Clulow 205*f7184619SJoshua M. Clulow int 206*f7184619SJoshua M. Clulow dis_min_instrlen(dis_handle_t *dhp) 207*f7184619SJoshua M. Clulow { 208*f7184619SJoshua M. Clulow return (dhp->dh_arch->da_min_instrlen(dhp)); 209*f7184619SJoshua M. Clulow } 210*f7184619SJoshua M. Clulow 211*f7184619SJoshua M. Clulow int 212*f7184619SJoshua M. Clulow dis_max_instrlen(dis_handle_t *dhp) 213*f7184619SJoshua M. Clulow { 214*f7184619SJoshua M. Clulow return (dhp->dh_arch->da_max_instrlen(dhp)); 215*f7184619SJoshua M. Clulow } 216*f7184619SJoshua M. Clulow 217*f7184619SJoshua M. Clulow int 218*f7184619SJoshua M. Clulow dis_instrlen(dis_handle_t *dhp, uint64_t pc) 219*f7184619SJoshua M. Clulow { 220*f7184619SJoshua M. Clulow return (dhp->dh_arch->da_instrlen(dhp, pc)); 221*f7184619SJoshua M. Clulow } 222*f7184619SJoshua M. Clulow 223*f7184619SJoshua M. Clulow int 224*f7184619SJoshua M. Clulow dis_vsnprintf(char *restrict s, size_t n, const char *restrict format, 225*f7184619SJoshua M. Clulow va_list args) 226*f7184619SJoshua M. Clulow { 227*f7184619SJoshua M. Clulow #ifdef DIS_STANDALONE 228*f7184619SJoshua M. Clulow return (mdb_iob_vsnprintf(s, n, format, args)); 229*f7184619SJoshua M. Clulow #else 230*f7184619SJoshua M. Clulow return (vsnprintf(s, n, format, args)); 231*f7184619SJoshua M. Clulow #endif 232*f7184619SJoshua M. Clulow } 233*f7184619SJoshua M. Clulow 234*f7184619SJoshua M. Clulow int 235*f7184619SJoshua M. Clulow dis_snprintf(char *restrict s, size_t n, const char *restrict format, ...) 236*f7184619SJoshua M. Clulow { 237*f7184619SJoshua M. Clulow va_list args; 238*f7184619SJoshua M. Clulow 239*f7184619SJoshua M. Clulow va_start(args, format); 240*f7184619SJoshua M. Clulow n = dis_vsnprintf(s, n, format, args); 241*f7184619SJoshua M. Clulow va_end(args); 242*f7184619SJoshua M. Clulow 243*f7184619SJoshua M. Clulow return (n); 244*f7184619SJoshua M. Clulow } 245