diff options
| author | Mark Rowe <mark@vector35.com> | 2026-06-03 21:25:55 -0700 |
|---|---|---|
| committer | Mark Rowe <mark@vector35.com> | 2026-06-04 14:31:09 -0700 |
| commit | d592ed6dafbb134553bf3a0b8ee70ff7f2049aba (patch) | |
| tree | 1bfe7e335e5b4e21371cde4bf8858c6439bc3f18 | |
| parent | 9987102015875991813200116558306851763009 (diff) | |
Add bswap, popcnt, clz, ctz, cls, and rbit instructions
| -rw-r--r-- | binaryninjaapi.h | 75 | ||||
| -rw-r--r-- | binaryninjacore.h | 30 | ||||
| -rw-r--r-- | docs/dev/bnil-hlil.md | 6 | ||||
| -rw-r--r-- | docs/dev/bnil-llil.md | 6 | ||||
| -rw-r--r-- | docs/dev/bnil-mlil.md | 6 | ||||
| -rw-r--r-- | highlevelilinstruction.cpp | 60 | ||||
| -rw-r--r-- | highlevelilinstruction.h | 18 | ||||
| -rw-r--r-- | lang/c/pseudoc.cpp | 79 | ||||
| -rw-r--r-- | lang/rust/pseudorust.cpp | 27 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 54 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 18 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 54 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 18 | ||||
| -rw-r--r-- | python/highlevelil.py | 44 | ||||
| -rw-r--r-- | python/lowlevelil.py | 44 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 44 | ||||
| -rw-r--r-- | rust/src/high_level_il/instruction.rs | 30 | ||||
| -rw-r--r-- | rust/src/high_level_il/lift.rs | 13 | ||||
| -rw-r--r-- | rust/src/low_level_il/expression.rs | 24 | ||||
| -rw-r--r-- | rust/src/low_level_il/lifting.rs | 30 | ||||
| -rw-r--r-- | rust/src/medium_level_il/instruction.rs | 30 | ||||
| -rw-r--r-- | rust/src/medium_level_il/lift.rs | 15 |
22 files changed, 714 insertions, 11 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index c42a25ba..82da9ea6 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -15006,6 +15006,69 @@ namespace BinaryNinja { */ ExprId Not(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + /*! Reverse the byte order of expression \c value of size \c size potentially setting flags + + \param size The size of the result in bytes + \param a The expression to byte swap + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>bswap.<size>{<flags>}(value)</tt> + */ + ExprId ByteSwap(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + + /*! Count the number of set bits in expression \c value of size \c size potentially setting flags + + \param size The size of the result in bytes + \param a The expression to count set bits in + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>popcnt.<size>{<flags>}(value)</tt> + */ + ExprId PopulationCount(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + + /*! Count the number of leading zero bits in expression \c value of size \c size potentially setting flags. + The result is <tt>8 * size</tt> when \c value is zero. + + \param size The size of the result in bytes + \param a The expression to count leading zeros in + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>clz.<size>{<flags>}(value)</tt> + */ + ExprId CountLeadingZeros(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + + /*! Count the number of trailing zero bits in expression \c value of size \c size potentially setting flags. + The result is <tt>8 * size</tt> when \c value is zero. + + \param size The size of the result in bytes + \param a The expression to count trailing zeros in + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>ctz.<size>{<flags>}(value)</tt> + */ + ExprId CountTrailingZeros(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + + /*! Reverse the bit order of expression \c value of size \c size potentially setting flags + + \param size The size of the result in bytes + \param a The expression to bit reverse + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>rbit.<size>{<flags>}(value)</tt> + */ + ExprId ReverseBits(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + + /*! Count the number of leading bits that match the sign bit in expression \c value of size \c size, + not counting the sign bit itself, potentially setting flags + + \param size The size of the result in bytes + \param a The expression to count leading sign bits in + \param flags Flags to set + \param loc Optional IL Location this expression was added from. + \return The expression <tt>cls.<size>{<flags>}(value)</tt> + */ + ExprId CountLeadingSigns(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); + /*! Two's complement sign-extends the expression in \c value to \c size bytes \param size The size of the result in bytes @@ -15886,6 +15949,12 @@ namespace BinaryNinja { size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ByteSwap(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId PopulationCount(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountLeadingZeros(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountTrailingZeros(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ReverseBits(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountLeadingSigns(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId SignExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); @@ -16287,6 +16356,12 @@ namespace BinaryNinja { size_t size, ExprId left, ExprId right, const ILSourceLocation& loc = ILSourceLocation()); ExprId Neg(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId Not(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ByteSwap(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId PopulationCount(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountLeadingZeros(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountTrailingZeros(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ReverseBits(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); + ExprId CountLeadingSigns(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId SignExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index d09690e5..428d7f82 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -762,7 +762,15 @@ extern "C" LLIL_REG_PHI, LLIL_REG_STACK_PHI, LLIL_FLAG_PHI, - LLIL_MEM_PHI + LLIL_MEM_PHI, + + // Bit manipulation + LLIL_BSWAP, // Reverse byte order of the whole value + LLIL_POPCNT, // Population count (number of set bits) + LLIL_CLZ, // Count leading zero bits; clz(0) == 8 * size + LLIL_CTZ, // Count trailing zero bits; ctz(0) == 8 * size + LLIL_RBIT, // Reverse bit order of the whole value + LLIL_CLS // Count leading sign bits; number of bits below the sign bit that match it }; BN_ENUM(uint8_t, BNLowLevelILFlagCondition) @@ -1540,7 +1548,15 @@ extern "C" MLIL_VAR_PHI, MLIL_MEM_PHI, - MLIL_BLOCK_TO_EXPAND // Must be expanded by a future workflow step, used temporarily to insert instructions + MLIL_BLOCK_TO_EXPAND, // Must be expanded by a future workflow step, used temporarily to insert instructions + + // Bit manipulation + MLIL_BSWAP, // Reverse byte order of the whole value + MLIL_POPCNT, // Population count (number of set bits) + MLIL_CLZ, // Count leading zero bits; clz(0) == 8 * size + MLIL_CTZ, // Count trailing zero bits; ctz(0) == 8 * size + MLIL_RBIT, // Reverse bit order of the whole value + MLIL_CLS // Count leading sign bits; number of bits below the sign bit that match it }; typedef struct BNMediumLevelILInstruction @@ -1714,7 +1730,15 @@ extern "C" HLIL_SYSCALL_SSA, HLIL_INTRINSIC_SSA, HLIL_VAR_PHI, - HLIL_MEM_PHI + HLIL_MEM_PHI, + + // Bit manipulation + HLIL_BSWAP, // Reverse byte order of the whole value + HLIL_POPCNT, // Population count (number of set bits) + HLIL_CLZ, // Count leading zero bits; clz(0) == 8 * size + HLIL_CTZ, // Count trailing zero bits; ctz(0) == 8 * size + HLIL_RBIT, // Reverse bit order of the whole value + HLIL_CLS // Count leading sign bits; number of bits below the sign bit that match it }; typedef struct BNHighLevelILInstruction diff --git a/docs/dev/bnil-hlil.md b/docs/dev/bnil-hlil.md index 03447eab..1b2754e1 100644 --- a/docs/dev/bnil-hlil.md +++ b/docs/dev/bnil-hlil.md @@ -111,6 +111,12 @@ There are a number of properties that can be queried on the [`HighLevelILInstruc * `HLIL_MODS_DP` - Signed double-precision modulus of `left` expression by the `right` expression * `HLIL_NEG` - Sign inversion of `src` expression * `HLIL_NOT` - Bitwise inversion of `src` expression +* `HLIL_BSWAP` - Reverse the byte order of `src` expression +* `HLIL_POPCNT` - Population count (number of set bits) of `src` expression +* `HLIL_CLZ` - Count leading zero bits of `src` expression; the result is `8 * size` when `src` is zero +* `HLIL_CTZ` - Count trailing zero bits of `src` expression; the result is `8 * size` when `src` is zero +* `HLIL_RBIT` - Reverse the bit order of `src` expression +* `HLIL_CLS` - Count leading sign bits of `src` expression (the number of bits below the sign bit that match it) * `HLIL_FADD` - IEEE754 floating point addition of `left` expression with `right` expression * `HLIL_FSUB` - IEEE754 floating point subtraction of `left` expression with `right` expression * `HLIL_FMUL` - IEEE754 floating point multiplication of `left` expression with `right` expression diff --git a/docs/dev/bnil-llil.md b/docs/dev/bnil-llil.md index 5509151e..b3a4f906 100644 --- a/docs/dev/bnil-llil.md +++ b/docs/dev/bnil-llil.md @@ -257,6 +257,12 @@ The double precision instruction multiply, divide, modulus instructions are part * `LLIL_MODS_DP` - Signed modulus double precision * `LLIL_NEG` - Sign negation * `LLIL_NOT` - Bitwise complement +* `LLIL_BSWAP` - Reverse the byte order of `src` +* `LLIL_POPCNT` - Population count (number of set bits) of `src` +* `LLIL_CLZ` - Count leading zero bits of `src`; the result is `8 * size` when `src` is zero +* `LLIL_CTZ` - Count trailing zero bits of `src`; the result is `8 * size` when `src` is zero +* `LLIL_RBIT` - Reverse the bit order of `src` +* `LLIL_CLS` - Count leading sign bits of `src` (the number of bits below the sign bit that match it) * `LLIL_TEST_BIT ` - Test if bit `right` in expression `left` is set * `LLIL_BOOL_TO_INT ` - Converts a bool `src` to an integer diff --git a/docs/dev/bnil-mlil.md b/docs/dev/bnil-mlil.md index 51028131..8e796ec8 100644 --- a/docs/dev/bnil-mlil.md +++ b/docs/dev/bnil-mlil.md @@ -348,6 +348,12 @@ The parameter list can be accessed through the `params` property: * `MLIL_MODS_DP` - Signed double-precision modulus of `left` expression by the `right` expression * `MLIL_NEG` - Sign inversion of `src` expression * `MLIL_NOT` - Bitwise inversion of `src` expression +* `MLIL_BSWAP` - Reverse the byte order of `src` expression +* `MLIL_POPCNT` - Population count (number of set bits) of `src` expression +* `MLIL_CLZ` - Count leading zero bits of `src` expression; the result is `8 * size` when `src` is zero +* `MLIL_CTZ` - Count trailing zero bits of `src` expression; the result is `8 * size` when `src` is zero +* `MLIL_RBIT` - Reverse the bit order of `src` expression +* `MLIL_CLS` - Count leading sign bits of `src` expression (the number of bits below the sign bit that match it) * `MLIL_FADD` - IEEE754 floating point addition of `left` expression with `right` expression * `MLIL_FSUB` - IEEE754 floating point subtraction of `left` expression with `right` expression * `MLIL_FMUL` - IEEE754 floating point multiplication of `left` expression with `right` expression diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp index 0ce32c27..92312549 100644 --- a/highlevelilinstruction.cpp +++ b/highlevelilinstruction.cpp @@ -260,6 +260,12 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{HLIL_INTRINSIC_SSA, {IntrinsicHighLevelOperandUsage, ParameterExprsHighLevelOperandUsage, DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}}, OperandUsage{HLIL_VAR_PHI, {DestSSAVariableHighLevelOperandUsage, SourceSSAVariablesHighLevelOperandUsage}}, OperandUsage{HLIL_MEM_PHI, {DestMemoryVersionHighLevelOperandUsage, SourceMemoryVersionsHighLevelOperandUsage}}, + OperandUsage{HLIL_BSWAP, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_POPCNT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CLZ, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CTZ, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_RBIT, {SourceExprHighLevelOperandUsage}}, + OperandUsage{HLIL_CLS, {SourceExprHighLevelOperandUsage}}, }; @@ -1261,6 +1267,12 @@ void HighLevelILInstruction::CollectSubExprs(stack<size_t>& toProcess) const case HLIL_ADDRESS_OF: case HLIL_NEG: case HLIL_NOT: + case HLIL_BSWAP: + case HLIL_POPCNT: + case HLIL_CLZ: + case HLIL_CTZ: + case HLIL_RBIT: + case HLIL_CLS: case HLIL_SX: case HLIL_ZX: case HLIL_LOW_PART: @@ -1569,6 +1581,12 @@ ExprId HighLevelILInstruction::CopyTo( return dest->Unreachable(loc); case HLIL_NEG: case HLIL_NOT: + case HLIL_BSWAP: + case HLIL_POPCNT: + case HLIL_CLZ: + case HLIL_CTZ: + case HLIL_RBIT: + case HLIL_CLS: case HLIL_SX: case HLIL_ZX: case HLIL_LOW_PART: @@ -2130,6 +2148,12 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons case HLIL_DEREF: case HLIL_NEG: case HLIL_NOT: + case HLIL_BSWAP: + case HLIL_POPCNT: + case HLIL_CLZ: + case HLIL_CTZ: + case HLIL_RBIT: + case HLIL_CLS: case HLIL_SX: case HLIL_ZX: case HLIL_LOW_PART: @@ -3097,6 +3121,42 @@ ExprId HighLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocation& } +ExprId HighLevelILFunction::ByteSwap(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_BSWAP, loc, size, src); +} + + +ExprId HighLevelILFunction::PopulationCount(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_POPCNT, loc, size, src); +} + + +ExprId HighLevelILFunction::CountLeadingZeros(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CLZ, loc, size, src); +} + + +ExprId HighLevelILFunction::CountTrailingZeros(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CTZ, loc, size, src); +} + + +ExprId HighLevelILFunction::ReverseBits(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_RBIT, loc, size, src); +} + + +ExprId HighLevelILFunction::CountLeadingSigns(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(HLIL_CLS, loc, size, src); +} + + ExprId HighLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) { return AddExprWithLocation(HLIL_SX, loc, size, src); diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h index 7ec5d18c..4272d2e2 100644 --- a/highlevelilinstruction.h +++ b/highlevelilinstruction.h @@ -1454,6 +1454,24 @@ namespace BinaryNinja struct HighLevelILInstructionAccessor<HLIL_NOT> : public HighLevelILOneOperandInstruction {}; template <> + struct HighLevelILInstructionAccessor<HLIL_BSWAP> : public HighLevelILOneOperandInstruction + {}; + template <> + struct HighLevelILInstructionAccessor<HLIL_POPCNT> : public HighLevelILOneOperandInstruction + {}; + template <> + struct HighLevelILInstructionAccessor<HLIL_CLZ> : public HighLevelILOneOperandInstruction + {}; + template <> + struct HighLevelILInstructionAccessor<HLIL_CTZ> : public HighLevelILOneOperandInstruction + {}; + template <> + struct HighLevelILInstructionAccessor<HLIL_RBIT> : public HighLevelILOneOperandInstruction + {}; + template <> + struct HighLevelILInstructionAccessor<HLIL_CLS> : public HighLevelILOneOperandInstruction + {}; + template <> struct HighLevelILInstructionAccessor<HLIL_SX> : public HighLevelILOneOperandInstruction {}; template <> diff --git a/lang/c/pseudoc.cpp b/lang/c/pseudoc.cpp index 35966230..dc37100e 100644 --- a/lang/c/pseudoc.cpp +++ b/lang/c/pseudoc.cpp @@ -2411,6 +2411,85 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H }(); break; + case HLIL_BSWAP: + [&]() { + auto src = instr.GetSourceExpr<HLIL_BSWAP>(); + string name; + if (src.size == 2) + name = "__builtin_bswap16"; + else if (src.size == 4) + name = "__builtin_bswap32"; + else if (src.size == 8) + name = "__builtin_bswap64"; + else + name = "__builtin_bswap"; + tokens.Append(OperationToken, name); + tokens.AppendOpenParen(); + GetExprTextInternal(src, tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + + case HLIL_POPCNT: + [&]() { + auto src = instr.GetSourceExpr<HLIL_POPCNT>(); + tokens.Append(OperationToken, src.size > 4 ? "__builtin_popcountll" : "__builtin_popcount"); + tokens.AppendOpenParen(); + GetExprTextInternal(src, tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + + case HLIL_CLZ: + [&]() { + auto src = instr.GetSourceExpr<HLIL_CLZ>(); + tokens.Append(OperationToken, src.size > 4 ? "__builtin_clzll" : "__builtin_clz"); + tokens.AppendOpenParen(); + GetExprTextInternal(src, tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + + case HLIL_CTZ: + [&]() { + auto src = instr.GetSourceExpr<HLIL_CTZ>(); + tokens.Append(OperationToken, src.size > 4 ? "__builtin_ctzll" : "__builtin_ctz"); + tokens.AppendOpenParen(); + GetExprTextInternal(src, tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + + case HLIL_RBIT: + [&]() { + tokens.Append(OperationToken, "__rbit"); + tokens.AppendOpenParen(); + GetExprTextInternal(instr.GetSourceExpr<HLIL_RBIT>(), tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + + case HLIL_CLS: + [&]() { + tokens.Append(OperationToken, "__cls"); + tokens.AppendOpenParen(); + GetExprTextInternal(instr.GetSourceExpr<HLIL_CLS>(), tokens, settings); + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); + }(); + break; + case HLIL_FLOAT_CONV: [&]() { const auto srcExpr = instr.GetSourceExpr<HLIL_FLOAT_CONV>(); diff --git a/lang/rust/pseudorust.cpp b/lang/rust/pseudorust.cpp index 2e233550..de1acae1 100644 --- a/lang/rust/pseudorust.cpp +++ b/lang/rust/pseudorust.cpp @@ -2428,6 +2428,33 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe }(); break; + case HLIL_BSWAP: + case HLIL_POPCNT: + case HLIL_CLZ: + case HLIL_CTZ: + case HLIL_RBIT: + case HLIL_CLS: + [&]() { + const char* method; + switch (instr.operation) + { + case HLIL_BSWAP: method = "swap_bytes"; break; + case HLIL_POPCNT: method = "count_ones"; break; + case HLIL_CLZ: method = "leading_zeros"; break; + case HLIL_CTZ: method = "trailing_zeros"; break; + case HLIL_RBIT: method = "reverse_bits"; break; + default: method = "leading_sign_bits"; break; + } + GetExprText(instr.GetSourceExpr(), tokens, settings, MemberAndFunctionOperatorPrecedence); + tokens.Append(TextToken, "."); + tokens.Append(OperationToken, method); + tokens.AppendOpenParen(); + tokens.AppendCloseParen(); + if (exprType != InnerExpression) + tokens.AppendSemicolon(); + }(); + break; + case HLIL_FLOAT_CONV: [&]() { const auto srcExpr = instr.GetSourceExpr<HLIL_FLOAT_CONV>(); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 228e8328..5a100080 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -332,6 +332,12 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{LLIL_REG_STACK_PHI, {DestSSARegisterStackLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage}}, OperandUsage{LLIL_FLAG_PHI, {DestSSAFlagLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage}}, OperandUsage{LLIL_MEM_PHI, {DestMemoryVersionLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage}}, + OperandUsage{LLIL_BSWAP, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_POPCNT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CLZ, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CTZ, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_RBIT, {SourceExprLowLevelOperandUsage}}, + OperandUsage{LLIL_CLS, {SourceExprLowLevelOperandUsage}}, }; @@ -1984,6 +1990,12 @@ void LowLevelILInstruction::VisitExprs(bn::base::function_ref<bool(const LowLeve case LLIL_PUSH: case LLIL_NEG: case LLIL_NOT: + case LLIL_BSWAP: + case LLIL_POPCNT: + case LLIL_CLZ: + case LLIL_CTZ: + case LLIL_RBIT: + case LLIL_CLS: case LLIL_SX: case LLIL_ZX: case LLIL_LOW_PART: @@ -2301,6 +2313,12 @@ ExprId LowLevelILInstruction::CopyTo( case LLIL_PUSH: case LLIL_NEG: case LLIL_NOT: + case LLIL_BSWAP: + case LLIL_POPCNT: + case LLIL_CLZ: + case LLIL_CTZ: + case LLIL_RBIT: + case LLIL_CLS: case LLIL_SX: case LLIL_ZX: case LLIL_LOW_PART: @@ -3352,6 +3370,42 @@ ExprId LowLevelILFunction::Not(size_t size, ExprId a, uint32_t flags, const ILSo } +ExprId LowLevelILFunction::ByteSwap(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_BSWAP, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::PopulationCount(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_POPCNT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::CountLeadingZeros(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CLZ, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::CountTrailingZeros(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CTZ, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::ReverseBits(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_RBIT, loc, size, flags, a); +} + + +ExprId LowLevelILFunction::CountLeadingSigns(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_CLS, loc, size, flags, a); +} + + ExprId LowLevelILFunction::SignExtend(size_t size, ExprId a, uint32_t flags, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_SX, loc, size, flags, a); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index c7bbc7f4..53e10b6c 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -2054,6 +2054,24 @@ namespace BinaryNinja struct LowLevelILInstructionAccessor<LLIL_NOT> : public LowLevelILOneOperandInstruction {}; template <> + struct LowLevelILInstructionAccessor<LLIL_BSWAP> : public LowLevelILOneOperandInstruction + {}; + template <> + struct LowLevelILInstructionAccessor<LLIL_POPCNT> : public LowLevelILOneOperandInstruction + {}; + template <> + struct LowLevelILInstructionAccessor<LLIL_CLZ> : public LowLevelILOneOperandInstruction + {}; + template <> + struct LowLevelILInstructionAccessor<LLIL_CTZ> : public LowLevelILOneOperandInstruction + {}; + template <> + struct LowLevelILInstructionAccessor<LLIL_RBIT> : public LowLevelILOneOperandInstruction + {}; + template <> + struct LowLevelILInstructionAccessor<LLIL_CLS> : public LowLevelILOneOperandInstruction + {}; + template <> struct LowLevelILInstructionAccessor<LLIL_SX> : public LowLevelILOneOperandInstruction {}; template <> diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 37a102d8..18610a55 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -304,6 +304,12 @@ static constexpr std::array s_instructionOperandUsage = { OperandUsage{MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, OperandUsage{MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, OperandUsage{MLIL_BLOCK_TO_EXPAND, {SourceExprsMediumLevelOperandUsage}}, + OperandUsage{MLIL_BSWAP, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_POPCNT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CLZ, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CTZ, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_RBIT, {SourceExprMediumLevelOperandUsage}}, + OperandUsage{MLIL_CLS, {SourceExprMediumLevelOperandUsage}}, }; VALIDATE_INSTRUCTION_ORDER(s_instructionOperandUsage); @@ -1514,6 +1520,12 @@ void MediumLevelILInstruction::VisitExprs(bn::base::function_ref<bool(const Medi break; case MLIL_NEG: case MLIL_NOT: + case MLIL_BSWAP: + case MLIL_POPCNT: + case MLIL_CLZ: + case MLIL_CTZ: + case MLIL_RBIT: + case MLIL_CLS: case MLIL_SX: case MLIL_ZX: case MLIL_LOW_PART: @@ -1855,6 +1867,12 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, GetOffset<MLIL_LOAD_STRUCT_SSA>(), GetSourceMemoryVersion<MLIL_LOAD_STRUCT_SSA>(), loc); case MLIL_NEG: case MLIL_NOT: + case MLIL_BSWAP: + case MLIL_POPCNT: + case MLIL_CLZ: + case MLIL_CTZ: + case MLIL_RBIT: + case MLIL_CLS: case MLIL_SX: case MLIL_ZX: case MLIL_LOW_PART: @@ -2864,6 +2882,42 @@ ExprId MediumLevelILFunction::Not(size_t size, ExprId src, const ILSourceLocatio } +ExprId MediumLevelILFunction::ByteSwap(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_BSWAP, loc, size, src); +} + + +ExprId MediumLevelILFunction::PopulationCount(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_POPCNT, loc, size, src); +} + + +ExprId MediumLevelILFunction::CountLeadingZeros(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CLZ, loc, size, src); +} + + +ExprId MediumLevelILFunction::CountTrailingZeros(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CTZ, loc, size, src); +} + + +ExprId MediumLevelILFunction::ReverseBits(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_RBIT, loc, size, src); +} + + +ExprId MediumLevelILFunction::CountLeadingSigns(size_t size, ExprId src, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_CLS, loc, size, src); +} + + ExprId MediumLevelILFunction::SignExtend(size_t size, ExprId src, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_SX, loc, size, src); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 3abe363e..41f154ba 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -1786,6 +1786,24 @@ namespace BinaryNinja struct MediumLevelILInstructionAccessor<MLIL_NOT> : public MediumLevelILOneOperandInstruction {}; template <> + struct MediumLevelILInstructionAccessor<MLIL_BSWAP> : public MediumLevelILOneOperandInstruction + {}; + template <> + struct MediumLevelILInstructionAccessor<MLIL_POPCNT> : public MediumLevelILOneOperandInstruction + {}; + template <> + struct MediumLevelILInstructionAccessor<MLIL_CLZ> : public MediumLevelILOneOperandInstruction + {}; + template <> + struct MediumLevelILInstructionAccessor<MLIL_CTZ> : public MediumLevelILOneOperandInstruction + {}; + template <> + struct MediumLevelILInstructionAccessor<MLIL_RBIT> : public MediumLevelILOneOperandInstruction + {}; + template <> + struct MediumLevelILInstructionAccessor<MLIL_CLS> : public MediumLevelILOneOperandInstruction + {}; + template <> struct MediumLevelILInstructionAccessor<MLIL_SX> : public MediumLevelILOneOperandInstruction {}; template <> diff --git a/python/highlevelil.py b/python/highlevelil.py index 4c81f687..bbeb0186 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -248,7 +248,13 @@ class HighLevelILInstruction(BaseILInstruction): ("left", "expr"), ("right", "expr") ], HighLevelILOperation.HLIL_MODS_DP: [("left", "expr"), ("right", "expr")], HighLevelILOperation.HLIL_NEG: [ ("src", "expr") - ], HighLevelILOperation.HLIL_NOT: [("src", "expr")], HighLevelILOperation.HLIL_SX: [ + ], HighLevelILOperation.HLIL_NOT: [("src", "expr")], HighLevelILOperation.HLIL_BSWAP: [ + ("src", "expr") + ], HighLevelILOperation.HLIL_POPCNT: [("src", "expr")], HighLevelILOperation.HLIL_CLZ: [ + ("src", "expr") + ], HighLevelILOperation.HLIL_CTZ: [("src", "expr")], HighLevelILOperation.HLIL_RBIT: [ + ("src", "expr") + ], HighLevelILOperation.HLIL_CLS: [("src", "expr")], HighLevelILOperation.HLIL_SX: [ ("src", "expr") ], HighLevelILOperation.HLIL_ZX: [("src", "expr")], HighLevelILOperation.HLIL_LOW_PART: [ ("src", "expr") @@ -1984,6 +1990,36 @@ class HighLevelILNot(HighLevelILUnaryBase, Arithmetic): @dataclass(frozen=True, repr=False, eq=False) +class HighLevelILBswap(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILPopcnt(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILClz(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILCtz(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILRbit(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class HighLevelILCls(HighLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) class HighLevelILSx(HighLevelILUnaryBase, Arithmetic): pass @@ -2478,6 +2514,12 @@ ILInstruction = { HighLevelILOperation.HLIL_MODS_DP: HighLevelILModsDp, # ("left", "expr"), ("right", "expr"), HighLevelILOperation.HLIL_NEG: HighLevelILNeg, # ("src", "expr"), HighLevelILOperation.HLIL_NOT: HighLevelILNot, # ("src", "expr"), + HighLevelILOperation.HLIL_BSWAP: HighLevelILBswap, # ("src", "expr"), + HighLevelILOperation.HLIL_POPCNT: HighLevelILPopcnt, # ("src", "expr"), + HighLevelILOperation.HLIL_CLZ: HighLevelILClz, # ("src", "expr"), + HighLevelILOperation.HLIL_CTZ: HighLevelILCtz, # ("src", "expr"), + HighLevelILOperation.HLIL_RBIT: HighLevelILRbit, # ("src", "expr"), + HighLevelILOperation.HLIL_CLS: HighLevelILCls, # ("src", "expr"), HighLevelILOperation.HLIL_SX: HighLevelILSx, # ("src", "expr"), HighLevelILOperation.HLIL_ZX: HighLevelILZx, # ("src", "expr"), HighLevelILOperation.HLIL_LOW_PART: HighLevelILLowPart, # ("src", "expr"), diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 714b663d..ce9770f2 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -377,7 +377,13 @@ class LowLevelILInstruction(BaseILInstruction): ("left", "expr"), ("right", "expr") ], LowLevelILOperation.LLIL_MODS_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_NEG: [ ("src", "expr") - ], LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_SX: [ + ], LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_BSWAP: [ + ("src", "expr") + ], LowLevelILOperation.LLIL_POPCNT: [("src", "expr")], LowLevelILOperation.LLIL_CLZ: [ + ("src", "expr") + ], LowLevelILOperation.LLIL_CTZ: [("src", "expr")], LowLevelILOperation.LLIL_RBIT: [ + ("src", "expr") + ], LowLevelILOperation.LLIL_CLS: [("src", "expr")], LowLevelILOperation.LLIL_SX: [ ("src", "expr") ], LowLevelILOperation.LLIL_ZX: [("src", "expr")], LowLevelILOperation.LLIL_LOW_PART: [ ("src", "expr") @@ -1363,6 +1369,36 @@ class LowLevelILNot(LowLevelILUnaryBase, Arithmetic): @dataclass(frozen=True, repr=False, eq=False) +class LowLevelILBswap(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILPopcnt(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILClz(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILCtz(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILRbit(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class LowLevelILCls(LowLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) class LowLevelILSx(LowLevelILUnaryBase, Arithmetic): pass @@ -3132,6 +3168,12 @@ ILInstruction:Dict[LowLevelILOperation, LowLevelILInstruction] = { # type: igno LowLevelILOperation.LLIL_MODS_DP: LowLevelILModsDp, # [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_NEG: LowLevelILNeg, # [("src", "expr")], LowLevelILOperation.LLIL_NOT: LowLevelILNot, # [("src", "expr")], + LowLevelILOperation.LLIL_BSWAP: LowLevelILBswap, # [("src", "expr")], + LowLevelILOperation.LLIL_POPCNT: LowLevelILPopcnt, # [("src", "expr")], + LowLevelILOperation.LLIL_CLZ: LowLevelILClz, # [("src", "expr")], + LowLevelILOperation.LLIL_CTZ: LowLevelILCtz, # [("src", "expr")], + LowLevelILOperation.LLIL_RBIT: LowLevelILRbit, # [("src", "expr")], + LowLevelILOperation.LLIL_CLS: LowLevelILCls, # [("src", "expr")], LowLevelILOperation.LLIL_SX: LowLevelILSx, # [("src", "expr")], LowLevelILOperation.LLIL_ZX: LowLevelILZx, # [("src", "expr")], LowLevelILOperation.LLIL_LOW_PART: LowLevelILLowPart, # [("src", "expr")], diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 155a3751..15db8ae1 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -265,7 +265,13 @@ class MediumLevelILInstruction(BaseILInstruction): ("right", "expr")], MediumLevelILOperation.MLIL_MODS_DP: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_NEG: [ ("src", "expr") - ], MediumLevelILOperation.MLIL_NOT: [("src", "expr")], MediumLevelILOperation.MLIL_SX: [ + ], MediumLevelILOperation.MLIL_NOT: [("src", "expr")], MediumLevelILOperation.MLIL_BSWAP: [ + ("src", "expr") + ], MediumLevelILOperation.MLIL_POPCNT: [("src", "expr")], MediumLevelILOperation.MLIL_CLZ: [ + ("src", "expr") + ], MediumLevelILOperation.MLIL_CTZ: [("src", "expr")], MediumLevelILOperation.MLIL_RBIT: [ + ("src", "expr") + ], MediumLevelILOperation.MLIL_CLS: [("src", "expr")], MediumLevelILOperation.MLIL_SX: [ ("src", "expr") ], MediumLevelILOperation.MLIL_ZX: [("src", "expr")], MediumLevelILOperation.MLIL_LOW_PART: [ ("src", "expr") @@ -1435,6 +1441,36 @@ class MediumLevelILNot(MediumLevelILUnaryBase, Arithmetic): @dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILBswap(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILPopcnt(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILClz(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILCtz(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILRbit(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) +class MediumLevelILCls(MediumLevelILUnaryBase, Arithmetic): + pass + + +@dataclass(frozen=True, repr=False, eq=False) class MediumLevelILSx(MediumLevelILUnaryBase, Arithmetic): pass @@ -3444,6 +3480,12 @@ ILInstruction = { MediumLevelILOperation.MLIL_MODS_DP: MediumLevelILModsDp, # [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_NEG: MediumLevelILNeg, # [("src", "expr")], MediumLevelILOperation.MLIL_NOT: MediumLevelILNot, # [("src", "expr")], + MediumLevelILOperation.MLIL_BSWAP: MediumLevelILBswap, # [("src", "expr")], + MediumLevelILOperation.MLIL_POPCNT: MediumLevelILPopcnt, # [("src", "expr")], + MediumLevelILOperation.MLIL_CLZ: MediumLevelILClz, # [("src", "expr")], + MediumLevelILOperation.MLIL_CTZ: MediumLevelILCtz, # [("src", "expr")], + MediumLevelILOperation.MLIL_RBIT: MediumLevelILRbit, # [("src", "expr")], + MediumLevelILOperation.MLIL_CLS: MediumLevelILCls, # [("src", "expr")], MediumLevelILOperation.MLIL_SX: MediumLevelILSx, # [("src", "expr")], MediumLevelILOperation.MLIL_ZX: MediumLevelILZx, # [("src", "expr")], MediumLevelILOperation.MLIL_LOW_PART: MediumLevelILLowPart, # [("src", "expr")], diff --git a/rust/src/high_level_il/instruction.rs b/rust/src/high_level_il/instruction.rs index 98839cae..0fbbb297 100644 --- a/rust/src/high_level_il/instruction.rs +++ b/rust/src/high_level_il/instruction.rs @@ -412,6 +412,24 @@ impl HighLevelILInstruction { HLIL_NOT => Op::Not(UnaryOp { src: HighLevelExpressionIndex::from(op.operands[0]), }), + HLIL_BSWAP => Op::Bswap(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), + HLIL_POPCNT => Op::Popcnt(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), + HLIL_CLZ => Op::Clz(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), + HLIL_CTZ => Op::Ctz(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), + HLIL_RBIT => Op::Rbit(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), + HLIL_CLS => Op::Cls(UnaryOp { + src: HighLevelExpressionIndex::from(op.operands[0]), + }), HLIL_SX => Op::Sx(UnaryOp { src: HighLevelExpressionIndex::from(op.operands[0]), }), @@ -794,6 +812,12 @@ impl HighLevelILInstruction { ReturnByRef(op) => Lifted::ReturnByRef(self.lift_unary_op(op)), Neg(op) => Lifted::Neg(self.lift_unary_op(op)), Not(op) => Lifted::Not(self.lift_unary_op(op)), + Bswap(op) => Lifted::Bswap(self.lift_unary_op(op)), + Popcnt(op) => Lifted::Popcnt(self.lift_unary_op(op)), + Clz(op) => Lifted::Clz(self.lift_unary_op(op)), + Ctz(op) => Lifted::Ctz(self.lift_unary_op(op)), + Rbit(op) => Lifted::Rbit(self.lift_unary_op(op)), + Cls(op) => Lifted::Cls(self.lift_unary_op(op)), Sx(op) => Lifted::Sx(self.lift_unary_op(op)), Zx(op) => Lifted::Zx(self.lift_unary_op(op)), LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)), @@ -1173,6 +1197,12 @@ pub enum HighLevelILInstructionKind { ReturnByRef(UnaryOp), Neg(UnaryOp), Not(UnaryOp), + Bswap(UnaryOp), + Popcnt(UnaryOp), + Clz(UnaryOp), + Ctz(UnaryOp), + Rbit(UnaryOp), + Cls(UnaryOp), Sx(UnaryOp), Zx(UnaryOp), LowPart(UnaryOp), diff --git a/rust/src/high_level_il/lift.rs b/rust/src/high_level_il/lift.rs index e2ce3686..3d32b369 100644 --- a/rust/src/high_level_il/lift.rs +++ b/rust/src/high_level_il/lift.rs @@ -116,6 +116,12 @@ pub enum HighLevelILLiftedInstructionKind { ReturnByRef(LiftedUnaryOp), Neg(LiftedUnaryOp), Not(LiftedUnaryOp), + Bswap(LiftedUnaryOp), + Popcnt(LiftedUnaryOp), + Clz(LiftedUnaryOp), + Ctz(LiftedUnaryOp), + Rbit(LiftedUnaryOp), + Cls(LiftedUnaryOp), Sx(LiftedUnaryOp), Zx(LiftedUnaryOp), LowPart(LiftedUnaryOp), @@ -246,6 +252,12 @@ impl HighLevelILLiftedInstruction { ReturnByRef(_) => "ReturnByRef", Neg(_) => "Neg", Not(_) => "Not", + Bswap(_) => "Bswap", + Popcnt(_) => "Popcnt", + Clz(_) => "Clz", + Ctz(_) => "Ctz", + Rbit(_) => "Rbit", + Cls(_) => "Cls", Sx(_) => "Sx", Zx(_) => "Zx", LowPart(_) => "LowPart", @@ -365,6 +377,7 @@ impl HighLevelILLiftedInstruction { Operand::ConstantData(op.constant_data.clone()), )], Deref(op) | AddressOf(op) | PassByRef(op) | ReturnByRef(op) | Neg(op) | Not(op) + | Bswap(op) | Popcnt(op) | Clz(op) | Ctz(op) | Rbit(op) | Cls(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) => { diff --git a/rust/src/low_level_il/expression.rs b/rust/src/low_level_il/expression.rs index 8103518c..92d57675 100644 --- a/rust/src/low_level_il/expression.rs +++ b/rust/src/low_level_il/expression.rs @@ -309,6 +309,12 @@ where Neg(Operation<'func, M, F, operation::UnaryOp>), Not(Operation<'func, M, F, operation::UnaryOp>), + Bswap(Operation<'func, M, F, operation::UnaryOp>), + Popcnt(Operation<'func, M, F, operation::UnaryOp>), + Clz(Operation<'func, M, F, operation::UnaryOp>), + Ctz(Operation<'func, M, F, operation::UnaryOp>), + Rbit(Operation<'func, M, F, operation::UnaryOp>), + Cls(Operation<'func, M, F, operation::UnaryOp>), Sx(Operation<'func, M, F, operation::UnaryOp>), Zx(Operation<'func, M, F, operation::UnaryOp>), LowPart(Operation<'func, M, F, operation::UnaryOp>), @@ -466,6 +472,12 @@ where LLIL_NEG => LowLevelILExpressionKind::Neg(Operation::new(function, op, index)), LLIL_NOT => LowLevelILExpressionKind::Not(Operation::new(function, op, index)), + LLIL_BSWAP => LowLevelILExpressionKind::Bswap(Operation::new(function, op, index)), + LLIL_POPCNT => LowLevelILExpressionKind::Popcnt(Operation::new(function, op, index)), + LLIL_CLZ => LowLevelILExpressionKind::Clz(Operation::new(function, op, index)), + LLIL_CTZ => LowLevelILExpressionKind::Ctz(Operation::new(function, op, index)), + LLIL_RBIT => LowLevelILExpressionKind::Rbit(Operation::new(function, op, index)), + LLIL_CLS => LowLevelILExpressionKind::Cls(Operation::new(function, op, index)), LLIL_SX => LowLevelILExpressionKind::Sx(Operation::new(function, op, index)), LLIL_ZX => LowLevelILExpressionKind::Zx(Operation::new(function, op, index)), @@ -620,7 +632,8 @@ where use self::LowLevelILExpressionKind::*; match *self { - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) + Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op) | Ctz(ref op) + | Rbit(ref op) | Cls(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => Some(op), @@ -664,7 +677,8 @@ where visit!(op.left()); visit!(op.right()); } - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) + Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op) | Ctz(ref op) + | Rbit(ref op) | Cls(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => { @@ -758,7 +772,8 @@ where DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => &op.op, - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) + Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op) | Ctz(ref op) + | Rbit(ref op) | Cls(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => &op.op, @@ -831,7 +846,8 @@ impl LowLevelILExpressionKind<'_, Mutable, NonSSA> { DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => op.flag_write(), - Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) + Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op) | Ctz(ref op) + | Rbit(ref op) | Cls(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op) | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op) | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => op.flag_write(), diff --git a/rust/src/low_level_il/lifting.rs b/rust/src/low_level_il/lifting.rs index 202c9ed6..ebd6e980 100644 --- a/rust/src/low_level_il/lifting.rs +++ b/rust/src/low_level_il/lifting.rs @@ -94,6 +94,12 @@ pub enum LowLevelILFlagWriteOp<R: ArchReg> { Push(usize, LowLevelILRegisterOrConstant<R>), Neg(usize, LowLevelILRegisterOrConstant<R>), Not(usize, LowLevelILRegisterOrConstant<R>), + Bswap(usize, LowLevelILRegisterOrConstant<R>), + Popcnt(usize, LowLevelILRegisterOrConstant<R>), + Clz(usize, LowLevelILRegisterOrConstant<R>), + Ctz(usize, LowLevelILRegisterOrConstant<R>), + Rbit(usize, LowLevelILRegisterOrConstant<R>), + Cls(usize, LowLevelILRegisterOrConstant<R>), Sx(usize, LowLevelILRegisterOrConstant<R>), Zx(usize, LowLevelILRegisterOrConstant<R>), LowPart(usize, LowLevelILRegisterOrConstant<R>), @@ -293,6 +299,12 @@ impl<R: ArchReg> LowLevelILFlagWriteOp<R> { (1, LLIL_PUSH) => op!(Push, 0), (1, LLIL_NEG) => op!(Neg, 0), (1, LLIL_NOT) => op!(Not, 0), + (1, LLIL_BSWAP) => op!(Bswap, 0), + (1, LLIL_POPCNT) => op!(Popcnt, 0), + (1, LLIL_CLZ) => op!(Clz, 0), + (1, LLIL_CTZ) => op!(Ctz, 0), + (1, LLIL_RBIT) => op!(Rbit, 0), + (1, LLIL_CLS) => op!(Cls, 0), (1, LLIL_SX) => op!(Sx, 0), (1, LLIL_ZX) => op!(Zx, 0), (1, LLIL_LOW_PART) => op!(LowPart, 0), @@ -351,6 +363,12 @@ impl<R: ArchReg> LowLevelILFlagWriteOp<R> { Push(size, ..) => (size, LLIL_PUSH), Neg(size, ..) => (size, LLIL_NEG), Not(size, ..) => (size, LLIL_NOT), + Bswap(size, ..) => (size, LLIL_BSWAP), + Popcnt(size, ..) => (size, LLIL_POPCNT), + Clz(size, ..) => (size, LLIL_CLZ), + Ctz(size, ..) => (size, LLIL_CTZ), + Rbit(size, ..) => (size, LLIL_RBIT), + Cls(size, ..) => (size, LLIL_CLS), Sx(size, ..) => (size, LLIL_SX), Zx(size, ..) => (size, LLIL_ZX), LowPart(size, ..) => (size, LLIL_LOW_PART), @@ -404,6 +422,12 @@ impl<R: ArchReg> LowLevelILFlagWriteOp<R> { | Push(_, op0) | Neg(_, op0) | Not(_, op0) + | Bswap(_, op0) + | Popcnt(_, op0) + | Clz(_, op0) + | Ctz(_, op0) + | Rbit(_, op0) + | Cls(_, op0) | Sx(_, op0) | Zx(_, op0) | LowPart(_, op0) @@ -1422,6 +1446,12 @@ impl LowLevelILMutableFunction { sized_unary_op_lifter!(neg, LLIL_NEG, ValueExpr); sized_unary_op_lifter!(not, LLIL_NOT, ValueExpr); + sized_unary_op_lifter!(bswap, LLIL_BSWAP, ValueExpr); + sized_unary_op_lifter!(popcnt, LLIL_POPCNT, ValueExpr); + sized_unary_op_lifter!(clz, LLIL_CLZ, ValueExpr); + sized_unary_op_lifter!(ctz, LLIL_CTZ, ValueExpr); + sized_unary_op_lifter!(rbit, LLIL_RBIT, ValueExpr); + sized_unary_op_lifter!(cls, LLIL_CLS, ValueExpr); size_changing_unary_op_lifter!(sx, LLIL_SX, ValueExpr); size_changing_unary_op_lifter!(zx, LLIL_ZX, ValueExpr); diff --git a/rust/src/medium_level_il/instruction.rs b/rust/src/medium_level_il/instruction.rs index 41f2bbe4..77a0be27 100644 --- a/rust/src/medium_level_il/instruction.rs +++ b/rust/src/medium_level_il/instruction.rs @@ -575,6 +575,24 @@ impl MediumLevelILInstruction { MLIL_NOT => Op::Not(UnaryOp { src: MediumLevelExpressionIndex::from(op.operands[0] as usize), }), + MLIL_BSWAP => Op::Bswap(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), + MLIL_POPCNT => Op::Popcnt(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), + MLIL_CLZ => Op::Clz(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), + MLIL_CTZ => Op::Ctz(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), + MLIL_RBIT => Op::Rbit(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), + MLIL_CLS => Op::Cls(UnaryOp { + src: MediumLevelExpressionIndex::from(op.operands[0] as usize), + }), MLIL_SX => Op::Sx(UnaryOp { src: MediumLevelExpressionIndex::from(op.operands[0] as usize), }), @@ -1099,6 +1117,12 @@ impl MediumLevelILInstruction { Neg(op) => Lifted::Neg(self.lift_unary_op(op)), Not(op) => Lifted::Not(self.lift_unary_op(op)), + Bswap(op) => Lifted::Bswap(self.lift_unary_op(op)), + Popcnt(op) => Lifted::Popcnt(self.lift_unary_op(op)), + Clz(op) => Lifted::Clz(self.lift_unary_op(op)), + Ctz(op) => Lifted::Ctz(self.lift_unary_op(op)), + Rbit(op) => Lifted::Rbit(self.lift_unary_op(op)), + Cls(op) => Lifted::Cls(self.lift_unary_op(op)), Sx(op) => Lifted::Sx(self.lift_unary_op(op)), Zx(op) => Lifted::Zx(self.lift_unary_op(op)), LowPart(op) => Lifted::LowPart(self.lift_unary_op(op)), @@ -1874,6 +1898,12 @@ pub enum MediumLevelILInstructionKind { StoreOutput(StoreOutput), Neg(UnaryOp), Not(UnaryOp), + Bswap(UnaryOp), + Popcnt(UnaryOp), + Clz(UnaryOp), + Ctz(UnaryOp), + Rbit(UnaryOp), + Cls(UnaryOp), Sx(UnaryOp), Zx(UnaryOp), LowPart(UnaryOp), diff --git a/rust/src/medium_level_il/lift.rs b/rust/src/medium_level_il/lift.rs index aee8139f..2f0d6653 100644 --- a/rust/src/medium_level_il/lift.rs +++ b/rust/src/medium_level_il/lift.rs @@ -154,6 +154,12 @@ pub enum MediumLevelILLiftedInstructionKind { SharedParamSlot(LiftedSharedParamSlot), Neg(LiftedUnaryOp), Not(LiftedUnaryOp), + Bswap(LiftedUnaryOp), + Popcnt(LiftedUnaryOp), + Clz(LiftedUnaryOp), + Ctz(LiftedUnaryOp), + Rbit(LiftedUnaryOp), + Cls(LiftedUnaryOp), Sx(LiftedUnaryOp), Zx(LiftedUnaryOp), LowPart(LiftedUnaryOp), @@ -313,6 +319,12 @@ impl MediumLevelILLiftedInstruction { StoreOutput(_) => "StoreOutput", Neg(_) => "Neg", Not(_) => "Not", + Bswap(_) => "Bswap", + Popcnt(_) => "Popcnt", + Clz(_) => "Clz", + Ctz(_) => "Ctz", + Rbit(_) => "Rbit", + Cls(_) => "Cls", Sx(_) => "Sx", Zx(_) => "Zx", LowPart(_) => "LowPart", @@ -542,7 +554,8 @@ impl MediumLevelILLiftedInstruction { ("params", Operand::ExprList(op.params.clone())), ("stack", Operand::Expr(*op.stack.clone())), ], - Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op) + Neg(op) | Not(op) | Bswap(op) | Popcnt(op) | Clz(op) | Ctz(op) | Rbit(op) | Cls(op) + | Sx(op) | Zx(op) | LowPart(op) | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op) | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op) | Ftrunc(op) | Load(op) => { vec![("src", Operand::Expr(*op.src.clone()))] |
