|
|
@ -10,6 +10,8 @@ |
|
|
|
#include "utils.h" |
|
|
|
#include "utils.h" |
|
|
|
#include "MCRegisterInfo.h" |
|
|
|
#include "MCRegisterInfo.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define INSN_CACHE_SIZE 64 |
|
|
|
|
|
|
|
|
|
|
|
cs_err (*arch_init[MAX_ARCH])(cs_struct *) = { NULL }; |
|
|
|
cs_err (*arch_init[MAX_ARCH])(cs_struct *) = { NULL }; |
|
|
|
cs_err (*arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = { NULL }; |
|
|
|
cs_err (*arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = { NULL }; |
|
|
|
void (*arch_destroy[MAX_ARCH]) (cs_struct *) = { NULL }; |
|
|
|
void (*arch_destroy[MAX_ARCH]) (cs_struct *) = { NULL }; |
|
|
@ -87,7 +89,7 @@ cs_err cs_errno(csh handle) |
|
|
|
if (!handle) |
|
|
|
if (!handle) |
|
|
|
return CS_ERR_CSH; |
|
|
|
return CS_ERR_CSH; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *ud = (cs_struct *)(uintptr_t)handle; |
|
|
|
struct cs_struct *ud = (struct cs_struct *)(uintptr_t)handle; |
|
|
|
|
|
|
|
|
|
|
|
return ud->errnum; |
|
|
|
return ud->errnum; |
|
|
|
} |
|
|
|
} |
|
|
@ -128,7 +130,7 @@ cs_err cs_open(cs_arch arch, cs_mode mode, csh *handle) |
|
|
|
archs_enable(); |
|
|
|
archs_enable(); |
|
|
|
|
|
|
|
|
|
|
|
if (arch < CS_ARCH_MAX && arch_init[arch]) { |
|
|
|
if (arch < CS_ARCH_MAX && arch_init[arch]) { |
|
|
|
cs_struct *ud; |
|
|
|
struct cs_struct *ud; |
|
|
|
|
|
|
|
|
|
|
|
ud = cs_mem_calloc(1, sizeof(*ud)); |
|
|
|
ud = cs_mem_calloc(1, sizeof(*ud)); |
|
|
|
if (!ud) { |
|
|
|
if (!ud) { |
|
|
@ -164,7 +166,7 @@ cs_err cs_close(csh handle) |
|
|
|
if (!handle) |
|
|
|
if (!handle) |
|
|
|
return CS_ERR_CSH; |
|
|
|
return CS_ERR_CSH; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *ud = (cs_struct *)(uintptr_t)handle; |
|
|
|
struct cs_struct *ud = (struct cs_struct *)(uintptr_t)handle; |
|
|
|
|
|
|
|
|
|
|
|
switch (ud->arch) { |
|
|
|
switch (ud->arch) { |
|
|
|
case CS_ARCH_X86: |
|
|
|
case CS_ARCH_X86: |
|
|
@ -191,17 +193,16 @@ cs_err cs_close(csh handle) |
|
|
|
#define MIN(x, y) ((x) < (y) ? (x) : (y)) |
|
|
|
#define MIN(x, y) ((x) < (y) ? (x) : (y)) |
|
|
|
|
|
|
|
|
|
|
|
// fill insn with mnemonic & operands info
|
|
|
|
// fill insn with mnemonic & operands info
|
|
|
|
static void fill_insn(cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci, |
|
|
|
static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci, |
|
|
|
PostPrinter_t postprinter, const uint8_t *code) |
|
|
|
PostPrinter_t postprinter, const uint8_t *code) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (handle->detail) { |
|
|
|
if (handle->detail) { |
|
|
|
// avoiding copy insn->detail
|
|
|
|
// avoiding copy insn->detail
|
|
|
|
memcpy(insn, &mci->flat_insn, sizeof(*insn) - sizeof(insn->detail)); |
|
|
|
memcpy(insn, (uintptr_t)&mci->flat_insn, sizeof(*insn) - sizeof(insn->detail)); |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: copy details in 2 chunks, since union is always put at address divisible by 8
|
|
|
|
// NOTE: copy details in 2 chunks, since union is always put at address divisible by 8
|
|
|
|
// copy from @regs_read until @arm
|
|
|
|
// copy from @regs_read until @arm
|
|
|
|
memcpy(insn->detail, |
|
|
|
memcpy(insn->detail, (void *)(&(mci->flat_insn)) + offsetof(cs_insn_flat, regs_read), |
|
|
|
(void*) ((uintptr_t) &mci->flat_insn + offsetof(cs_insn_flat, regs_read)), |
|
|
|
|
|
|
|
offsetof(cs_detail, arm) - offsetof(cs_detail, regs_read)); |
|
|
|
offsetof(cs_detail, arm) - offsetof(cs_detail, regs_read)); |
|
|
|
// then copy from @arm until end
|
|
|
|
// then copy from @arm until end
|
|
|
|
memcpy((void *)((uintptr_t)(insn->detail) + offsetof(cs_detail, arm)), |
|
|
|
memcpy((void *)((uintptr_t)(insn->detail) + offsetof(cs_detail, arm)), |
|
|
@ -263,7 +264,7 @@ cs_err cs_option(csh ud, cs_opt_type type, size_t value) |
|
|
|
return CS_ERR_OK; |
|
|
|
return CS_ERR_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cs_struct *handle = (cs_struct *)(uintptr_t)ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle) |
|
|
|
if (!handle) |
|
|
|
return CS_ERR_CSH; |
|
|
|
return CS_ERR_CSH; |
|
|
|
|
|
|
|
|
|
|
@ -281,7 +282,8 @@ static cs_insn *get_prev_insn(cs_insn *cache, unsigned int f, void *total, size_ |
|
|
|
if (f == 0) { |
|
|
|
if (f == 0) { |
|
|
|
if (total == NULL) |
|
|
|
if (total == NULL) |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
// get the trailing insn from total buffer
|
|
|
|
// get the trailing insn from total buffer, which is at
|
|
|
|
|
|
|
|
// the end of the latest cache trunk
|
|
|
|
return (cs_insn *)((void*)((uintptr_t)total + total_size - sizeof(cs_insn))); |
|
|
|
return (cs_insn *)((void*)((uintptr_t)total + total_size - sizeof(cs_insn))); |
|
|
|
} else |
|
|
|
} else |
|
|
|
return &cache[f - 1]; |
|
|
|
return &cache[f - 1]; |
|
|
@ -291,12 +293,12 @@ static cs_insn *get_prev_insn(cs_insn *cache, unsigned int f, void *total, size_ |
|
|
|
// NOTE: caller must free() the allocated memory itself to avoid memory leaking
|
|
|
|
// NOTE: caller must free() the allocated memory itself to avoid memory leaking
|
|
|
|
size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn) |
|
|
|
size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cs_struct *handle = (cs_struct *)(uintptr_t)ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
MCInst mci; |
|
|
|
MCInst mci; |
|
|
|
uint16_t insn_size; |
|
|
|
uint16_t insn_size; |
|
|
|
size_t c = 0; |
|
|
|
size_t c = 0; |
|
|
|
unsigned int f = 0; |
|
|
|
unsigned int f = 0; |
|
|
|
cs_insn insn_cache[64]; |
|
|
|
cs_insn insn_cache[INSN_CACHE_SIZE]; |
|
|
|
void *total = NULL; |
|
|
|
void *total = NULL; |
|
|
|
size_t total_size = 0; |
|
|
|
size_t total_size = 0; |
|
|
|
|
|
|
|
|
|
|
@ -308,6 +310,9 @@ size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, |
|
|
|
|
|
|
|
|
|
|
|
handle->errnum = CS_ERR_OK; |
|
|
|
handle->errnum = CS_ERR_OK; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// reset previous prefix for X86
|
|
|
|
|
|
|
|
handle->prev_prefix = 0; |
|
|
|
|
|
|
|
|
|
|
|
memset(insn_cache, 0, sizeof(insn_cache)); |
|
|
|
memset(insn_cache, 0, sizeof(insn_cache)); |
|
|
|
|
|
|
|
|
|
|
|
while (size > 0) { |
|
|
|
while (size > 0) { |
|
|
@ -340,7 +345,7 @@ size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, |
|
|
|
|
|
|
|
|
|
|
|
if (f == ARR_SIZE(insn_cache)) { |
|
|
|
if (f == ARR_SIZE(insn_cache)) { |
|
|
|
// resize total to contain newly disasm insns
|
|
|
|
// resize total to contain newly disasm insns
|
|
|
|
total_size += sizeof(insn_cache); |
|
|
|
total_size += (sizeof(cs_insn) * INSN_CACHE_SIZE); |
|
|
|
void *tmp = cs_mem_realloc(total, total_size); |
|
|
|
void *tmp = cs_mem_realloc(total, total_size); |
|
|
|
if (tmp == NULL) { // insufficient memory
|
|
|
|
if (tmp == NULL) { // insufficient memory
|
|
|
|
cs_mem_free(total); |
|
|
|
cs_mem_free(total); |
|
|
@ -350,6 +355,7 @@ size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, |
|
|
|
|
|
|
|
|
|
|
|
total = tmp; |
|
|
|
total = tmp; |
|
|
|
memcpy((void*)((uintptr_t)total + total_size - sizeof(insn_cache)), insn_cache, sizeof(insn_cache)); |
|
|
|
memcpy((void*)((uintptr_t)total + total_size - sizeof(insn_cache)), insn_cache, sizeof(insn_cache)); |
|
|
|
|
|
|
|
|
|
|
|
// reset f back to 0
|
|
|
|
// reset f back to 0
|
|
|
|
f = 0; |
|
|
|
f = 0; |
|
|
|
} |
|
|
|
} |
|
|
@ -385,6 +391,7 @@ size_t cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, |
|
|
|
|
|
|
|
|
|
|
|
total = tmp; |
|
|
|
total = tmp; |
|
|
|
memcpy((void*)((uintptr_t)total + total_size), insn_cache, f * sizeof(insn_cache[0])); |
|
|
|
memcpy((void*)((uintptr_t)total + total_size), insn_cache, f * sizeof(insn_cache[0])); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*insn = total; |
|
|
|
*insn = total; |
|
|
@ -407,7 +414,7 @@ void cs_free(cs_insn *insn, size_t count) |
|
|
|
// return friendly name of regiser in a string
|
|
|
|
// return friendly name of regiser in a string
|
|
|
|
const char *cs_reg_name(csh ud, unsigned int reg) |
|
|
|
const char *cs_reg_name(csh ud, unsigned int reg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cs_struct *handle = (cs_struct *)(uintptr_t)ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
|
|
|
|
|
|
|
|
if (!handle || handle->reg_name == NULL) { |
|
|
|
if (!handle || handle->reg_name == NULL) { |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
@ -418,7 +425,7 @@ const char *cs_reg_name(csh ud, unsigned int reg) |
|
|
|
|
|
|
|
|
|
|
|
const char *cs_insn_name(csh ud, unsigned int insn) |
|
|
|
const char *cs_insn_name(csh ud, unsigned int insn) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cs_struct *handle = (cs_struct *)(uintptr_t)ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
|
|
|
|
|
|
|
|
if (!handle || handle->insn_name == NULL) { |
|
|
|
if (!handle || handle->insn_name == NULL) { |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
@ -444,7 +451,7 @@ bool cs_insn_group(csh ud, cs_insn *insn, unsigned int group_id) |
|
|
|
if (!ud) |
|
|
|
if (!ud) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *handle = (cs_struct *)(uintptr_t)ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle->detail) { |
|
|
|
if (!handle->detail) { |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -458,7 +465,7 @@ bool cs_reg_read(csh ud, cs_insn *insn, unsigned int reg_id) |
|
|
|
if (!ud) |
|
|
|
if (!ud) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *handle = (cs_struct *) (uintptr_t) ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle->detail) { |
|
|
|
if (!handle->detail) { |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -472,7 +479,7 @@ bool cs_reg_write(csh ud, cs_insn *insn, unsigned int reg_id) |
|
|
|
if (!ud) |
|
|
|
if (!ud) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *handle = (cs_struct *) (uintptr_t) ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle->detail) { |
|
|
|
if (!handle->detail) { |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -486,7 +493,7 @@ int cs_op_count(csh ud, cs_insn *insn, unsigned int op_type) |
|
|
|
if (!ud) |
|
|
|
if (!ud) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *handle = (cs_struct *) (uintptr_t) ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle->detail) { |
|
|
|
if (!handle->detail) { |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
@ -536,7 +543,7 @@ int cs_op_index(csh ud, cs_insn *insn, unsigned int op_type, |
|
|
|
if (!ud) |
|
|
|
if (!ud) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
struct cs_struct *handle = (cs_struct *) (uintptr_t) ud; |
|
|
|
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; |
|
|
|
if (!handle->detail) { |
|
|
|
if (!handle->detail) { |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
handle->errnum = CS_ERR_DETAIL; |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|