mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-22 22:06:50 +00:00
Initial major cleanup of the RAnal module
This commit is contained in:
parent
2a4b1f0d96
commit
196cfd0534
@ -104,8 +104,7 @@ R_API void r_anal_plugin_free (RAnalPlugin *p) {
|
||||
R_API RAnal *r_anal_free(RAnal *a) {
|
||||
if (!a) return NULL;
|
||||
/* TODO: Free anals here */
|
||||
free (a->cpu);
|
||||
a->cpu = NULL;
|
||||
R_FREE (a->cpu);
|
||||
r_list_free (a->plugins);
|
||||
a->fcns->free = r_anal_fcn_free;
|
||||
r_list_free (a->fcns);
|
||||
@ -245,10 +244,9 @@ R_API void r_anal_trace_bb(RAnal *anal, ut64 addr) {
|
||||
R_API RList* r_anal_get_fcns (RAnal *anal) { return anal->fcns; }
|
||||
|
||||
R_API int r_anal_project_load(RAnal *anal, const char *prjfile) {
|
||||
if (!prjfile || !*prjfile)
|
||||
return R_FALSE;
|
||||
r_anal_xrefs_load (anal, prjfile);
|
||||
return R_TRUE;
|
||||
if (prjfile && *prjfile)
|
||||
return r_anal_xrefs_load (anal, prjfile);
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_anal_project_save(RAnal *anal, const char *prjfile) {
|
||||
|
@ -32,9 +32,8 @@ R_API void r_anal_bb_free(RAnalBlock *bb) {
|
||||
}
|
||||
if (bb->op_bytes)
|
||||
free (bb->op_bytes);
|
||||
if (bb->switch_op) {
|
||||
if (bb->switch_op)
|
||||
r_anal_switch_op_free (bb->switch_op);
|
||||
}
|
||||
#if R_ANAL_BB_HAS_OPS
|
||||
if (bb->ops)
|
||||
r_list_free (bb->ops);
|
||||
@ -143,7 +142,6 @@ R_API RAnalBlock *r_anal_bb_from_offset(RAnal *anal, ut64 off) {
|
||||
r_list_foreach (anal->fcns, iter, fcn)
|
||||
r_list_foreach (fcn->bbs, iter2, bb)
|
||||
if (r_anal_bb_is_in_offset (bb, off))
|
||||
//if (off >= bb->addr && off < bb->addr + bb->size)
|
||||
return bb;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
/* radare - LGPL - Copyright 2014 - condret */
|
||||
|
||||
#include <r_anal.h>
|
||||
#include <r_list.h>
|
||||
#include <r_types.h>
|
||||
|
||||
|
||||
R_API RAnalCycleFrame *r_anal_cycle_frame_new ()
|
||||
{
|
||||
R_API RAnalCycleFrame *r_anal_cycle_frame_new () {
|
||||
RAnalCycleFrame *cf = R_NEW0 (RAnalCycleFrame);
|
||||
cf->hooks = r_list_new ();
|
||||
return cf;
|
||||
}
|
||||
|
||||
R_API void r_anal_cycle_frame_free (RAnalCycleFrame *cf)
|
||||
{
|
||||
R_API void r_anal_cycle_frame_free (RAnalCycleFrame *cf) {
|
||||
if (!cf) return;
|
||||
r_list_free (cf->hooks);
|
||||
free (cf);
|
||||
|
247
libr/anal/fcn.c
247
libr/anal/fcn.c
@ -8,6 +8,7 @@
|
||||
|
||||
#define JMP_IS_EOB 0
|
||||
#define JMP_IS_EOB_RANGE 512
|
||||
#define CALL_IS_EOB 0
|
||||
|
||||
// 64KB max size
|
||||
#define MAX_FCN_SIZE 65535
|
||||
@ -43,8 +44,6 @@ R_API int r_anal_fcn_resize (RAnalFunction *fcn, int newsize) {
|
||||
R_API RAnalFunction *r_anal_fcn_new() {
|
||||
RAnalFunction *fcn = R_NEW0 (RAnalFunction);
|
||||
if (!fcn) return NULL;
|
||||
fcn->name = NULL;
|
||||
fcn->dsc = NULL;
|
||||
/* Function return type */
|
||||
fcn->rets = 0;
|
||||
fcn->size = 0;
|
||||
@ -53,7 +52,6 @@ R_API RAnalFunction *r_anal_fcn_new() {
|
||||
/* Function calling convention: cdecl/stdcall/fastcall/etc */
|
||||
fcn->call = R_ANAL_CC_TYPE_NONE;
|
||||
/* Function attributes: weak/noreturn/format/etc */
|
||||
fcn->attr = NULL;
|
||||
fcn->addr = -1;
|
||||
fcn->bits = 0;
|
||||
fcn->refs = r_anal_ref_list_new ();
|
||||
@ -61,9 +59,6 @@ R_API RAnalFunction *r_anal_fcn_new() {
|
||||
fcn->bbs = r_anal_bb_list_new ();
|
||||
fcn->fingerprint = NULL;
|
||||
fcn->diff = r_anal_diff_new ();
|
||||
fcn->args = NULL;
|
||||
fcn->locs = NULL;
|
||||
//fcn->locals = NULL;
|
||||
return fcn;
|
||||
}
|
||||
|
||||
@ -84,11 +79,9 @@ R_API void r_anal_fcn_free(void *_fcn) {
|
||||
r_list_free (fcn->xrefs);
|
||||
r_list_free (fcn->locs);
|
||||
#if 0
|
||||
// XXX: some shared basic blocks make it crash.
|
||||
// TODO: fix it with sdb
|
||||
r_list_free (fcn->bbs);
|
||||
//r_list_free (fcn->locals);
|
||||
r_list_free (fcn->locals);
|
||||
#endif
|
||||
r_list_free (fcn->bbs);
|
||||
free (fcn->fingerprint);
|
||||
r_anal_diff_free (fcn->diff);
|
||||
free (fcn->args);
|
||||
@ -97,18 +90,16 @@ R_API void r_anal_fcn_free(void *_fcn) {
|
||||
|
||||
R_API int r_anal_fcn_xref_add (RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr, int type) {
|
||||
RAnalRef *ref;
|
||||
if (!fcn || !a|| !(ref = r_anal_ref_new ()))
|
||||
if (!fcn || !a)
|
||||
return R_FALSE;
|
||||
if (!a->iob.is_valid_offset (a->iob.io, addr))
|
||||
return R_FALSE;
|
||||
ref = r_anal_ref_new ();
|
||||
if (!ref)
|
||||
return R_FALSE;
|
||||
// TODO: check if valid memory
|
||||
if (addr < 0xff) {
|
||||
free (ref);
|
||||
return R_FALSE; // invalid reference
|
||||
}
|
||||
// set global reference
|
||||
r_anal_xrefs_set (a, type, at, addr);
|
||||
// set per-function reference
|
||||
#if 1
|
||||
// with old function storage enabled there are some wrong analysis stuff
|
||||
#if FCN_OLD
|
||||
ref->at = at; // from
|
||||
ref->addr = addr; // to
|
||||
@ -116,17 +107,13 @@ R_API int r_anal_fcn_xref_add (RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr,
|
||||
// TODO: ensure we are not dupping xrefs
|
||||
r_list_append (fcn->refs, ref);
|
||||
#endif
|
||||
#endif
|
||||
#if FCN_SDB
|
||||
char key[1024];
|
||||
#if 0
|
||||
SETKEY ("fcn.0x%08"PFMT64x".name", fcn->addr);
|
||||
sdb_add (DB, key, fcn->name, 0);
|
||||
SETKEY ("fcn.name.%s", fcn->name);
|
||||
sdb_num_add (DB, key, fcn->addr, 0);
|
||||
#endif
|
||||
SETKEY ("fcn.0x%08"PFMT64x".xrefs", fcn->addr);
|
||||
sdb_array_add_num (DB, key, at, 0);
|
||||
sdb_add (DB, sdb_fmt (0, "fcn.0x%08"PFMT64x".name"), fcn->name, 0);
|
||||
// encode the name in base64 ?
|
||||
sdb_num_add (DB, sdb_fmt (0, "fcn.name.%s", fcn->name), fcn->addr, 0);
|
||||
sdb_array_add_num (DB,
|
||||
sdb_fmt (0, "fcn.0x%08"PFMT64x".xrefs", fcn->addr),
|
||||
at, 0);
|
||||
#endif
|
||||
return R_TRUE;
|
||||
}
|
||||
@ -175,6 +162,17 @@ static int bbsum(RAnalFunction *fcn) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static RAnalBlock* appendBasicBlock (RAnalFunction *fcn, ut64 addr) {
|
||||
RAnalBlock *bb = r_anal_bb_new();
|
||||
bb->addr = addr;
|
||||
bb->size = 0;
|
||||
bb->jump = UT64_MAX;
|
||||
bb->fail = UT64_MAX;
|
||||
bb->type = 0; // TODO
|
||||
r_list_append (fcn->bbs, bb);
|
||||
return bb;
|
||||
}
|
||||
|
||||
#define FITFCNSZ() {st64 n=bb->addr+bb->size-fcn->addr; \
|
||||
if(n<0) { fcn->addr += n; fcn->size = -n; } else \
|
||||
if(fcn->size<n)fcn->size=n; } \
|
||||
@ -182,30 +180,36 @@ static int bbsum(RAnalFunction *fcn) {
|
||||
eprintf ("Function too big at 0x%"PFMT64x"\n", bb->addr); \
|
||||
fcn->size = 0; \
|
||||
return R_ANAL_RET_ERROR; }
|
||||
|
||||
#define MAXBBSIZE 8096
|
||||
|
||||
#define gotoBeach(x) ret=x;goto beach;
|
||||
static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int depth) {
|
||||
RAnalBlock *bb = NULL;
|
||||
RAnalBlock *bbg = NULL;
|
||||
int ret = R_ANAL_RET_END;
|
||||
ut8 bbuf[8096];
|
||||
ut8 bbuf[MAXBBSIZE];
|
||||
int overlapped = 0;
|
||||
char *varname;
|
||||
RAnalOp op = {0};
|
||||
int oplen, idx = 0;
|
||||
int delay_cnt = 0, delay_idx = 0, delay_after = 0, delay_pending = 0, delay_adjust = 0, undelayed_idx = 0;
|
||||
// add basic block
|
||||
RAnalBlock *bb = NULL;
|
||||
RAnalBlock *bbg = NULL;
|
||||
struct {
|
||||
int cnt;
|
||||
int idx;
|
||||
int after;
|
||||
int pending;
|
||||
int adjust;
|
||||
int un_idx; // delay.un_idx
|
||||
} delay = {0};
|
||||
|
||||
if (depth<1) {
|
||||
return R_ANAL_RET_ERROR; // MUST BE TOO DEEP
|
||||
}
|
||||
if (bbget (fcn, addr)) {
|
||||
return R_ANAL_RET_ERROR; // MUST BE DUP
|
||||
}
|
||||
bb = r_anal_bb_new();
|
||||
bb->addr = addr;
|
||||
bb->size = 0;
|
||||
bb->jump = UT64_MAX;
|
||||
bb->fail = UT64_MAX;
|
||||
bb->type = 0; // TODO
|
||||
r_list_append (fcn->bbs, bb);
|
||||
|
||||
bb = appendBasicBlock (fcn, addr);
|
||||
|
||||
VERBOSE_ANAL eprintf ("Append bb at 0x%08"PFMT64x" (fcn)\n", addr);
|
||||
|
||||
@ -222,9 +226,7 @@ repeat:
|
||||
if ((oplen = r_anal_op (anal, &op, addr+idx, buf+idx, len-idx)) < 1) {
|
||||
VERBOSE_ANAL eprintf ("Unknown opcode at 0x%08"PFMT64x"\n", addr+idx);
|
||||
if (idx == 0) {
|
||||
r_anal_op_fini (&op);
|
||||
FITFCNSZ();
|
||||
return R_ANAL_RET_END;
|
||||
gotoBeach (R_ANAL_RET_END);
|
||||
} else {
|
||||
break; // unspecified behaviour
|
||||
}
|
||||
@ -239,47 +241,47 @@ repeat:
|
||||
}
|
||||
}
|
||||
idx += oplen;
|
||||
undelayed_idx = idx;
|
||||
delay.un_idx = idx;
|
||||
if (!overlapped) {
|
||||
bb->size += oplen;
|
||||
fcn->ninstr++;
|
||||
// FITFCNSZ(); // defer this, in case this instruction is a branch delay entry
|
||||
// fcn->size += oplen; /// XXX. must be the sum of all the bblocks
|
||||
}
|
||||
if (op.delay>0 && delay_pending == 0) {
|
||||
if (op.delay>0 && delay.pending == 0) {
|
||||
// Handle first pass through a branch delay jump:
|
||||
// Come back and handle the current instruction later.
|
||||
// Save the location of it in `delay_idx`
|
||||
// Save the location of it in `delay.idx`
|
||||
// note, we have still increased size of basic block
|
||||
// (and function)
|
||||
VERBOSE_DELAY eprintf ("Enter branch delay at 0x%08"PFMT64x ". bb->sz=%d\n", addr+idx-oplen, bb->size);
|
||||
delay_idx = idx - oplen;
|
||||
delay_cnt = op.delay;
|
||||
delay_pending = 1; // we need this in case the actual idx is zero...
|
||||
delay_adjust = !overlapped; // adjustment is required later to avoid double count
|
||||
delay.idx = idx - oplen;
|
||||
delay.cnt = op.delay;
|
||||
delay.pending = 1; // we need this in case the actual idx is zero...
|
||||
delay.adjust = !overlapped; // adjustment is required later to avoid double count
|
||||
continue;
|
||||
}
|
||||
|
||||
if (delay_cnt > 0) {
|
||||
if (delay.cnt > 0) {
|
||||
// if we had passed a branch delay instruction, keep
|
||||
// track of how many still to process.
|
||||
delay_cnt--;
|
||||
if (delay_cnt == 0) {
|
||||
delay.cnt--;
|
||||
if (delay.cnt == 0) {
|
||||
VERBOSE_DELAY eprintf ("Last branch delayed opcode at 0x%08"PFMT64x ". bb->sz=%d\n", addr+idx-oplen, bb->size);
|
||||
delay_after = idx;
|
||||
idx = delay_idx;
|
||||
delay.after = idx;
|
||||
idx = delay.idx;
|
||||
// At this point, we are still looking at the
|
||||
// last instruction in the branch delay group.
|
||||
// Next time, we will again be looking
|
||||
// at the original instruction that entered
|
||||
// the branch delay.
|
||||
}
|
||||
} else if (op.delay > 0 && delay_pending) {
|
||||
} else if (op.delay > 0 && delay.pending) {
|
||||
VERBOSE_DELAY eprintf ("Revisit branch delay jump at 0x%08"PFMT64x ". bb->sz=%d\n", addr+idx-oplen, bb->size);
|
||||
// This is the second pass of the branch delaying opcode
|
||||
// But we also already counted this instruction in the
|
||||
// size of the current basic block, so we need to fix that
|
||||
if (delay_adjust) {
|
||||
if (delay.adjust) {
|
||||
bb->size -= oplen;
|
||||
fcn->ninstr--;
|
||||
VERBOSE_DELAY eprintf ("Correct for branch delay @ %08"PFMT64x " bb.addr=%08"PFMT64x " corrected.bb=%d f.uncorr=%d\n",
|
||||
@ -287,9 +289,9 @@ repeat:
|
||||
FITFCNSZ();
|
||||
}
|
||||
// Next time, we go to the opcode after the delay count
|
||||
// Take care not to use this below, use undelayed_idx instead ...
|
||||
idx = delay_after;
|
||||
delay_pending = delay_after = delay_idx = delay_adjust = 0;
|
||||
// Take care not to use this below, use delay.un_idx instead ...
|
||||
idx = delay.after;
|
||||
delay.pending = delay.after = delay.idx = delay.adjust = 0;
|
||||
}
|
||||
// Note: if we got two branch delay instructions in a row due to an
|
||||
// compiler bug or junk or something it wont get treated as a delay
|
||||
@ -345,29 +347,26 @@ repeat:
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_NOP:
|
||||
if (anal->nopskip) {
|
||||
if ((addr + undelayed_idx-oplen) == fcn->addr) {
|
||||
//fcn->addr = bb->addr = addr + undelayed_idx;
|
||||
if ((addr + delay.un_idx-oplen) == fcn->addr) {
|
||||
//fcn->addr = bb->addr = addr + delay.un_idx;
|
||||
fcn->addr += oplen;
|
||||
idx = undelayed_idx;
|
||||
idx = delay.un_idx;
|
||||
goto repeat;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
#if JMP_IS_EOB
|
||||
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump,
|
||||
R_ANAL_REF_TYPE_CODE)) {
|
||||
#if 0
|
||||
FITFCNSZ();
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_ERROR;
|
||||
#endif
|
||||
}
|
||||
#if JMP_IS_EOB
|
||||
if (!overlapped) {
|
||||
bb->jump = op.jump;
|
||||
bb->fail = UT64_MAX;
|
||||
}
|
||||
FITFCNSZ();
|
||||
return R_ANAL_RET_END;
|
||||
#else
|
||||
// hardcoded jmp size // must be checked at the end wtf?
|
||||
// always fitfcnsz and retend
|
||||
@ -378,90 +377,58 @@ repeat:
|
||||
#if JMP_IS_EOB_RANGE>0
|
||||
} else {
|
||||
if (op.jump < addr-JMP_IS_EOB_RANGE && op.jump<addr) {
|
||||
FITFCNSZ();
|
||||
return R_ANAL_RET_END;
|
||||
gotoBeach (R_ANAL_RET_END);
|
||||
}
|
||||
if (op.jump > addr+JMP_IS_EOB_RANGE) {
|
||||
FITFCNSZ();
|
||||
return R_ANAL_RET_END;
|
||||
gotoBeach (R_ANAL_RET_END);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
//
|
||||
//FITFCNSZ();
|
||||
//return R_ANAL_RET_END;
|
||||
/// DO not follow jmps.. this is probably a bug ...
|
||||
#if 0
|
||||
anal->iob.read_at (anal->iob.io, op.jump, bbuf, sizeof (bbuf));
|
||||
FITFCNSZ();
|
||||
return fcn_recurse (anal, fcn, op.jump, bbuf, sizeof (bbuf), depth-1);
|
||||
#endif
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump,
|
||||
R_ANAL_REF_TYPE_CODE)) {
|
||||
FITFCNSZ();
|
||||
/// XXX. fcn_xref_add returning false shouldnt result in fcn chop
|
||||
#if 0
|
||||
r_anal_op_fini (&op);
|
||||
eprintf ("ERR CJMP JAJAJWAT\n");
|
||||
return R_ANAL_RET_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define recurseAt(x) \
|
||||
anal->iob.read_at (anal->iob.io, x, bbuf, sizeof (bbuf));\
|
||||
FITFCNSZ();\
|
||||
ret = fcn_recurse (anal, fcn, x, bbuf, sizeof (bbuf), depth-1);
|
||||
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
|
||||
if (!overlapped) {
|
||||
bb->jump = op.jump;
|
||||
bb->fail = op.fail;
|
||||
}
|
||||
anal->iob.read_at (anal->iob.io, op.jump, bbuf, sizeof (bbuf));
|
||||
FITFCNSZ();
|
||||
fcn_recurse (anal, fcn, op.jump, bbuf, sizeof (bbuf), depth-1);
|
||||
recurseAt (op.jump);
|
||||
recurseAt (op.fail);
|
||||
|
||||
// OK. What happens now, if the fail path is fully _inside_ the jump path?
|
||||
// How to avoid double counting the end address of the function?
|
||||
|
||||
anal->iob.read_at (anal->iob.io, op.fail, bbuf, sizeof (bbuf));
|
||||
FITFCNSZ();
|
||||
// TODO: Discuss bypassing this 'return' statement,
|
||||
// is this only necessary for branch delayed instructions?
|
||||
ret = fcn_recurse (anal, fcn, op.fail, bbuf, sizeof (bbuf), depth-1);
|
||||
if (1) { // XXX breaks mips analysis too !op.delay) {
|
||||
// this will be all x86, arm (at least)
|
||||
// without which the analysis is really slow,
|
||||
// presumably because each opcode would get revisited
|
||||
// (and already covered by a bb) many times
|
||||
return ret;
|
||||
}
|
||||
// XXX breaks mips analysis too !op.delay
|
||||
// this will be all x86, arm (at least)
|
||||
// without which the analysis is really slow,
|
||||
// presumably because each opcode would get revisited
|
||||
// (and already covered by a bb) many times
|
||||
gotoBeach (ret);
|
||||
// For some reason, branch delayed code (MIPS) needs to continue
|
||||
#if 0
|
||||
// do not add xrefs for cjmps?
|
||||
r_anal_op_fini (&op);
|
||||
#endif
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CALL)) {
|
||||
//fcn->size = bbsum (fcn);
|
||||
FITFCNSZ ();
|
||||
#if 0
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_ERROR;
|
||||
(void)r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CALL);
|
||||
#if CALL_IS_EOB
|
||||
recurseAt (op.jump);
|
||||
recurseAt (op.fail);
|
||||
gotoBeach (R_ANAL_RET_NEW);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
//case R_ANAL_OP_TYPE_HLT:
|
||||
case R_ANAL_OP_TYPE_TRAP:
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
VERBOSE_ANAL eprintf ("RET 0x%08"PFMT64x". %d %d %d\n",
|
||||
addr+undelayed_idx-oplen, overlapped,
|
||||
addr+delay.un_idx-oplen, overlapped,
|
||||
bb->size, fcn->size);
|
||||
FITFCNSZ();
|
||||
FITFCNSZ ();
|
||||
r_anal_op_fini (&op);
|
||||
//fcn->size = bbsum (fcn);
|
||||
return R_ANAL_RET_END;
|
||||
}
|
||||
}
|
||||
beach:
|
||||
r_anal_op_fini (&op);
|
||||
FITFCNSZ ();
|
||||
return ret;
|
||||
@ -493,16 +460,11 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
fcn->size = 0;
|
||||
fcn->type = (reftype==R_ANAL_REF_TYPE_CODE)?
|
||||
R_ANAL_FCN_TYPE_LOC: R_ANAL_FCN_TYPE_FCN;
|
||||
|
||||
if (fcn->addr == UT64_MAX) fcn->addr = addr;
|
||||
|
||||
if (anal->cur && anal->cur->fcn){
|
||||
int result = anal->cur->fcn(anal, fcn, addr, buf, len, reftype);
|
||||
if (anal->cur->custom_fn_anal) return result;
|
||||
}
|
||||
|
||||
//if (len>16)
|
||||
// len -= 16; // XXX: hack to avoid buffer overflow by reading >64 bytes..
|
||||
return fcn_recurse (anal, fcn, addr, buf, len, FCN_DEPTH);
|
||||
}
|
||||
|
||||
@ -515,14 +477,12 @@ R_API int r_anal_fcn_insert(RAnal *anal, RAnalFunction *fcn) {
|
||||
r_listrange_add (anal->fcnstore, fcn);
|
||||
// HUH? store it here .. for backweird compatibility
|
||||
#endif
|
||||
#if ANAL_FCN_SDB
|
||||
#if 0
|
||||
// override bits, size,
|
||||
fcn.<offset>=name,size,type
|
||||
fcn.<offset>.bbs
|
||||
fcn.name.<name>=<offset>
|
||||
#endif
|
||||
sdb_set (DB, "fcn.0x080", "", 0);
|
||||
sdb_set (DB, sdb_fmt (0, "fcn.0x%"PFMT64x"", "", 0));
|
||||
#endif
|
||||
r_list_append (anal->fcns, fcn);
|
||||
return R_TRUE;
|
||||
@ -646,7 +606,7 @@ R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name) {
|
||||
R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff) {
|
||||
RAnalBlock *bb = NULL, *bbi;
|
||||
RListIter *iter;
|
||||
int append = 0, mid = 0;
|
||||
int mid = 0;
|
||||
|
||||
r_list_foreach (fcn->bbs, iter, bbi) {
|
||||
if (addr == bbi->addr) {
|
||||
@ -654,15 +614,15 @@ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump,
|
||||
mid = 0;
|
||||
break;
|
||||
} else
|
||||
if (addr > bbi->addr && addr < bbi->addr+bbi->size)
|
||||
if ((addr > bbi->addr) && \
|
||||
(addr < bbi->addr+bbi->size))
|
||||
mid = 1;
|
||||
}
|
||||
if (mid)
|
||||
return R_FALSE;
|
||||
if (bb == NULL) {
|
||||
if (!(bb = r_anal_bb_new ()))
|
||||
return R_FALSE;
|
||||
append = 1;
|
||||
bb = appendBasicBlock (fcn, addr);
|
||||
if (!bb) return R_FALSE;
|
||||
}
|
||||
bb->addr = addr;
|
||||
bb->size = size;
|
||||
@ -676,7 +636,6 @@ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump,
|
||||
if (diff->name)
|
||||
bb->diff->name = strdup (diff->name);
|
||||
}
|
||||
if (append) r_list_append (fcn->bbs, bb);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
@ -730,7 +689,7 @@ R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
|
||||
}
|
||||
|
||||
// TODO: rename fcn_bb_overlap()
|
||||
R_API int r_anal_fcn_overlap_bb(RAnalFunction *fcn, RAnalBlock *bb) {
|
||||
R_API int r_anal_fcn_bb_overlaps(RAnalFunction *fcn, RAnalBlock *bb) {
|
||||
RAnalBlock *bbi;
|
||||
RListIter *iter;
|
||||
#if R_ANAL_BB_HAS_OPS
|
||||
@ -787,6 +746,7 @@ R_API int r_anal_fcn_cc(RAnalFunction *fcn) {
|
||||
return E-N+(2*P);
|
||||
}
|
||||
|
||||
#if 0
|
||||
R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int type) {
|
||||
RAnalVar *var;
|
||||
RListIter *iter;
|
||||
@ -799,31 +759,32 @@ R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int type) {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
R_API char *r_anal_fcn_to_string(RAnal *a, RAnalFunction* fs) {
|
||||
int i;
|
||||
char *sign;
|
||||
RAnalVar *arg, *ret;
|
||||
if (fs->type != R_ANAL_FCN_TYPE_FCN || fs->type != R_ANAL_FCN_TYPE_SYM)
|
||||
return NULL;
|
||||
return NULL;
|
||||
#if 0
|
||||
ret = r_anal_fcn_get_var (fs, 0, R_ANAL_VAR_SCOPE_RET);
|
||||
sign = ret ? r_str_newf ("%s %s (", ret->name, fs->name):
|
||||
r_str_newf ("void %s (", fs->name);
|
||||
|
||||
/* FIXME: Use RAnalType instead */
|
||||
for (i = 0; ; i++) {
|
||||
if (!(arg = r_anal_fcn_get_var (fs, i,
|
||||
R_ANAL_VAR_SCOPE_ARG|R_ANAL_VAR_SCOPE_ARGREG)))
|
||||
break;
|
||||
#if 0
|
||||
// TODO: implement array support using sdb
|
||||
if (arg->type->type == R_ANAL_TYPE_ARRAY)
|
||||
sign = r_str_concatf (sign, i?", %s %s:%02x[%d]":"%s %s:%02x[%d]",
|
||||
arg->type, arg->name, arg->delta, arg->type->custom.a->count);
|
||||
else
|
||||
#endif
|
||||
sign = r_str_concatf (sign, i?", %s %s:%02x":"%s %s:%02x",
|
||||
arg->type, arg->name, arg->delta);
|
||||
}
|
||||
#endif
|
||||
return (sign = r_str_concatf (sign, ");"));
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,11 @@
|
||||
#include <r_util.h>
|
||||
#include <r_list.h>
|
||||
|
||||
// XXX this .c wraps a reversed xrefs.c api.. this is dupping code. we must merge apis!
|
||||
// NOTE: This file uses the xrefs api which is sdb based
|
||||
// This file contains the reversed api for querying xrefs.c which
|
||||
// is implemented on top of sdb. Anyway, the sdbization is not
|
||||
// complete because there's still r_anal_ref_new() which doesnt
|
||||
// serializes with sdb_native
|
||||
|
||||
R_API RAnalRef *r_anal_ref_new() {
|
||||
RAnalRef *ref = R_NEW (RAnalRef);
|
||||
if (ref) {
|
||||
@ -26,7 +29,6 @@ R_API void r_anal_ref_free(void *ref) {
|
||||
free (ref);
|
||||
}
|
||||
|
||||
// TODO: use sdb or hashmap for fucks sake
|
||||
R_API int r_anal_ref_add(RAnal *anal, ut64 addr, ut64 at, int type) {
|
||||
r_anal_xrefs_set (anal, type, at, addr);
|
||||
return R_TRUE;
|
||||
@ -41,8 +43,6 @@ R_API int r_anal_ref_del(RAnal *anal, ut64 at, ut64 addr) {
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 addr);
|
||||
// XXX: MAJOR SLOWDOWN PLZ FIX
|
||||
R_API RList *r_anal_xref_get(RAnal *anal, ut64 addr) {
|
||||
return r_anal_xrefs_get (anal, addr);
|
||||
}
|
||||
|
@ -172,3 +172,56 @@ R_API char *r_anal_type_format (RAnal *anal, const char *t) {
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//NOTES FROM THE OLD CPARSE IMPLEMENTATION
|
||||
enum {
|
||||
R_ANAL_TYPE_VARIABLE = 1,
|
||||
R_ANAL_TYPE_POINTER = 2,
|
||||
R_ANAL_TYPE_ARRAY = 3,
|
||||
R_ANAL_TYPE_STRUCT = 4,
|
||||
R_ANAL_TYPE_UNION = 5,
|
||||
R_ANAL_TYPE_ALLOCA = 6,
|
||||
R_ANAL_TYPE_FUNCTION = 7,
|
||||
R_ANAL_TYPE_ANY = 8,
|
||||
};
|
||||
|
||||
// [0:3] bits - place to store variable size
|
||||
#define R_ANAL_VAR_TYPE_SIZE_MASK 0xF
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_CHAR = 1,
|
||||
R_ANAL_VAR_TYPE_BYTE = 2,
|
||||
R_ANAL_VAR_TYPE_WORD = 3,
|
||||
R_ANAL_VAR_TYPE_DWORD = 4,
|
||||
R_ANAL_VAR_TYPE_QWORD = 5,
|
||||
R_ANAL_VAR_TYPE_SHORT = 6,
|
||||
R_ANAL_VAR_TYPE_INT = 7,
|
||||
R_ANAL_VAR_TYPE_LONG = 8,
|
||||
R_ANAL_VAR_TYPE_LONGLONG = 9,
|
||||
R_ANAL_VAR_TYPE_FLOAT = 10,
|
||||
R_ANAL_VAR_TYPE_DOUBLE = 11,
|
||||
R_ANAL_VAR_TYPE_VOID = 12,
|
||||
};
|
||||
|
||||
|
||||
// [4:7] bits - place to store sign of variable
|
||||
#define R_ANAL_VAR_TYPE_SIGN_MASK 0xF0
|
||||
#define R_ANAL_VAR_TYPE_SIGN_SHIFT 4
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_SIGNED = 1,
|
||||
R_ANAL_VAR_TYPE_UNSIGNED = 2,
|
||||
};
|
||||
|
||||
// [8:11] bits - place to store variable modifiers/parameters
|
||||
#define R_ANAL_VAR_TYPE_MODIFIER_MASK 0xF00
|
||||
#define R_ANAL_VAR_TYPE_MODIFIER_SHIFT 8
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_REGISTER = 1,
|
||||
R_ANAL_VAR_TYPE_CONST = 2,
|
||||
R_ANAL_VAR_TYPE_STATIC = 3,
|
||||
R_ANAL_VAR_TYPE_VOLATILE = 4,
|
||||
};
|
||||
#endif
|
||||
|
@ -28,35 +28,52 @@ static void XREFKEY(char * const key, const size_t key_len,
|
||||
snprintf (key, key_len, "%s.%s.0x%"PFMT64x, kind, _sdb_type, addr);
|
||||
}
|
||||
|
||||
R_API void r_anal_xrefs_load(RAnal *anal, const char *prjfile) {
|
||||
R_API int r_anal_xrefs_load(RAnal *anal, const char *prjfile) {
|
||||
char *path, *db = r_str_newf (R2_HOMEDIR"/projects/%s.d", prjfile);
|
||||
if (!db) return R_FALSE;
|
||||
path = r_str_home (db);
|
||||
if (!path) {
|
||||
free (db);
|
||||
return R_FALSE;
|
||||
}
|
||||
sdb_free (DB);
|
||||
DB = sdb_new (path, "xrefs", 0);
|
||||
if (!DB) {
|
||||
free (db);
|
||||
free (path);
|
||||
return R_FALSE;
|
||||
}
|
||||
sdb_ns_set (anal->sdb, "xrefs", DB);
|
||||
free (path);
|
||||
free (db);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API void r_anal_xrefs_save(RAnal *anal, const char *prjfile) {
|
||||
sdb_sync (anal->sdb_xrefs);
|
||||
}
|
||||
|
||||
R_API void r_anal_xrefs_set (RAnal *anal, const RAnalRefType type,
|
||||
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type,
|
||||
ut64 from, ut64 to) {
|
||||
char key[32];
|
||||
if (!anal || !DB)
|
||||
return R_FALSE;
|
||||
XREFKEY (key, sizeof (key), "ref", type, from);
|
||||
sdb_array_add_num (DB, key, to, 0);
|
||||
XREFKEY (key, sizeof (key), "xref", type, to);
|
||||
sdb_array_add_num (DB, key, from, 0);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API void r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
|
||||
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
|
||||
char key[32];
|
||||
if (!anal || !DB)
|
||||
return R_FALSE;
|
||||
XREFKEY (key, sizeof (key), "ref", type, from);
|
||||
sdb_array_remove_num (DB, key, to, 0);
|
||||
XREFKEY (key, sizeof (key), "xref", type, to);
|
||||
sdb_array_remove_num (DB, key, from, 0);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
|
||||
@ -110,9 +127,11 @@ R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
|
||||
return list;
|
||||
}
|
||||
|
||||
R_API void r_anal_xrefs_init (RAnal *anal) {
|
||||
R_API int r_anal_xrefs_init (RAnal *anal) {
|
||||
sdb_reset (DB);
|
||||
if (!DB) return R_FALSE;
|
||||
sdb_array_set (DB, "types", -1, "code.jmp,code.call,data.mem,data.string", 0);
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
static int xrefs_list_cb_rad(RAnal *anal, const char *k, const char *v) {
|
||||
|
@ -434,7 +434,7 @@ R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head) {
|
||||
goto error;
|
||||
} else if (bblen == R_ANAL_RET_END) { /* bb analysis complete */
|
||||
if (split)
|
||||
ret = r_anal_fcn_overlap_bb (fcn, bb);
|
||||
ret = r_anal_fcn_bb_overlaps (fcn, bb);
|
||||
if (ret == R_ANAL_RET_NEW) {
|
||||
r_list_append (fcn->bbs, bb);
|
||||
fail = bb->fail;
|
||||
|
@ -1834,9 +1834,9 @@ if (ret) {
|
||||
break;
|
||||
default:{
|
||||
const char* help_msg[] = {
|
||||
"Usage:", "a", "",
|
||||
"Usage:", "a", "[8adefFghoprxstc] [...]",
|
||||
"a8", " [hexpairs]", "analyze bytes",
|
||||
"aa", "", "analyze all (fcns + bbs)",
|
||||
"aa", "", "analyze all (fcns + bbs) (aa0 to avoid sub renaming)",
|
||||
"ad", "", "analyze data trampoline (wip)",
|
||||
"ad", " [from] [to]", "analyze data pointers to (from-to)",
|
||||
"ae", " [expr]", "analyze opcode eval expression (see ao)",
|
||||
@ -1850,7 +1850,7 @@ if (ret) {
|
||||
"ax", "[?ld-*]", "manage refs/xrefs (see also afx?)",
|
||||
"as", " [num]", "analyze syscall using dbg.reg",
|
||||
"at", "[trd+-%*?] [.]", "analyze execution traces",
|
||||
"ac", "[cycles]", "analyze which op could be executed in [cycles] cycles, only cycles supporting archs",
|
||||
"ac", " [cycles]", "analyze which op could be executed in [cycles]",
|
||||
//"ax", " [-cCd] [f] [t]", "manage code/call/data xrefs",
|
||||
NULL
|
||||
};
|
||||
|
@ -52,35 +52,6 @@ typedef struct r_anal_meta_item_t {
|
||||
#define R_ANAL_UNMASK_TYPE(x) (x&R_ANAL_VAR_TYPE_SIZE_MASK)
|
||||
#define R_ANAL_UNMASK_SIGN(x) (((x& R_ANAL_VAR_TYPE_SIGN_MASK)>> R_ANAL_VAR_TYPE_SIGN_SHIFT)==R_ANAL_VAR_TYPE_UNSIGNED)?0:1
|
||||
|
||||
enum {
|
||||
R_ANAL_TYPE_VARIABLE = 1,
|
||||
R_ANAL_TYPE_POINTER = 2,
|
||||
R_ANAL_TYPE_ARRAY = 3,
|
||||
R_ANAL_TYPE_STRUCT = 4,
|
||||
R_ANAL_TYPE_UNION = 5,
|
||||
R_ANAL_TYPE_ALLOCA = 6,
|
||||
R_ANAL_TYPE_FUNCTION = 7,
|
||||
R_ANAL_TYPE_ANY = 8,
|
||||
};
|
||||
|
||||
// [0:3] bits - place to store variable size
|
||||
#define R_ANAL_VAR_TYPE_SIZE_MASK 0xF
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_CHAR = 1,
|
||||
R_ANAL_VAR_TYPE_BYTE = 2,
|
||||
R_ANAL_VAR_TYPE_WORD = 3,
|
||||
R_ANAL_VAR_TYPE_DWORD = 4,
|
||||
R_ANAL_VAR_TYPE_QWORD = 5,
|
||||
R_ANAL_VAR_TYPE_SHORT = 6,
|
||||
R_ANAL_VAR_TYPE_INT = 7,
|
||||
R_ANAL_VAR_TYPE_LONG = 8,
|
||||
R_ANAL_VAR_TYPE_LONGLONG = 9,
|
||||
R_ANAL_VAR_TYPE_FLOAT = 10,
|
||||
R_ANAL_VAR_TYPE_DOUBLE = 11,
|
||||
R_ANAL_VAR_TYPE_VOID = 12,
|
||||
};
|
||||
|
||||
enum {
|
||||
R_ANAL_DATA_TYPE_NULL = 0,
|
||||
R_ANAL_DATA_TYPE_STRING = 1,
|
||||
@ -92,26 +63,6 @@ enum {
|
||||
R_ANAL_DATA_TYPE_UNKNOWN = 7,
|
||||
};
|
||||
|
||||
// [4:7] bits - place to store sign of variable
|
||||
#define R_ANAL_VAR_TYPE_SIGN_MASK 0xF0
|
||||
#define R_ANAL_VAR_TYPE_SIGN_SHIFT 4
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_SIGNED = 1,
|
||||
R_ANAL_VAR_TYPE_UNSIGNED = 2,
|
||||
};
|
||||
|
||||
// [8:11] bits - place to store variable modifiers/parameters
|
||||
#define R_ANAL_VAR_TYPE_MODIFIER_MASK 0xF00
|
||||
#define R_ANAL_VAR_TYPE_MODIFIER_SHIFT 8
|
||||
|
||||
enum {
|
||||
R_ANAL_VAR_TYPE_REGISTER = 1,
|
||||
R_ANAL_VAR_TYPE_CONST = 2,
|
||||
R_ANAL_VAR_TYPE_STATIC = 3,
|
||||
R_ANAL_VAR_TYPE_VOLATILE = 4,
|
||||
};
|
||||
|
||||
/* type = (R_ANAL_VAR_TYPE_BYTE & R_ANAL_VAR_TYPE_SIZE_MASK) |
|
||||
* ( RANAL_VAR_TYPE_SIGNED & RANAL_VAR_TYPE_SIGN_MASK) |
|
||||
* ( RANAL_VAR_TYPE_CONST & RANAL_VAR_TYPE_MODIFIER_MASK)
|
||||
@ -1049,7 +1000,7 @@ R_API int r_anal_fcn_var_del_byindex (RAnal *a, ut64 fna, const char kind,
|
||||
|
||||
R_API int r_anal_fcn_cc(RAnalFunction *fcn);
|
||||
R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr);
|
||||
R_API int r_anal_fcn_overlap_bb(RAnalFunction *fcn, RAnalBlock *bb);
|
||||
R_API int r_anal_fcn_bb_overlaps(RAnalFunction *fcn, RAnalBlock *bb);
|
||||
R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int dir);
|
||||
R_API void r_anal_fcn_fit_overlaps (RAnal *anal, RAnalFunction *fcn);
|
||||
R_API RAnalFunction *r_anal_fcn_next(RAnal *anal, ut64 addr);
|
||||
@ -1071,8 +1022,8 @@ R_API void r_anal_xrefs_list(RAnal *anal, int rad);
|
||||
R_API RList* r_anal_fcn_get_refs (RAnalFunction *anal);
|
||||
R_API RList* r_anal_fcn_get_xrefs (RAnalFunction *anal);
|
||||
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr);
|
||||
R_API void r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
|
||||
R_API void r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
|
||||
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
|
||||
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
|
||||
R_API void r_anal_xrefs_save(RAnal *anal, const char *prjfile);
|
||||
R_API RList* r_anal_fcn_get_vars (RAnalFunction *anal);
|
||||
R_API RList* r_anal_fcn_get_bbs (RAnalFunction *anal);
|
||||
@ -1113,8 +1064,8 @@ R_API RAnalVarAccess *r_anal_var_access_get(RAnal *anal, RAnalVar *var, ut64 fro
|
||||
/* project */
|
||||
R_API int r_anal_project_load(RAnal *anal, const char *prjfile);
|
||||
R_API int r_anal_project_save(RAnal *anal, const char *prjfile);
|
||||
R_API void r_anal_xrefs_load(RAnal *anal, const char *prjfile);
|
||||
R_API void r_anal_xrefs_init (RAnal *anal);
|
||||
R_API int r_anal_xrefs_load(RAnal *anal, const char *prjfile);
|
||||
R_API int r_anal_xrefs_init (RAnal *anal);
|
||||
|
||||
#define R_ANAL_THRESHOLDFCN 0.7F
|
||||
#define R_ANAL_THRESHOLDBB 0.7F
|
||||
@ -1221,10 +1172,8 @@ R_API void r_anal_hint_set_size (RAnal *a, ut64 addr, int length);
|
||||
R_API void r_anal_hint_set_opcode (RAnal *a, ut64 addr, const char *str);
|
||||
R_API void r_anal_hint_set_esil (RAnal *a, ut64 addr, const char *str);
|
||||
R_API void r_anal_hint_set_pointer (RAnal *a, ut64 addr, ut64 jump);
|
||||
|
||||
R_API int r_anal_esil_eval(RAnal *anal, const char *str);
|
||||
|
||||
|
||||
/* switch.c APIs */
|
||||
R_API RAnalSwitchOp * r_anal_switch_op_new(ut64 addr, ut64 min_val, ut64 max_val);
|
||||
R_API void r_anal_switch_op_free(RAnalSwitchOp * swop);
|
||||
|
@ -189,8 +189,9 @@ typedef int (*RIODescClose)(RIO *io, RIODesc *);
|
||||
typedef ut8 * (*RIODescRead)(RIO *io, RIODesc *desc, ut64 *sz);
|
||||
typedef ut64 (*RIODescSeek)(RIO *io, RIODesc *desc, ut64 offset);
|
||||
typedef ut64 (*RIODescSize)(RIO *io, RIODesc *desc);
|
||||
typedef int (*RIOIsValidOffset)(RIO *io, ut64 addr);
|
||||
|
||||
typedef void (*RIOSectionAdd)(RIO *io, ut64 offset, ut64 vaddr, ut64 size, ut64 vsize, int rwx, const char *name, ut32 bin_id, int fd);
|
||||
typedef RIOSection* (*RIOSectionAdd)(RIO *io, ut64 offset, ut64 vaddr, ut64 size, ut64 vsize, int rwx, const char *name, ut32 bin_id, int fd);
|
||||
typedef int (*RIOSectionSetArchBinID)(RIO *io, ut64 addr, const char *arch, int bits, ut32 bin_id);
|
||||
typedef int (*RIOSectionSetArchBin)(RIO *io, ut64 addr, const char *arch, int bits);
|
||||
|
||||
@ -204,6 +205,7 @@ typedef struct r_io_bind_t {
|
||||
RIOWriteAt write_at;
|
||||
RIOSize size;
|
||||
RIOSeek seek;
|
||||
RIOIsValidOffset is_valid_offset;
|
||||
|
||||
RIOSectionAdd section_add;
|
||||
RIOSectionSetArchBin section_set_arch;
|
||||
|
@ -76,40 +76,41 @@ typedef struct sdb_ns_t {
|
||||
SDB_API Sdb* sdb_new0 ();
|
||||
Sdb* sdb_new (const char *path, const char *file, int lock);
|
||||
void sdb_config (Sdb *s, int options);
|
||||
int sdb_free (Sdb* s);
|
||||
int sdb_free (Sdb* s);
|
||||
void sdb_file (Sdb* s, const char *dir);
|
||||
void sdb_reset (Sdb* s);
|
||||
void sdb_setup (Sdb* s, int options);
|
||||
void sdb_drain (Sdb*, Sdb*);
|
||||
|
||||
int sdb_query (Sdb* s, const char *cmd);
|
||||
int sdb_queryf (Sdb* s, const char *fmt, ...);
|
||||
int sdb_query_lines (Sdb *s, const char *cmd);
|
||||
int sdb_query (Sdb* s, const char *cmd);
|
||||
int sdb_queryf (Sdb* s, const char *fmt, ...);
|
||||
int sdb_query_lines (Sdb *s, const char *cmd);
|
||||
char *sdb_querys (Sdb* s, char *buf, size_t len, const char *cmd);
|
||||
char *sdb_querysf (Sdb* s, char *buf, size_t buflen, const char *fmt, ...);
|
||||
int sdb_query_file(Sdb *s, const char* file);
|
||||
int sdb_exists (Sdb*, const char *key);
|
||||
int sdb_unset (Sdb*, const char *key, ut32 cas);
|
||||
int sdb_unset_matching(Sdb *s, const char *k);
|
||||
int sdb_query_file(Sdb *s, const char* file);
|
||||
int sdb_exists (Sdb*, const char *key);
|
||||
int sdb_unset (Sdb*, const char *key, ut32 cas);
|
||||
int sdb_unset_matching(Sdb *s, const char *k);
|
||||
char *sdb_get (Sdb*, const char *key, ut32 *cas);
|
||||
const char *sdb_const_get (Sdb*, const char *key, ut32 *cas);
|
||||
const char *sdb_const_get_len (Sdb* s, const char *key, int *vlen, ut32 *cas);
|
||||
int sdb_set (Sdb*, const char *key, const char *data, ut32 cas);
|
||||
int sdb_set_owned (Sdb* s, const char *key, char *val, ut32 cas);
|
||||
int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_add (Sdb* s, const char *key, const char *val, ut32 cas);
|
||||
int sdb_set (Sdb*, const char *key, const char *data, ut32 cas);
|
||||
int sdb_set_owned (Sdb* s, const char *key, char *val, ut32 cas);
|
||||
int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_add (Sdb* s, const char *key, const char *val, ut32 cas);
|
||||
void sdb_list(Sdb*);
|
||||
int sdb_sync (Sdb*);
|
||||
int sdb_sync (Sdb*);
|
||||
void sdb_kv_free (SdbKv *kv);
|
||||
|
||||
/* num.c */
|
||||
int sdb_num_exists (Sdb*, const char *key);
|
||||
int sdb_num_base (const char *s);
|
||||
ut64 sdb_num_get (Sdb* s, const char *key, ut32 *cas);
|
||||
int sdb_num_set (Sdb* s, const char *key, ut64 v, ut32 cas);
|
||||
ut64 sdb_num_inc (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
ut64 sdb_num_dec (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
int sdb_num_exists (Sdb*, const char *key);
|
||||
int sdb_num_base (const char *s);
|
||||
ut64 sdb_num_get (Sdb* s, const char *key, ut32 *cas);
|
||||
int sdb_num_set (Sdb* s, const char *key, ut64 v, ut32 cas);
|
||||
int sdb_num_add (Sdb *s, const char *key, ut64 v, ut32 cas);
|
||||
ut64 sdb_num_inc (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
ut64 sdb_num_dec (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
|
||||
typedef int (*SdbForeachCallback)(void *user, const char *k, const char *v);
|
||||
int sdb_foreach (Sdb* s, SdbForeachCallback cb, void *user);
|
||||
|
@ -751,6 +751,7 @@ R_API int r_io_bind(RIO *io, RIOBind *bnd) {
|
||||
bnd->write_at = r_io_write_at;
|
||||
bnd->size = r_io_size;
|
||||
bnd->seek = r_io_seek;
|
||||
bnd->is_valid_offset = r_io_is_valid_offset;
|
||||
|
||||
bnd->desc_open = r_io_open_nomap;
|
||||
bnd->desc_close = r_io_close;
|
||||
@ -760,6 +761,7 @@ R_API int r_io_bind(RIO *io, RIOBind *bnd) {
|
||||
bnd->desc_get_by_fd = r_io_desc_get;
|
||||
|
||||
bnd->section_add = r_io_section_add;
|
||||
|
||||
bnd->section_set_arch = r_io_section_set_archbits;
|
||||
bnd->section_set_arch_bin_id = r_io_section_set_archbits_bin_id;
|
||||
|
||||
|
@ -216,13 +216,18 @@ SDB_API char *sdb_json_indent(const char *s) {
|
||||
char *o, *O, *OE, *tmp;
|
||||
if (!s) return NULL;
|
||||
osz = (1+strlen (s)) * 20;
|
||||
if (osz<1) return NULL;
|
||||
O = malloc (osz);
|
||||
OE = O+osz;
|
||||
if (!O) return NULL;
|
||||
OE = O+osz;
|
||||
for (o=O; *s; s++) {
|
||||
if (o + indent + 10 > OE) {
|
||||
int delta = o-O;
|
||||
osz += 0x1000+indent;
|
||||
if (osz<1) {
|
||||
free (O);
|
||||
return NULL;
|
||||
}
|
||||
tmp = realloc (O, osz);
|
||||
if (!O) {
|
||||
free (tmp);
|
||||
|
@ -6,8 +6,10 @@
|
||||
#include "rangstr.h"
|
||||
|
||||
void rangstr_print (Rangstr *s) {
|
||||
/*printf ("%.%s", s->t-s->f, s->p); */
|
||||
if (s->p) fwrite (s->p+s->f, s->t-s->f, 1, stdout);
|
||||
if (s && s->p) {
|
||||
(void) fwrite (s->p+s->f,
|
||||
s->t-s->f, 1, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
Rangstr rangstr_new (const char *s) {
|
||||
|
@ -15,6 +15,13 @@ SDB_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas) {
|
||||
return sdb_atoi (v);
|
||||
}
|
||||
|
||||
SDB_API int sdb_num_add(Sdb *s, const char *key, ut64 v, ut32 cas) {
|
||||
char *val, b[128];
|
||||
int numbase = sdb_num_base (sdb_const_get (s, key, NULL));
|
||||
val = sdb_itoa (v, b, numbase);
|
||||
return sdb_add (s, key, val, cas);
|
||||
}
|
||||
|
||||
SDB_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas) {
|
||||
char *val, b[128];
|
||||
int numbase = sdb_num_base (sdb_const_get (s, key, NULL));
|
||||
|
@ -76,40 +76,41 @@ typedef struct sdb_ns_t {
|
||||
SDB_API Sdb* sdb_new0 ();
|
||||
Sdb* sdb_new (const char *path, const char *file, int lock);
|
||||
void sdb_config (Sdb *s, int options);
|
||||
int sdb_free (Sdb* s);
|
||||
int sdb_free (Sdb* s);
|
||||
void sdb_file (Sdb* s, const char *dir);
|
||||
void sdb_reset (Sdb* s);
|
||||
void sdb_setup (Sdb* s, int options);
|
||||
void sdb_drain (Sdb*, Sdb*);
|
||||
|
||||
int sdb_query (Sdb* s, const char *cmd);
|
||||
int sdb_queryf (Sdb* s, const char *fmt, ...);
|
||||
int sdb_query_lines (Sdb *s, const char *cmd);
|
||||
int sdb_query (Sdb* s, const char *cmd);
|
||||
int sdb_queryf (Sdb* s, const char *fmt, ...);
|
||||
int sdb_query_lines (Sdb *s, const char *cmd);
|
||||
char *sdb_querys (Sdb* s, char *buf, size_t len, const char *cmd);
|
||||
char *sdb_querysf (Sdb* s, char *buf, size_t buflen, const char *fmt, ...);
|
||||
int sdb_query_file(Sdb *s, const char* file);
|
||||
int sdb_exists (Sdb*, const char *key);
|
||||
int sdb_unset (Sdb*, const char *key, ut32 cas);
|
||||
int sdb_unset_matching(Sdb *s, const char *k);
|
||||
int sdb_query_file(Sdb *s, const char* file);
|
||||
int sdb_exists (Sdb*, const char *key);
|
||||
int sdb_unset (Sdb*, const char *key, ut32 cas);
|
||||
int sdb_unset_matching(Sdb *s, const char *k);
|
||||
char *sdb_get (Sdb*, const char *key, ut32 *cas);
|
||||
const char *sdb_const_get (Sdb*, const char *key, ut32 *cas);
|
||||
const char *sdb_const_get_len (Sdb* s, const char *key, int *vlen, ut32 *cas);
|
||||
int sdb_set (Sdb*, const char *key, const char *data, ut32 cas);
|
||||
int sdb_set_owned (Sdb* s, const char *key, char *val, ut32 cas);
|
||||
int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_add (Sdb* s, const char *key, const char *val, ut32 cas);
|
||||
int sdb_set (Sdb*, const char *key, const char *data, ut32 cas);
|
||||
int sdb_set_owned (Sdb* s, const char *key, char *val, ut32 cas);
|
||||
int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas);
|
||||
int sdb_add (Sdb* s, const char *key, const char *val, ut32 cas);
|
||||
void sdb_list(Sdb*);
|
||||
int sdb_sync (Sdb*);
|
||||
int sdb_sync (Sdb*);
|
||||
void sdb_kv_free (SdbKv *kv);
|
||||
|
||||
/* num.c */
|
||||
int sdb_num_exists (Sdb*, const char *key);
|
||||
int sdb_num_base (const char *s);
|
||||
ut64 sdb_num_get (Sdb* s, const char *key, ut32 *cas);
|
||||
int sdb_num_set (Sdb* s, const char *key, ut64 v, ut32 cas);
|
||||
ut64 sdb_num_inc (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
ut64 sdb_num_dec (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
int sdb_num_exists (Sdb*, const char *key);
|
||||
int sdb_num_base (const char *s);
|
||||
ut64 sdb_num_get (Sdb* s, const char *key, ut32 *cas);
|
||||
int sdb_num_set (Sdb* s, const char *key, ut64 v, ut32 cas);
|
||||
int sdb_num_add (Sdb *s, const char *key, ut64 v, ut32 cas);
|
||||
ut64 sdb_num_inc (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
ut64 sdb_num_dec (Sdb* s, const char *key, ut64 n, ut32 cas);
|
||||
|
||||
typedef int (*SdbForeachCallback)(void *user, const char *k, const char *v);
|
||||
int sdb_foreach (Sdb* s, SdbForeachCallback cb, void *user);
|
||||
|
Loading…
x
Reference in New Issue
Block a user