Skip to content

Commit

Permalink
capstone2llvmir/mips: add semantics for more instructions, #393.
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterMatula committed Jan 3, 2019
1 parent d51c39a commit bfd6efb
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* New Feature: Added presentation of imported types and TypeRef hashes for .NET binaries ([#363](https://github.com/avast-tl/retdec/issues/363), [#364](https://github.com/avast-tl/retdec/issues/364), [#428](https://github.com/avast-tl/retdec/issues/428)).
* New Feature: Added computation and presentation of icon hashes for exact and also similarity matching in PE files ([#339](https://github.com/avast-tl/retdec/issues/339)).
* Enhancement: Added semantics for more MIPS instructions.
* Enhancement: Capstone2LlvmIr library refactoring ([#115](https://github.com/avast-tl/retdec/issues/115)).
* Enhancement: Removed the build and runtime dependency on ncurses/libtinfo ([#409](https://github.com/avast-tl/retdec/pull/409)).
* Enhancement: Add a check into our scripts that they are run from an installation directory and not from the `scripts` directory ([#418](https://github.com/avast-tl/retdec/issues/418)).
Expand Down
68 changes: 65 additions & 3 deletions src/capstone2llvmir/mips/mips.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,11 @@ bool Capstone2LlvmIrTranslatorMips_impl::isOperandRegister(cs_mips_op& op)
return op.type == MIPS_OP_REG;
}

bool Capstone2LlvmIrTranslatorMips_impl::isGeneralPurposeRegister(uint32_t r)
{
return MIPS_REG_0 <= r && r <= MIPS_REG_31;
}

//
//==============================================================================
// MIPS instruction translation methods.
Expand Down Expand Up @@ -1214,6 +1219,25 @@ void Capstone2LlvmIrTranslatorMips_impl::translateMaddf(cs_insn* i, cs_mips* mi,
storeOp(mi->operands[0], add, irb);
}

/**
* MIPS_INS_NEG
*/
void Capstone2LlvmIrTranslatorMips_impl::translateNeg(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
if (mi->op_count == 2
&& isOperandRegister(mi->operands[0])
&& isGeneralPurposeRegister(mi->operands[0].reg)
&& isOperandRegister(mi->operands[1])
&& isGeneralPurposeRegister(mi->operands[1].reg))
{
translateNegu(i, mi, irb);
}
else
{
translatePseudoAsmOp0FncOp1(i, mi, irb);
}
}

/**
* MIPS_INS_NEGU
*/
Expand Down Expand Up @@ -1580,6 +1604,18 @@ void Capstone2LlvmIrTranslatorMips_impl::translateNor(cs_insn* i, cs_mips* mi, l
storeOp(mi->operands[0], x, irb);
}

/**
* MIPS_INS_NOT
*/
void Capstone2LlvmIrTranslatorMips_impl::translateNot(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
EXPECT_IS_BINARY(i, mi, irb);

op1 = loadOpBinaryOp1(mi, irb);
op1 = irb.CreateNot(op1);
storeOp(mi->operands[0], op1, irb);
}

/**
* MIPS_INS_OR, MIPS_INS_ORI
*/
Expand Down Expand Up @@ -1641,7 +1677,7 @@ void Capstone2LlvmIrTranslatorMips_impl::translateSeh(cs_insn* i, cs_mips* mi, l
}

/**
* MIPS_INS_SLL, MIPS_INS_SLLV
* MIPS_INS_SLL, MIPS_INS_SLLI, MIPS_INS_SLLV
*/
void Capstone2LlvmIrTranslatorMips_impl::translateSll(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
Expand Down Expand Up @@ -1679,7 +1715,7 @@ void Capstone2LlvmIrTranslatorMips_impl::translateSltu(cs_insn* i, cs_mips* mi,
}

/**
* MIPS_INS_SRA, MIPS_INS_SRAV
* MIPS_INS_SRA, MIPS_INS_SRAI, MIPS_INS_SRAV
*/
void Capstone2LlvmIrTranslatorMips_impl::translateSra(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
Expand All @@ -1691,7 +1727,7 @@ void Capstone2LlvmIrTranslatorMips_impl::translateSra(cs_insn* i, cs_mips* mi, l
}

/**
* MIPS_INS_SRL, MIPS_INS_SRLV
* MIPS_INS_SRL, MIPS_INS_SRLI, MIPS_INS_SRLV
*/
void Capstone2LlvmIrTranslatorMips_impl::translateSrl(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
Expand Down Expand Up @@ -1754,5 +1790,31 @@ void Capstone2LlvmIrTranslatorMips_impl::translateXor(cs_insn* i, cs_mips* mi, l
storeOp(mi->operands[0], x, irb);
}

/**
* MIPS_INS_SNE, MIPS_INS_SNEI
* op0 = (op1 != op2) ? 1 : 0
*/
void Capstone2LlvmIrTranslatorMips_impl::translateSne(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
EXPECT_IS_BINARY_OR_TERNARY(i, mi, irb);

std::tie(op1, op2) = loadOpBinaryOrTernaryOp1Op2(mi, irb, eOpConv::SEXT_TRUNC);
auto* ne = irb.CreateICmpNE(op1, op2);
storeOp(mi->operands[0], ne, irb, eOpConv::ZEXT_TRUNC);
}

/**
* MIPS_INS_SEQ, MIPS_INS_SEQI
* op0 = (op1 != op2) ? 1 : 0
*/
void Capstone2LlvmIrTranslatorMips_impl::translateSeq(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb)
{
EXPECT_IS_BINARY_OR_TERNARY(i, mi, irb);

std::tie(op1, op2) = loadOpBinaryOrTernaryOp1Op2(mi, irb, eOpConv::SEXT_TRUNC);
auto* ne = irb.CreateICmpEQ(op1, op2);
storeOp(mi->operands[0], ne, irb, eOpConv::ZEXT_TRUNC);
}

} // namespace capstone2llvmir
} // namespace retdec
5 changes: 5 additions & 0 deletions src/capstone2llvmir/mips/mips_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class Capstone2LlvmIrTranslatorMips_impl :
bool isFpInstructionVariant(cs_insn* i);

virtual bool isOperandRegister(cs_mips_op& op) override;
bool isGeneralPurposeRegister(uint32_t r);
//
//==============================================================================
// MIPS implementation data.
Expand Down Expand Up @@ -156,18 +157,22 @@ class Capstone2LlvmIrTranslatorMips_impl :
void translateMovz(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateMul(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateMult(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNeg(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNegu(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNmadd(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNmsub(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNop(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNor(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateNot(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateOr(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateRotr(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSeb(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSeh(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSeq(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSll(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSlt(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSltu(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSne(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSra(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateSrl(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
void translateStoreMemory(cs_insn* i, cs_mips* mi, llvm::IRBuilder<>& irb);
Expand Down
26 changes: 13 additions & 13 deletions src/capstone2llvmir/mips/mips_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ Capstone2LlvmIrTranslatorMips_impl::_i2fm =
{MIPS_INS_FMSUB, nullptr},
{MIPS_INS_FMUL, nullptr},
{MIPS_INS_MUL, &Capstone2LlvmIrTranslatorMips_impl::translateMul},
{MIPS_INS_NEG, &Capstone2LlvmIrTranslatorMips_impl::translatePseudoAsmOp0FncOp1},
{MIPS_INS_NEG, &Capstone2LlvmIrTranslatorMips_impl::translateNeg},
{MIPS_INS_FRCP, nullptr},
{MIPS_INS_FRINT, nullptr},
{MIPS_INS_FRSQRT, nullptr},
Expand Down Expand Up @@ -685,9 +685,9 @@ Capstone2LlvmIrTranslatorMips_impl::_i2fm =
{MIPS_INS_LDC2, nullptr},
{MIPS_INS_LDC3, &Capstone2LlvmIrTranslatorMips_impl::translateLoadMemory},
{MIPS_INS_LDI, nullptr},
{MIPS_INS_LDL, nullptr},
{MIPS_INS_LDL, &Capstone2LlvmIrTranslatorMips_impl::translatePseudoAsmOp0FncOp1},
{MIPS_INS_LDPC, nullptr},
{MIPS_INS_LDR, nullptr},
{MIPS_INS_LDR, &Capstone2LlvmIrTranslatorMips_impl::translatePseudoAsmOp0FncOp1},
{MIPS_INS_LDXC1, nullptr},
{MIPS_INS_LH, &Capstone2LlvmIrTranslatorMips_impl::translateLoadMemory},
{MIPS_INS_LHU16, nullptr},
Expand Down Expand Up @@ -796,7 +796,7 @@ Capstone2LlvmIrTranslatorMips_impl::_i2fm =
{MIPS_INS_NOR, &Capstone2LlvmIrTranslatorMips_impl::translateNor},
{MIPS_INS_NORI, &Capstone2LlvmIrTranslatorMips_impl::translateNor},
{MIPS_INS_NOT16, nullptr},
{MIPS_INS_NOT, nullptr},
{MIPS_INS_NOT, &Capstone2LlvmIrTranslatorMips_impl::translateNot},
{MIPS_INS_OR, &Capstone2LlvmIrTranslatorMips_impl::translateOr},
{MIPS_INS_OR16, nullptr},
{MIPS_INS_ORI, &Capstone2LlvmIrTranslatorMips_impl::translateOr},
Expand Down Expand Up @@ -839,16 +839,16 @@ Capstone2LlvmIrTranslatorMips_impl::_i2fm =
{MIPS_INS_SDC1, &Capstone2LlvmIrTranslatorMips_impl::translateStoreMemory},
{MIPS_INS_SDC2, nullptr},
{MIPS_INS_SDC3, &Capstone2LlvmIrTranslatorMips_impl::translateStoreMemory},
{MIPS_INS_SDL, nullptr},
{MIPS_INS_SDR, nullptr},
{MIPS_INS_SDL, &Capstone2LlvmIrTranslatorMips_impl::translatePseudoAsmFncOp0Op1},
{MIPS_INS_SDR, &Capstone2LlvmIrTranslatorMips_impl::translatePseudoAsmFncOp0Op1},
{MIPS_INS_SDXC1, nullptr},
{MIPS_INS_SEB, &Capstone2LlvmIrTranslatorMips_impl::translateSeb},
{MIPS_INS_SEH, &Capstone2LlvmIrTranslatorMips_impl::translateSeh},
{MIPS_INS_SELEQZ, nullptr},
{MIPS_INS_SELNEZ, nullptr},
{MIPS_INS_SEL, nullptr},
{MIPS_INS_SEQ, nullptr},
{MIPS_INS_SEQI, nullptr},
{MIPS_INS_SEQ, &Capstone2LlvmIrTranslatorMips_impl::translateSeq},
{MIPS_INS_SEQI, &Capstone2LlvmIrTranslatorMips_impl::translateSeq},
{MIPS_INS_SH, &Capstone2LlvmIrTranslatorMips_impl::translateStoreMemory},
{MIPS_INS_SH16, nullptr},
{MIPS_INS_SHF, nullptr},
Expand All @@ -868,24 +868,24 @@ Capstone2LlvmIrTranslatorMips_impl::_i2fm =
{MIPS_INS_SLD, nullptr},
{MIPS_INS_SLL, &Capstone2LlvmIrTranslatorMips_impl::translateSll},
{MIPS_INS_SLL16, nullptr},
{MIPS_INS_SLLI, nullptr},
{MIPS_INS_SLLI, &Capstone2LlvmIrTranslatorMips_impl::translateSll},
{MIPS_INS_SLLV, &Capstone2LlvmIrTranslatorMips_impl::translateSll},
{MIPS_INS_SLT, &Capstone2LlvmIrTranslatorMips_impl::translateSlt},
{MIPS_INS_SLTI, &Capstone2LlvmIrTranslatorMips_impl::translateSlt},
{MIPS_INS_SLTIU, &Capstone2LlvmIrTranslatorMips_impl::translateSltu},
{MIPS_INS_SLTU, &Capstone2LlvmIrTranslatorMips_impl::translateSltu},
{MIPS_INS_SNE, nullptr},
{MIPS_INS_SNEI, nullptr},
{MIPS_INS_SNE, &Capstone2LlvmIrTranslatorMips_impl::translateSne},
{MIPS_INS_SNEI, &Capstone2LlvmIrTranslatorMips_impl::translateSne},
{MIPS_INS_SPLATI, nullptr},
{MIPS_INS_SPLAT, nullptr},
{MIPS_INS_SRA, &Capstone2LlvmIrTranslatorMips_impl::translateSra},
{MIPS_INS_SRAI, nullptr},
{MIPS_INS_SRAI, &Capstone2LlvmIrTranslatorMips_impl::translateSra},
{MIPS_INS_SRARI, nullptr},
{MIPS_INS_SRAR, nullptr},
{MIPS_INS_SRAV, &Capstone2LlvmIrTranslatorMips_impl::translateSra},
{MIPS_INS_SRL, &Capstone2LlvmIrTranslatorMips_impl::translateSrl},
{MIPS_INS_SRL16, nullptr},
{MIPS_INS_SRLI, nullptr},
{MIPS_INS_SRLI, &Capstone2LlvmIrTranslatorMips_impl::translateSrl},
{MIPS_INS_SRLRI, nullptr},
{MIPS_INS_SRLR, nullptr},
{MIPS_INS_SRLV, &Capstone2LlvmIrTranslatorMips_impl::translateSrl},
Expand Down
100 changes: 78 additions & 22 deletions tests/capstone2llvmir/mips_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,29 @@ TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NOR_3_op)
EXPECT_NO_VALUE_CALLED();
}

//
// MIPS_INS_NOT
//

TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NOT)
{
SKIP_MODE_64;

setRegisters({
{MIPS_REG_1, 0x12345678},
{MIPS_REG_2, 0xff00ff00},
});

emulate("not $1, $2");

EXPECT_JUST_REGISTERS_LOADED({MIPS_REG_2});
EXPECT_JUST_REGISTERS_STORED({
{MIPS_REG_1, 0x00ff00ff},
});
EXPECT_NO_MEMORY_LOADED_STORED();
EXPECT_NO_VALUE_CALLED();
}

//
// MIPS_INS_MUL
//
Expand Down Expand Up @@ -1513,6 +1536,21 @@ TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_CLZ_ones)
// TODO: Keystone -- instruction requires a CPU feature not currently enabled.
//

//
// MIPS_INS_SNE, MIPS_INS_SNEI
// TODO: Keystone -- instruction requires a CPU feature not currently enabled.
//

//
// MIPS_INS_SNE, MIPS_INS_SNEI
// TODO: Keystone -- instruction requires a CPU feature not currently enabled.
//

//
// MIPS_INS_SEQ, MIPS_INS_SEQI
// TODO: Keystone -- instruction requires a CPU feature not currently enabled.
//

//
// MIPS_INS_EXT
// TODO: Keystone -- instruction requires a CPU feature not currently enabled.
Expand Down Expand Up @@ -4341,10 +4379,50 @@ TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_ABS_d_64)
});
}

//
// MIPS_INS_NEGU
//

TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NEGU)
{
SKIP_MODE_64;

setRegisters({
{MIPS_REG_1, 0x00ffffff},
});

emulate("negu $1, $1");

EXPECT_JUST_REGISTERS_LOADED({MIPS_REG_1});
EXPECT_JUST_REGISTERS_STORED({
{MIPS_REG_1, 0xff000001},
});
EXPECT_NO_MEMORY_LOADED_STORED();
EXPECT_NO_VALUE_CALLED();
}

//
// MIPS_INS_NEG
//

TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NEG_int)
{
SKIP_MODE_64;

setRegisters({
{MIPS_REG_1, 0x00ffffff},
});

emulate("neg $1, $1");

EXPECT_JUST_REGISTERS_LOADED({MIPS_REG_1});
EXPECT_JUST_REGISTERS_STORED({
{MIPS_REG_1, 0xff000001},
});
EXPECT_NO_MEMORY_LOADED_STORED();
EXPECT_NO_VALUE_CALLED();
}

TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NEG_s_32)
{
SKIP_MODE_64;
Expand Down Expand Up @@ -6010,28 +6088,6 @@ TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_C_ule_d_32)
EXPECT_NO_VALUE_CALLED();
}

//
// MIPS_INS_NEGU
//

TEST_P(Capstone2LlvmIrTranslatorMipsTests, MIPS_INS_NEGU)
{
SKIP_MODE_64;

setRegisters({
{MIPS_REG_1, 0x00ffffff},
});

emulate("negu $1, $1");

EXPECT_JUST_REGISTERS_LOADED({MIPS_REG_1});
EXPECT_JUST_REGISTERS_STORED({
{MIPS_REG_1, 0xff000001},
});
EXPECT_NO_MEMORY_LOADED_STORED();
EXPECT_NO_VALUE_CALLED();
}

} // namespace tests
} // namespace capstone2llvmir
} // namespace retdec

0 comments on commit bfd6efb

Please sign in to comment.