Print this page
BE_32 wont work in libstand mode
take to dis and libdisasm with an axe; does not yet compile
*** 25,39 ****
*/
/*
* Copyright 2007 Jason King. All rights reserved.
* Use is subject to license terms.
*/
- #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
--- 25,38 ----
*/
/*
* Copyright 2007 Jason King. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
*/
/*
* 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,150 ****
#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)
{
#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) {
(void) dis_seterrno(E_DIS_INVALFLAG);
! return (NULL);
}
! if ((dhp = dis_zalloc(sizeof (struct dis_handle))) == NULL) {
(void) dis_seterrno(E_DIS_NOMEM);
return (NULL);
}
- 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);
opt2 = strdup(opt);
if (opt2 == NULL) {
dis_handle_destroy(dhp);
(void) dis_seterrno(E_DIS_NOMEM);
! return (NULL);
}
save = opt2;
while (opt2 != NULL) {
end = strchr(opt2, ',');
--- 102,154 ----
#if !defined(DIS_STANDALONE)
static void do_binary(uint32_t);
#endif /* DIS_STANDALONE */
! 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
! /* 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 (-1);
}
! 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;
#if !defined(DIS_STANDALONE)
opt = getenv("_LIBDISASM_DEBUG");
if (opt == NULL)
! 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 (-1);
}
save = opt2;
while (opt2 != NULL) {
end = strchr(opt2, ',');
*** 151,214 ****
if (end != 0)
*end++ = '\0';
if (strcasecmp("synth-all", opt2) == 0)
! dhp->dh_debug |= DIS_DEBUG_SYN_ALL;
if (strcasecmp("compat", opt2) == 0)
! dhp->dh_debug |= DIS_DEBUG_COMPAT;
if (strcasecmp("synth-none", opt2) == 0)
! dhp->dh_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
if (strcasecmp("binary", opt2) == 0)
! dhp->dh_debug |= DIS_DEBUG_PRTBIN;
if (strcasecmp("format", opt2) == 0)
! dhp->dh_debug |= DIS_DEBUG_PRTFMT;
if (strcasecmp("all", opt2) == 0)
! dhp->dh_debug = DIS_DEBUG_ALL;
if (strcasecmp("none", opt2) == 0)
! dhp->dh_debug = DIS_DEBUG_NONE;
opt2 = end;
}
free(save);
#endif /* DIS_STANDALONE */
! return (dhp);
}
! void
! dis_handle_destroy(dis_handle_t *dhp)
{
! dis_free(dhp, sizeof (dis_handle_t));
}
- 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)
{
return (4);
}
/*
--- 155,201 ----
if (end != 0)
*end++ = '\0';
if (strcasecmp("synth-all", opt2) == 0)
! dhx->dhx_debug |= DIS_DEBUG_SYN_ALL;
if (strcasecmp("compat", opt2) == 0)
! dhx->dhx_debug |= DIS_DEBUG_COMPAT;
if (strcasecmp("synth-none", opt2) == 0)
! dhx->dhx_debug &= ~(DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT);
if (strcasecmp("binary", opt2) == 0)
! dhx->dhx_debug |= DIS_DEBUG_PRTBIN;
if (strcasecmp("format", opt2) == 0)
! dhx->dhx_debug |= DIS_DEBUG_PRTFMT;
if (strcasecmp("all", opt2) == 0)
! dhx->dhx_debug = DIS_DEBUG_ALL;
if (strcasecmp("none", opt2) == 0)
! dhx->dhx_debug = DIS_DEBUG_NONE;
opt2 = end;
}
free(save);
#endif /* DIS_STANDALONE */
! return (0);
}
! /* ARGSUSED */
! static int
! dis_sparc_max_instrlen(dis_handle_t *dhp)
{
! return (4);
}
/* ARGSUSED */
! static int
! dis_sparc_min_instrlen(dis_handle_t *dhp)
{
return (4);
}
/*
*** 215,226 ****
* 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)
{
if (n <= 0)
return (pc);
if (pc < n)
--- 202,213 ----
* 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 */
! static uint64_t
! dis_sparc_previnstr(dis_handle_t *dhp, uint64_t pc, int n)
{
if (n <= 0)
return (pc);
if (pc < n)
*** 227,239 ****
return (pc);
return (pc - n*4);
}
! int
! dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
{
const table_t *tp = &initial_table;
const inst_t *inp = NULL;
uint32_t instr;
uint32_t idx = 0;
--- 214,228 ----
return (pc);
return (pc - n*4);
}
! 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,260 ****
if (dhp->dh_read(dhp->dh_data, addr, &instr, sizeof (instr)) !=
sizeof (instr))
return (-1);
! dhp->dh_buf = buf;
! dhp->dh_buflen = buflen;
dhp->dh_addr = addr;
buf[0] = '\0';
/* this allows sparc code to be tested on x86 */
instr = BE_32(instr);
#if !defined(DIS_STANDALONE)
! if ((dhp->dh_debug & DIS_DEBUG_PRTBIN) != 0)
do_binary(instr);
#endif /* DIS_STANDALONE */
/* CONSTCOND */
while (1) {
--- 229,251 ----
if (dhp->dh_read(dhp->dh_data, addr, &instr, sizeof (instr)) !=
sizeof (instr))
return (-1);
! 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 ((dhx->dhx_debug & DIS_DEBUG_PRTBIN) != 0)
do_binary(instr);
#endif /* DIS_STANDALONE */
/* CONSTCOND */
while (1) {
*** 335,339 ****
--- 326,352 ----
(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
+ };