Print this page
BE_32 wont work in libstand mode
take to dis and libdisasm with an axe; does not yet compile
@@ -25,15 +25,14 @@
*/
/*
* Copyright 2007 Jason King. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* The sparc disassembler is mostly straightforward, each instruction is
* represented by an inst_t structure. The inst_t definitions are organized
* into tables. The tables are correspond to the opcode maps documented in the
* various sparc architecture manuals. Each table defines the bit range of the
@@ -103,48 +102,53 @@
#if !defined(DIS_STANDALONE)
static void do_binary(uint32_t);
#endif /* DIS_STANDALONE */
-dis_handle_t *
-dis_handle_create(int flags, void *data, dis_lookup_f lookup_func,
- dis_read_f read_func)
+static void
+dis_sparc_handle_detach(dis_handle_t *dhp)
{
+ dis_free(dhp->dh_arch_private, sizeof (dis_handle_sparc_t));
+ dhp->dh_arch_private = NULL;
+}
+static int
+dis_sparc_handle_attach(dis_handle_t *dhp)
+{
+ dis_handle_sparc_t *dhx;
+
#if !defined(DIS_STANDALONE)
char *opt = NULL;
char *opt2, *save, *end;
#endif
- dis_handle_t *dhp;
- if ((flags & (DIS_SPARC_V8|DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0) {
+ /* Validate architecture flags */
+ if ((dhp->dh_flags & (DIS_SPARC_V8|DIS_SPARC_V9|DIS_SPARC_V9_SGI))
+ == 0) {
(void) dis_seterrno(E_DIS_INVALFLAG);
- return (NULL);
+ return (-1);
}
- if ((dhp = dis_zalloc(sizeof (struct dis_handle))) == NULL) {
+ if ((dhx = dis_zalloc(sizeof (dis_handle_sparc_t))) == NULL) {
(void) dis_seterrno(E_DIS_NOMEM);
return (NULL);
}
+ dhx->dhx_debug = DIS_DEBUG_COMPAT;
+ dhp->dh_arch_private = dhx;
- dhp->dh_lookup = lookup_func;
- dhp->dh_read = read_func;
- dhp->dh_flags = flags;
- dhp->dh_data = data;
- dhp->dh_debug = DIS_DEBUG_COMPAT;
-
#if !defined(DIS_STANDALONE)
opt = getenv("_LIBDISASM_DEBUG");
if (opt == NULL)
- return (dhp);
+ return (0);
opt2 = strdup(opt);
if (opt2 == NULL) {
dis_handle_destroy(dhp);
+ dis_free(dhx, sizeof (dis_handle_sparc_t));
(void) dis_seterrno(E_DIS_NOMEM);
- return (NULL);
+ return (-1);
}
save = opt2;
while (opt2 != NULL) {
end = strchr(opt2, ',');
@@ -151,64 +155,47 @@
if (end != 0)
*end++ = '\0';
if (strcasecmp("synth-all", opt2) == 0)
- dhp->dh_debug |= DIS_DEBUG_SYN_ALL;
+ dhx->dhx_debug |= DIS_DEBUG_SYN_ALL;
if (strcasecmp("compat", opt2) == 0)
- dhp->dh_debug |= DIS_DEBUG_COMPAT;
+ dhx->dhx_debug |= DIS_DEBUG_COMPAT;
if (strcasecmp("synth-none", opt2) == 0)
- dhp->dh_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
+ dhx->dhx_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
if (strcasecmp("binary", opt2) == 0)
- dhp->dh_debug |= DIS_DEBUG_PRTBIN;
+ dhx->dhx_debug |= DIS_DEBUG_PRTBIN;
if (strcasecmp("format", opt2) == 0)
- dhp->dh_debug |= DIS_DEBUG_PRTFMT;
+ dhx->dhx_debug |= DIS_DEBUG_PRTFMT;
if (strcasecmp("all", opt2) == 0)
- dhp->dh_debug = DIS_DEBUG_ALL;
+ dhx->dhx_debug = DIS_DEBUG_ALL;
if (strcasecmp("none", opt2) == 0)
- dhp->dh_debug = DIS_DEBUG_NONE;
+ dhx->dhx_debug = DIS_DEBUG_NONE;
opt2 = end;
}
free(save);
#endif /* DIS_STANDALONE */
- return (dhp);
+ return (0);
}
-void
-dis_handle_destroy(dis_handle_t *dhp)
+/* ARGSUSED */
+static int
+dis_sparc_max_instrlen(dis_handle_t *dhp)
{
- dis_free(dhp, sizeof (dis_handle_t));
+ return (4);
}
-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;
-}
-
/* ARGSUSED */
-int
-dis_max_instrlen(dis_handle_t *dhp)
+static int
+dis_sparc_min_instrlen(dis_handle_t *dhp)
{
return (4);
}
/*
@@ -215,12 +202,12 @@
* The dis_i386.c comment for this says it returns the previous instruction,
* however, I'm fairly sure it's actually returning the _address_ of the
* nth previous instruction.
*/
/* ARGSUSED */
-uint64_t
-dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
+static uint64_t
+dis_sparc_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
{
if (n <= 0)
return (pc);
if (pc < n)
@@ -227,13 +214,15 @@
return (pc);
return (pc - n*4);
}
-int
-dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
+static int
+dis_sparc_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
+ size_t buflen)
{
+ dis_handle_sparc_t *dhx = dhp->dh_arch_private;
const table_t *tp = &initial_table;
const inst_t *inp = NULL;
uint32_t instr;
uint32_t idx = 0;
@@ -240,21 +229,23 @@
if (dhp->dh_read(dhp->dh_data, addr, &instr, sizeof (instr)) !=
sizeof (instr))
return (-1);
- dhp->dh_buf = buf;
- dhp->dh_buflen = buflen;
+ dhx->dhx_buf = buf;
+ dhx->dhx_buflen = buflen;
dhp->dh_addr = addr;
buf[0] = '\0';
/* this allows sparc code to be tested on x86 */
+#if !defined(DIS_STANDALONE)
instr = BE_32(instr);
+#endif /* DIS_STANDALONE */
#if !defined(DIS_STANDALONE)
- if ((dhp->dh_debug & DIS_DEBUG_PRTBIN) != 0)
+ if ((dhx->dhx_debug & DIS_DEBUG_PRTBIN) != 0)
do_binary(instr);
#endif /* DIS_STANDALONE */
/* CONSTCOND */
while (1) {
@@ -335,5 +326,27 @@
(void) fprintf(stderr, "DISASM: ");
prt_binary(instr, 32);
(void) fprintf(stderr, "\n");
}
#endif /* DIS_STANDALONE */
+
+static int
+dis_sparc_supports_flags(int flags)
+{
+ int archflags = flags & DIS_ARCH_MASK;
+
+ if (archflags == DIS_SPARC_V8 ||
+ (archflags & (DIS_SPARC_V9 | DIS_SPARC_V8)) == DIS_SPARC_V9)
+ return (1);
+
+ return (0);
+}
+
+const dis_arch_t dis_arch_sparc = {
+ dis_sparc_supports_flags,
+ dis_sparc_handle_attach,
+ dis_sparc_handle_detach,
+ dis_sparc_disassemble,
+ dis_sparc_previnstr,
+ dis_sparc_min_instrlen,
+ dis_sparc_max_instrlen
+};