diff options
author | Joshua M. Clulow <josh@sysmgr.org> | 2015-01-20 20:27:53 -0500 |
---|---|---|
committer | Dan McDonald <danmcd@omniti.com> | 2015-01-23 22:17:34 -0500 |
commit | f7184619589931c4b827180c213074c470f08a8f (patch) | |
tree | b8594d45bca78fc4eddbc8a0d35061dc23e8ba8b /usr/src/lib/libdisasm/common/libdisasm.c | |
parent | 22253b45e469decdb988b799c90598f2652597cd (diff) | |
download | illumos-joyent-f7184619589931c4b827180c213074c470f08a8f.tar.gz |
3317 dis(1) should support cross-target disassembly
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Joshua M. Clulow <josh@sysmgr.org>
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/lib/libdisasm/common/libdisasm.c')
-rw-r--r-- | usr/src/lib/libdisasm/common/libdisasm.c | 156 |
1 files changed, 154 insertions, 2 deletions
diff --git a/usr/src/lib/libdisasm/common/libdisasm.c b/usr/src/lib/libdisasm/common/libdisasm.c index 197c2c34df..7f040a04b8 100644 --- a/usr/src/lib/libdisasm/common/libdisasm.c +++ b/usr/src/lib/libdisasm/common/libdisasm.c @@ -22,19 +22,48 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org> + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <libdisasm.h> #include <stdlib.h> #ifdef DIS_STANDALONE #include <mdb/mdb_modapi.h> +#define _MDB +#include <mdb/mdb_io.h> +#else +#include <stdio.h> #endif +#include "libdisasm_impl.h" + static int _dis_errno; /* + * If we're building the standalone library, then we only want to + * include support for disassembly of the native architecture. + * The regular shared library should include support for all + * architectures. + */ +#if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64) +extern dis_arch_t dis_arch_i386; +#endif +#if !defined(DIS_STANDALONE) || defined(__sparc) +extern dis_arch_t dis_arch_sparc; +#endif + +static dis_arch_t *dis_archs[] = { +#if !defined(DIS_STANDALONE) || defined(__i386) || defined(__amd64) + &dis_arch_i386, +#endif +#if !defined(DIS_STANDALONE) || defined(__sparc) + &dis_arch_sparc, +#endif + NULL +}; + +/* * For the standalone library, we need to link against mdb's malloc/free. * Otherwise, use the standard malloc/free. */ @@ -86,7 +115,130 @@ dis_strerror(int error) return ("out of memory"); case E_DIS_INVALFLAG: return ("invalid flags for this architecture"); + case E_DIS_UNSUPARCH: + return ("unsupported machine architecture"); default: return ("unknown error"); } } + +void +dis_set_data(dis_handle_t *dhp, void *data) +{ + dhp->dh_data = data; +} + +void +dis_flags_set(dis_handle_t *dhp, int f) +{ + dhp->dh_flags |= f; +} + +void +dis_flags_clear(dis_handle_t *dhp, int f) +{ + dhp->dh_flags &= ~f; +} + +void +dis_handle_destroy(dis_handle_t *dhp) +{ + dhp->dh_arch->da_handle_detach(dhp); + dis_free(dhp, sizeof (dis_handle_t)); +} + +dis_handle_t * +dis_handle_create(int flags, void *data, dis_lookup_f lookup_func, + dis_read_f read_func) +{ + dis_handle_t *dhp; + dis_arch_t *arch = NULL; + int i; + + /* Select an architecture based on flags */ + for (i = 0; dis_archs[i] != NULL; i++) { + if (dis_archs[i]->da_supports_flags(flags)) { + arch = dis_archs[i]; + break; + } + } + if (arch == NULL) { + (void) dis_seterrno(E_DIS_UNSUPARCH); + return (NULL); + } + + if ((dhp = dis_zalloc(sizeof (dis_handle_t))) == NULL) { + (void) dis_seterrno(E_DIS_NOMEM); + return (NULL); + } + dhp->dh_arch = arch; + dhp->dh_lookup = lookup_func; + dhp->dh_read = read_func; + dhp->dh_flags = flags; + dhp->dh_data = data; + + /* + * Allow the architecture-specific code to allocate + * its private data. + */ + if (arch->da_handle_attach(dhp) != 0) { + dis_free(dhp, sizeof (dis_handle_t)); + /* dis errno already set */ + return (NULL); + } + + return (dhp); +} + +int +dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen) +{ + return (dhp->dh_arch->da_disassemble(dhp, addr, buf, buflen)); +} + +uint64_t +dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n) +{ + return (dhp->dh_arch->da_previnstr(dhp, pc, n)); +} + +int +dis_min_instrlen(dis_handle_t *dhp) +{ + return (dhp->dh_arch->da_min_instrlen(dhp)); +} + +int +dis_max_instrlen(dis_handle_t *dhp) +{ + return (dhp->dh_arch->da_max_instrlen(dhp)); +} + +int +dis_instrlen(dis_handle_t *dhp, uint64_t pc) +{ + return (dhp->dh_arch->da_instrlen(dhp, pc)); +} + +int +dis_vsnprintf(char *restrict s, size_t n, const char *restrict format, + va_list args) +{ +#ifdef DIS_STANDALONE + return (mdb_iob_vsnprintf(s, n, format, args)); +#else + return (vsnprintf(s, n, format, args)); +#endif +} + +int +dis_snprintf(char *restrict s, size_t n, const char *restrict format, ...) +{ + va_list args; + + va_start(args, format); + n = dis_vsnprintf(s, n, format, args); + va_end(args); + + return (n); +} |