-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix USE_DS
for MIPS ##emu
#23307
base: master
Are you sure you want to change the base?
Fix USE_DS
for MIPS ##emu
#23307
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,22 +64,25 @@ R_IPI int mips_assemble(const char *str, ut64 pc, ut8 *out); | |
|
||
|
||
// call with delay slot | ||
#define ES_CALL_DR(ra, addr) "pc,4,+,"ra",=,"ES_J(addr) | ||
#define ES_CALL_DR(ra, addr) "pc,4,+,"ra",=,"ES_J_D(addr) | ||
#define ES_CALL_D(addr) ES_CALL_DR("ra", addr) | ||
|
||
// call without delay slot | ||
#define ES_CALL_NDR(ra, addr) "pc,"ra",=,"ES_J(addr) | ||
#define ES_CALL_NDR(ra, addr) "pc,"ra",=,"ES_J_ND(addr) | ||
#define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr) | ||
|
||
#define USE_DS 0 | ||
#define USE_DS 1 | ||
#if USE_DS | ||
// emit ERR trap if executed in a delay slot | ||
#define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,}," | ||
// jump to address | ||
#define ES_J(addr) addr",SETJT,1,SETD" | ||
// Record jump-to-address and set delay slot flag. | ||
#define ES_J_D(addr) addr",SETJT,1,SETD" | ||
// Jump to address. | ||
#define ES_J_ND(addr) addr",pc,:=" | ||
#else | ||
#define ES_TRAP_DS() "" | ||
#define ES_J(addr) addr",pc,:=" | ||
#define ES_J_D(addr) addr",pc,:=" | ||
#define ES_J_ND(addr) ES_J_D(addr) | ||
#endif | ||
|
||
#define ES_B(x) "0xff,"x",&" | ||
|
@@ -241,6 +244,7 @@ static const char *arg(csh *handle, cs_insn *insn, char *buf, size_t buf_sz, int | |
static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn) { | ||
char str[8][32] = {{0}}; | ||
int i; | ||
u_int64_t addr = insn->address; | ||
|
||
r_strbuf_init (&op->esil); | ||
r_strbuf_set (&op->esil, ""); | ||
|
@@ -314,6 +318,15 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn | |
case MIPS_INS_SLL: | ||
r_strbuf_appendf (&op->esil, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0)); | ||
break; | ||
case MIPS_INS_BALC: | ||
// BALC address | ||
// Branch And Link, Compact. Unconditional PC relative branch to address, placing return address | ||
// in register $31. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_ND ("%s"), ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. $$ is a keyword that should be removed because we have PC and op->addr already, so there's no need to have an extra keyword for that. also its better to build the string right away instead of using replacef There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So would you suggest to change the macro like this to avoid #if USE_DS
#define ES_TRAP_DS(addr) "$ds,!,!,?{," addr ",1,TRAP,BREAK,},"
#else
#define ES_TRAP_DS(addr) ""
#endif With that we can remove the #if USE_DS
r_strbuf_appendf (&op->esil, ES_TRAP_DS ("0x%"PFMT64x) "" ES_CALL_DR ("%s", "%s"), addr, ARG (0), ARG (1));
#else
r_strbuf_appendf (&op->esil, "" ES_CALL_DR ("%s", "%s"), ARG (0), ARG (1));
#endif where r_strbuf_appendf (&op->esil, ES_TRAP_DS ("0x%3$"PFMT64x) "" ES_CALL_DR ("%s", "%s"), ARG (0), ARG (1), addr); But that could, depending on compiler settings, complain about the wrong number of args in the format string. The problem with using PC is that AFAIK it points to the first byte after instruction, and we would need to subtract its size, which may actually be 4 or 2 bytes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
FYI, the manual has the following to say about putting a branch/jump into the branch delay slot: "If a branch or jump instruction is placed in the branch delay slot, the operation of both instructions is undefined." So I guess what happens depends on the impl of the CPU u are running on. To me, it seems like trapping on that is reasonable, but given that behavior is undefined, it would also be OK to throw this part out completely and just let the emulator decide. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what mainly worries me here is the fact that there are two compile time ways to have this esil expression. so i would prefer to have only one and not depend on compile time options There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, so completely throw away the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well. if the code is trapping, the linear emulation code should be ignoring those stop points.. did you had a look at the failing tests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i mean in theory the change looks good to me, but will need some refinements and checks to see if the behaviour keeps correct for the current usecases. thanks for taking the time! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the delay - was on vacation. Then I'll now work on a version with only one compile time version of the ESIL. Once that one is ready, I'll certainly need some help since I have no idea where those changes might break something (besides the tests of course) in the larger There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Count on me for that help, don't hesitate to make questions or join discord/telegram/matrix channel for a more fluent chat. Thanks! |
||
#endif | ||
break; | ||
case MIPS_INS_BAL: | ||
case MIPS_INS_JAL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_D ("%s"), ARG (0)); | ||
|
@@ -348,48 +361,94 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn | |
break; | ||
case MIPS_INS_JRADDIUSP: | ||
// increment stackpointer in X and jump to %ra | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,sp,+=," ES_J ("ra"), ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,sp,+=," ES_J_D ("ra"), ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_JR: | ||
case MIPS_INS_JRC: | ||
case MIPS_INS_BC: | ||
// JRC rt | ||
// Jump Register, Compact. Unconditional jump to address in register $rt. | ||
// BC address | ||
// Branch, Compact. Unconditional PC relative branch to address. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_J_ND ("%s"), ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_JR: | ||
case MIPS_INS_J: | ||
case MIPS_INS_B: // ??? | ||
// jump to address with conditional | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_J ("%s"), ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_J_D ("%s"), ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BNEC: | ||
// BNEC rs, rt, address | ||
// Branch Not Equal, Compact. PC relative branch to address if register $rs is not equal to | ||
// register $rt. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,!,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1), ARG (2)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BNE: // bne $s, $t, offset | ||
case MIPS_INS_BNEL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,!,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,!,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1), ARG (2)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BEQC: | ||
// BEQC rs, rt, address | ||
// Branch if Equal, Compact. PC relative branch to address if registers $rs and $rt are are equal. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1), ARG (2)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BEQ: | ||
case MIPS_INS_BEQL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1), ARG (2)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BEQZC: | ||
// BEQZC rt, address # when rt and address are in range | ||
// Branch if Equal to Zero, Compact. PC relative branch to address if register $rt equals zero. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BZ: | ||
case MIPS_INS_BEQZ: | ||
case MIPS_INS_BEQZC: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BNEZC: | ||
// BNEZC rt, address | ||
// Branch if Not Equal to Zero, Compact. PC relative branch to address if register $rt is not equal to zero. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,!,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BNEZ: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,!,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,!,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
|
@@ -402,21 +461,45 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn | |
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BLEZ: | ||
case MIPS_INS_BLEZC: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{," ES_J_ND ("%s") ",BREAK,},", | ||
ARG (0), ARG (1)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BLEZ: | ||
case MIPS_INS_BLEZL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{," ES_J ("%s") ",BREAK,},", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{," ES_J_D ("%s") ",BREAK,},", | ||
ARG (0), ARG (1)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BGEZ: | ||
case MIPS_INS_BGEC: | ||
// BGEC rs, rt, address | ||
// Branch if Greater than or Equal, Compact. PC relative branch to address if register $rs | ||
// is greater than or equal to register $rt. | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,>=,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (1), ARG (0), ARG (2)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BGEZC: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BGEZ: | ||
case MIPS_INS_BGEZL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
|
@@ -450,33 +533,46 @@ static int analop_esil(RArchSession *as, RAnalOp *op, csh *handle, cs_insn *insn | |
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BLTZ: | ||
case MIPS_INS_BLTZC: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BLTZ: | ||
case MIPS_INS_BLTZL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BGTZ: | ||
case MIPS_INS_BGTZC: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{,BREAK,},", ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_ND ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BGTZ: | ||
case MIPS_INS_BGTZL: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{,BREAK,},", ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}", | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J_D ("%s") ",}", | ||
ARG (0), ARG (1)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BTEQZ: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,?{," ES_J ("%s") ",}", ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,?{," ES_J_D ("%s") ",}", ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
break; | ||
case MIPS_INS_BTNEZ: | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,!,?{," ES_J ("%s") ",}", ARG (0)); | ||
r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,!,?{," ES_J_D ("%s") ",}", ARG (0)); | ||
#if USE_DS | ||
r_strbuf_replacef (&op->esil, "$$", "0x%"PFMT64x, addr); | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use ut64 in r2land, its an alias to
uint64_t
but just good for consistency sugarThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I also hate writing out
u_int64_t
^^