plasma-disassembler / plasma

Plasma is an interactive disassembler for x86/ARM/MIPS. It can generates indented pseudo-code with colored syntax.
GNU General Public License v3.0
3.05k stars 275 forks source link

MIPS add Pseudo-C for slt* instructions #82

Closed GH0st3rs closed 6 years ago

GH0st3rs commented 6 years ago
diff --git a/plasma/lib/arch/mips/output.py b/plasma/lib/arch/mips/output.py
index 22b204b..67fa1fa 100644
--- a/plasma/lib/arch/mips/output.py
+++ b/plasma/lib/arch/mips/output.py
@@ -31,7 +31,7 @@ from capstone.mips import (MIPS_OP_IMM, MIPS_OP_MEM, MIPS_OP_REG,
 from plasma.lib.output import OutputAbs
 from plasma.lib.arch.mips.utils import (inst_symbol, is_call, is_jump, is_ret,
     is_uncond_jump, cond_symbol)
-
+from capstone.mips import (MIPS_INS_SLT, MIPS_INS_SLTI, MIPS_INS_SLTIU, MIPS_INS_SLTU)

 # ASSIGNMENT_OPS = {ARM_INS_EOR, ARM_INS_AND, ARM_INS_ORR}
 ASSIGNMENT_OPS = {}
@@ -67,7 +67,7 @@ INST_CHECK = {MIPS_INS_AND, MIPS_INS_SLL, MIPS_INS_SRA, MIPS_INS_SRL,
 ADD_CHECK = {MIPS_INS_ADD, MIPS_INS_ADDU, MIPS_INS_ADDIU}

 SUB_CHECK = {MIPS_INS_SUB, MIPS_INS_SUBU}
-
+SLT_CHECK = {MIPS_INS_SLT, MIPS_INS_SLTI, MIPS_INS_SLTIU, MIPS_INS_SLTU}

 class Output(OutputAbs):
     def _operand(self, i, num_op, hexa=False, show_deref=True,
@@ -176,6 +176,15 @@ class Output(OutputAbs):
                 self._operand(i, 0)
                 return

+            if i.id in SLT_CHECK:
+                self._operand(i, 0)
+                self._add(" = 1 if ")
+                self._operand(i, 1)
+                self._add(" < ")
+                self._operand(i, 2)
+                self._add(" else 0")
+                return
+
             if i.id == MIPS_INS_NEG:
                 self._operand(i, 0)
                 self._add(" = -")

Result:

    0x80000118: $v0 = 1 if $v0 < 33 else 0
    # 0x8000011c: bnez $v0, 0x80000168
    0x80000120: $v0 = 48
    if == 0 {

But ideally, it's better to do so:

    # 0x80000118: $v0 = 1 if $v0 < 33 else 0
    # 0x8000011c: bnez $v0, 0x80000168
    0x80000120: $v0 = 48
    if not ($v0 < 33) {

or

    # 0x80000118: $v0 = 1 if $v0 < 33 else 0
    # 0x8000011c: bnez $v0, 0x80000168
    0x80000120: $v0 = 48
    if $v0 >= 33 {
plasma-disassembler commented 6 years ago

Thank you for your comment.

Yes that could be a temporary solution, but the second proposal is a bit more complicated ;). There is a special process to manage conditional instructions: it tries to fuse with a previous instruction. But it's actually done only for x86[_64] and a bit for ARM.

The process function should be implemented in lib/arch/*/process_ast.py. You can take a look on x86 there is a function fuse_inst_with_if which is called just after the ast generation (lib/generate_ast.py). During the output the lib.ast.Ast_Ifelse call the appropriate function _if_cond in lib/arch*/output.py.

Moreover, it's not a good idea to write directly self._add(" < ") because you can't know in advance which branch will be taken for the if and the else. You have to use the function cond_symbol defined in lib/arch/*/utils.py and called by _if_cond. And recently I've added a patch which allows the user to invert the condition in the visual mode (the condition symbol is then automatically inverted).

The simplification of certain instructions in the function _sub_asm_inst is only for non-conditional instructions.

If I've time I will try to do it.

GH0st3rs commented 6 years ago

Yes, you are right. But my solution - just wrapper for SLT* instructions.

I will send you PULL-request with fix _if_cond and other functions for mips

plasma-disassembler commented 6 years ago

dc2f552