Skip to content

Commit

Permalink
fix windowcheck
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Dec 16, 2024
1 parent 46ae49c commit b69c99c
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 40 deletions.
1 change: 1 addition & 0 deletions librz/arch/isa/xtensa/xtensa.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ bool xtensa_disassemble(XtensaContext *self, const ut8 *buf, int len, ut64 addr)
void xtensa_disassemble_fini(XtensaContext *self);
void xtensa_analyze_op_esil(XtensaContext *ctx, RzAnalysisOp *op);
void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op);
RzAnalysisILConfig *xtensa_il_config(RzAnalysis *a);

static inline cs_xtensa_op_mem *xtensa_op_mem(cs_insn *insn, unsigned int index) {
cs_xtensa_op *op = &insn->detail->xtensa.operands[index];
Expand Down
157 changes: 130 additions & 27 deletions librz/arch/isa/xtensa/xtensa_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,55 @@ static const char *eps_tbl[] = {

#include <rz_il/rz_il_opbuilder_begin.h>

static const char *xAR[] = {
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"a10",
"a11",
"a12",
"a13",
"a14",
"a15",
};

static RzILOpPure *x_ARindex(ut8 i) {
return MUL(U32(4), LOGOR(U32(i & 0x3), SHIFTL0(ADD(VARG("windowbase"), U32((i & 0xc) >> 2)), U32(2))));
}

/**
* We need to hook VARG and SETG to replace a0-a15 with the actual address according to windowbase and windowstart.
*/
static RzILOpPure *x_varg(const char *name) {
for (size_t i = 0; i < RZ_ARRAY_SIZE(xAR); ++i) {
if (RZ_STR_EQ(name, xAR[i])) {
return rz_il_op_new_loadw(1, x_ARindex(i), 32);
}
}
return VARG(name);
}

static RzILOpEffect *x_setg(const char *name, RzILOpPure *x) {
for (size_t i = 0; i < RZ_ARRAY_SIZE(xAR); ++i) {
if (RZ_STR_EQ(name, xAR[i])) {
return rz_il_op_new_storew(1, x_ARindex(i), x);
}
}
return SETG(name, x);
}

#undef VARG
#undef SETG
#define VARG x_varg
#define SETG x_setg

#define FORMAT (ctx->insn->detail->xtensa.format)
#define PC (ctx->insn->address)
#define nextPC (ctx->insn->address + ctx->insn->size)
Expand All @@ -32,13 +81,13 @@ typedef RzAnalysisLiftedILOp (*fn_analyze_op_il)(XtensaContext *ctx);
typedef RzILOpPure *(fn_op2)(RzILOpBool *x, RzILOpBool *y);

enum {
PS_INTLEVEL,
PS_EXCM,
PS_INTLEVEL, /// Interrupt level mask
PS_EXCM, /// Exception mask
PS_UM,
PS_RING,
PS_OWB,
PS_CALLINC,
PS_WOE,
PS_OWB, /// Old window base
PS_CALLINC, /// Call increment
PS_WOE, /// Window overflow enable
};

enum {
Expand Down Expand Up @@ -553,13 +602,19 @@ static RzAnalysisLiftedILOp op_bltz(XtensaContext *ctx) {
* endprocedure WindowCheck
*/
static RzILOpEffect *WindowCheck(XtensaContext *ctx, RzILOpPure *wr, RzILOpPure *ws, RzILOpPure *wt) {
// TODO: it's not clear what the WindowStartWindowBase+1 means
return SEQ3(
SETL("cwoe", ITE(NON_ZERO(PS_field_get(PS_EXCM)), U32(0), PS_field_get(PS_WOE))),
SETL("n",
ITE(AND(OR(NE(wr, U32(0)), OR(NE(ws, U32(0)), NE(wt, U32(0)))), NE(VARG("windowstart"), U32(0))), U32(1),
ITE(AND(OR(NE(DUP(wr), U32(0)), OR(NE(DUP(ws), U32(0)), NE(DUP(wt), U32(0)))), NE(VARG("windowstart"), U32(1))), U32(2),
ITE(AND(OR(EQ(DUP(wr), U32(3)), OR(EQ(DUP(ws), U32(3)), EQ(DUP(wt), U32(3)))), NE(VARG("windowstart"), U32(2))), U32(3), U32(0))))),
ITE(AND(OR(NON_ZERO(wr), OR(NON_ZERO(ws), NON_ZERO(wt))),
NON_ZERO(EXTRACT32(VARG("windowstart"), ADD(VARG("windowbase"), U32(1)), U32(1)))),
U32(1),
ITE(AND(OR(NON_ZERO(DUP(wr)), OR(NON_ZERO(DUP(ws)), NON_ZERO(DUP(wt)))),
NON_ZERO(EXTRACT32(VARG("windowstart"), ADD(VARG("windowbase"), U32(2)), U32(1)))),
U32(2),
ITE(AND(OR(EQ(DUP(wr), U32(3)), OR(EQ(DUP(ws), U32(3)), EQ(DUP(wt), U32(3)))),
NON_ZERO(EXTRACT32(VARG("windowstart"), ADD(VARG("windowbase"), U32(3)), U32(1)))),
U32(3),
U32(0))))),
BRANCH(
AND(EQ(VARL("cwoe"), U32(1)), NE(VARL("n"), U32(0))),
SEQ6(
Expand All @@ -579,31 +634,31 @@ static RzAnalysisLiftedILOp op_break(XtensaContext *ctx) {
static RzAnalysisLiftedILOp op_call0(XtensaContext *ctx) {
return SEQ2(
SETG("a0", U32(nextPC)),
JMP(U32(PC + IMM(0))));
JMP(U32((PC + IMM(0)) & ~0x3)));
}

static RzAnalysisLiftedILOp op_call4(XtensaContext *ctx) {
return SEQ4(
WindowCheck(ctx, U32(0), U32(0), U32(1)),
PS_field_set(PS_CALLINC, U32(1)),
SETG("a4", U32(0x40000000 | (nextPC & 0x3fffffff))),
JMP(U32(PC + IMM(0))));
JMP(U32((PC + IMM(0)) & ~0x3)));
}

static RzAnalysisLiftedILOp op_call8(XtensaContext *ctx) {
return SEQ4(
WindowCheck(ctx, U32(0), U32(0), U32(2)),
PS_field_set(PS_CALLINC, U32(2)),
SETG("a8", U32(0x80000000 | (nextPC & 0x3fffffff))),
JMP(U32(PC + IMM(0))));
JMP(U32((PC + IMM(0)) & ~0x3)));
}

static RzAnalysisLiftedILOp op_call12(XtensaContext *ctx) {
return SEQ4(
WindowCheck(ctx, U32(0), U32(0), U32(3)),
PS_field_set(PS_CALLINC, U32(3)),
SETG("a12", U32(0xc0000000 | (nextPC & 0x3fffffff))),
JMP(U32(PC + IMM(0))));
JMP(U32((PC + IMM(0)) & ~0x3)));
}

static RzAnalysisLiftedILOp op_callx0(XtensaContext *ctx) {
Expand Down Expand Up @@ -938,9 +993,9 @@ else
endif
*/
static RzAnalysisLiftedILOp op_movsp(XtensaContext *ctx) {
// FIXME: WindowStart_{WindowBase-0011..WindowBase-0001}
return BRANCH(
EQ(VARG("windowstart"), U32(0x03)),
EQ(EXTRACT32(VARG("windowstart"), SUB(VARG("windowbase"), U32(1)), U32(3)),
U32(0x03)),
NOP(),
SETG(REGN(0), IREG(1)));
}
Expand All @@ -966,6 +1021,10 @@ static RzAnalysisLiftedILOp op_movgez(XtensaContext *ctx) {
NOP());
}

static RzAnalysisLiftedILOp op_mov(XtensaContext *ctx) {
return SETG(REGN(0), IREG(1));
}

static RzAnalysisLiftedILOp op_movi(XtensaContext *ctx) {
return SETG(REGN(0), U32(IMM(1)));
}
Expand Down Expand Up @@ -1266,15 +1325,20 @@ static RzAnalysisLiftedILOp op_retw(XtensaContext *ctx) {
SETL("nextPC", LOGOR(U32(PC & (0x3 << 30)), LOGAND(VARG("a0"), U32(0x3fffffff)))),
SETL("owb", VARG("windowbase")),
SETL("m",
// // FIXME: WindowStart_WindowBase-xxxx ← 0
ITE(EQ(VARG("windowstart"), U32(1)), U32(1),
ITE(EQ(VARG("windowstart"), U32(2)), U32(2),
ITE(EQ(VARG("windowstart"), U32(3)), U32(3),
ITE(EQ(
EXTRACT32(VARG("windowstart"), SUB(VARG("windowbase"), U32(1)), U32(1)),
U32(1)),
U32(1),
ITE(EQ(EXTRACT32(VARG("windowstart"), SUB(VARG("windowbase"), U32(2)), U32(1)),
U32(1)),
U32(2),
ITE(EQ(EXTRACT32(VARG("windowstart"), SUB(VARG("windowbase"), U32(3)), U32(1)),
U32(1)),
U32(3),
U32(0))))),
BRANCH(OR(EQ(VARL("n"), U32(0)),
OR(AND(NE(VARL("m"), U32(0)), NE(VARL("m"), VARL("n"))),
OR(EQ(PS_field_get(PS_WOE), U32(0)),
EQ(PS_field_get(PS_EXCM), U32(1))))),
BRANCH(OR(AND(NE(VARL("m"), U32(0)), NE(VARL("m"), VARL("n"))),
OR(EQ(PS_field_get(PS_WOE), U32(0)),
EQ(PS_field_get(PS_EXCM), U32(1)))),
// Undefined operation, may raise illegal instruction exception
NOP(),
SEQ4(
Expand Down Expand Up @@ -1316,17 +1380,19 @@ static RzAnalysisLiftedILOp op_rfr(XtensaContext *ctx) {
static RzAnalysisLiftedILOp op_rfwo(XtensaContext *ctx) {
return SEQ4(
PS_EXCM_CLEAR,
// FIXME: WindowStart_WindowBase ← 0
SETG("windowstart", U32(0)),
SETG("windowstart",
DEPOSIT32(VARG("windowstart"), VARG("windowbase"), U32(1),
U32(0))),
SETG("windowbase", PS_field_get(PS_OWB)),
JMP(IEPC(1)));
}

static RzAnalysisLiftedILOp op_rfwu(XtensaContext *ctx) {
return SEQ4(
PS_EXCM_CLEAR,
// FIXME: WindowStart_WindowBase ← 1
SETG("windowstart", U32(1)),
SETG("windowstart",
DEPOSIT32(VARG("windowstart"), VARG("windowbase"), U32(1),
U32(1))),
SETG("windowbase", PS_field_get(PS_OWB)),
JMP(IEPC(1)));
}
Expand Down Expand Up @@ -1815,6 +1881,7 @@ static const fn_analyze_op_il fn_tbl[] = {
[XTENSA_INS_MINU] = op_minu,
[XTENSA_INS_MKDADJ_S] = op_mkdadj_s,
[XTENSA_INS_MKSADJ_S] = op_mksadj_s,
[XTENSA_INS_MOV_N] = op_mov,
[XTENSA_INS_MOVEQZ] = op_moveqz,
[XTENSA_INS_MOVEQZ_S] = op_moveqz,
[XTENSA_INS_MOVF] = op_movf,
Expand Down Expand Up @@ -2062,6 +2129,41 @@ static const fn_analyze_op_il fn_tbl[] = {
[XTENSA_INS_MV_QR] = op_nop,
};

void xtensa_il_init_cb(RzAnalysisILVM *vm, RzReg *reg) {
RzBuffer *buf = rz_buf_new_sparse(0);
if (!buf) {
return;
}
RzILMem *mem = rz_il_mem_new(buf, 32);
if (!mem) {
rz_buf_free(buf);
return;
}
rz_il_vm_add_mem(vm->vm, 1, mem);
}

RzAnalysisILConfig *xtensa_il_config(RzAnalysis *a) {
rz_return_val_if_fail(a, NULL);

RzAnalysisILConfig *cfg = rz_analysis_il_config_new(32, a->big_endian, 32);
if (!cfg) {
return NULL;
}
cfg->init_state = rz_analysis_il_init_state_new();
if (!cfg->init_state) {
rz_analysis_il_config_free(cfg);
return NULL;
}
cfg->init_state->cb = xtensa_il_init_cb;
RzAnalysisILInitStateVar var = {
.name = "ps",
// WOE=1
.val = rz_il_value_new_bitv(rz_bv_new_from_ut64(32, 1 << 18))
};
rz_vector_push(&cfg->init_state->vars, &var);
return cfg;
}

void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op) {
unsigned id = ctx->insn->id;
if (id >= RZ_ARRAY_SIZE(fn_tbl)) {
Expand All @@ -2073,4 +2175,5 @@ void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op) {
return;
}
op->il_op = fn(ctx);
RZ_LOG_VERBOSE("op->il_op\n");
}
17 changes: 4 additions & 13 deletions librz/arch/p/analysis/analysis_xtensa_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@
#include <rz_endian.h>
#include <xtensa/xtensa.h>

RzAnalysisILConfig *xtensa_il_config(RzAnalysis *a) {
rz_return_val_if_fail(a, NULL);

RzAnalysisILConfig *cfg = rz_analysis_il_config_new(32, a->big_endian, 32);
// cfg->reg_bindings = xtensa_registers;
return cfg;
}

static int xtensa_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
switch (query) {
case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
Expand Down Expand Up @@ -449,7 +441,7 @@ static void xtensa_analyze_op(RzAnalysis *a, RzAnalysisOp *op, XtensaContext *ct
case XTENSA_INS_CALL8:
case XTENSA_INS_CALL12:
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
op->jump = ctx->insn->address + IMM(0);
op->jump = (ctx->insn->address + IMM(0)) & ~3;
op->fail = ctx->insn->address + ctx->insn->size;
break;
case XTENSA_INS_MOVEQZ: /* moveqz */
Expand Down Expand Up @@ -498,6 +490,9 @@ static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut
goto beach;
}

op->size = ctx->insn->size;
op->id = ctx->insn->id;
op->addr = addr;
xtensa_analyze_op(analysis, op, ctx);

if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
Expand All @@ -516,10 +511,6 @@ static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut
xtensa_analyze_op_rzil(ctx, op);
}

op->size = ctx->insn->size;
op->id = ctx->insn->id;
op->addr = addr;

xtensa_disassemble_fini(ctx);
return op->size;
beach:
Expand Down

0 comments on commit b69c99c

Please sign in to comment.