diff --git a/libr/arch/p/mips/mips_utils.h b/libr/arch/p/mips/mips_utils.h index 931a6c4b68..2726bcd7cd 100644 --- a/libr/arch/p/mips/mips_utils.h +++ b/libr/arch/p/mips/mips_utils.h @@ -4,6 +4,7 @@ #define R_MIPS_UTILS_H #include +#include #include static inline ut64 mips_read_ptr_at(RBin *bin, ut64 addr, bool be, int bits) { @@ -15,4 +16,31 @@ static inline ut64 mips_read_ptr_at(RBin *bin, ut64 addr, bool be, int bits) { return ptrsz == 8 ? r_read_ble64 (v, be) : r_read_ble32 (v, be); } +// esil for the unaligned lwl/lwr/ldl/ldr loads and swl/swr/sdl/sdr stores +static inline void mips_esil_unaligned(RStrBuf *esil, const RArchConfig *cfg, const char *addr, const char *rt, int w, bool left, bool store) { + const char *mask = (w == 8)? "0xffffffffffffffff": "0xffffffff"; + const char *align = (w == 8)? "0xfffffffffffffff8": "0xfffffffffffffffc"; + const bool sx = !store && w == 4 && cfg->bits == 64; + // a le cpu counts the addressed byte from the other end of the word + char *sh = (R_ARCH_CONFIG_IS_BIG_ENDIAN (cfg) == left) + ? r_str_newf ("3,%s,%d,&,<<", addr, w - 1) + : r_str_newf ("3,%s,%d,&,%d,-,<<", addr, w - 1, w - 1); + char *mem = r_str_newf ("%s,%s,&,[%d]", addr, align, w); + if (store && left) { + r_strbuf_appendf (esil, "%s,%s,>>,%s,^,%s,&,%s,%s,%s,&,>>,|,%s,%s,&,=[%d]", + sh, mask, mask, mem, sh, mask, rt, addr, align, w); + } else if (store) { + r_strbuf_appendf (esil, "%s,%s,%s,&,<<,1,%s,1,<<,-,%s,&,|,%s,%s,&,=[%d]", + sh, mask, rt, sh, mem, addr, align, w); + } else if (left) { + r_strbuf_appendf (esil, "%s%s,%s,<<,%s,&,1,%s,1,<<,-,%s,&,|,%s%s,=", + sx? "32,": "", sh, mem, mask, sh, rt, sx? "~,": "", rt); + } else { + r_strbuf_appendf (esil, "%s%s,%s,>>,%s,%s,%s,>>,^,%s,&,|,%s%s,=", + sx? "32,": "", sh, mem, mask, sh, mask, rt, sx? "~,": "", rt); + } + free (sh); + free (mem); +} + #endif diff --git a/libr/arch/p/mips/plugin_cs.c b/libr/arch/p/mips/plugin_cs.c index fc82795c5d..91271349c0 100644 --- a/libr/arch/p/mips/plugin_cs.c +++ b/libr/arch/p/mips/plugin_cs.c @@ -291,11 +291,19 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn ARG (0), ARG (1)); break; case MIPS_INS_SW: - case MIPS_INS_SWL: - case MIPS_INS_SWR: r_strbuf_appendf (&op->esil, "%s,%s,=[4]", ARG (0), ARG (1)); break; + case MIPS_INS_SWL: + case MIPS_INS_SWR: + case MIPS_INS_SDL: + case MIPS_INS_SDR: + { + const bool wide = insn->id == MIPS_INS_SDL || insn->id == MIPS_INS_SDR; + const bool left = insn->id == MIPS_INS_SWL || insn->id == MIPS_INS_SDL; + mips_esil_unaligned (&op->esil, as->config, ARG (1), ARG (0), wide? 8: 4, left, true); + } + break; case MIPS_INS_SH: r_strbuf_appendf (&op->esil, "%s,%s,=[2]", ARG (0), ARG (1)); @@ -648,13 +656,19 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn break; case MIPS_INS_LWC1: case MIPS_INS_LWC2: - case MIPS_INS_LWL: - case MIPS_INS_LWR: case MIPS_INS_LWU: ESIL_LOAD ("4"); break; - + case MIPS_INS_LWL: + case MIPS_INS_LWR: case MIPS_INS_LDL: + case MIPS_INS_LDR: + PROTECT_ZERO () { + const bool wide = insn->id == MIPS_INS_LDL || insn->id == MIPS_INS_LDR; + const bool left = insn->id == MIPS_INS_LWL || insn->id == MIPS_INS_LDL; + mips_esil_unaligned (&op->esil, as->config, ARG (1), REG (0), wide? 8: 4, left, false); + } + break; case MIPS_INS_LDC1: case MIPS_INS_LDC2: case MIPS_INS_LLD: @@ -1172,6 +1186,8 @@ static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) { case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: + case MIPS_INS_SDL: + case MIPS_INS_SDR: op->type = R_ANAL_OP_TYPE_STORE; break; case MIPS_INS_NOP: diff --git a/test/db/esil/mips_32 b/test/db/esil/mips_32 index 120ca0b5df..b87230c166 100644 --- a/test/db/esil/mips_32 +++ b/test/db/esil/mips_32 @@ -2206,3 +2206,121 @@ EXPECT=< /dev/null +wx 11223344 @ 4 +aei +aeim +s 8 +ar t3=4 +wx 89680001 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +wx 99680001 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +wx 89680003 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +wx 99680003 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +EOF +EXPECT=< /dev/null +aei +aeim +s 8 +ar t3=4 +ar t1=0x55667788 +wx 11223344 @ 4 +wx a9690001 @ 8 +ar pc=8 +aes +p8 4 @ 4 +wx 11223344 @ 4 +wx b9690001 @ 8 +ar pc=8 +aes +p8 4 @ 4 +wx 11223344 @ 4 +wx a9690003 @ 8 +ar pc=8 +aes +p8 4 @ 4 +wx 11223344 @ 4 +wx b9690003 @ 8 +ar pc=8 +aes +p8 4 @ 4 +EOF +EXPECT=< /dev/null +wx 11223344 @ 4 +aei +aeim +s 8 +ar t3=4 +ar t1=0x55667788 +wx 01006889 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +wx 01006899 @ 8 +ar t0=0xaabbccdd +ar pc=8 +aes +ar t0 +wx 11223344 @ 4 +wx 010069a9 @ 8 +ar pc=8 +aes +p8 4 @ 4 +wx 11223344 @ 4 +wx 010069b9 @ 8 +ar pc=8 +aes +p8 4 @ 4 +EOF +EXPECT=< /dev/null +wx 1122334455667788 @ 8 +aei +aeim +s 0x20 +ar t3=8 +wx 69680001 @ 0x20 +ar t0=0xa1a2a3a4a5a6a7a8 +ar pc=0x20 +aes +ar t0 +wx 6d680001 @ 0x20 +ar t0=0xa1a2a3a4a5a6a7a8 +ar pc=0x20 +aes +ar t0 +EOF +EXPECT=< /dev/null +aei +aeim +s 0x20 +ar t3=8 +ar t1=0xf1f2f3f4f5f6f7f8 +wx 1122334455667788 @ 8 +wx b1690001 @ 0x20 +ar pc=0x20 +aes +p8 8 @ 8 +wx 1122334455667788 @ 8 +wx b5690001 @ 0x20 +ar pc=0x20 +aes +p8 8 @ 8 +EOF +EXPECT=< /dev/null +wx 80223344 @ 4 +aei +aeim +s 0x20 +ar t3=4 +wx 89680000 @ 0x20 +ar t0=0xa1a2a3a4a5a6a7a8 +ar pc=0x20 +aes +ar t0 +wx 99680003 @ 0x20 +ar t0=0xa1a2a3a4a5a6a7a8 +ar pc=0x20 +aes +ar t0 +wx 89680002 @ 0x20 +ar t0=0xa1a2a3a4a5a6a7a8 +ar pc=0x20 +aes +ar t0 +EOF +EXPECT=<