From b69c99c1bdfacad928359c6ee63b4201adba1e84 Mon Sep 17 00:00:00 2001 From: billow Date: Mon, 16 Dec 2024 21:34:06 +0800 Subject: [PATCH] fix windowcheck --- librz/arch/isa/xtensa/xtensa.h | 1 + librz/arch/isa/xtensa/xtensa_il.c | 157 +++++++++++++++++---- librz/arch/p/analysis/analysis_xtensa_cs.c | 17 +-- 3 files changed, 135 insertions(+), 40 deletions(-) diff --git a/librz/arch/isa/xtensa/xtensa.h b/librz/arch/isa/xtensa/xtensa.h index edec9923343..1ac178cc22f 100644 --- a/librz/arch/isa/xtensa/xtensa.h +++ b/librz/arch/isa/xtensa/xtensa.h @@ -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]; diff --git a/librz/arch/isa/xtensa/xtensa_il.c b/librz/arch/isa/xtensa/xtensa_il.c index ecdec03cc6c..74ee9cb4214 100644 --- a/librz/arch/isa/xtensa/xtensa_il.c +++ b/librz/arch/isa/xtensa/xtensa_il.c @@ -12,6 +12,55 @@ static const char *eps_tbl[] = { #include +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) @@ -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 { @@ -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( @@ -579,7 +634,7 @@ 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) { @@ -587,7 +642,7 @@ static RzAnalysisLiftedILOp op_call4(XtensaContext *ctx) { 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) { @@ -595,7 +650,7 @@ static RzAnalysisLiftedILOp op_call8(XtensaContext *ctx) { 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) { @@ -603,7 +658,7 @@ static RzAnalysisLiftedILOp op_call12(XtensaContext *ctx) { 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) { @@ -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))); } @@ -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))); } @@ -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( @@ -1316,8 +1380,9 @@ 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))); } @@ -1325,8 +1390,9 @@ static RzAnalysisLiftedILOp op_rfwo(XtensaContext *ctx) { 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))); } @@ -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, @@ -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)) { @@ -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"); } diff --git a/librz/arch/p/analysis/analysis_xtensa_cs.c b/librz/arch/p/analysis/analysis_xtensa_cs.c index e174d0b166e..f055bc4518d 100644 --- a/librz/arch/p/analysis/analysis_xtensa_cs.c +++ b/librz/arch/p/analysis/analysis_xtensa_cs.c @@ -7,14 +7,6 @@ #include #include -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: @@ -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 */ @@ -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) { @@ -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: