mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-24 13:49:50 +00:00
Add mips pseudocode, anal.hasnext, fix anal bugs
Better mips analysis Implemented mips pseudocode plugin Change asm.parser in asm.arch callback
This commit is contained in:
parent
48ea6840f5
commit
5c236fa0e3
6
TODO
6
TODO
@ -5,6 +5,12 @@
|
||||
|
||||
------8<-------------------8<--------------------8<-----------------8<----------
|
||||
|
||||
0.9.2
|
||||
- 'Vdu' onnly undefines a basic block. not the whole function!
|
||||
- it does not unflags the address if loc.
|
||||
- search for CALL instructions in text segment.
|
||||
- analyze the destination address of each call destination
|
||||
|
||||
====[[ 0.9.4 ]]====
|
||||
* Integrate dwarf parser with disassembler and debugger
|
||||
* Analysis: assume there's a function at the end of each function
|
||||
|
@ -52,7 +52,7 @@ R_API int r_anal_bb(RAnal *anal, RAnalBlock *bb, ut64 addr, ut8 *buf, ut64 len,
|
||||
bb->addr = addr;
|
||||
len -= 16; // XXX: hack to avoid segfault by x86im
|
||||
while (idx < len) {
|
||||
if (!(op = r_anal_op_new ())) {
|
||||
if (!(op = r_anal_op_new ())) { // TODO: too slow object construction
|
||||
eprintf ("Error: new (op)\n");
|
||||
return R_ANAL_RET_ERROR;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2010-2012 */
|
||||
/* nibble<.ds@gmail.com> + pancake<nopcode.org> */
|
||||
/* radare - LGPL - Copyright 2010-2012 - nibble, pancake */
|
||||
|
||||
#include <r_anal.h>
|
||||
#include <r_util.h>
|
||||
@ -60,13 +59,11 @@ R_API void r_anal_fcn_free(void *_fcn) {
|
||||
|
||||
R_API int r_anal_fcn_xref_add (RAnal *anal, RAnalFunction *fcn, ut64 at, ut64 addr, int type) {
|
||||
RAnalRef *ref;
|
||||
if (!fcn || !anal)
|
||||
if (!fcn || !anal || !(ref = r_anal_ref_new ()))
|
||||
return R_FALSE;
|
||||
if (!(ref = r_anal_ref_new ()))
|
||||
return R_FALSE;
|
||||
ref->type = type;
|
||||
ref->at = at;
|
||||
ref->addr = addr;
|
||||
ref->type = type;
|
||||
// TODO: ensure we are not dupping xrefs
|
||||
r_list_append (fcn->refs, ref);
|
||||
return R_TRUE;
|
||||
@ -93,10 +90,10 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
int oplen, idx = 0;
|
||||
if (fcn->addr == -1)
|
||||
fcn->addr = addr;
|
||||
//fcn->size = 0;
|
||||
fcn->type = (reftype==R_ANAL_REF_TYPE_CODE)?
|
||||
R_ANAL_FCN_TYPE_LOC: R_ANAL_FCN_TYPE_FCN;
|
||||
len -= 16; // XXX: hack to avoid buffer overflow by reading >64 bytes..
|
||||
if (len>16)
|
||||
len -= 16; // XXX: hack to avoid buffer overflow by reading >64 bytes..
|
||||
|
||||
while (idx < len) {
|
||||
r_anal_op_fini (&op);
|
||||
@ -106,7 +103,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
}
|
||||
if ((oplen = r_anal_op (anal, &op, addr+idx, buf+idx, len-idx)) < 1) {
|
||||
if (idx == 0) {
|
||||
// eprintf ("Unknown opcode at 0x%08"PFMT64x"\n", addr+idx);
|
||||
VERBOSE_ANAL eprintf ("Unknown opcode at 0x%08"PFMT64x"\n", addr+idx);
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_END;
|
||||
} else break;
|
||||
@ -119,6 +116,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
case R_ANAL_STACK_INCSTACK:
|
||||
fcn->stack += op.value;
|
||||
break;
|
||||
// TODO: use fcn->stack to know our stackframe
|
||||
case R_ANAL_STACK_SET:
|
||||
if (op.ref > 0) {
|
||||
varname = r_str_dup_printf ("arg_%x", op.ref);
|
||||
@ -131,6 +129,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
}
|
||||
free (varname);
|
||||
break;
|
||||
// TODO: use fcn->stack to know our stackframe
|
||||
case R_ANAL_STACK_GET:
|
||||
if (op.ref > 0) {
|
||||
varname = r_str_dup_printf ("arg_%x", op.ref);
|
||||
@ -147,6 +146,11 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
#if 0
|
||||
// do not add xrefs for cjmps?
|
||||
r_anal_op_fini (&op);
|
||||
break;
|
||||
#endif
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump,
|
||||
op.type == R_ANAL_OP_TYPE_CALL?
|
||||
@ -310,6 +314,7 @@ R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
|
||||
bb->jump = bbi->jump;
|
||||
bb->fail = bbi->fail;
|
||||
bb->conditional = bbi->conditional;
|
||||
|
||||
bbi->size = addr - bbi->addr;
|
||||
bbi->jump = addr;
|
||||
bbi->fail = -1;
|
||||
|
@ -44,7 +44,7 @@ R_API void r_anal_op_free(void *_op) {
|
||||
}
|
||||
|
||||
R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
|
||||
if (anal && op && anal->cur && anal->cur->op)
|
||||
if (len>0 && anal && op && anal->cur && anal->cur->op)
|
||||
return anal->cur->op (anal, op, addr, data, len);
|
||||
return R_FALSE;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
unsigned int opcode;
|
||||
char buf[10];
|
||||
int reg, optype, oplen = (anal->bits==16)?2:4;
|
||||
int family, reg, optype, oplen = (anal->bits==16)?2:4;
|
||||
|
||||
if (op == NULL)
|
||||
return oplen;
|
||||
@ -17,6 +17,7 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
memset (op, 0, sizeof (RAnalOp));
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
op->length = oplen;
|
||||
op->delay = 4;
|
||||
|
||||
//r_mem_copyendian ((ut8*)&opcode, b, 4, !anal->big_endian);
|
||||
memcpy (&opcode, b, 4);
|
||||
@ -74,6 +75,8 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
op->type = R_ANAL_OP_TYPE_SWI;
|
||||
break;
|
||||
case 13: // break
|
||||
op->type = R_ANAL_OP_TYPE_TRAP;
|
||||
break;
|
||||
case 16: // mfhi
|
||||
case 18: // mflo
|
||||
|
||||
@ -85,14 +88,25 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
|
||||
case 26: // div
|
||||
case 27: // divu
|
||||
op->type = R_ANAL_OP_TYPE_DIV;
|
||||
break;
|
||||
case 32: // add
|
||||
case 33: // addu
|
||||
op->type = R_ANAL_OP_TYPE_ADD;
|
||||
break;
|
||||
case 34: // sub
|
||||
case 35: // subu
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
break;
|
||||
case 36: // and
|
||||
|
||||
op->type = R_ANAL_OP_TYPE_AND;
|
||||
break;
|
||||
case 37: // or
|
||||
op->type = R_ANAL_OP_TYPE_OR;
|
||||
break;
|
||||
case 38: // xor
|
||||
op->type = R_ANAL_OP_TYPE_XOR;
|
||||
break;
|
||||
case 39: // nor
|
||||
case 42: // slt
|
||||
case 43: // sltu
|
||||
@ -102,7 +116,7 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
// eprintf ("%llx %d\n", addr, optype);
|
||||
break;
|
||||
}
|
||||
optype = 'R';
|
||||
family = 'R';
|
||||
} else
|
||||
if ((optype & 0x3e) == 2) {
|
||||
#if 0
|
||||
@ -113,12 +127,18 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
(b[0]>>2) ((b[0]&3)<<24)+(b[1]<<16)+(b[2]<<8)+b[3]
|
||||
#endif
|
||||
int address = ((b[0]&3)<<24)+(b[1]<<16)+(b[2]<<8)+b[3];
|
||||
optype = 'J';
|
||||
switch (optype) {
|
||||
case 2: // j
|
||||
op->type = R_ANAL_OP_TYPE_JMP;
|
||||
op->jump = address;
|
||||
break;
|
||||
case 3: // jal
|
||||
op->type = R_ANAL_OP_TYPE_CALL;
|
||||
op->jump = address;
|
||||
op->fail = addr+8;
|
||||
break;
|
||||
}
|
||||
family = 'J';
|
||||
} else
|
||||
if ((optype & 0x10) == 0x1c) {
|
||||
#if 0
|
||||
@ -139,7 +159,7 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
int fs = (b[2]>>3);
|
||||
int fd = (b[2]&7)+(b[3]>>6);
|
||||
int fun = (b[3]&63);
|
||||
optype = 'C';
|
||||
family = 'C';
|
||||
switch (fun) {
|
||||
case 0: // mtc1
|
||||
break;
|
||||
@ -172,13 +192,12 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
switch (optype) {
|
||||
case 1: if (rt) { /* bgez */ } else { /* bltz */ }
|
||||
case 4: // beq
|
||||
case 5: // bne
|
||||
case 5: // bne // also bnez
|
||||
case 6: // blez
|
||||
case 7: // bgtz
|
||||
// XXX: use imm here
|
||||
op->type = R_ANAL_OP_TYPE_JMP;
|
||||
//reg = (((opcode&0x00ff0000)>>16) + ((opcode&0xff000000)>>24));
|
||||
op->jump = addr+(imm<<2)+4; //(reg<<2) + 4;
|
||||
op->type = R_ANAL_OP_TYPE_CJMP;
|
||||
op->jump = addr+(imm<<2)+4;
|
||||
op->fail = addr+8;
|
||||
break;
|
||||
case 8: // addi
|
||||
@ -201,7 +220,7 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
case 57: // swc1
|
||||
break;
|
||||
}
|
||||
optype = 'I';
|
||||
family = 'I';
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -311,98 +330,6 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
mul.s fd, fs, ft 000010 10000
|
||||
sub.s fd, fs, ft 000001 10000
|
||||
#endif
|
||||
|
||||
//eprintf ("--> %x %02x %02x\n", opcode, opcode &0xff , opcode &0x3f);
|
||||
switch (opcode & 0x3f) {
|
||||
// J-Type
|
||||
case 2: // j
|
||||
// branch to register
|
||||
//XXX TODO
|
||||
op->type = R_ANAL_OP_TYPE_UJMP;
|
||||
break;
|
||||
// R-Type
|
||||
case 1: // bltz
|
||||
// 04100001 bltzal zero,0x2aaa8cb4
|
||||
case 4: // beq // bal
|
||||
case 5: // bne
|
||||
case 6: // blez
|
||||
case 7: // bgtz
|
||||
case 16: //beqz
|
||||
case 20: //bnel
|
||||
op->type = R_ANAL_OP_TYPE_CJMP;
|
||||
reg = (((opcode&0x00ff0000)>>16) + ((opcode&0xff000000)>>24));
|
||||
op->jump = addr+(reg<<2) + 4;
|
||||
op->fail = addr+8;
|
||||
// calculate jump
|
||||
break;
|
||||
case 0x24: // jalx
|
||||
case 0x34: // jalx
|
||||
op->type = R_ANAL_OP_TYPE_UJMP;
|
||||
break;
|
||||
case 3: // jalr
|
||||
op->type = R_ANAL_OP_TYPE_UCALL;
|
||||
switch (opcode) {
|
||||
case 0x03e00008:
|
||||
case 0x0800e003: // jr ra
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 9: // jalr
|
||||
reg = opcode>>24;
|
||||
if (reg<10) {
|
||||
op->type = R_ANAL_OP_TYPE_UCALL;
|
||||
snprintf (buf, sizeof (buf), "t%d", reg); // XXX must be rN...!regs* should be synced here
|
||||
op->jump = 1234;//flag_get_addr(buf);
|
||||
op->fail = addr+8;
|
||||
}
|
||||
break;
|
||||
case 8: // jr
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
break;
|
||||
case 12:
|
||||
op->type = R_ANAL_OP_TYPE_SWI;
|
||||
break;
|
||||
case 13:
|
||||
op->type = R_ANAL_OP_TYPE_TRAP;
|
||||
break;
|
||||
default:
|
||||
switch (opcode) {
|
||||
case 0:
|
||||
op->type = R_ANAL_OP_TYPE_NOP;
|
||||
break;
|
||||
case 32: // add
|
||||
case 33: // addu
|
||||
op->type = R_ANAL_OP_TYPE_ADD;
|
||||
break;
|
||||
case 34: // sub
|
||||
case 35: // subu
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
break;
|
||||
case 0x03e00008:
|
||||
case 0x0800e003: // jr ra
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
break;
|
||||
case 0x0000000d: // case 26:
|
||||
case 0x0d000000: // break
|
||||
op->type = R_ANAL_OP_TYPE_TRAP;
|
||||
break;
|
||||
default:
|
||||
//switch((opcode<<24)&0xff) { //b[3]) { // TODO handle endian ?
|
||||
switch ((b[3])) {
|
||||
case 0xc:
|
||||
op->type = R_ANAL_OP_TYPE_SWI;
|
||||
break;
|
||||
case 0x9:
|
||||
case 0x8:
|
||||
op->type = R_ANAL_OP_TYPE_UJMP;
|
||||
break;
|
||||
case 0x21:
|
||||
op->type = R_ANAL_OP_TYPE_PUSH; // XXX move
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return op->length;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ static inline int r_asm_pseudo_int64(RAsm *a, RAsmOp *op, char *input) {
|
||||
|
||||
static inline int r_asm_pseudo_byte(RAsmOp *op, char *input) {
|
||||
int i, len = 0;
|
||||
r_str_subchr (input, ',', ' ');
|
||||
r_str_replace_char (input, ',', ' ');
|
||||
len = r_str_word_count (input);
|
||||
r_str_word_set0 (input);
|
||||
for (i=0; i<len; i++) {
|
||||
|
@ -85,6 +85,10 @@ static int disassemble(struct r_asm_t *a, struct r_asm_op_t *op, const ut8 *buf,
|
||||
return op->inst_len;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *str) {
|
||||
return mips_assemble (str, a->pc, op->buf);
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_mips = {
|
||||
.name = "mips",
|
||||
.arch = "mips",
|
||||
@ -93,7 +97,7 @@ RAsmPlugin r_asm_plugin_mips = {
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.disassemble = &disassemble,
|
||||
.assemble = NULL,
|
||||
.assemble = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
|
@ -3,6 +3,7 @@ OBJ_MIPS=asm_mips.o
|
||||
OBJ_MIPS+=../arch/mips/gnu/mips-dis.o
|
||||
OBJ_MIPS+=../arch/mips/gnu/mips16-opc.o
|
||||
OBJ_MIPS+=../arch/mips/gnu/mips-opc.o
|
||||
OBJ_MIPS+=../arch/mips/mipsasm.o
|
||||
|
||||
TARGET_MIPS=asm_mips.${EXT_SO}
|
||||
ALL_TARGETS+=${TARGET_MIPS}
|
||||
|
@ -125,12 +125,21 @@ R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head) {
|
||||
if (ret == R_ANAL_RET_DUP) { /* Dupped bb */
|
||||
goto error;
|
||||
} else if (ret == R_ANAL_RET_NEW) { /* New bb */
|
||||
// XXX: use static buffer size of 512 or so
|
||||
if (!(buf = malloc (core->blocksize)))
|
||||
goto error;
|
||||
do {
|
||||
if ((buflen = r_io_read_at (core->io, at+bblen, buf, core->blocksize)) != core->blocksize)
|
||||
#if 1
|
||||
// check io error
|
||||
if (r_io_read_at (core->io, at+bblen, buf, 4) != 4)
|
||||
//core->blocksize)) != core->blocksize)
|
||||
goto error;
|
||||
#endif
|
||||
r_core_read_at (core, at+bblen, buf, core->blocksize);
|
||||
buflen = core->blocksize;
|
||||
//eprintf ("Pre %llx %d\n", at, buflen);
|
||||
bblen = r_anal_bb (core->anal, bb, at+bblen, buf, buflen, head);
|
||||
//eprintf ("Pos %d\n", bblen);
|
||||
if (bblen == R_ANAL_RET_ERROR ||
|
||||
(bblen == R_ANAL_RET_END && bb->size < 1)) { /* Error analyzing bb */
|
||||
goto error;
|
||||
@ -150,13 +159,13 @@ R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head) {
|
||||
} while (bblen != R_ANAL_RET_END);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
free (buf);
|
||||
return R_TRUE;
|
||||
|
||||
error:
|
||||
r_list_unlink(fcn->bbs, bb);
|
||||
r_anal_bb_free(bb);
|
||||
free(buf);
|
||||
r_list_unlink (fcn->bbs, bb);
|
||||
r_anal_bb_free (bb);
|
||||
free (buf);
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
@ -182,8 +191,15 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
int buflen, fcnlen = 0;
|
||||
RAnalFunction *fcn = NULL, *fcni;
|
||||
RAnalRef *ref = NULL, *refi;
|
||||
ut64 *next = NULL;
|
||||
int i, nexti = 0;
|
||||
ut8 *buf;
|
||||
#define ANALBS 256
|
||||
|
||||
if (at>>63 == 1)
|
||||
return R_FALSE;
|
||||
if (at == UT64_MAX)
|
||||
return R_FALSE;
|
||||
if (depth < 0)
|
||||
return R_FALSE;
|
||||
#warning This must be optimized to use the fcnstore api
|
||||
@ -211,14 +227,25 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
eprintf ("Error: new (fcn)\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
if (!(buf = malloc (core->blocksize))) {
|
||||
if (!(buf = malloc (ANALBS))) { //core->blocksize))) {
|
||||
eprintf ("Error: malloc (buf)\n");
|
||||
goto error;
|
||||
}
|
||||
#define MAXNEXT 1032 // TODO: make it relocatable
|
||||
if (r_config_get_i (core->config, "anal.hasnext")) {
|
||||
|
||||
next = R_NEWS0 (ut64, MAXNEXT);
|
||||
}
|
||||
|
||||
//eprintf ("FUNC 0x%08"PFMT64x"\n", at+fcnlen);
|
||||
do {
|
||||
if ((buflen = r_io_read_at (core->io, at+fcnlen, buf, core->blocksize)) != core->blocksize)
|
||||
// check io error
|
||||
if ((buflen = r_io_read_at (core->io, at+fcnlen, buf, 4) != 4))
|
||||
goto error;
|
||||
// real read.
|
||||
if (!r_core_read_at (core, at+fcnlen, buf, ANALBS))
|
||||
goto error;
|
||||
buflen = ANALBS;
|
||||
if (r_cons_singleton ()->breaked)
|
||||
break;
|
||||
fcnlen = r_anal_fcn (core->anal, fcn, at+fcnlen, buf, buflen, reftype);
|
||||
@ -246,6 +273,7 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
eprintf ("fun depth fail for 0x%08"PFMT64x"\n", fcn->addr);
|
||||
} else fcn->depth = 256-fcn->depth;
|
||||
r_list_sort (fcn->bbs, &cmpaddr);
|
||||
|
||||
/* New function: Add initial xref */
|
||||
if (from != -1) {
|
||||
if (!(ref = r_anal_ref_new ())) {
|
||||
@ -259,6 +287,21 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
}
|
||||
// XXX: this looks weird
|
||||
r_anal_fcn_insert (core->anal, fcn);
|
||||
#if 1
|
||||
if (next && nexti<MAXNEXT) {
|
||||
int i;
|
||||
ut64 addr = fcn->addr + fcn->size;
|
||||
for (i=0;i<nexti;i++)
|
||||
if (next[i] == addr)
|
||||
break;
|
||||
if (i==nexti) {
|
||||
// TODO: ensure next address is function after padding (nop or trap or wat)
|
||||
eprintf ("FUNC 0x%08"PFMT64x" > 0x%08"PFMT64x"\r",
|
||||
fcn->addr, fcn->addr + fcn->size);
|
||||
next[nexti++] = fcn->addr + fcn->size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//r_list_append (core->anal->fcns, fcn);
|
||||
r_list_foreach (fcn->refs, iter, refi)
|
||||
if (refi->addr != -1)
|
||||
@ -268,18 +311,29 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
}
|
||||
} while (fcnlen != R_ANAL_RET_END);
|
||||
free (buf);
|
||||
|
||||
if (next) {
|
||||
for (i=0; i<nexti; i++) {
|
||||
if (!next[i]) continue;
|
||||
r_core_anal_fcn (core, next[i], from, 0, depth-1);
|
||||
}
|
||||
free (next);
|
||||
}
|
||||
|
||||
return R_TRUE;
|
||||
|
||||
error:
|
||||
free (buf);
|
||||
// ugly hack to free fcn
|
||||
if (fcn) {
|
||||
if (fcn->addr == UT64_MAX) {
|
||||
if (fcn->size == 0 || fcn->addr == UT64_MAX) {
|
||||
r_anal_fcn_free (fcn);
|
||||
return R_FALSE;
|
||||
}
|
||||
// TODO: mark this function as not properly analyzed
|
||||
eprintf ("Analysis of function at 0x%08"PFMT64x" has failed\n", fcn->addr);
|
||||
eprintf ("Analysis of function 0x%08"PFMT64x
|
||||
" has failed at 0x%08"PFMT64x"\n",
|
||||
fcn->addr, fcn->addr+fcn->size);
|
||||
if (!fcn->name) {
|
||||
// XXX dupped code.
|
||||
fcn->name = r_str_dup_printf ("%s.%08"PFMT64x,
|
||||
@ -298,6 +352,15 @@ error:
|
||||
r_anal_fcn_free (fcn);
|
||||
#endif
|
||||
}
|
||||
if (next) {
|
||||
if (nexti<MAXNEXT)
|
||||
next[nexti++] = fcn->addr + fcn->size;
|
||||
for (i=0; i<nexti; i++) {
|
||||
if (!next[i]) continue;
|
||||
r_core_anal_fcn (core, next[i], next[i], 0, depth-1);
|
||||
}
|
||||
free(next);
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
@ -693,7 +756,7 @@ R_API int r_core_anal_all(RCore *core) {
|
||||
r_list_foreach (list, iter, symbol) {
|
||||
if (core->cons->breaked)
|
||||
break;
|
||||
if (!strncmp (symbol->type,"FUNC", 4))
|
||||
if (!strncmp (symbol->type, "FUNC", 4))
|
||||
r_core_anal_fcn (core, offset + va?baddr+symbol->rva:symbol->offset, -1,
|
||||
R_ANAL_REF_TYPE_NULL, depth);
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ static int cmd_eval(void *data, const char *input) {
|
||||
char *p;
|
||||
const char *val = r_config_get (core->config, input+2);
|
||||
p = r_core_editor (core, val);
|
||||
r_str_subchr (p, '\n', ';');
|
||||
r_str_replace_char (p, '\n', ';');
|
||||
r_config_set (core->config, input+2, p);
|
||||
} else eprintf ("Usage: ee varname\n");
|
||||
break;
|
||||
|
@ -203,6 +203,8 @@ static int cmd_anal(void *data, const char *input) {
|
||||
ut32 tbs = core->blocksize;
|
||||
|
||||
#if 1
|
||||
switch (input[0]) {
|
||||
case 'o':
|
||||
if (input[0] && input[1]) {
|
||||
l = (int) r_num_get (core->num, input+2);
|
||||
if (l>0) len = l;
|
||||
@ -211,6 +213,7 @@ static int cmd_anal(void *data, const char *input) {
|
||||
len = l;
|
||||
}
|
||||
} else len = l = core->blocksize;
|
||||
}
|
||||
#endif
|
||||
|
||||
r_cons_break (NULL, NULL);
|
||||
|
@ -59,13 +59,19 @@ R_API int r_core_search_preludes(RCore *core) {
|
||||
ret = r_core_search_prelude (core, from, to, kw, kwlen, NULL, 0);
|
||||
free (kw);
|
||||
} else
|
||||
if (strstr (arch, "mips")) {
|
||||
ret = r_core_search_prelude (core, from, to,
|
||||
(const ut8 *)"\x27\xbd\x00", 3, NULL, 0);
|
||||
} else
|
||||
if (strstr (arch, "x86")) {
|
||||
switch (bits) {
|
||||
case 32:
|
||||
ret = r_core_search_prelude (core, from, to, (const ut8 *)"\x55\x89\xe5", 3, NULL, 0);
|
||||
ret = r_core_search_prelude (core, from, to,
|
||||
(const ut8 *)"\x55\x89\xe5", 3, NULL, 0);
|
||||
break;
|
||||
case 64:
|
||||
ret = r_core_search_prelude (core, from, to, (const ut8 *)"\x55\x48\x89\xe5", 3, NULL, 0);
|
||||
ret = r_core_search_prelude (core, from, to,
|
||||
(const ut8 *)"\x55\x48\x89\xe5", 3, NULL, 0);
|
||||
//r_core_cmd0 (core, "./x 554989e5");
|
||||
break;
|
||||
default:
|
||||
|
@ -354,6 +354,12 @@ static int config_asmarch_callback(void *user, void *data) {
|
||||
r_egg_setup (core->egg, node->value, core->anal->bits, 0, R_SYS_OS);
|
||||
if (!r_asm_use (core->assembler, node->value))
|
||||
eprintf ("asm.arch: cannot find (%s)\n", node->value);
|
||||
{
|
||||
char asmparser[32];
|
||||
snprintf (asmparser, sizeof (asmparser), "%s.pseudo", node->value);
|
||||
|
||||
r_config_set (core->config, "asm.parser", asmparser);
|
||||
}
|
||||
if (!r_config_set (core->config, "anal.plugin", node->value)) {
|
||||
char *p, *s = strdup (node->value);
|
||||
p = strchr (s, '.');
|
||||
@ -375,9 +381,9 @@ static int config_asmparser_callback(void *user, void *data) {
|
||||
RCore *core = (RCore*) user;
|
||||
RConfigNode *node = (RConfigNode*) data;
|
||||
// XXX this is wrong? snprintf(buf, 127, "parse_%s", node->value),
|
||||
r_parse_use (core->parser, node->value);
|
||||
return r_parse_use (core->parser, node->value);
|
||||
// TODO: control error and restore old value (return false?) show errormsg?
|
||||
return R_TRUE;
|
||||
//return R_TRUE;
|
||||
}
|
||||
|
||||
static int config_asmbits_callback(void *user, void *data) {
|
||||
@ -449,6 +455,8 @@ R_API int r_core_config_init(RCore *core) {
|
||||
/* anal */
|
||||
r_config_set (cfg, "anal.prelude", "");
|
||||
r_config_desc (cfg, "anal.prelude", "Specify an hexpair to find preludes in code");
|
||||
r_config_set (cfg, "anal.hasnext", "true");
|
||||
r_config_desc (cfg, "anal.hasnext", "Continue analysis after each function");
|
||||
r_config_set_i (cfg, "anal.depth", 50); // XXX: warn if depth is > 50 .. can be problematic
|
||||
r_config_desc (cfg, "anal.depth", "Max depth at code analysis");
|
||||
r_config_set_i (cfg, "anal.ptrdepth", 3);
|
||||
|
@ -534,8 +534,8 @@ R_API int r_core_block_size(RCore *core, int bsize) {
|
||||
if (bsize<1)
|
||||
bsize = 1;
|
||||
else if (bsize>core->blocksize_max) {
|
||||
eprintf ("blocksize is bigger than io.maxblk. dimmed to 0x%x\n",
|
||||
core->blocksize_max);
|
||||
eprintf ("blocksize is bigger than io.maxblk. dimmed to 0x%x > 0x%x\n",
|
||||
bsize, core->blocksize_max);
|
||||
bsize = core->blocksize_max;
|
||||
} else ret = R_TRUE;
|
||||
core->block = realloc (core->block, bsize+1);
|
||||
|
@ -179,5 +179,5 @@ R_API int r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size) {
|
||||
if (addr>=core->offset && addr<=core->offset+core->blocksize)
|
||||
r_core_block_read (core, 0);
|
||||
#endif
|
||||
return (ret!=UT64_MAX);
|
||||
return (ret==size); //UT64_MAX);
|
||||
}
|
||||
|
@ -778,7 +778,7 @@ R_API void r_core_visual_title (RCore *core, int color) {
|
||||
break;
|
||||
case 1: // pd
|
||||
case 2: // pd+dbg
|
||||
r_core_block_size (core, core->cons->rows *4); // this is hacky
|
||||
r_core_block_size (core, core->cons->rows *5); // this is hacky
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2009 nibble<.ds@gmail.com> */
|
||||
/* radare - LGPL - Copyright 2009-2012 - pancake, nibble */
|
||||
|
||||
#ifndef _INCLUDE_R_PARSE_H_
|
||||
#define _INCLUDE_R_PARSE_H_
|
||||
@ -45,6 +45,7 @@ R_API int r_parse_varsub(RParse *p, RAnalFunction *f, char *data, char *str, int
|
||||
extern struct r_parse_plugin_t r_parse_plugin_dummy;
|
||||
extern struct r_parse_plugin_t r_parse_plugin_att2intel;
|
||||
extern struct r_parse_plugin_t r_parse_plugin_x86_pseudo;
|
||||
extern struct r_parse_plugin_t r_parse_plugin_mips_pseudo;
|
||||
extern struct r_parse_plugin_t r_parse_plugin_mreplace;
|
||||
#endif
|
||||
|
||||
|
@ -92,6 +92,7 @@ typedef void (*PrintfCallback)(const char *str, ...);
|
||||
|
||||
#define BITS2BYTES(x) ((x/8)+((x%8)?1:0))
|
||||
#define ZERO_FILL(x) memset (x, 0, sizeof (x))
|
||||
#define R_NEWS0(x,y) (x*)memset (malloc(sizeof(x)*y), 0, sizeof(x)*y);
|
||||
#define R_NEWS(x,y) (x*)malloc(sizeof(x)*y)
|
||||
#define R_NEW(x) (x*)malloc(sizeof(x))
|
||||
#define R_NEW0(x) (x*)calloc(1,sizeof(x))
|
||||
|
@ -356,7 +356,7 @@ R_API char* r_str_replace(char *str, const char *key, const char *val, int g);
|
||||
R_API void r_str_cpy(char *dst, const char *src);
|
||||
R_API int r_str_bits (char *strout, const ut8 *buf, int len, const char *bitz);
|
||||
R_API int r_str_rwx(const char *str);
|
||||
R_API void r_str_subchr (char *s, int a, int b);
|
||||
R_API void r_str_replace_char (char *s, int a, int b);
|
||||
R_API const char *r_str_rwx_i(int rwx);
|
||||
R_API void r_str_writef(int fd, const char *fmt, ...);
|
||||
R_API char **r_str_argv(const char *str, int *_argc);
|
||||
|
8
libr/parse/p/mips_pseudo.mk
Normal file
8
libr/parse/p/mips_pseudo.mk
Normal file
@ -0,0 +1,8 @@
|
||||
OBJ_MIPSPSEUDO+=parse_mips_pseudo.o
|
||||
|
||||
TARGET_MIPSPSEUDO=parse_mips_pseudo.${EXT_SO}
|
||||
ALL_TARGETS+=${TARGET_MIPSPSEUDO}
|
||||
STATIC_OBJ+=${OBJ_MIPSPSEUDO}
|
||||
|
||||
${TARGET_MIPSPSEUDO}: ${OBJ_MIPSPSEUDO}
|
||||
${CC} $(call libname,parse_mips_pseudo) -L../../util -lr_util -shared ${CFLAGS} -o ${TARGET_MIPSPSEUDO} ${OBJ_MIPSPSEUDO}
|
@ -91,11 +91,11 @@ static int parse(RParse *p, const char *data, char *str) {
|
||||
strcpy (str, data);
|
||||
return R_TRUE;
|
||||
}
|
||||
r_str_subchr (buf, '$', 0);
|
||||
r_str_subchr (buf, '%', 0);
|
||||
r_str_subchr (buf, '\t', ' ');
|
||||
r_str_subchr (buf, '(', '[');
|
||||
r_str_subchr (buf, ')', ']');
|
||||
r_str_replace_char (buf, '$', 0);
|
||||
r_str_replace_char (buf, '%', 0);
|
||||
r_str_replace_char (buf, '\t', ' ');
|
||||
r_str_replace_char (buf, '(', '[');
|
||||
r_str_replace_char (buf, ')', ']');
|
||||
ptr = strchr (buf, '[');
|
||||
if (ptr) {
|
||||
int n;
|
||||
|
263
libr/parse/p/parse_mips_pseudo.c
Normal file
263
libr/parse/p/parse_mips_pseudo.c
Normal file
@ -0,0 +1,263 @@
|
||||
/* radare - LGPL - Copyright 2012 - pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_flags.h>
|
||||
#include <r_anal.h>
|
||||
#include <r_parse.h>
|
||||
|
||||
static int replace(int argc, const char *argv[], char *newstr) {
|
||||
int i,j,k;
|
||||
struct {
|
||||
char *op;
|
||||
char *str;
|
||||
} ops[] = {
|
||||
{ "li", "1 = 2"},
|
||||
{ "lui", "1 = 2"},
|
||||
{ "jr", "ret 1"},
|
||||
{ "bne", "if (1 != 2) goto 3"},
|
||||
{ "beq", "if (1 == 2) goto 3"},
|
||||
{ "beqz", "if (!1) goto 2"},
|
||||
{ "bnez", "if (1) goto 2"},
|
||||
{ "begz", "if (1 >= 0) goto 2"},
|
||||
{ "begzal", "if (1 >= 0) call 2"},
|
||||
{ "bgtz", "if (1 > 0) goto 2"},
|
||||
{ "bltz", "if (1 < 0) goto 2"},
|
||||
{ "bltzal", "if (1 < 0) call 2"},
|
||||
{ "negu", "1 = !2"},
|
||||
{ "and", "1 = 2 & 3"},
|
||||
{ "andi", "1 = 2 & 3"},
|
||||
{ "ori", "1 = 2 | 3"},
|
||||
{ "subu", "1 = 2 - 3"},
|
||||
{ "xor", "1 = 2 ^ 3"},
|
||||
{ "xori", "1 = 2 ^ 3"},
|
||||
{ "addi", "1 = 2 + 3"},
|
||||
{ "addiu", "1 = 2 + 3"},
|
||||
{ "addu", "1 = 2 + 3"},
|
||||
//{ "jal", "call 1"},
|
||||
{ "bal", "call 1"},
|
||||
{ "jalr", "call 1"},
|
||||
{ "b", "goto 1"},
|
||||
{ "move", "1 = 2"},
|
||||
{ "sll", "1 = 2 << 3"},
|
||||
{ "sllv", "1 = 2 << 3"},
|
||||
{ "slr", "1 = 2 >> 3"}, // logic
|
||||
{ "sra", "1 = 2 >> 3"}, // arithmetic
|
||||
{ "slt", "1 = (2 < 3)"},
|
||||
{ "slti", "1 = (2 < 3)"},
|
||||
{ "sltiu", "1 = (2 < 3)"},
|
||||
{ "sltu", "1 = unsigned (2 < 3)"},
|
||||
{ "lb", "1 = byte [3 + 2]"},
|
||||
{ "lw", "1 = [3 + 2]"},
|
||||
{ "sb", "byte [3 + 2] = 1"},
|
||||
{ "lbu", "1 = byte [3 + 2]"},
|
||||
{ "sw", "[3 + 2] = 1"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
for (i=0; ops[i].op != NULL; i++) {
|
||||
if (!strcmp (ops[i].op, argv[0])) {
|
||||
if (newstr != NULL) {
|
||||
for (j=k=0;ops[i].str[j]!='\0';j++,k++) {
|
||||
if (ops[i].str[j]>='1' && ops[i].str[j]<='9') {
|
||||
const char *w = argv[ ops[i].str[j]-'0' ];
|
||||
if (w != NULL) {
|
||||
strcpy (newstr+k, w);
|
||||
k += strlen(w)-1;
|
||||
}
|
||||
} else newstr[k] = ops[i].str[j];
|
||||
}
|
||||
newstr[k]='\0';
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: this is slow */
|
||||
if (newstr != NULL) {
|
||||
newstr[0] = '\0';
|
||||
for (i=0; i<argc; i++) {
|
||||
strcat (newstr, argv[i]);
|
||||
strcat (newstr, (i == 0 || i== argc - 1)?" ":", ");
|
||||
}
|
||||
}
|
||||
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
static int parse(RParse *p, const char *data, char *str) {
|
||||
int i, len = strlen (data);
|
||||
char w0[32];
|
||||
char w1[32];
|
||||
char w2[32];
|
||||
char w3[32];
|
||||
char w4[32];
|
||||
char *buf, *ptr, *optr;
|
||||
|
||||
// malloc can be slow here :?
|
||||
if ((buf = malloc (len+1)) == NULL)
|
||||
return R_FALSE;
|
||||
memcpy (buf, data, len+1);
|
||||
|
||||
if (!strcmp (data, "jr ra")) {
|
||||
strcpy (str, "ret");
|
||||
return R_TRUE;
|
||||
}
|
||||
r_str_replace_char (buf, '(', ',');
|
||||
r_str_replace_char (buf, ')', ' ');
|
||||
r_str_chop (buf);
|
||||
|
||||
if (*buf) {
|
||||
w0[0]='\0';
|
||||
w1[0]='\0';
|
||||
w2[0]='\0';
|
||||
w3[0]='\0';
|
||||
w4[0]='\0';
|
||||
ptr = strchr (buf, ' ');
|
||||
if (ptr == NULL)
|
||||
ptr = strchr (buf, '\t');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr==' '; ptr++);
|
||||
strcpy (w0, buf);
|
||||
strcpy (w1, ptr);
|
||||
|
||||
optr=ptr;
|
||||
ptr = strchr (ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr==' '; ptr++);
|
||||
strcpy (w1, optr);
|
||||
strcpy (w2, ptr);
|
||||
optr=ptr;
|
||||
ptr = strchr (ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr==' '; ptr++);
|
||||
strcpy (w2, optr);
|
||||
strcpy (w3, ptr);
|
||||
optr=ptr;
|
||||
// bonus
|
||||
ptr = strchr (ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
for (++ptr; *ptr==' '; ptr++);
|
||||
strcpy (w3, optr);
|
||||
strcpy (w4, ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const char *wa[] = { w0, w1, w2, w3, w4 };
|
||||
int nw = 0;
|
||||
for (i=0; i<4; i++) {
|
||||
if (wa[i][0] != '\0')
|
||||
nw++;
|
||||
}
|
||||
replace (nw, wa, str);
|
||||
{
|
||||
char *p = strdup (str);
|
||||
p = r_str_replace (p, "+ -", "- ", 0);
|
||||
#if EXPERIMENTAL_ZERO
|
||||
p = r_str_replace (p, "zero", "0", 0);
|
||||
if (!memcmp (p, "0 = ", 4)) *p = 0; // nop
|
||||
#endif
|
||||
if (!strcmp (w1, w2)) {
|
||||
char a[32], b[32];
|
||||
#define REPLACE(x,y) \
|
||||
sprintf (a, x, w1, w1); \
|
||||
sprintf (b, y, w1); \
|
||||
p = r_str_replace (p, a, b, 0);
|
||||
|
||||
// TODO: optimize
|
||||
REPLACE ("%s = %s +", "%s +=");
|
||||
REPLACE ("%s = %s -", "%s -=");
|
||||
REPLACE ("%s = %s &", "%s &=");
|
||||
REPLACE ("%s = %s |", "%s |=");
|
||||
REPLACE ("%s = %s ^", "%s ^=");
|
||||
REPLACE ("%s = %s >>", "%s >>=");
|
||||
REPLACE ("%s = %s <<", "%s <<=");
|
||||
}
|
||||
strcpy (str, p);
|
||||
free (p);
|
||||
}
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
static int assemble(RParse *p, char *data, char *str) {
|
||||
char *ptr;
|
||||
printf ("assembling '%s' to generate real asm code\n", str);
|
||||
ptr = strchr (str, '=');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
sprintf (data, "mov %s, %s", str, ptr+1);
|
||||
} else strcpy (data, str);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
static int filter(RParse *p, RFlag *f, char *data, char *str, int len) {
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
char *ptr, *ptr2;
|
||||
ut64 off;
|
||||
ptr = data;
|
||||
while ((ptr = strstr (ptr, "0x"))) {
|
||||
for (ptr2 = ptr; *ptr2 && !isseparator (*ptr2); ptr2++);
|
||||
off = r_num_math (NULL, ptr);
|
||||
if (!off) {
|
||||
ptr = ptr2;
|
||||
continue;
|
||||
}
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (flag->offset == off && strchr (flag->name, '.')) {
|
||||
*ptr = 0;
|
||||
snprintf (str, len, "%s%s%s", data, flag->name, ptr2!=ptr? ptr2: "");
|
||||
return R_TRUE;
|
||||
}
|
||||
}
|
||||
ptr = ptr2;
|
||||
}
|
||||
strncpy (str, data, len);
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
static int varsub(RParse *p, RAnalFunction *f, char *data, char *str, int len) {
|
||||
char *ptr, *ptr2;
|
||||
int i;
|
||||
|
||||
strncpy (str, data, len);
|
||||
for (i = 0; i < R_ANAL_VARSUBS; i++)
|
||||
if (f->varsubs[i].pat[0] != '\0' && f->varsubs[i].sub[0] != '\0' &&
|
||||
(ptr = strstr (data, f->varsubs[i].pat))) {
|
||||
*ptr = '\0';
|
||||
ptr2 = ptr + strlen (f->varsubs[i].pat);
|
||||
snprintf (str, len, "%s%s%s", data, f->varsubs[i].sub, ptr2);
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
struct r_parse_plugin_t r_parse_plugin_mips_pseudo = {
|
||||
.name = "mips.pseudo",
|
||||
.desc = "MIPS pseudo syntax",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.parse = parse,
|
||||
.assemble = &assemble,
|
||||
.filter = &filter,
|
||||
.varsub = &varsub,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_PARSE,
|
||||
.data = &r_parse_plugin_mips_pseudo
|
||||
};
|
||||
#endif
|
@ -101,6 +101,7 @@ static int parse(RParse *p, const char *data, char *str) {
|
||||
for (++ptr; *ptr==' '; ptr++);
|
||||
strcpy (w1, optr);
|
||||
strcpy (w2, ptr);
|
||||
optr=ptr;
|
||||
ptr = strchr (ptr, ',');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
|
@ -69,7 +69,7 @@ main () {
|
||||
}
|
||||
#endif
|
||||
|
||||
R_API void r_str_subchr (char *s, int a, int b) {
|
||||
R_API void r_str_replace_char (char *s, int a, int b) {
|
||||
char *o = s;
|
||||
for (; *o; s++, o++) {
|
||||
if (*o==a) {
|
||||
|
@ -22,9 +22,9 @@ R_API int r_vm_op_eval(struct r_vm_t *vm, const char *str) {
|
||||
s = alloca(len);
|
||||
memcpy (p, str, len);
|
||||
memcpy (s, str, len);
|
||||
r_str_subchr (s, ',', 0);
|
||||
r_str_subchr (s, '\t', 0);
|
||||
r_str_subchr (s, '#', 0);
|
||||
r_str_replace_char (s, ',', 0);
|
||||
r_str_replace_char (s, '\t', 0);
|
||||
r_str_replace_char (s, '#', 0);
|
||||
|
||||
nargs = r_str_word_set0(s);
|
||||
arg0 = r_str_word_get0(s, 0);
|
||||
|
@ -99,6 +99,7 @@ io.procpid
|
||||
io.shm
|
||||
parse.mreplace
|
||||
parse.att2intel
|
||||
parse.mips_pseudo
|
||||
parse.x86_pseudo"
|
||||
SHARED="
|
||||
asm.csr
|
||||
|
Loading…
Reference in New Issue
Block a user