RzReg: Associate roles with RzRegItem instead of name strings (#6291)
Register roles (RzRegisterId) are now associated directly with an RzRegItem in RzReg rather than mapping to name strings, which previously needed an additional hashtable lookup to get more information about the register. Conversely, if the name is needed from an RzRegItem, it is available directly as a member. This is not a pure refactor as there were cases before where a register name was assigned to a role in the register profile, but no register actually existed under that name. Such cases will now cause a warning to be printed during profile load and the role association will be ignored. Changes in register profiles in this commit are for fixing such cases.
This commit is contained in:
parent
9d5dc6edd1
commit
245e198cf1
26 changed files with 164 additions and 158 deletions
|
|
@ -762,8 +762,8 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
|
|||
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||
}
|
||||
|
||||
const char *bp_reg = analysis->reg->name[RZ_REG_NAME_BP];
|
||||
const char *sp_reg = analysis->reg->name[RZ_REG_NAME_SP];
|
||||
const char *bp_reg = rz_reg_get_name(analysis->reg, RZ_REG_NAME_BP);
|
||||
const char *sp_reg = rz_reg_get_name(analysis->reg, RZ_REG_NAME_SP);
|
||||
bool has_stack_regs = bp_reg && sp_reg;
|
||||
|
||||
if (analysis->opt.nopskip && fcn->addr == at) {
|
||||
|
|
@ -2223,7 +2223,7 @@ static bool can_affect_bp(RzAnalysis *analysis, RzAnalysisOp *op) {
|
|||
RzAnalysisValue *src = op->src[0];
|
||||
const char *opdreg = (dst && dst->reg) ? dst->reg->name : NULL;
|
||||
const char *opsreg = (src && src->reg) ? src->reg->name : NULL;
|
||||
const char *bp_name = analysis->reg->name[RZ_REG_NAME_BP];
|
||||
const char *bp_name = rz_reg_get_name(analysis->reg, RZ_REG_NAME_BP);
|
||||
bool is_bp_dst = opdreg && !dst->memref && !strcmp(opdreg, bp_name);
|
||||
bool is_bp_src = opsreg && !src->memref && !strcmp(opsreg, bp_name);
|
||||
if (op->type == RZ_ANALYSIS_OP_TYPE_XCHG) {
|
||||
|
|
@ -2260,14 +2260,17 @@ static void __analysis_fcn_check_bp_use(RzAnalysis *analysis, RzAnalysisFunction
|
|||
}
|
||||
switch (op.type) {
|
||||
case RZ_ANALYSIS_OP_TYPE_MOV:
|
||||
case RZ_ANALYSIS_OP_TYPE_LEA:
|
||||
if (can_affect_bp(analysis, &op) && op.src[0] && op.src[0]->reg && op.src[0]->reg->name && strcmp(op.src[0]->reg->name, analysis->reg->name[RZ_REG_NAME_SP])) {
|
||||
case RZ_ANALYSIS_OP_TYPE_LEA: {
|
||||
const char *sp = rz_reg_get_name(analysis->reg, RZ_REG_NAME_SP);
|
||||
const char *srcreg = op.src[0] && op.src[0]->reg ? op.src[0]->reg->name : NULL;
|
||||
if (can_affect_bp(analysis, &op) && srcreg && sp && strcmp(srcreg, sp)) {
|
||||
fcn->bp_frame = false;
|
||||
rz_analysis_op_fini(&op);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RZ_ANALYSIS_OP_TYPE_ADD:
|
||||
case RZ_ANALYSIS_OP_TYPE_AND:
|
||||
case RZ_ANALYSIS_OP_TYPE_CMOV:
|
||||
|
|
|
|||
|
|
@ -178,8 +178,8 @@ char *pic_midrange_get_reg_profile(RzAnalysis *a) {
|
|||
const char *p =
|
||||
"=PC pc\n"
|
||||
"=SP stkptr\n"
|
||||
"=A0 porta\n"
|
||||
"=A1 portb\n"
|
||||
// not defined: "=A0 porta\n"
|
||||
// not defined: "=A1 portb\n"
|
||||
"gpr indf0 .8 0 0\n"
|
||||
"gpr indf1 .8 1 0\n"
|
||||
"gpr pcl .8 2 0\n"
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ static char *get_reg_profile(RzAnalysis *analysis) {
|
|||
"=SP sp\n"
|
||||
"=ZF z\n"
|
||||
"=A0 r1\n"
|
||||
"=A1 r5\n"
|
||||
"=A1 tp\n"
|
||||
"=A2 r6\n"
|
||||
"=A3 r7\n"
|
||||
"=A4 r8\n"
|
||||
|
|
|
|||
|
|
@ -4322,8 +4322,7 @@ static int agraph_refresh(AGraphContext *grp_ctx) {
|
|||
// allow to change the current function during debugging
|
||||
if (g->is_instep && core->bin->is_debugger) {
|
||||
// seek only when the graph node changes
|
||||
const char *pc = rz_reg_get_name(core->dbg->reg, RZ_REG_NAME_PC);
|
||||
RzRegItem *r = rz_reg_get(core->dbg->reg, pc, -1);
|
||||
RzRegItem *r = rz_reg_get_by_role(core->dbg->reg, RZ_REG_NAME_PC);
|
||||
ut64 addr = rz_reg_get_value(core->dbg->reg, r);
|
||||
RzANode *acur = get_anode(g->curnode);
|
||||
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ static void autocmplt_cmd_arg_reg_filter(RzCore *core, const RzCmdDesc *cd, RzLi
|
|||
rz_line_ns_completion_result_propose(res, "all", s, len);
|
||||
|
||||
for (int role = 0; role < RZ_REG_NAME_LAST; role++) {
|
||||
if (!reg->name[role]) {
|
||||
if (!rz_reg_get_by_role(reg, role)) {
|
||||
// don't autocomplete if there isn't a register with this role anyway
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,24 +113,22 @@ RZ_API bool rz_core_debug_continue_until(RzCore *core, ut64 addr) {
|
|||
#endif
|
||||
ut64 pc;
|
||||
if (!strcmp(core->dbg->btalgo, "trace") && core->dbg->arch && !strcmp(core->dbg->arch, "x86") && core->dbg->bits == 4) {
|
||||
const char *pc_name = core->dbg->reg->name[RZ_REG_NAME_PC];
|
||||
bool prev_call = false;
|
||||
bool prev_ret = false;
|
||||
const char *sp_name = core->dbg->reg->name[RZ_REG_NAME_SP];
|
||||
ut64 old_sp, cur_sp;
|
||||
rz_cons_break_push(NULL, NULL);
|
||||
rz_list_free(core->dbg->call_frames);
|
||||
core->dbg->call_frames = rz_list_new();
|
||||
core->dbg->call_frames->free = free;
|
||||
rz_debug_reg_sync(core->dbg, RZ_REG_TYPE_GPR, false);
|
||||
old_sp = rz_debug_reg_get(core->dbg, sp_name);
|
||||
old_sp = rz_debug_reg_get_by_role(core->dbg, RZ_REG_NAME_SP);
|
||||
while (true) {
|
||||
rz_debug_reg_sync(core->dbg, RZ_REG_TYPE_GPR, false);
|
||||
pc = rz_debug_reg_get(core->dbg, pc_name);
|
||||
pc = rz_debug_reg_get_by_role(core->dbg, RZ_REG_NAME_PC);
|
||||
if (prev_call) {
|
||||
ut32 ret_addr;
|
||||
RzDebugFrame *frame = RZ_NEW0(RzDebugFrame);
|
||||
cur_sp = rz_debug_reg_get(core->dbg, sp_name);
|
||||
cur_sp = rz_debug_reg_get_by_role(core->dbg, RZ_REG_NAME_SP);
|
||||
(void)core->dbg->iob.read_at(core->dbg->iob.io, cur_sp, (ut8 *)&ret_addr,
|
||||
sizeof(ret_addr));
|
||||
frame->addr = ret_addr;
|
||||
|
|
|
|||
|
|
@ -758,10 +758,7 @@ RZ_IPI int rz_core_analysis_set_reg(RzCore *core, const char *regname, ut64 val)
|
|||
if (!r) {
|
||||
int role = rz_reg_get_name_idx(regname);
|
||||
if (role != -1) {
|
||||
const char *alias = rz_reg_get_name(rreg, role);
|
||||
if (alias) {
|
||||
r = rz_reg_get(rreg, alias, -1);
|
||||
}
|
||||
r = rz_reg_get_by_role(rreg, role);
|
||||
}
|
||||
}
|
||||
if (!r) {
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ static bool step_until_optype(RzCore *core, RzList /*<char *>*/ *optypes_list) {
|
|||
break;
|
||||
}
|
||||
rz_debug_step(core->dbg, 1);
|
||||
pc = rz_debug_reg_get(core->dbg, core->dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
pc = rz_debug_reg_get_by_role(core->dbg, RZ_REG_NAME_PC);
|
||||
// 'Copy' from rz_debug_step_soft
|
||||
if (!core->dbg->iob.read_at) {
|
||||
RZ_LOG_ERROR("ERROR\n");
|
||||
|
|
|
|||
|
|
@ -627,13 +627,9 @@ RZ_IPI RzCmdStatus rz_regs_args_handler(RzCore *core, RzReg *reg, RzCmdRegSync s
|
|||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
for (int i = RZ_REG_NAME_A0; i <= RZ_REG_NAME_A9; i++) {
|
||||
const char *name = rz_reg_get_name(reg, i);
|
||||
if (!name) {
|
||||
break;
|
||||
}
|
||||
RzRegItem *item = rz_reg_get(reg, name, RZ_REG_TYPE_ANY);
|
||||
RzRegItem *item = rz_reg_get_by_role(reg, i);
|
||||
if (!item) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
rz_list_push(ritems, item);
|
||||
}
|
||||
|
|
@ -657,8 +653,9 @@ RZ_IPI RzCmdStatus rz_reg_types_handler(RzCore *core, RzReg *reg, int argc, cons
|
|||
RZ_IPI RzCmdStatus rz_reg_roles_handler(RzCore *core, RzReg *reg, int argc, const char **argv) {
|
||||
for (int i = 0; i < RZ_REG_NAME_LAST; i++) {
|
||||
rz_cons_print(rz_reg_get_role(i));
|
||||
if (reg->name[i]) {
|
||||
rz_cons_printf(" -> %s", reg->name[i]);
|
||||
RzRegItem *ri = rz_reg_get_by_role(reg, i);
|
||||
if (ri && ri->name) {
|
||||
rz_cons_printf(" -> %s", ri->name);
|
||||
}
|
||||
rz_cons_print("\n");
|
||||
}
|
||||
|
|
@ -724,11 +721,12 @@ RZ_IPI RzCmdStatus rz_reg_profile_handler(RzCore *core, RzReg *reg, int argc, co
|
|||
pj_k(pj, "alias_info");
|
||||
pj_a(pj);
|
||||
for (i = 0; i < RZ_REG_NAME_LAST; i++) {
|
||||
if (reg->name[i]) {
|
||||
RzRegItem *ri = rz_reg_get_by_role(reg, i);
|
||||
if (ri && ri->name) {
|
||||
pj_o(pj);
|
||||
pj_kn(pj, "role", i);
|
||||
pj_ks(pj, "role_str", rz_reg_get_role(i));
|
||||
pj_ks(pj, "reg", reg->name[i]);
|
||||
pj_ks(pj, "reg", ri->name);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -912,16 +912,13 @@ static ut64 num_callback(RzNum *userptr, const char *str, int *ok) {
|
|||
if (!r) {
|
||||
int role = rz_reg_get_name_idx(str);
|
||||
if (role != -1) {
|
||||
const char *alias = rz_reg_get_name(reg, role);
|
||||
if (alias) {
|
||||
r = rz_reg_get(reg, alias, -1);
|
||||
if (r) {
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
ret = rz_reg_get_value(reg, r);
|
||||
return ret;
|
||||
r = rz_reg_get_by_role(reg, role);
|
||||
if (r) {
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
}
|
||||
ret = rz_reg_get_value(reg, r);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -531,8 +531,8 @@ RZ_API ut64 rz_debug_execute(RzDebug *dbg, const ut8 *buf, int len, int restore)
|
|||
if (rz_debug_is_dead(dbg)) {
|
||||
return false;
|
||||
}
|
||||
ripc = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_PC], RZ_REG_TYPE_GPR);
|
||||
risp = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_SP], RZ_REG_TYPE_GPR);
|
||||
ripc = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_PC);
|
||||
risp = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_SP);
|
||||
if (ripc) {
|
||||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_GPR, false);
|
||||
orig = rz_reg_get_bytes(dbg->reg, RZ_REG_TYPE_ANY, &orig_sz);
|
||||
|
|
@ -567,7 +567,7 @@ RZ_API ut64 rz_debug_execute(RzDebug *dbg, const ut8 *buf, int len, int restore)
|
|||
}
|
||||
|
||||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_GPR, false);
|
||||
ri = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_A0], RZ_REG_TYPE_GPR);
|
||||
ri = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_A0);
|
||||
ra0 = rz_reg_get_value(dbg->reg, ri);
|
||||
if (restore) {
|
||||
rz_reg_read_regs(dbg->reg, orig, orig_sz);
|
||||
|
|
@ -743,10 +743,9 @@ RZ_API RzDebugReasonType rz_debug_wait(RzDebug *dbg, RzBreakpointItem **bp) {
|
|||
RzBreakpointItem *b = NULL;
|
||||
ut64 pc;
|
||||
|
||||
/* get the program coounter */
|
||||
pc_ri = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_PC], -1);
|
||||
if (!pc_ri) { /* couldn't find PC?! */
|
||||
eprintf("Couldn't find PC!\n");
|
||||
pc_ri = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_PC);
|
||||
if (!pc_ri) {
|
||||
RZ_LOG_ERROR("debug: no PC register known");
|
||||
return RZ_DEBUG_REASON_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -790,7 +789,7 @@ RZ_API RzDebugReasonType rz_debug_wait(RzDebug *dbg, RzBreakpointItem **bp) {
|
|||
|
||||
RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
||||
ut8 buf[32];
|
||||
ut64 pc, sp, r;
|
||||
ut64 r;
|
||||
ut64 next[2];
|
||||
RzAnalysisOp op = { 0 };
|
||||
int br, i, ret;
|
||||
|
|
@ -811,11 +810,11 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const bool has_lr_reg = rz_reg_get_name(dbg->reg, RZ_REG_NAME_LR);
|
||||
RzRegItem *rilr = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_LR);
|
||||
const bool arch_ret_is_pop = !strcmp(dbg->arch, "arm") && dbg->bits <= RZ_SYS_BITS_32;
|
||||
|
||||
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
sp = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_SP]);
|
||||
ut64 pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
ut64 sp = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_SP);
|
||||
|
||||
if (!dbg->iob.read_at) {
|
||||
return false;
|
||||
|
|
@ -837,8 +836,8 @@ RZ_API int rz_debug_step_soft(RzDebug *dbg) {
|
|||
if (arch_ret_is_pop && op.stackop == RZ_ANALYSIS_STACK_INC) {
|
||||
dbg->iob.read_at(dbg->iob.io, sp - op.stackptr - 4, (ut8 *)&sp_top, 4);
|
||||
next[0] = sp_top.r32[0];
|
||||
} else if (has_lr_reg) {
|
||||
next[0] = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_LR]);
|
||||
} else if (rilr && rilr->name) {
|
||||
next[0] = rz_debug_reg_get(dbg, rilr->name);
|
||||
} else {
|
||||
dbg->iob.read_at(dbg->iob.io, sp, (ut8 *)&sp_top, 8);
|
||||
next[0] = (dbg->bits <= RZ_SYS_BITS_32) ? sp_top.r32[0] : sp_top.r64;
|
||||
|
|
@ -1074,11 +1073,11 @@ RZ_API int rz_debug_step_over(RzDebug *dbg, int steps) {
|
|||
}
|
||||
|
||||
// Initial refill
|
||||
buf_pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
buf_pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
dbg->iob.read_at(dbg->iob.io, buf_pc, buf, sizeof(buf));
|
||||
|
||||
for (; steps_taken < steps; steps_taken++) {
|
||||
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
// Try to keep the buffer full
|
||||
if (pc - buf_pc > sizeof(buf)) {
|
||||
buf_pc = pc;
|
||||
|
|
@ -1164,7 +1163,10 @@ RZ_API int rz_debug_continue_kill(RzDebug *dbg, int sig) {
|
|||
// Go to the end or the next breakpoint in the changes
|
||||
if (dbg->session && dbg->session->cnum != dbg->session->maxcnum) {
|
||||
bool has_bp = false;
|
||||
RzRegItem *ripc = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_PC], RZ_REG_TYPE_GPR);
|
||||
RzRegItem *ripc = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_PC);
|
||||
if (!ripc) {
|
||||
return 0;
|
||||
}
|
||||
RzVector *vreg = ht_up_find(dbg->session->registers, ripc->offset | (ripc->arena << 16), NULL);
|
||||
RzDebugChangeReg *reg;
|
||||
rz_vector_foreach_prev (vreg, reg) {
|
||||
|
|
@ -1377,7 +1379,7 @@ RZ_API int rz_debug_continue_until_optype(RzDebug *dbg, int type, int over) {
|
|||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_GPR, false);
|
||||
|
||||
// Initial refill
|
||||
buf_pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
buf_pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
dbg->iob.read_at(dbg->iob.io, buf_pc, buf, sizeof(buf));
|
||||
|
||||
// step first, we don't want to check current optype
|
||||
|
|
@ -1386,7 +1388,7 @@ RZ_API int rz_debug_continue_until_optype(RzDebug *dbg, int type, int over) {
|
|||
break;
|
||||
}
|
||||
|
||||
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
// Try to keep the buffer full
|
||||
if (pc - buf_pc > sizeof(buf)) {
|
||||
buf_pc = pc;
|
||||
|
|
@ -1435,7 +1437,7 @@ static int rz_debug_continue_until_internal(RzDebug *dbg, ut64 addr, bool block)
|
|||
if (rz_debug_is_dead(dbg) || dbg->reason.type) {
|
||||
break;
|
||||
}
|
||||
ut64 pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
ut64 pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
if (pc == addr) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -1463,10 +1465,14 @@ RZ_API bool rz_debug_continue_back(RzDebug *dbg) {
|
|||
int cnum;
|
||||
bool has_bp = false;
|
||||
|
||||
RzRegItem *ripc = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_PC], RZ_REG_TYPE_GPR);
|
||||
RzRegItem *ripc = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_PC);
|
||||
if (!ripc) {
|
||||
RZ_LOG_ERROR("debug: no PC register known");
|
||||
return false;
|
||||
}
|
||||
RzVector *vreg = ht_up_find(dbg->session->registers, ripc->offset | (ripc->arena << 16), NULL);
|
||||
if (!vreg) {
|
||||
eprintf("Error: cannot find PC change vector");
|
||||
RZ_LOG_ERROR("debug: cannot find PC change vector");
|
||||
return false;
|
||||
}
|
||||
RzDebugChangeReg *reg;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ static int esilbreak_check_pc(RzDebug *dbg, ut64 pc) {
|
|||
RzDebugEsilWatchpoint *ew;
|
||||
RzListIter *iter;
|
||||
if (!pc) {
|
||||
pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
}
|
||||
rz_list_foreach (EWPS, iter, ew) {
|
||||
if (ew->rwx & RZ_PERM_X) {
|
||||
|
|
@ -222,7 +222,7 @@ RZ_API int rz_debug_esil_stepi(RzDebug *d) {
|
|||
}
|
||||
|
||||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_GPR, false);
|
||||
opc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
opc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
dbg->iob.read_at(dbg->iob.io, opc, obuf, sizeof(obuf));
|
||||
|
||||
// dbg->iob.read_at (dbg->iob.io, npc, buf, sizeof (buf));
|
||||
|
|
|
|||
|
|
@ -111,6 +111,23 @@ RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name) {
|
|||
return rz_reg_getv_by_role_or_name(dbg->reg, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the register with the given role, including syncing first.
|
||||
*/
|
||||
RZ_API ut64 rz_debug_reg_get_by_role(RZ_NONNULL RzDebug *dbg, RzRegisterId role) {
|
||||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_ANY, false);
|
||||
RzRegItem *ri = rz_reg_get_by_role(dbg->reg, role);
|
||||
if (!ri) {
|
||||
if (role == RZ_REG_NAME_PC) {
|
||||
// Debug generally requires the existence of a PC register,
|
||||
// other registers may be optional.
|
||||
RZ_LOG_ERROR("debug: no PC register known");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return rz_reg_get_value(dbg->reg, ri);
|
||||
}
|
||||
|
||||
RZ_API ut64 rz_debug_num_callback(RzNum *userptr, const char *str, int *ok) {
|
||||
RzDebug *dbg = (RzDebug *)userptr;
|
||||
rz_debug_reg_sync(dbg, RZ_REG_TYPE_ANY, false);
|
||||
|
|
|
|||
|
|
@ -86,7 +86,11 @@ RZ_API bool rz_debug_add_checkpoint(RzDebug *dbg) {
|
|||
rz_vector_push(dbg->session->checkpoints, &checkpoint);
|
||||
|
||||
// Add PC register change so we can check for breakpoints when continue [back]
|
||||
RzRegItem *ripc = rz_reg_get(dbg->reg, dbg->reg->name[RZ_REG_NAME_PC], RZ_REG_TYPE_GPR);
|
||||
RzRegItem *ripc = rz_reg_get_by_role(dbg->reg, RZ_REG_NAME_PC);
|
||||
if (!ripc) {
|
||||
RZ_LOG_ERROR("debug: no PC register known\n");
|
||||
return false;
|
||||
}
|
||||
ut64 data = rz_reg_get_value(dbg->reg, ripc);
|
||||
rz_debug_session_add_reg_change(dbg->session, ripc->arena, ripc->offset, data);
|
||||
|
||||
|
|
|
|||
|
|
@ -314,8 +314,7 @@ static int rz_debug_gdb_reg_write(RzDebug *dbg, int type, const ut8 *buf, int si
|
|||
int buflen = 0;
|
||||
RzReg *rreg = rz_analysis_get_reg(dbg->analysis);
|
||||
int bits = rz_analysis_get_bits(dbg->analysis);
|
||||
const char *pcname = rz_reg_get_name(rreg, RZ_REG_NAME_PC);
|
||||
RzRegItem *reg = rz_reg_get(rreg, pcname, 0);
|
||||
RzRegItem *reg = rz_reg_get_by_role(rreg, RZ_REG_NAME_PC);
|
||||
if (reg && bits != reg->size) {
|
||||
bits = reg->size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,7 @@ static int debug_qnx_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
|
|||
}
|
||||
RzReg *rreg = rz_analysis_get_reg(dbg->analysis);
|
||||
int bits = rz_analysis_get_bits(dbg->analysis);
|
||||
const char *pcname = rz_reg_get_name(rreg, RZ_REG_NAME_PC);
|
||||
RzRegItem *reg = rz_reg_get(rreg, pcname, 0);
|
||||
RzRegItem *reg = rz_reg_get_by_role(rreg, RZ_REG_NAME_PC);
|
||||
if (!ctx->reg_buf) {
|
||||
// we cannot write registers before we once read them
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -84,13 +84,7 @@ static RzList /*<RzDebugFrame *>*/ *backtrace_fuzzy(RzDebug *dbg, ut64 at) {
|
|||
if (at == UT64_MAX) {
|
||||
RzRegItem *ri;
|
||||
RzReg *reg = dbg->reg;
|
||||
const char *spname = rz_reg_get_name(reg, RZ_REG_NAME_SP);
|
||||
if (!spname) {
|
||||
eprintf("Cannot find stack pointer register\n");
|
||||
free(stack);
|
||||
return NULL;
|
||||
}
|
||||
ri = rz_reg_get(reg, spname, RZ_REG_TYPE_GPR);
|
||||
ri = rz_reg_get_by_role(reg, RZ_REG_NAME_SP);
|
||||
if (!ri) {
|
||||
eprintf("Cannot find stack pointer register\n");
|
||||
free(stack);
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@
|
|||
#endif
|
||||
return rz_str_dup(
|
||||
"=PC pc\n"
|
||||
"=SP sp\n" // XXX
|
||||
"=BP x30\n" // XXX
|
||||
"=SP sp\n"
|
||||
"=BP x29\n"
|
||||
"=A0 x0\n"
|
||||
"=A1 x1\n"
|
||||
"=A2 x2\n"
|
||||
"=A3 x3\n"
|
||||
"=ZF zf\n"
|
||||
// not yet defined: "=ZF zf\n"
|
||||
"=SF nf\n"
|
||||
"=OF vf\n"
|
||||
"=CF cf\n"
|
||||
// not yet defined: "=OF vf\n"
|
||||
// not yet defined: "=CF cf\n"
|
||||
"gpr x0 .64 0 0\n" // r14
|
||||
"gpr x1 .64 8 0\n" // r14
|
||||
"gpr x2 .64 16 0\n" // r14
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ RZ_API bool rz_debug_trace_ins_before(RzDebug *dbg) {
|
|||
ut8 buf_pc[32];
|
||||
|
||||
// Analyze current instruction
|
||||
ut64 pc = rz_debug_reg_get(dbg, dbg->reg->name[RZ_REG_NAME_PC]);
|
||||
ut64 pc = rz_debug_reg_get_by_role(dbg, RZ_REG_NAME_PC);
|
||||
if (!dbg->iob.read_at) {
|
||||
RZ_LOG_ERROR("dbg->iob.read_at missing\n");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -243,19 +243,14 @@ RZ_API void rz_il_vm_setup_reg_binding(RZ_NONNULL RzILVM *vm, RZ_NONNULL RZ_BORR
|
|||
RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg) {
|
||||
rz_return_val_if_fail(vm && rb && reg, false);
|
||||
bool perfect = true;
|
||||
const char *pc = rz_reg_get_name(reg, RZ_REG_NAME_PC);
|
||||
if (pc) {
|
||||
RzRegItem *ri = rz_reg_get(reg, pc, RZ_REG_TYPE_ANY);
|
||||
if (ri) {
|
||||
RzBitVector *pcbv = rz_bv_new_zero(ri->size);
|
||||
if (pcbv) {
|
||||
perfect &= rz_bv_len(pcbv) == rz_bv_len(vm->pc);
|
||||
rz_bv_copy_nbits(pcbv, 0, vm->pc, 0, RZ_MIN(rz_bv_len(pcbv), rz_bv_len(vm->pc)));
|
||||
rz_reg_set_bv(reg, ri, pcbv);
|
||||
rz_bv_free(pcbv);
|
||||
} else {
|
||||
perfect = false;
|
||||
}
|
||||
RzRegItem *ripc = rz_reg_get_by_role(reg, RZ_REG_NAME_PC);
|
||||
if (ripc) {
|
||||
RzBitVector *pcbv = rz_bv_new_zero(ripc->size);
|
||||
if (pcbv) {
|
||||
perfect &= rz_bv_len(pcbv) == rz_bv_len(vm->pc);
|
||||
rz_bv_copy_nbits(pcbv, 0, vm->pc, 0, RZ_MIN(rz_bv_len(pcbv), rz_bv_len(vm->pc)));
|
||||
rz_reg_set_bv(reg, ripc, pcbv);
|
||||
rz_bv_free(pcbv);
|
||||
} else {
|
||||
perfect = false;
|
||||
}
|
||||
|
|
@ -317,16 +312,13 @@ RZ_API bool rz_il_vm_sync_to_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILRegBindin
|
|||
*/
|
||||
RZ_API void rz_il_vm_sync_from_reg(RZ_NONNULL RzILVM *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg) {
|
||||
rz_return_if_fail(vm && rb && reg);
|
||||
const char *pc = rz_reg_get_name(reg, RZ_REG_NAME_PC);
|
||||
if (pc) {
|
||||
RzRegItem *ri = rz_reg_get(reg, pc, RZ_REG_TYPE_ANY);
|
||||
if (ri) {
|
||||
rz_bv_set_all(vm->pc, 0);
|
||||
RzBitVector *pcbv = rz_reg_get_bv(reg, ri);
|
||||
if (pcbv) {
|
||||
rz_bv_copy_nbits(vm->pc, 0, pcbv, 0, RZ_MIN(rz_bv_len(pcbv), rz_bv_len(vm->pc)));
|
||||
rz_bv_free(pcbv);
|
||||
}
|
||||
RzRegItem *ripc = rz_reg_get_by_role(reg, RZ_REG_NAME_PC);
|
||||
if (ripc) {
|
||||
rz_bv_set_all(vm->pc, 0);
|
||||
RzBitVector *pcbv = rz_reg_get_bv(reg, ripc);
|
||||
if (pcbv) {
|
||||
rz_bv_copy_nbits(vm->pc, 0, pcbv, 0, RZ_MIN(rz_bv_len(pcbv), rz_bv_len(vm->pc)));
|
||||
rz_bv_free(pcbv);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < rb->regs_count; i++) {
|
||||
|
|
|
|||
|
|
@ -539,6 +539,7 @@ RZ_API bool rz_debug_reg_profile_sync(RzDebug *dbg);
|
|||
RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write);
|
||||
RZ_API int rz_debug_reg_set(RzDebug *dbg, const char *name, ut64 num);
|
||||
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name);
|
||||
RZ_API ut64 rz_debug_reg_get_by_role(RZ_NONNULL RzDebug *dbg, RzRegisterId role);
|
||||
|
||||
RZ_API ut64 rz_debug_execute(RzDebug *dbg, const ut8 *buf, int len, int restore);
|
||||
RZ_API bool rz_debug_map_sync(RzDebug *dbg);
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ typedef struct rz_reg_t {
|
|||
char *reg_profile_cmt;
|
||||
char *reg_profile_str;
|
||||
RzRegProfile reg_profile;
|
||||
char *name[RZ_REG_NAME_LAST]; // aliases
|
||||
RZ_NULLABLE RzRegItem *by_role[RZ_REG_NAME_LAST]; ///< Registers with known common meanings for quick access
|
||||
RzRegSet regset[RZ_REG_TYPE_LAST];
|
||||
RzList /*<RzRegItem *>*/ *allregs;
|
||||
RzList /*<char *>*/ *roregs;
|
||||
|
|
@ -172,7 +172,6 @@ typedef struct rz_reg_flags_t {
|
|||
RZ_API void rz_reg_free(RzReg *reg);
|
||||
RZ_API void rz_reg_free_internal(RzReg *reg, bool init);
|
||||
RZ_API RzReg *rz_reg_new(void);
|
||||
RZ_API bool rz_reg_set_name(RZ_NONNULL RzReg *reg, RzRegisterId role, RZ_NONNULL const char *name);
|
||||
RZ_API bool rz_reg_set_profile_string(RZ_NONNULL RzReg *reg, RZ_NONNULL const char *profile);
|
||||
RZ_API char *rz_reg_profile_to_cc(RzReg *reg);
|
||||
RZ_API bool rz_reg_set_reg_profile(RZ_BORROW RzReg *reg);
|
||||
|
|
|
|||
|
|
@ -382,13 +382,6 @@ RZ_API bool rz_reg_set_reg_profile(RZ_BORROW RzReg *reg) {
|
|||
rz_return_val_if_fail(reg->reg_profile.alias && reg->reg_profile.defs, false);
|
||||
|
||||
RzListIter *it;
|
||||
RzRegProfileAlias *alias;
|
||||
rz_list_foreach (reg->reg_profile.alias, it, alias) {
|
||||
if (!rz_reg_set_name(reg, alias->role, alias->reg_name)) {
|
||||
RZ_LOG_WARN("Invalid alias gviven.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
RzRegProfileDef *def;
|
||||
rz_list_foreach (reg->reg_profile.defs, it, def) {
|
||||
RzRegItem *item = RZ_NEW0(RzRegItem);
|
||||
|
|
@ -420,6 +413,14 @@ RZ_API bool rz_reg_set_reg_profile(RZ_BORROW RzReg *reg) {
|
|||
|
||||
add_item_to_regset(reg, item);
|
||||
}
|
||||
RzRegProfileAlias *alias;
|
||||
rz_list_foreach (reg->reg_profile.alias, it, alias) {
|
||||
RzRegItem *item = rz_reg_get(reg, alias->reg_name, RZ_REG_TYPE_ANY);
|
||||
if (!item) {
|
||||
RZ_LOG_WARN("Invalid alias given in register profile: %s.\n", alias->reg_name);
|
||||
}
|
||||
reg->by_role[alias->role] = item;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,31 +154,16 @@ RZ_API int rz_reg_get_name_idx(const char *type) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
RZ_API bool rz_reg_set_name(RZ_NONNULL RzReg *reg, RzRegisterId role, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(reg && name, false);
|
||||
if (role >= 0 && role < RZ_REG_NAME_LAST) {
|
||||
char *tmp = rz_str_dup(name);
|
||||
free(reg->name[role]);
|
||||
reg->name[role] = tmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RZ_API const char *rz_reg_get_name(const RzReg *reg, const int role) {
|
||||
if (reg && role >= 0 && role < RZ_REG_NAME_LAST) {
|
||||
return reg->name[role];
|
||||
return reg->by_role[role] ? reg->by_role[role]->name : NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RZ_API RzRegItem *rz_reg_get_by_role(RzReg *reg, RzRegisterId role) {
|
||||
rz_return_val_if_fail(reg, NULL);
|
||||
const char *name = rz_reg_get_name(reg, role);
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_reg_get(reg, name, RZ_REG_TYPE_ANY);
|
||||
return reg->by_role[role];
|
||||
}
|
||||
|
||||
static const char *roles[RZ_REG_NAME_LAST + 1] = {
|
||||
|
|
@ -221,12 +206,8 @@ RZ_API void rz_reg_free_internal(RzReg *reg, bool init) {
|
|||
rz_list_free(reg->reg_profile.defs);
|
||||
reg->reg_profile.alias = 0;
|
||||
reg->reg_profile.defs = 0;
|
||||
memset(reg->by_role, 0, sizeof(reg->by_role));
|
||||
|
||||
for (i = 0; i < RZ_REG_NAME_LAST; i++) {
|
||||
if (reg->name[i]) {
|
||||
RZ_FREE(reg->name[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
|
||||
ht_sp_free(reg->regset[i].ht_regs);
|
||||
reg->regset[i].ht_regs = NULL;
|
||||
|
|
|
|||
|
|
@ -57,8 +57,12 @@ RZ_API ut64 rz_reg_get_value(RZ_NONNULL RzReg *reg, RZ_NONNULL RzRegItem *item)
|
|||
* \return Value stored in the register
|
||||
*/
|
||||
RZ_API ut64 rz_reg_get_value_by_role(RZ_NONNULL RzReg *reg, RzRegisterId role) {
|
||||
// TODO use mapping from RzRegisterId to RzRegItem (via RzRegSet)
|
||||
return rz_reg_get_value(reg, rz_reg_get(reg, rz_reg_get_name(reg, role), -1));
|
||||
rz_return_val_if_fail(reg, 0);
|
||||
RzRegItem *ri = rz_reg_get_by_role(reg, role);
|
||||
if (!ri) {
|
||||
return 0;
|
||||
}
|
||||
return rz_reg_get_value(reg, ri);
|
||||
}
|
||||
|
||||
static bool reg_set_value(RzReg *reg, RzRegItem *item, ut64 value) {
|
||||
|
|
@ -179,11 +183,10 @@ RZ_API bool rz_reg_set_value(RZ_NONNULL RzReg *reg, RZ_NONNULL RzRegItem *item,
|
|||
* \return On success returns true, otherwise false
|
||||
*/
|
||||
RZ_API bool rz_reg_set_value_by_role(RZ_NONNULL RzReg *reg, RzRegisterId role, ut64 value) {
|
||||
// TODO use mapping from RzRegisterId to RzRegItem (via RzRegSet)
|
||||
const char *name = rz_reg_get_name(reg, role);
|
||||
if (!name) {
|
||||
rz_return_val_if_fail(reg, false);
|
||||
RzRegItem *ri = rz_reg_get_by_role(reg, role);
|
||||
if (!ri) {
|
||||
return false;
|
||||
}
|
||||
RzRegItem *r = rz_reg_get(reg, name, -1);
|
||||
return r ? rz_reg_set_value(reg, r, value) : false;
|
||||
return ri ? rz_reg_set_value(reg, ri, value) : false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,27 +4,15 @@
|
|||
#include <rz_reg.h>
|
||||
#include "minunit.h"
|
||||
|
||||
bool test_rz_reg_set_name(void) {
|
||||
RzReg *reg;
|
||||
|
||||
reg = rz_reg_new();
|
||||
mu_assert_notnull(reg, "rz_reg_new () failed");
|
||||
|
||||
rz_reg_set_name(reg, RZ_REG_NAME_PC, "eip");
|
||||
const char *name = rz_reg_get_name(reg, RZ_REG_NAME_PC);
|
||||
mu_assert_streq(name, "eip", "PC register alias is eip");
|
||||
|
||||
rz_reg_free(reg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_reg_set_profile_string(void) {
|
||||
RzReg *reg;
|
||||
|
||||
reg = rz_reg_new();
|
||||
mu_assert_notnull(reg, "rz_reg_new () failed");
|
||||
|
||||
rz_reg_set_profile_string(reg, "=PC eip");
|
||||
rz_reg_set_profile_string(reg,
|
||||
"=PC eip\n"
|
||||
"gpr eip .32 0 0");
|
||||
const char *name = rz_reg_get_name(reg, RZ_REG_NAME_PC);
|
||||
mu_assert_streq(name, "eip", "PC register alias is eip");
|
||||
|
||||
|
|
@ -170,6 +158,36 @@ bool test_rz_reg_get(void) {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_reg_get_by_role(void) {
|
||||
RzReg *reg;
|
||||
RzRegItem *r;
|
||||
|
||||
reg = rz_reg_new();
|
||||
mu_assert_notnull(reg, "rz_reg_new () failed");
|
||||
|
||||
bool success = rz_reg_set_profile_string(reg,
|
||||
"=PC eip\n"
|
||||
"=SP esp\n"
|
||||
"gpr eip .32 0 0\n"
|
||||
"gpr esp .32 4 0\n"
|
||||
"gpr eax .32 8 0");
|
||||
mu_assert_eq(success, true, "load profile");
|
||||
|
||||
r = rz_reg_get_by_role(reg, RZ_REG_NAME_PC);
|
||||
mu_assert_notnull(r, "rz_reg_get_by_role pc");
|
||||
mu_assert_streq(r->name, "eip", "rz_reg_get_by_role pc");
|
||||
|
||||
r = rz_reg_get_by_role(reg, RZ_REG_NAME_SP);
|
||||
mu_assert_notnull(r, "rz_reg_get_by_role sp");
|
||||
mu_assert_streq(r->name, "esp", "rz_reg_get_by_role sp");
|
||||
|
||||
r = rz_reg_get_by_role(reg, RZ_REG_NAME_BP);
|
||||
mu_assert_null(r, "rz_reg_get_by_role bp (nonexistent)");
|
||||
|
||||
rz_reg_free(reg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_reg_get_list(void) {
|
||||
RzReg *reg;
|
||||
const RzList *l;
|
||||
|
|
@ -369,11 +387,11 @@ bool test_rz_reg_set_bv(void) {
|
|||
}
|
||||
|
||||
int all_tests() {
|
||||
mu_run_test(test_rz_reg_set_name);
|
||||
mu_run_test(test_rz_reg_set_profile_string);
|
||||
mu_run_test(test_rz_reg_get_value_gpr);
|
||||
mu_run_test(test_rz_reg_get_value_flag);
|
||||
mu_run_test(test_rz_reg_get);
|
||||
mu_run_test(test_rz_reg_get_by_role);
|
||||
mu_run_test(test_rz_reg_get_list);
|
||||
mu_run_test(test_rz_reg_get_bv);
|
||||
mu_run_test(test_rz_reg_set_bv);
|
||||
|
|
|
|||
Loading…
Reference in a new issue