mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
* Highlight destination offset when cursor on jmp/call in visual
* Show call decompilations under the opcode as a comment * Rename RRegister as RReg - Deprecate r_reg_init and use r_reg_new - Rewrite the list.h dependency in r_reg in order to use r_list - Fix some memory leaks * Implement push/pop methods in RReg class - add test case using it - will be used for register diffing and tracing
This commit is contained in:
parent
90a2b9f84a
commit
1356a9bdd1
8
AUTHORS
8
AUTHORS
@ -2,3 +2,11 @@ Main developers aka /dev/radare
|
||||
|
||||
- pancake <nopcode.org>
|
||||
- nibble.ds <gmail.com>
|
||||
|
||||
Contributors
|
||||
- earada
|
||||
- esteve <estlack.org>
|
||||
- elektranox
|
||||
- neuroflip
|
||||
- graz
|
||||
- pof
|
||||
|
19
TODO
19
TODO
@ -14,19 +14,12 @@ Questions
|
||||
|
||||
0.6 RELEASE
|
||||
===========
|
||||
* Add support for STATIC_PLUGINS in r_lang
|
||||
- r_lang_define is implemented in lang.c, but requires the collaboration
|
||||
of the plugins to properly setup the environment for the script execution.
|
||||
- Add support for STATIC_PLUGINS in r_lang
|
||||
- dlerror(/usr/lib/radare2/lang_perl.so): libperl.so: cannot open shared object file: No such file or directory
|
||||
This issue is fixed by setting LD_LIBRARY_PATH...looks like dlopen ignores rpath
|
||||
* Colorize destination address when cursor in branch
|
||||
* Reimplement or fix the delta diffing in C
|
||||
- first we need to do it for ired..
|
||||
* Add dex format support to rabin (android)
|
||||
* Trace contents of buffers: filter search results..? cc 8080 @@ hit* .. check for values that has changed.
|
||||
* Create radare2-testsuite project
|
||||
* Colorize registers that has changed
|
||||
|
||||
Build system:
|
||||
-------------
|
||||
@ -70,6 +63,7 @@ TODO pancake
|
||||
------------
|
||||
* Display eflags in ascii mode
|
||||
- use r_str_bits()
|
||||
- r_reg must have a format string for flags, using r_str_bitz
|
||||
- r_reg_eflags(dbg->reg, "cpastidor", mode) // must be in r_util.. as a bit helper
|
||||
- static buffer in dbg->reg..fixed size (32)
|
||||
- printf("eflags: %s\n", r_reg_get_flags (dbg->reg, "cpastidor");
|
||||
@ -90,10 +84,8 @@ TODO pancake
|
||||
- function signature comparsion if they dont match
|
||||
r_anal_fcn_cmp (anal, f1, f2);
|
||||
}
|
||||
- add support for sign/unsigned registers..or at least a way to cast them
|
||||
- add push/pop of register states (maybe we only need 2 levels of states)
|
||||
- display regs in colors
|
||||
- can be used for diffing registers
|
||||
- display changed registers in colors
|
||||
- is also useful to store values before emulating code
|
||||
- we can probably implement this in a clone() method? (too heavy? more orgtogonal)
|
||||
|
||||
@ -143,7 +135,14 @@ Refactoring
|
||||
0.7
|
||||
===
|
||||
* Is RCore->block and blocksize a RBuf ? refactor!11
|
||||
* add support for sign/unsigned registers..or at least a way to cast them
|
||||
* Implement rap:// upload/download protocol commands (maybe just system() with rsc2+wget?
|
||||
* Add support for STATIC_PLUGINS in r_lang
|
||||
- r_lang_define is implemented in lang.c, but requires the collaboration
|
||||
of the plugins to properly setup the environment for the script execution.
|
||||
- Add support for STATIC_PLUGINS in r_lang
|
||||
- dlerror(/usr/lib/radare2/lang_perl.so): libperl.so: cannot open shared object file: No such file or directory
|
||||
This issue is fixed by setting LD_LIBRARY_PATH...looks like dlopen ignores rpath
|
||||
|
||||
Future
|
||||
======
|
||||
|
@ -25,6 +25,11 @@ static int checkbpcallback(RCore *core) {
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
static void printoffset(ut64 off, int show_color) {
|
||||
if (show_color)
|
||||
r_cons_printf (Color_GREEN"0x%08"PFMT64x" "Color_RESET, off);
|
||||
else r_cons_printf ("0x%08"PFMT64x" ", off);
|
||||
}
|
||||
/* TODO: move to print/disasm.c */
|
||||
static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len, int l) {
|
||||
RAnalFcn *fcn, *fcni = NULL;
|
||||
@ -39,8 +44,8 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
|
||||
RAnalOp analop;
|
||||
RFlagItem *flag;
|
||||
RMetaItem *mi;
|
||||
ut64 dest = UT64_MAX;
|
||||
|
||||
r_vm_reset (core->vm);
|
||||
// TODO: import values from debugger is possible
|
||||
// TODO: allow to get those register snapshots from traces
|
||||
// TODO: per-function register state trace
|
||||
@ -64,6 +69,7 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
|
||||
int linesopts = 0;
|
||||
nb = nbytes*2;
|
||||
|
||||
r_vm_reset (core->vm);
|
||||
if (core->print->cur_enabled) {
|
||||
if (core->print->cur<0)
|
||||
core->print->cur = 0;
|
||||
@ -92,6 +98,22 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (core->print->cur_enabled) {
|
||||
// TODO: support in-the-middle-of-instruction too
|
||||
int ret = r_anal_aop (core->anal, &analop, core->offset+core->print->cur,
|
||||
buf+core->print->cur, (int)(len-core->print->cur));
|
||||
// TODO: check for analop.type and ret
|
||||
dest = analop.jump;
|
||||
#if 0
|
||||
if (ret)
|
||||
switch (analop.type) {
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
dest = analop.jump;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// TODO: make anal->reflines implicit
|
||||
free (core->reflines); // TODO: leak
|
||||
free (core->reflines2); // TODO: leak
|
||||
@ -187,19 +209,16 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
|
||||
if (flag && !show_bytes) {
|
||||
if (show_lines && line)
|
||||
r_cons_strcat (line);
|
||||
if (show_offset) {
|
||||
if (show_color)
|
||||
r_cons_printf (Color_GREEN"0x%08"PFMT64x" "Color_RESET, at);
|
||||
else r_cons_printf ("0x%08"PFMT64x" ", at);
|
||||
}
|
||||
if (show_offset)
|
||||
printoffset(at, show_color);
|
||||
r_cons_printf ("%s:\n", flag->name);
|
||||
}
|
||||
if (show_lines && line)
|
||||
r_cons_strcat (line);
|
||||
if (show_offset) {
|
||||
if (show_color)
|
||||
r_cons_printf (Color_GREEN"0x%08"PFMT64x" "Color_RESET, at);
|
||||
else r_cons_printf ("0x%08"PFMT64x" ", at);
|
||||
if (at == dest)
|
||||
r_cons_invert (R_TRUE, R_TRUE);
|
||||
printoffset (at, show_color);
|
||||
}
|
||||
if (show_trace) {
|
||||
RDebugTracepoint *tp = r_debug_trace_get (core->dbg, at);
|
||||
@ -375,8 +394,8 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
|
||||
if((st64)esp<0) esp=-esp;
|
||||
nargs = (esp)/4;
|
||||
#endif
|
||||
|
||||
fcn = r_anal_fcn_find (core->anal, analop.jump);
|
||||
r_cons_printf("\n ");
|
||||
if(fcn&&fcn->name) r_cons_printf ("; %s(", fcn->name);
|
||||
else r_cons_printf ("; 0x%08"PFMT64x"(", analop.jump);
|
||||
for(i=0;i<nargs;i++) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
/* restore program counter after breakpoint hit */
|
||||
static int r_debug_recoil(RDebug *dbg) {
|
||||
int recoil, ret = R_FALSE;
|
||||
RRegisterItem *ri;
|
||||
RRegItem *ri;
|
||||
r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE);
|
||||
ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], -1);
|
||||
if (ri) {
|
||||
@ -83,7 +83,7 @@ R_API ut64 r_debug_execute(struct r_debug_t *dbg, ut8 *buf, int len) {
|
||||
int orig_sz;
|
||||
ut8 stackbackup[4096];
|
||||
ut8 *backup, *orig = NULL;
|
||||
RRegisterItem *ri, *risp, *ripc;
|
||||
RRegItem *ri, *risp, *ripc;
|
||||
ut64 rsp, rpc, ra0 = 0LL;
|
||||
ripc = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], R_REG_TYPE_GPR);
|
||||
risp = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], R_REG_TYPE_GPR);
|
||||
|
@ -839,7 +839,7 @@ static int r_debug_native_bp_read(int pid, ut64 addr, int hw, int rwx) {
|
||||
#if __i386__
|
||||
/* TODO: Can I use this as in a coroutine? */
|
||||
static RList *r_debug_native_frames(RDebug *dbg) {
|
||||
RRegister *reg = dbg->reg;
|
||||
RReg *reg = dbg->reg;
|
||||
ut32 i, _esp, esp, ebp2;
|
||||
RList *list = r_list_new ();
|
||||
RIOBind *bio = &dbg->iob;
|
||||
@ -873,7 +873,7 @@ static RList *r_debug_native_frames(RDebug *dbg) {
|
||||
ut64 ptr, ebp2;
|
||||
ut64 _rip, _rsp, _rbp;
|
||||
RList *list;
|
||||
RRegister *reg = dbg->reg;
|
||||
RReg *reg = dbg->reg;
|
||||
RIOBind *bio = &dbg->iob;
|
||||
|
||||
_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
|
||||
|
@ -18,7 +18,7 @@
|
||||
1865 DWORD ErrorSelector;
|
||||
1866 DWORD DataOffset;
|
||||
1867 DWORD DataSelector;
|
||||
1868 BYTE RegisterArea[80];
|
||||
1868 BYTE RegArea[80];
|
||||
1869 DWORD Cr0NpxState;
|
||||
1870 } FLOATING_SAVE_AREA;
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
1893 DWORD EFlags;
|
||||
1894 DWORD Esp;
|
||||
1895 DWORD SegSs;
|
||||
1896 BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
|
||||
1896 BYTE ExtendedRegs[MAXIMUM_SUPPORTED_EXTENSION];
|
||||
1897 } CONTEXT;
|
||||
#endif
|
||||
|
||||
|
@ -28,8 +28,11 @@ R_API int r_debug_reg_sync(struct r_debug_t *dbg, int type, int write) {
|
||||
|
||||
R_API int r_debug_reg_list(struct r_debug_t *dbg, int type, int size, int rad) {
|
||||
int cols, n = 0;
|
||||
struct list_head *pos, *head;
|
||||
RList *head; //struct list_head *pos, *head;
|
||||
RListIter *iter;
|
||||
RRegItem *item;
|
||||
const char *fmt, *fmt2;
|
||||
|
||||
if (!dbg || !dbg->reg)
|
||||
return R_FALSE;
|
||||
head = r_reg_get_list(dbg->reg, type);
|
||||
@ -42,9 +45,8 @@ R_API int r_debug_reg_list(struct r_debug_t *dbg, int type, int size, int rad) {
|
||||
fmt2 = "%4s 0x%08"PFMT64x"%s";
|
||||
cols = 4;
|
||||
}
|
||||
list_for_each (pos, head) {
|
||||
r_list_foreach (head, iter, item) {
|
||||
ut64 value;
|
||||
struct r_reg_item_t *item = list_entry (pos, struct r_reg_item_t, list);
|
||||
if (type != -1 && type != item->type)
|
||||
continue;
|
||||
if (size != 0 && size != item->size)
|
||||
@ -63,7 +65,7 @@ R_API int r_debug_reg_list(struct r_debug_t *dbg, int type, int size, int rad) {
|
||||
}
|
||||
|
||||
R_API int r_debug_reg_set(struct r_debug_t *dbg, const char *name, ut64 num) {
|
||||
RRegisterItem *ri;
|
||||
RRegItem *ri;
|
||||
int role = r_reg_get_name_idx (name);
|
||||
if (!dbg || !dbg->reg)
|
||||
return R_FALSE;
|
||||
@ -78,7 +80,7 @@ R_API int r_debug_reg_set(struct r_debug_t *dbg, const char *name, ut64 num) {
|
||||
}
|
||||
|
||||
R_API ut64 r_debug_reg_get(struct r_debug_t *dbg, const char *name) {
|
||||
RRegisterItem *ri = NULL;
|
||||
RRegItem *ri = NULL;
|
||||
ut64 ret = 0LL;
|
||||
int role = r_reg_get_name_idx (name);
|
||||
if (!dbg || !dbg->reg)
|
||||
|
@ -29,7 +29,7 @@ R_API int r_debug_trace_tag (RDebug *dbg, int tag) {
|
||||
|
||||
R_API int r_debug_trace_pc (RDebug *dbg) {
|
||||
ut8 buf[32];
|
||||
RRegisterItem *ri;
|
||||
RRegItem *ri;
|
||||
RAnalOp aop;
|
||||
static ut64 oldpc = 0LL; // Must trace the previously traced instruction
|
||||
r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE);
|
||||
|
@ -127,7 +127,7 @@ typedef struct r_anal_t {
|
||||
RList *bbs;
|
||||
RList *fcns;
|
||||
RList *vartypes;
|
||||
RRegister *reg;
|
||||
RReg *reg;
|
||||
struct r_anal_ctx_t *ctx;
|
||||
struct r_anal_plugin_t *cur;
|
||||
struct list_head anals;
|
||||
@ -140,8 +140,8 @@ typedef struct r_anal_value_t {
|
||||
ut64 base ; // numeric address
|
||||
int delta; // numeric delta
|
||||
int mul; // multiplier (reg*4+base)
|
||||
RRegisterItem *reg; // register index used (-1 if no reg)
|
||||
RRegisterItem *regdelta; // register index used (-1 if no reg)
|
||||
RRegItem *reg; // register index used (-1 if no reg)
|
||||
RRegItem *regdelta; // register index used (-1 if no reg)
|
||||
} RAnalValue;
|
||||
|
||||
typedef struct r_anal_aop_t {
|
||||
|
@ -36,32 +36,31 @@ typedef struct r_reg_item_t {
|
||||
int offset; // offset in data structure
|
||||
int packed_size; /* 0 means no packed register, 1byte pack, 2b pack... */
|
||||
struct list_head list;
|
||||
} RRegisterItem;
|
||||
} RRegItem;
|
||||
|
||||
typedef struct r_reg_arena_t {
|
||||
ut8 *bytes;
|
||||
int size;
|
||||
struct list_head list;
|
||||
} RRegisterArena;
|
||||
} RRegArena;
|
||||
|
||||
typedef struct r_reg_set_t {
|
||||
struct r_reg_arena_t *arena;
|
||||
struct list_head arenas; /* r_reg_arena_t */
|
||||
struct list_head regs; /* r_reg_item_t */
|
||||
} RRegisterSet;
|
||||
RRegArena *arena;
|
||||
RList *pool; /* RRegArena */
|
||||
RList *regs; /* RRegItem */
|
||||
} RRegSet;
|
||||
|
||||
typedef struct r_reg_t {
|
||||
char *profile;
|
||||
char *name[R_REG_NAME_LAST];
|
||||
RRegisterSet regset[R_REG_TYPE_LAST];
|
||||
} RRegister;
|
||||
RRegSet regset[R_REG_TYPE_LAST];
|
||||
} RReg;
|
||||
|
||||
#define r_reg_new() r_reg_init (R_NEW (RRegister))
|
||||
|
||||
#ifdef R_API
|
||||
R_API const char *r_reg_get_type(int idx);
|
||||
R_API struct r_reg_t *r_reg_free(struct r_reg_t *reg);
|
||||
R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg);
|
||||
R_API struct r_reg_t *r_reg_new();
|
||||
//R_API struct r_reg_t *r_reg_new();
|
||||
R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *profile);
|
||||
R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile);
|
||||
@ -71,7 +70,7 @@ R_API const char *r_reg_get_name(struct r_reg_t *reg, int kind);
|
||||
R_API int r_reg_set_name(struct r_reg_t *reg, int role, const char *name);
|
||||
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name, int type);
|
||||
R_API struct list_head *r_reg_get_list(struct r_reg_t *reg, int type);
|
||||
R_API RList *r_reg_get_list(struct r_reg_t *reg, int type);
|
||||
R_API int r_reg_type_by_name(const char *str);
|
||||
|
||||
/* value */
|
||||
@ -85,11 +84,11 @@ R_API int r_reg_set_pvalue(struct r_reg_t *reg, struct r_reg_item_t *item, ut64
|
||||
/* byte arena */
|
||||
R_API ut8* r_reg_get_bytes(struct r_reg_t *reg, int type, int *size);
|
||||
R_API int r_reg_set_bytes(struct r_reg_t *reg, int type, const ut8* buf, int len);
|
||||
R_API RRegisterArena *r_reg_arena_new (int size);
|
||||
R_API RRegArena *r_reg_arena_new (int size);
|
||||
R_API void r_reg_arena_free(RRegArena* ra);
|
||||
R_API int r_reg_fit_arena(struct r_reg_t *reg);
|
||||
|
||||
// TODO: r_reg typedef must be renamed to this shorter version
|
||||
#define RReg RRegister
|
||||
R_API int r_reg_push(RReg *reg);
|
||||
R_API void r_reg_pop(RReg *reg);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,10 @@
|
||||
/* radare - LGPL - Copyright 2009-2010 pancake<nopcode.org> */
|
||||
|
||||
#include <r_reg.h>
|
||||
/* TODO: add push/pop.. */
|
||||
|
||||
/* non-endian safe - used for raw mapping with system registers */
|
||||
R_API ut8* r_reg_get_bytes(struct r_reg_t *reg, int type, int *size) {
|
||||
RRegisterArena *arena;
|
||||
R_API ut8* r_reg_get_bytes(RReg *reg, int type, int *size) {
|
||||
RRegArena *arena;
|
||||
int i, sz, osize;
|
||||
ut8 *buf;
|
||||
if (type == -1) {
|
||||
@ -38,22 +37,21 @@ R_API ut8* r_reg_get_bytes(struct r_reg_t *reg, int type, int *size) {
|
||||
}
|
||||
|
||||
/* reduce number of return statements */
|
||||
R_API int r_reg_set_bytes(struct r_reg_t *reg, int type, const ut8* buf, int len) {
|
||||
R_API int r_reg_set_bytes(RReg *reg, int type, const ut8* buf, int len) {
|
||||
int i, ret = R_FALSE;
|
||||
struct r_reg_set_t *regset;
|
||||
struct r_reg_arena_t *arena;
|
||||
RRegArena *arena;
|
||||
int off = 0;
|
||||
|
||||
if (type == -1) {
|
||||
ret = R_TRUE;
|
||||
/* deserialize ALL register types in a single buffer */
|
||||
for(i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
arena = reg->regset[i].arena;
|
||||
if (arena == NULL) {
|
||||
arena = reg->regset[i].arena = R_NEW (RRegisterArena);
|
||||
if (!reg->regset[i].arena) {
|
||||
arena = reg->regset[i].arena = R_NEW (RRegArena);
|
||||
arena->size = len;
|
||||
arena->bytes = malloc(len);
|
||||
}
|
||||
} else arena = reg->regset[i].arena;
|
||||
if (arena->bytes == NULL)
|
||||
return R_FALSE;
|
||||
memcpy (arena->bytes, buf+off, arena->size);
|
||||
@ -75,16 +73,14 @@ R_API int r_reg_set_bytes(struct r_reg_t *reg, int type, const ut8* buf, int len
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_reg_export_to(struct r_reg_t *reg, struct r_reg_t *dst) {
|
||||
//struct r_reg_arena_t *arena;
|
||||
struct r_reg_item_t *r;
|
||||
struct list_head *pos;
|
||||
R_API int r_reg_export_to(RReg *reg, RReg *dst) {
|
||||
RRegItem *r;
|
||||
RListIter *iter;
|
||||
int i, ret = R_FALSE;
|
||||
if (dst) {
|
||||
// foreach reg of every time in reg, define it in dst
|
||||
for(i=0;i<R_REG_TYPE_LAST;i++) {
|
||||
list_for_each(pos, ®->regset[i].regs) {
|
||||
r = list_entry(pos, struct r_reg_item_t, list);
|
||||
r_list_foreach (reg->regset[i].regs, iter, r) {
|
||||
// TODO: export to not implemented
|
||||
//r_reg_set(dst, r_reg_get(dst, r->name), );
|
||||
//r_mem_copybits_delta(
|
||||
@ -94,19 +90,18 @@ R_API int r_reg_export_to(struct r_reg_t *reg, struct r_reg_t *dst) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_reg_fit_arena(struct r_reg_t *reg) {
|
||||
struct list_head *pos;
|
||||
struct r_reg_item_t *r;
|
||||
struct r_reg_arena_t *arena;
|
||||
R_API int r_reg_fit_arena(RReg *reg) {
|
||||
RRegArena *arena;
|
||||
RListIter *iter;
|
||||
RRegItem *r;
|
||||
int size, i;
|
||||
|
||||
/* propagate arenas */
|
||||
for(i=0;i<R_REG_TYPE_LAST;i++) {
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
arena = reg->regset[i].arena;
|
||||
arena->size = 0;
|
||||
list_for_each(pos, ®->regset[i].regs) {
|
||||
r = list_entry(pos, struct r_reg_item_t, list);
|
||||
size = BITS2BYTES(r->offset+r->size);
|
||||
r_list_foreach (reg->regset[i].regs, iter, r) {
|
||||
size = BITS2BYTES (r->offset+r->size);
|
||||
if (size>arena->size) {
|
||||
arena->size = size;
|
||||
arena->bytes = realloc (arena->bytes, size);
|
||||
@ -114,18 +109,25 @@ R_API int r_reg_fit_arena(struct r_reg_t *reg) {
|
||||
return R_FALSE;
|
||||
}
|
||||
}
|
||||
memset(arena->bytes, 0, arena->size);
|
||||
memset (arena->bytes, 0, arena->size);
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
R_API RRegisterArena *r_reg_arena_new (int size) {
|
||||
RRegisterArena *arena = R_NEW (RRegisterArena);
|
||||
R_API RRegArena *r_reg_arena_new (int size) {
|
||||
RRegArena *arena = R_NEW (RRegArena);
|
||||
if (arena) {
|
||||
if ((arena->bytes = malloc (size+8)) == NULL) {
|
||||
if (size<1)
|
||||
size = 1;
|
||||
if (!(arena->bytes = malloc (size+8))) {
|
||||
free (arena);
|
||||
arena = NULL;
|
||||
} else arena->size = size;
|
||||
}
|
||||
return arena;
|
||||
}
|
||||
|
||||
R_API void r_reg_arena_free(RRegArena* ra) {
|
||||
free (ra->bytes);
|
||||
free (ra);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ seg xgs .32 40 0
|
||||
seg xcs .32 52 0
|
||||
seg xss .32 52 0
|
||||
gpr eflags .32 56 0
|
||||
#>cpazstidor0 carry parity above zero XX trap XX direction XX XX XX
|
||||
|
||||
# base address is 448bit
|
||||
flg carry .1 .448 0
|
||||
|
153
libr/reg/reg.c
153
libr/reg/reg.c
@ -14,17 +14,9 @@ R_API const char *r_reg_get_type(int idx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void r_reg_free_internal(struct r_reg_t *reg) {
|
||||
struct list_head *pos, *n;
|
||||
RRegisterItem *r;
|
||||
int i;
|
||||
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++)
|
||||
list_for_each_safe (pos, n, ®->regset[i].regs) {
|
||||
r = list_entry (pos, RRegisterItem, list);
|
||||
list_del (&r->list);
|
||||
free (r);
|
||||
}
|
||||
static void r_reg_item_free(RRegItem *item) {
|
||||
free (item->name);
|
||||
free (item);
|
||||
}
|
||||
|
||||
R_API int r_reg_get_name_idx(const char *type) {
|
||||
@ -42,51 +34,107 @@ R_API int r_reg_get_name_idx(const char *type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
R_API int r_reg_set_name(struct r_reg_t *reg, int role, const char *name) {
|
||||
int ret = R_TRUE;
|
||||
|
||||
R_API int r_reg_set_name(RReg *reg, int role, const char *name) {
|
||||
// TODO: ensure this range check in a define.. somewhere
|
||||
if (role>=0 && role<R_REG_NAME_LAST)
|
||||
if (role>=0 && role<R_REG_NAME_LAST) {
|
||||
reg->name[role] = r_str_dup (reg->name[role], name);
|
||||
else ret = R_FALSE;
|
||||
return ret;
|
||||
return R_TRUE;
|
||||
}
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API const char *r_reg_get_name(struct r_reg_t *reg, int role) {
|
||||
R_API const char *r_reg_get_name(RReg *reg, int role) {
|
||||
if (reg && role>=0 && role<R_REG_NAME_LAST)
|
||||
return reg->name[role];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API struct r_reg_t *r_reg_free(struct r_reg_t *reg) {
|
||||
R_API void r_reg_free_internal(RReg *reg) {
|
||||
int i;
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
r_list_destroy (reg->regset[i].regs);
|
||||
r_list_destroy (reg->regset[i].pool);
|
||||
reg->regset[i].arena = r_reg_arena_new (0);
|
||||
}
|
||||
}
|
||||
|
||||
R_API RReg *r_reg_free(RReg *reg) {
|
||||
if (reg) {
|
||||
// TODO: free more things here
|
||||
r_reg_free_internal (reg);
|
||||
free (reg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: must be deprecated.. use from _new()
|
||||
R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg) {
|
||||
R_API RReg *r_reg_new() {
|
||||
RReg *reg = R_NEW (RReg);
|
||||
int i;
|
||||
if (!reg)
|
||||
return NULL;
|
||||
reg->profile = NULL;
|
||||
for (i=0; i<R_REG_NAME_LAST; i++)
|
||||
reg->name[i] = NULL;
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
INIT_LIST_HEAD (®->regset[i].arenas);
|
||||
INIT_LIST_HEAD (®->regset[i].regs);
|
||||
if ((reg->regset[i].arena = r_reg_arena_new (0)) == NULL)
|
||||
reg->regset[i].pool = r_list_new ();
|
||||
reg->regset[i].pool->free = (RListFree)r_reg_arena_free;
|
||||
reg->regset[i].regs = r_list_new ();
|
||||
reg->regset[i].regs->free = (RListFree)r_reg_item_free;
|
||||
if (!(reg->regset[i].arena = r_reg_arena_new (0)))
|
||||
return NULL;
|
||||
list_add_tail (®->regset[i].arena->list,
|
||||
®->regset[i].arenas);
|
||||
r_list_append (reg->regset[i].pool, reg->regset[i].arena);
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
static RRegisterItem *r_reg_item_new() {
|
||||
RRegisterItem *item = R_NEW (RRegisterItem);
|
||||
memset (item, 0, sizeof (RRegisterItem));
|
||||
R_API int r_reg_push(RReg *reg) {
|
||||
int i;
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
if (!(reg->regset[i].arena = r_reg_arena_new (0)))
|
||||
return 0;
|
||||
r_list_prepend (reg->regset[i].pool, reg->regset[i].arena);
|
||||
}
|
||||
return r_list_length (reg->regset[0].pool);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
arena2
|
||||
|
||||
// notify the debugger that something has changed, and registers needs to be pushed
|
||||
r_debug_reg_change()
|
||||
|
||||
for(;;) {
|
||||
read_regs \___ reg_pre()
|
||||
r_reg_push /
|
||||
|
||||
step
|
||||
|
||||
read_regs \_.
|
||||
r_reg_cmp(); / '- reg_post()
|
||||
|
||||
r_reg_pop() >-- reg_fini()
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
R_API void r_reg_pop(RReg *reg) {
|
||||
int i;
|
||||
for (i=0; i<R_REG_TYPE_LAST; i++) {
|
||||
if (r_list_length(reg->regset[i].pool)>0) {
|
||||
r_list_delete (reg->regset[i].pool,
|
||||
r_list_head (reg->regset[i].pool));
|
||||
// SEGFAULT: r_reg_arena_free (reg->regset[i].arena);
|
||||
reg->regset[i].arena = (RRegArena*)r_list_head (
|
||||
reg->regset[i].pool);
|
||||
} else {
|
||||
eprintf ("Cannot pop more\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static RRegItem *r_reg_item_new() {
|
||||
RRegItem *item = R_NEW (RRegItem);
|
||||
memset (item, 0, sizeof (RRegItem));
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -102,7 +150,7 @@ R_API int r_reg_type_by_name(const char *str) {
|
||||
}
|
||||
|
||||
/* TODO: make this parser better and cleaner */
|
||||
static int r_reg_set_word(RRegisterItem *item, int idx, char *word) {
|
||||
static int r_reg_set_word(RRegItem *item, int idx, char *word) {
|
||||
int ret = R_TRUE;
|
||||
switch(idx) {
|
||||
case 0:
|
||||
@ -135,8 +183,8 @@ static int r_reg_set_word(RRegisterItem *item, int idx, char *word) {
|
||||
}
|
||||
|
||||
/* TODO: make this parser better and cleaner */
|
||||
R_API int r_reg_set_profile_string(RRegister *reg, const char *str) {
|
||||
RRegisterItem *item;
|
||||
R_API int r_reg_set_profile_string(RReg *reg, const char *str) {
|
||||
RRegItem *item;
|
||||
int setname = -1;
|
||||
int ret = R_FALSE;
|
||||
int lastchar = 0;
|
||||
@ -160,7 +208,7 @@ R_API int r_reg_set_profile_string(RRegister *reg, const char *str) {
|
||||
switch (*str) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
// UGLY PASTAFARIAN TO PARSE
|
||||
/* UGLY PASTAFARIAN PARSING */
|
||||
if (word==0 && *buf=='=') {
|
||||
setname = r_reg_get_name_idx (buf+1);
|
||||
if (setname == -1)
|
||||
@ -177,7 +225,7 @@ R_API int r_reg_set_profile_string(RRegister *reg, const char *str) {
|
||||
else if (word>3) {
|
||||
r_reg_set_word (item, word, buf);
|
||||
if (item->name != NULL) {
|
||||
list_add_tail(&item->list, ®->regset[item->type].regs);
|
||||
r_list_append (reg->regset[item->type].regs, item);
|
||||
item = r_reg_item_new();
|
||||
}
|
||||
}
|
||||
@ -194,16 +242,13 @@ R_API int r_reg_set_profile_string(RRegister *reg, const char *str) {
|
||||
lastchar = *str;
|
||||
str++;
|
||||
}
|
||||
free (item->name);
|
||||
free (item);
|
||||
r_reg_item_free (item);
|
||||
r_reg_fit_arena (reg);
|
||||
|
||||
/* do we reach the end ? */
|
||||
if (!*str) ret = R_TRUE;
|
||||
return ret;
|
||||
|
||||
return *str?ret:R_TRUE;
|
||||
}
|
||||
|
||||
R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile) {
|
||||
R_API int r_reg_set_profile(RReg *reg, const char *profile) {
|
||||
int ret = R_FALSE;
|
||||
const char *base;
|
||||
char *str, *file;
|
||||
@ -222,9 +267,9 @@ R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RRegisterItem *r_reg_get(struct r_reg_t *reg, const char *name, int type) {
|
||||
struct list_head *pos;
|
||||
RRegisterItem *r;
|
||||
R_API RRegItem *r_reg_get(RReg *reg, const char *name, int type) {
|
||||
RListIter *iter;
|
||||
RRegItem *r;
|
||||
int i, e;
|
||||
if (!reg)
|
||||
return NULL;
|
||||
@ -236,19 +281,17 @@ R_API RRegisterItem *r_reg_get(struct r_reg_t *reg, const char *name, int type)
|
||||
e = type+1;
|
||||
}
|
||||
|
||||
// TODO: use RList here
|
||||
for (; i<e; i++)
|
||||
list_for_each (pos, ®->regset[i].regs) {
|
||||
r = list_entry (pos, RRegisterItem, list);
|
||||
if (!strcmp (r->name, name))
|
||||
return r;
|
||||
for (; i<e; i++) {
|
||||
r_list_foreach (reg->regset[i].regs, iter, r) {
|
||||
if (!strcmp (r->name, name))
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: deprecate.. must use RList here
|
||||
R_API struct list_head *r_reg_get_list(struct r_reg_t *reg, int type) {
|
||||
R_API RList *r_reg_get_list(RReg *reg, int type) {
|
||||
if (type<0 || type>R_REG_TYPE_LAST)
|
||||
return NULL;
|
||||
return ®->regset[type].regs;
|
||||
return reg->regset[type].regs;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include <r_reg.h>
|
||||
|
||||
void show_regs(struct r_reg_t *reg, int bitsize)
|
||||
{
|
||||
struct list_head *pos, *reglist;
|
||||
void show_regs(struct r_reg_t *reg, int bitsize) {
|
||||
RList *reglist;
|
||||
RListIter *iter;
|
||||
RRegItem *ri;
|
||||
printf("%d bit registers:\n", bitsize);
|
||||
reglist = r_reg_get_list(reg, R_REG_TYPE_GPR);
|
||||
list_for_each(pos, reglist) {
|
||||
struct r_reg_item_t *ri = list_entry(pos, struct r_reg_item_t, list);
|
||||
r_list_foreach (reglist, iter, ri) {
|
||||
if (ri->size == bitsize)
|
||||
printf(" - %s : 0x%08"PFMT64x"\n", ri->name, r_reg_get_value(reg, ri));
|
||||
}
|
||||
@ -37,5 +37,24 @@ int main() {
|
||||
for (i=0;(type=r_reg_get_type(i));i++)
|
||||
printf (" - %s\n", type);
|
||||
|
||||
r_reg_push(reg);
|
||||
r_reg_pop(reg);
|
||||
|
||||
r_reg_push(reg);
|
||||
r_reg_push(reg);
|
||||
r_reg_push(reg);
|
||||
r_reg_pop(reg);
|
||||
r_reg_pop(reg);
|
||||
r_reg_push(reg);
|
||||
r_reg_pop(reg);
|
||||
r_reg_pop(reg);
|
||||
|
||||
/*
|
||||
r_reg_pop(reg);
|
||||
r_reg_pop(reg);
|
||||
r_reg_pop(reg);
|
||||
r_reg_pop(reg);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user