2009-02-05 21:08:46 +00:00
|
|
|
/* radare - LGPL - Copyright 2009 nibble<.ds@gmail.com> */
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <r_types.h>
|
|
|
|
#include <r_util.h>
|
2009-04-11 16:49:09 +00:00
|
|
|
#include <r_cmd.h>
|
2009-02-05 21:08:46 +00:00
|
|
|
#include <r_asm.h>
|
2009-02-18 00:49:26 +00:00
|
|
|
#include <list.h>
|
2009-03-08 23:49:15 +00:00
|
|
|
#include "../config.h"
|
|
|
|
|
|
|
|
static struct r_asm_handle_t *asm_static_plugins[] =
|
2009-03-09 12:03:42 +00:00
|
|
|
{ R_ASM_STATIC_PLUGINS };
|
2009-02-18 00:49:26 +00:00
|
|
|
|
2009-04-14 23:19:42 +00:00
|
|
|
static int r_asm_asciz(void *data, const char *input)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
struct r_asm_aop_t **aop = (struct r_asm_aop_t**)data;
|
|
|
|
char *arg = strchr(input, ' ');
|
|
|
|
if (arg && (len = strlen(arg+1)+1)) {
|
|
|
|
arg += 1;
|
|
|
|
r_hex_bin2str((u8*)arg, len, (*aop)->buf_hex);
|
|
|
|
strncpy((char*)(*aop)->buf, arg, 1024);
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2009-04-11 16:49:09 +00:00
|
|
|
static int r_asm_byte(void *data, const char *input)
|
|
|
|
{
|
2009-04-14 23:19:42 +00:00
|
|
|
int len = 0;
|
2009-04-11 16:49:09 +00:00
|
|
|
struct r_asm_aop_t **aop = (struct r_asm_aop_t**)data;
|
|
|
|
char *arg = strchr(input, ' ');
|
2009-04-14 23:19:42 +00:00
|
|
|
if (arg) {
|
|
|
|
arg += 1;
|
|
|
|
len = r_hex_str2bin(arg, (*aop)->buf);
|
|
|
|
strncpy((*aop)->buf_hex, r_str_trim(arg), 1024);
|
|
|
|
}
|
|
|
|
return len;
|
2009-04-11 16:49:09 +00:00
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API struct r_asm_t *r_asm_new()
|
2009-02-18 00:49:26 +00:00
|
|
|
{
|
|
|
|
struct r_asm_t *a = MALLOC_STRUCT(struct r_asm_t);
|
|
|
|
r_asm_init(a);
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API void r_asm_free(struct r_asm_t *a)
|
2009-02-18 00:49:26 +00:00
|
|
|
{
|
|
|
|
free(a);
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_init(struct r_asm_t *a)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-03-08 23:49:15 +00:00
|
|
|
int i;
|
2009-02-18 00:49:26 +00:00
|
|
|
a->user = NULL;
|
2009-03-10 01:49:24 +00:00
|
|
|
a->cur = NULL;
|
2009-02-18 00:49:26 +00:00
|
|
|
INIT_LIST_HEAD(&a->asms);
|
2009-04-14 13:21:19 +00:00
|
|
|
a->bits = 32;
|
|
|
|
a->big_endian = 0;
|
|
|
|
a->syntax = R_ASM_SYN_INTEL;
|
|
|
|
a->pc = 0;
|
2009-03-08 23:49:15 +00:00
|
|
|
for(i=0;asm_static_plugins[i];i++)
|
|
|
|
r_asm_add(a, asm_static_plugins[i]);
|
2009-04-11 16:49:09 +00:00
|
|
|
r_cmd_init(&a->cmd);
|
2009-04-14 23:19:42 +00:00
|
|
|
r_cmd_add(&a->cmd, "a", ".asciz", &r_asm_asciz);
|
|
|
|
r_cmd_add_long(&a->cmd, "asciz", "a", ".asciz");
|
2009-04-11 16:49:09 +00:00
|
|
|
r_cmd_add(&a->cmd, "b", ".byte", &r_asm_byte);
|
|
|
|
r_cmd_add_long(&a->cmd, "byte", "b", ".byte");
|
2009-02-05 21:08:46 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API void r_asm_set_user_ptr(struct r_asm_t *a, void *user)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-02-18 00:49:26 +00:00
|
|
|
a->user = user;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_add(struct r_asm_t *a, struct r_asm_handle_t *foo)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-03-08 23:49:15 +00:00
|
|
|
struct list_head *pos;
|
2009-02-18 00:49:26 +00:00
|
|
|
if (foo->init)
|
|
|
|
foo->init(a->user);
|
2009-03-08 23:49:15 +00:00
|
|
|
/* avoid dupped plugins */
|
|
|
|
list_for_each_prev(pos, &a->asms) {
|
|
|
|
struct r_asm_handle_t *h = list_entry(pos, struct r_asm_handle_t, list);
|
|
|
|
if (!strcmp(h->name, foo->name))
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-02-18 00:49:26 +00:00
|
|
|
list_add_tail(&(foo->list), &(a->asms));
|
|
|
|
return R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-12 22:46:44 +00:00
|
|
|
R_API int r_asm_del(struct r_asm_t *a, const char *name)
|
|
|
|
{
|
2009-04-14 23:19:42 +00:00
|
|
|
/* TODO: Implement r_asm_del */
|
2009-04-12 22:46:44 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_list(struct r_asm_t *a)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-02-18 00:49:26 +00:00
|
|
|
struct list_head *pos;
|
|
|
|
list_for_each_prev(pos, &a->asms) {
|
|
|
|
struct r_asm_handle_t *h = list_entry(pos, struct r_asm_handle_t, list);
|
|
|
|
printf(" %s: %s\n", h->name, h->desc);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-02-18 00:49:26 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_set(struct r_asm_t *a, const char *name)
|
2009-02-18 00:49:26 +00:00
|
|
|
{
|
|
|
|
struct list_head *pos;
|
|
|
|
list_for_each_prev(pos, &a->asms) {
|
|
|
|
struct r_asm_handle_t *h = list_entry(pos, struct r_asm_handle_t, list);
|
2009-02-19 15:41:51 +00:00
|
|
|
if (!strcmp(h->name, name)) {
|
2009-02-18 00:49:26 +00:00
|
|
|
a->cur = h;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
static int has_bits(struct r_asm_handle_t *h, int bits)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (h && h->bits) {
|
|
|
|
for(i=0; h->bits[i]; i++) {
|
|
|
|
if (bits == h->bits[i])
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_set_bits(struct r_asm_t *a, int bits)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-14 13:21:19 +00:00
|
|
|
if (has_bits(a->cur, bits)) {
|
2009-02-05 21:08:46 +00:00
|
|
|
a->bits = bits;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-04-11 21:22:20 +00:00
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_set_big_endian(struct r_asm_t *a, int boolean)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
a->big_endian = boolean;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_set_syntax(struct r_asm_t *a, int syntax)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
switch (syntax) {
|
|
|
|
case R_ASM_SYN_INTEL:
|
|
|
|
case R_ASM_SYN_ATT:
|
|
|
|
a->syntax = syntax;
|
|
|
|
return R_TRUE;
|
|
|
|
default:
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_set_pc(struct r_asm_t *a, u64 pc)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
|
|
|
a->pc = pc;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_disassemble(struct r_asm_t *a, struct r_asm_aop_t *aop, u8 *buf, u64 len)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-14 13:21:19 +00:00
|
|
|
int ret = 0;
|
2009-02-18 00:49:26 +00:00
|
|
|
if (a->cur && a->cur->disassemble)
|
2009-04-14 13:21:19 +00:00
|
|
|
ret = a->cur->disassemble(a, aop, buf, len);
|
|
|
|
if (ret > 0) {
|
|
|
|
memcpy(aop->buf, buf, ret);
|
|
|
|
r_hex_bin2str(buf, ret, aop->buf_hex);
|
|
|
|
}
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-07 00:26:41 +00:00
|
|
|
R_API int r_asm_assemble(struct r_asm_t *a, struct r_asm_aop_t *aop, const char *buf)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-14 13:21:19 +00:00
|
|
|
int ret = 0;
|
2009-04-11 21:22:20 +00:00
|
|
|
struct list_head *pos;
|
|
|
|
if (a->cur) {
|
|
|
|
if (a->cur->assemble)
|
2009-04-14 13:21:19 +00:00
|
|
|
ret = a->cur->assemble(a, aop, buf);
|
|
|
|
else /* find callback if no assembler support in current plugin */
|
|
|
|
list_for_each_prev(pos, &a->asms) {
|
|
|
|
struct r_asm_handle_t *h = list_entry(pos, struct r_asm_handle_t, list);
|
|
|
|
if (h->arch && h->assemble && has_bits(h, a->bits) && !strcmp(a->cur->arch, h->arch)) {
|
|
|
|
ret = h->assemble(a, aop, buf);
|
|
|
|
break;
|
2009-04-13 22:47:02 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-11 21:22:20 +00:00
|
|
|
}
|
2009-04-14 23:19:42 +00:00
|
|
|
if (aop && ret > 0) {
|
2009-04-14 13:21:19 +00:00
|
|
|
r_hex_bin2str(aop->buf, ret, aop->buf_hex);
|
2009-04-14 23:19:42 +00:00
|
|
|
strncpy(aop->buf_asm, buf, 1024);
|
|
|
|
}
|
2009-04-14 13:21:19 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-04-08 23:03:49 +00:00
|
|
|
|
|
|
|
R_API int r_asm_massemble(struct r_asm_t *a, struct r_asm_aop_t *aop, char *buf)
|
|
|
|
{
|
|
|
|
char *lbuf=NULL, *ptr = NULL, *tokens[1024], buf_hex[1024];
|
|
|
|
u8 buf_bin[1024];
|
|
|
|
int ret, idx, ctr, i, j;
|
|
|
|
|
|
|
|
if (buf == NULL)
|
|
|
|
return 0;
|
|
|
|
lbuf = strdup(buf);
|
|
|
|
|
|
|
|
for (tokens[0] = lbuf, ctr = 0;
|
|
|
|
(ptr = strchr(tokens[ctr], ';'));
|
|
|
|
tokens[++ctr] = ptr+1)
|
|
|
|
*ptr = '\0';
|
|
|
|
|
2009-04-11 16:49:09 +00:00
|
|
|
r_cmd_set_data(&a->cmd, &aop);
|
2009-04-08 23:03:49 +00:00
|
|
|
for (ret = idx = i = 0, *buf_hex='\0'; i <= ctr; i++, idx+=ret) {
|
|
|
|
r_asm_set_pc(a, a->pc + ret);
|
2009-04-11 16:49:09 +00:00
|
|
|
if ((ptr = strchr(tokens[i], '.'))) /* Pseudo */
|
2009-04-14 23:19:42 +00:00
|
|
|
ret = r_cmd_call_long(&a->cmd, ptr+1);
|
2009-04-11 16:49:09 +00:00
|
|
|
else /* Instruction */
|
|
|
|
ret = r_asm_assemble(a, aop, tokens[i]);
|
2009-04-08 23:03:49 +00:00
|
|
|
if (ret) {
|
|
|
|
for (j = 0; j < ret; j++)
|
|
|
|
buf_bin[idx+j] = aop->buf[j];
|
|
|
|
strcat(buf_hex, aop->buf_hex);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(aop->buf, buf_bin, 1024);
|
|
|
|
memcpy(aop->buf_hex, buf_hex, 1024);
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|