radare2/libr/asm/p/asm_m68k_cs.c
2018-11-23 20:50:23 +01:00

167 lines
3.4 KiB
C

/* radare2 - LGPL - Copyright 2015-2018 - pancake */
#include <r_asm.h>
#include <r_lib.h>
#include <capstone/capstone.h>
#ifdef CAPSTONE_M68K_H
#define CAPSTONE_HAS_M68K 1
#else
#define CAPSTONE_HAS_M68K 0
#ifdef _MSC_VER
#pragma message ("Cannot find capstone-m68k support")
#else
#warning Cannot find capstone-m68k support
#endif
#endif
#if CAPSTONE_HAS_M68K
static bool check_features(RAsm *a, cs_insn *insn);
static csh cd = 0;
#include "cs_mnemonics.c"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
const char *buf_asm = NULL;
static int omode = -1;
static int obits = 32;
cs_insn* insn = NULL;
int ret = 0, n = 0;
cs_mode mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN;
if (mode != omode || a->bits != obits) {
cs_close (&cd);
cd = 0; // unnecessary
omode = mode;
obits = a->bits;
}
// replace this with the asm.features?
if (a->cpu && strstr (a->cpu, "68000")) {
mode |= CS_MODE_M68K_000;
}
if (a->cpu && strstr (a->cpu, "68010")) {
mode |= CS_MODE_M68K_010;
}
if (a->cpu && strstr (a->cpu, "68020")) {
mode |= CS_MODE_M68K_020;
}
if (a->cpu && strstr (a->cpu, "68030")) {
mode |= CS_MODE_M68K_030;
}
if (a->cpu && strstr (a->cpu, "68040")) {
mode |= CS_MODE_M68K_040;
}
if (a->cpu && strstr (a->cpu, "68060")) {
mode |= CS_MODE_M68K_060;
}
if (op) {
op->size = 4;
}
if (cd == 0) {
ret = cs_open (CS_ARCH_M68K, mode, &cd);
if (ret) {
ret = -1;
goto beach;
}
}
if (a->features && *a->features) {
cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON);
} else {
cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF);
}
if (!buf) {
goto beach;
}
ut8 mybuf[8] = {0};
int mylen = R_MIN (8, len);
memcpy (mybuf, buf, R_MIN (8, len));
n = cs_disasm (cd, mybuf, mylen, a->pc, 1, &insn);
if (n < 1) {
ret = -1;
goto beach;
}
if (op) {
op->size = 0;
}
if (insn->size<1) {
ret = -1;
goto beach;
}
if (a->features && *a->features) {
if (!check_features (a, insn)) {
if (op) {
op->size = insn->size;
buf_asm = "illegal";
}
}
}
if (op && !op->size) {
op->size = insn->size;
buf_asm = sdb_fmt ("%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str);
}
if (op && buf_asm) {
char *p = r_str_replace (strdup (buf_asm), "$", "0x", true);
if (p) {
r_str_rmch (p, '#');
r_asm_op_set_asm (op, p);
free (p);
}
}
cs_free (insn, n);
beach:
//cs_close (&cd);
if (op && buf_asm) {
if (!strncmp (buf_asm, "dc.w", 4)) {
r_asm_op_set_asm (op, "invalid");
}
return op->size;
}
return ret;
}
RAsmPlugin r_asm_plugin_m68k_cs = {
.name = "m68k",
.desc = "Capstone M68K disassembler",
.cpus = "68000,68010,68020,68030,68040,68060",
.license = "BSD",
.arch = "m68k",
.bits = 16 | 32,
.endian = R_SYS_ENDIAN_LITTLE | R_SYS_ENDIAN_BIG,
.disassemble = &disassemble,
.mnemonics = &mnemonics,
};
static bool check_features(RAsm *a, cs_insn *insn) {
/* TODO: Implement support for m68k */
return true;
}
#ifndef CORELIB
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_m68k_cs,
.version = R2_VERSION
};
#endif
#else
RAsmPlugin r_asm_plugin_m68k_cs = {
.name = "m68k.cs (unsupported)",
.desc = "Capstone M68K disassembler (unsupported)",
.license = "BSD",
.author = "pancake",
.arch = "m68k",
.bits = 16 | 32,
.endian = R_SYS_ENDIAN_LITTLE | R_SYS_ENDIAN_BIG,
};
#ifndef CORELIB
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_m68k_cs,
.version = R2_VERSION
};
#endif
#endif