Add several common bit operations to RzIL. (#3977)
This commit is contained in:
parent
6b9d56282c
commit
1ec21a8d32
8 changed files with 583 additions and 9 deletions
|
|
@ -23,15 +23,6 @@
|
|||
*/
|
||||
#define DCACHE_LINE_SIZE 128
|
||||
|
||||
/**
|
||||
* \brief Writes to the info log that an unimplemented instruction was encountered and returns an EMPTY() effect.
|
||||
*/
|
||||
#define NOT_IMPLEMENTED \
|
||||
do { \
|
||||
RZ_LOG_INFO("IL instruction not implemented."); \
|
||||
return NULL; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \brief Unsigned value \p i which is PPC_ARCH_BITS (32 or 64) wide.
|
||||
*/
|
||||
|
|
|
|||
213
librz/il/il_routines.c
Normal file
213
librz/il/il_routines.c
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
// SPDX-FileCopyrightText: 2023 Rot127 <unisono@quyllur.org>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
/**
|
||||
* \file Implements common bit operation perfomed on values.
|
||||
*/
|
||||
|
||||
#include <rz_util/rz_assert.h>
|
||||
#include <rz_il/rz_il_opcodes.h>
|
||||
#include <rz_types.h>
|
||||
|
||||
/**
|
||||
* \brief Extracts \p length bits from \p start of \p value and returns them as U32.
|
||||
*
|
||||
* Performed operation: ((value >> start) & (~0U >> (0x20 - length)));
|
||||
*
|
||||
* \param value The value to extract the bits from. It must be a bitvector of size 32.
|
||||
* \param start The start index of the bits to extract. Passed bitvector can be of any width.
|
||||
* \param length Number of bits to extract. Passed bitvector must be 32bits in size.
|
||||
*
|
||||
* \return A 32bit wide bitvector with the extracted value.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_extract32(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length) {
|
||||
rz_return_val_if_fail(value && start && length, NULL);
|
||||
RzILOpPure *op_RSHIFT_0 = rz_il_op_new_shiftr(rz_il_op_new_b0(), value, start);
|
||||
RzILOpPure *op_SUB_4 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x20), length);
|
||||
RzILOpPure *op_RSHIFT_5 = rz_il_op_new_shiftr(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, -1), op_SUB_4);
|
||||
RzILOpPure *op_AND_6 = rz_il_op_new_log_and(op_RSHIFT_0, op_RSHIFT_5);
|
||||
return op_AND_6;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extracts \p length bits from \p start of \p value and returns them as U64.
|
||||
*
|
||||
* Performed operation: ((value >> start) & (~0ULL >> (0x40 - length)));
|
||||
*
|
||||
* \param value The value to extract the bits from. It must be a bitvector of size 64.
|
||||
* \param start The start index of the bits to extract. Passed bitvector can be of any width.
|
||||
* \param length Number of bits to extract. Passed bitvector must be 32bits in size.
|
||||
*
|
||||
* \return A 64bit wide bitvector with the extracted value.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_extract64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length) {
|
||||
rz_return_val_if_fail(value && start && length, NULL);
|
||||
RzILOpPure *op_RSHIFT_0 = rz_il_op_new_shiftr(rz_il_op_new_b0(), value, start);
|
||||
RzILOpPure *op_SUB_4 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x40), length);
|
||||
RzILOpPure *op_RSHIFT_5 = rz_il_op_new_shiftr(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, -1), op_SUB_4);
|
||||
RzILOpPure *op_AND_6 = rz_il_op_new_log_and(op_RSHIFT_0, op_RSHIFT_5);
|
||||
return op_AND_6;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Extracts \p length bits from \p start from \p value and returns them as S64. The extracted value is sign extended.
|
||||
*
|
||||
* Performed operation: (((st64) (value << 0x40 - length - start)) >> 0x40 - length);
|
||||
*
|
||||
* \param value The value to extract the bits from. It must be a bitvector of size 64.
|
||||
* \param start The start index of the bits to extract. Passed bitvector must be 32bits in size.
|
||||
* \param length Number of bits to extract. Passed bitvector must be 32bits in size.
|
||||
*
|
||||
* \return A 64bit wide sign extended bitvector with the extracted value.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_sextract64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length) {
|
||||
rz_return_val_if_fail(value && start && length, NULL);
|
||||
RzILOpPure *op_SUB_1 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x40), length);
|
||||
RzILOpPure *op_SUB_2 = rz_il_op_new_sub(op_SUB_1, start);
|
||||
RzILOpPure *op_LSHIFT_3 = rz_il_op_new_shiftl(rz_il_op_new_b0(), value, op_SUB_2);
|
||||
RzILOpPure *op_SUB_6 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x40), rz_il_op_pure_dup(length));
|
||||
RzILOpPure *op_RSHIFT_7 = rz_il_op_new_shiftr_arith(rz_il_op_new_cast(64, rz_il_op_new_b0(), op_LSHIFT_3), op_SUB_6);
|
||||
return op_RSHIFT_7;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Deposits \p fieldval in \p value. The \p fieldval is inserted at \p start until \p start + \p length.
|
||||
*
|
||||
* Performed operation: ((value & (~((~0ULL >> (0x40 - length)) << start))) | ((fieldval << start) & ((~0ULL >> (0x40 - length)) << start)));
|
||||
*
|
||||
* \param value The value to deposit \p fieldval into. It must be a bitvector of size 64.
|
||||
* \param start The start index to deposit \p fieldval into. Passed bitvector can be of any width.
|
||||
* \param length Number of bits to deposit. Passed bitvector must be 32bits in size.
|
||||
* \param fieldval The bits to deposit into \p value into. It must be a bitvector of size 64.
|
||||
*
|
||||
* \return \p value where bits[start:length] are replaced with \p fieldval
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_deposit64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length, RZ_BORROW RzILOpBitVector *fieldval) {
|
||||
rz_return_val_if_fail(value && start && length && fieldval, NULL);
|
||||
RzILOpPure *op_SUB_4 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x40), length);
|
||||
RzILOpPure *op_RSHIFT_5 = rz_il_op_new_shiftr(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(64, -1), op_SUB_4);
|
||||
RzILOpPure *op_LSHIFT_6 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_RSHIFT_5, start);
|
||||
RzILOpPure *op_NOT_8 = rz_il_op_new_log_not(op_LSHIFT_6);
|
||||
RzILOpPure *op_AND_9 = rz_il_op_new_log_and(value, op_NOT_8);
|
||||
RzILOpPure *op_LSHIFT_10 = rz_il_op_new_shiftl(rz_il_op_new_b0(), fieldval, rz_il_op_pure_dup(start));
|
||||
RzILOpPure *op_AND_11 = rz_il_op_new_log_and(op_LSHIFT_10, rz_il_op_pure_dup(op_LSHIFT_6));
|
||||
RzILOpPure *op_OR_12 = rz_il_op_new_log_or(op_AND_9, op_AND_11);
|
||||
return op_OR_12;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Deposits \p fieldval in \p value. The \p fieldval is inserted at \p start until \p start + \p length.
|
||||
*
|
||||
* Performed operation: ((value & (~((~0U >> (0x20 - length)) << start))) | ((fieldval << start) & ((~0U >> (0x20 - length)) << start)));
|
||||
*
|
||||
* \param value The value to deposit \p fieldval into. It must be a bitvector of size 32.
|
||||
* \param start The start index to deposit \p fieldval into. Passed bitvector can be of any width.
|
||||
* \param length Number of bits to deposit. Passed bitvector must be 32bits in size.
|
||||
* \param fieldval The bits to deposit into \p value into. It must be a bitvector of size 32.
|
||||
*
|
||||
* \return \p value where bits[start:length] are replaced with \p fieldval.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_deposit32(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length, RZ_BORROW RzILOpBitVector *fieldval) {
|
||||
rz_return_val_if_fail(value && start && length && fieldval, NULL);
|
||||
RzILOpPure *op_SUB_4 = rz_il_op_new_sub(rz_il_op_new_bitv_from_st64(32, 0x20), length);
|
||||
RzILOpPure *op_RSHIFT_5 = rz_il_op_new_shiftr(rz_il_op_new_b0(), rz_il_op_new_bitv_from_ut64(32, -1), op_SUB_4);
|
||||
RzILOpPure *op_LSHIFT_6 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_RSHIFT_5, start);
|
||||
RzILOpPure *op_NOT_8 = rz_il_op_new_log_not(op_LSHIFT_6);
|
||||
RzILOpPure *op_AND_9 = rz_il_op_new_log_and(value, op_NOT_8);
|
||||
RzILOpPure *op_LSHIFT_10 = rz_il_op_new_shiftl(rz_il_op_new_b0(), fieldval, rz_il_op_pure_dup(start));
|
||||
RzILOpPure *op_AND_11 = rz_il_op_new_log_and(op_LSHIFT_10, rz_il_op_pure_dup(op_LSHIFT_6));
|
||||
RzILOpPure *op_OR_12 = rz_il_op_new_log_or(op_AND_9, op_AND_11);
|
||||
return op_OR_12;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performes a byte swap of \p t.
|
||||
*
|
||||
* Perfomed operation: (((((st32) t) & 0xff00) >> 0x8) | ((((st32) t) & 0xff) << 0x8));
|
||||
*
|
||||
* \param t A 16bit wide bitvector for which to swap the bytes.
|
||||
*
|
||||
* \return The bitvector \p t with swapped bytes.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap16(RZ_BORROW RzILOpBitVector *t) {
|
||||
rz_return_val_if_fail(t, NULL);
|
||||
RzILOpPure *op_AND_2 = rz_il_op_new_log_and(rz_il_op_new_cast(32, rz_il_op_new_b0(), t), rz_il_op_new_bitv_from_st64(32, 0xff00));
|
||||
RzILOpPure *op_RSHIFT_4 = rz_il_op_new_shiftr_arith(op_AND_2, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_AND_7 = rz_il_op_new_log_and(rz_il_op_new_cast(32, rz_il_op_new_b0(), rz_il_op_pure_dup(t)), rz_il_op_new_bitv_from_st64(32, 0xff));
|
||||
RzILOpPure *op_LSHIFT_9 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_7, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_OR_10 = rz_il_op_new_log_or(op_RSHIFT_4, op_LSHIFT_9);
|
||||
return rz_il_op_new_cast(16, rz_il_op_new_b0(), op_OR_10);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performes a byte swap of \p t.
|
||||
*
|
||||
* Perfomed operation:
|
||||
* ((t & ((ut32) 0xff)) << 0x18)
|
||||
* | ((t & ((ut32) 0xff00)) << 0x8))
|
||||
* | ((t & ((ut32) 0xff0000)) >> 0x8))
|
||||
* | ((t & ((ut32) 0xff000000)) >> 0x18));
|
||||
*
|
||||
* \param t A 32bit wide bitvector for which to swap the bytes.
|
||||
*
|
||||
* \return The bitvector \p t with swapped bytes.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap32(RZ_BORROW RzILOpBitVector *t) {
|
||||
rz_return_val_if_fail(t, NULL);
|
||||
RzILOpPure *op_AND_2 = rz_il_op_new_log_and(t, rz_il_op_new_cast(32, rz_il_op_new_b0(), rz_il_op_new_bitv_from_st64(32, 0xff)));
|
||||
RzILOpPure *op_LSHIFT_4 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_2, rz_il_op_new_bitv_from_st64(32, 24));
|
||||
RzILOpPure *op_AND_7 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_cast(32, rz_il_op_new_b0(), rz_il_op_new_bitv_from_st64(32, 0xff00)));
|
||||
RzILOpPure *op_LSHIFT_9 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_7, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_OR_10 = rz_il_op_new_log_or(op_LSHIFT_4, op_LSHIFT_9);
|
||||
RzILOpPure *op_AND_13 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_cast(32, rz_il_op_new_b0(), rz_il_op_new_bitv_from_st64(32, 0xff0000)));
|
||||
RzILOpPure *op_RSHIFT_15 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_13, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_OR_16 = rz_il_op_new_log_or(op_OR_10, op_RSHIFT_15);
|
||||
RzILOpPure *op_AND_19 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_cast(32, rz_il_op_new_b0(), rz_il_op_new_bitv_from_st64(32, 0xff000000)));
|
||||
RzILOpPure *op_RSHIFT_21 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_19, rz_il_op_new_bitv_from_st64(32, 24));
|
||||
RzILOpPure *op_OR_22 = rz_il_op_new_log_or(op_OR_16, op_RSHIFT_21);
|
||||
return op_OR_22;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performes a byte swap of \p t.
|
||||
*
|
||||
* Perfomed operation:
|
||||
* ((t & 0xff) << 0x38)
|
||||
* | ((t & 0xff00) << 0x28))
|
||||
* | ((t & 0xff0000) << 0x18))
|
||||
* | ((t & 0xff000000) << 0x8))
|
||||
* | ((t & 0xff00000000) >> 0x8))
|
||||
* | ((t & 0xff0000000000) >> 0x18))
|
||||
* | ((t & 0xff000000000000) >> 0x28))
|
||||
* | ((t & 0xff00000000000000) >> 0x38));
|
||||
*
|
||||
* \param t A 64bit wide bitvector for which to swap the bytes.
|
||||
*
|
||||
* \return The bitvector \p t with swapped bytes.
|
||||
*/
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap64(RZ_BORROW RzILOpBitVector *t) {
|
||||
RzILOpPure *op_AND_1 = rz_il_op_new_log_and(t, rz_il_op_new_bitv_from_ut64(64, 0xff));
|
||||
RzILOpPure *op_LSHIFT_3 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_1, rz_il_op_new_bitv_from_st64(32, 0x38));
|
||||
RzILOpPure *op_AND_5 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff00));
|
||||
RzILOpPure *op_LSHIFT_7 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_5, rz_il_op_new_bitv_from_st64(32, 0x28));
|
||||
RzILOpPure *op_OR_8 = rz_il_op_new_log_or(op_LSHIFT_3, op_LSHIFT_7);
|
||||
RzILOpPure *op_AND_10 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff0000));
|
||||
RzILOpPure *op_LSHIFT_12 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_10, rz_il_op_new_bitv_from_st64(32, 24));
|
||||
RzILOpPure *op_OR_13 = rz_il_op_new_log_or(op_OR_8, op_LSHIFT_12);
|
||||
RzILOpPure *op_AND_15 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff000000));
|
||||
RzILOpPure *op_LSHIFT_17 = rz_il_op_new_shiftl(rz_il_op_new_b0(), op_AND_15, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_OR_18 = rz_il_op_new_log_or(op_OR_13, op_LSHIFT_17);
|
||||
RzILOpPure *op_AND_20 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff00000000));
|
||||
RzILOpPure *op_RSHIFT_22 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_20, rz_il_op_new_bitv_from_st64(32, 8));
|
||||
RzILOpPure *op_OR_23 = rz_il_op_new_log_or(op_OR_18, op_RSHIFT_22);
|
||||
RzILOpPure *op_AND_25 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff0000000000));
|
||||
RzILOpPure *op_RSHIFT_27 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_25, rz_il_op_new_bitv_from_st64(32, 24));
|
||||
RzILOpPure *op_OR_28 = rz_il_op_new_log_or(op_OR_23, op_RSHIFT_27);
|
||||
RzILOpPure *op_AND_30 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff000000000000));
|
||||
RzILOpPure *op_RSHIFT_32 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_30, rz_il_op_new_bitv_from_st64(32, 0x28));
|
||||
RzILOpPure *op_OR_33 = rz_il_op_new_log_or(op_OR_28, op_RSHIFT_32);
|
||||
RzILOpPure *op_AND_35 = rz_il_op_new_log_and(rz_il_op_pure_dup(t), rz_il_op_new_bitv_from_ut64(64, 0xff00000000000000));
|
||||
RzILOpPure *op_RSHIFT_37 = rz_il_op_new_shiftr(rz_il_op_new_b0(), op_AND_35, rz_il_op_new_bitv_from_st64(32, 0x38));
|
||||
RzILOpPure *op_OR_38 = rz_il_op_new_log_or(op_OR_33, op_RSHIFT_37);
|
||||
return op_OR_38;
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ rz_il_sources = [
|
|||
'il_export_json.c',
|
||||
'il_graph.c',
|
||||
'il_opcodes.c',
|
||||
'il_routines.c',
|
||||
'il_reg.c',
|
||||
'il_validate.c',
|
||||
'il_vm.c',
|
||||
|
|
|
|||
|
|
@ -170,4 +170,19 @@
|
|||
#define JMP(tgt) rz_il_op_new_jmp(tgt)
|
||||
#define GOTO(lbl) rz_il_op_new_goto(lbl)
|
||||
|
||||
#define NOT_IMPLEMENTED \
|
||||
do { \
|
||||
RZ_LOG_INFO("IL instruction not implemented."); \
|
||||
return NULL; \
|
||||
} while (0)
|
||||
|
||||
#define EXTRACT32(value, start, length) rz_il_extract32(value, start, length)
|
||||
#define EXTRACT64(value, start, length) rz_il_extract64(value, start, length)
|
||||
#define SEXTRACT64(value, start, length) rz_il_sextract64(value, start, length)
|
||||
#define DEPOSIT32(value, start, length, fieldval) rz_il_deposit32(value, start, length, fieldval)
|
||||
#define DEPOSIT64(value, start, length, fieldval) rz_il_deposit64(value, start, length, fieldval)
|
||||
#define BSWAP16(t) rz_il_bswap16(t)
|
||||
#define BSWAP32(t) rz_il_bswap32(t)
|
||||
#define BSWAP64(t) rz_il_bswap64(t)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -133,4 +133,15 @@
|
|||
#undef JMP
|
||||
#undef GOTO
|
||||
|
||||
#undef NOT_IMPLEMENTED
|
||||
|
||||
#undef EXTRACT32
|
||||
#undef EXTRACT64
|
||||
#undef SEXTRACT64
|
||||
#undef DEPOSIT32
|
||||
#undef DEPOSIT64
|
||||
#undef BSWAP16
|
||||
#undef BSWAP32
|
||||
#undef BSWAP64
|
||||
|
||||
#undef RZ_IL_OPBUILDER_BEGIN_H
|
||||
|
|
|
|||
|
|
@ -769,6 +769,15 @@ RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_frootn(RzFloatRMode rmode, RZ_NONNULL Rz
|
|||
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_fpown(RzFloatRMode rmode, RZ_NONNULL RzILOpFloat *x, RZ_NONNULL RzILOpBitVector *n);
|
||||
RZ_API RZ_OWN RzILOpFloat *rz_il_op_new_fcompound(RzFloatRMode rmode, RZ_NONNULL RzILOpFloat *x, RZ_NONNULL RzILOpBitVector *n);
|
||||
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_extract32(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_extract64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_sextract64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_deposit64(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length, RZ_BORROW RzILOpBitVector *fieldval);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_deposit32(RZ_BORROW RzILOpBitVector *value, RZ_BORROW RzILOpBitVector *start, RZ_BORROW RzILOpBitVector *length, RZ_BORROW RzILOpBitVector *fieldval);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap16(RZ_BORROW RzILOpBitVector *t);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap32(RZ_BORROW RzILOpBitVector *t);
|
||||
RZ_API RZ_OWN RzILOpBitVector *rz_il_bswap64(RZ_BORROW RzILOpBitVector *t);
|
||||
|
||||
///////////////////////////////
|
||||
// Opcodes of type 'a effect //
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ if get_option('enable_tests')
|
|||
'il_reg',
|
||||
'il_validate',
|
||||
'il_vm',
|
||||
'il_helpers',
|
||||
'intervaltree',
|
||||
'io',
|
||||
'io_ihex',
|
||||
|
|
|
|||
333
test/unit/test_il_helpers.c
Normal file
333
test/unit/test_il_helpers.c
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
// SPDX-FileCopyrightText: 2023 Rot127 <unisono@quyllur.org>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_il.h>
|
||||
#include <rz_util.h>
|
||||
#include "minunit.h"
|
||||
#include "rz_il/rz_il_opcodes.h"
|
||||
#include "rz_il/rz_il_vm.h"
|
||||
|
||||
static bool test_il_extract32() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Extract all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(32, 0x01234567);
|
||||
RzILOpBitVector *start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
RzILOpBitVector *len = rz_il_op_new_bitv_from_ut64(32, 32);
|
||||
RzILOpBitVector *result = rz_il_extract32(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x01234567, "extract32(0x01234567, 0, 32) resulting value mismatch.");
|
||||
|
||||
// Extract none
|
||||
val = rz_il_op_new_bitv_from_ut64(32, 0x01234567);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
result = rz_il_extract32(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0, "extract32(0x01234567, 0, 0) resulting value mismatch.");
|
||||
|
||||
// Extract within
|
||||
val = rz_il_op_new_bitv_from_ut64(32, 0x01234567);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 4);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 5);
|
||||
result = rz_il_extract32(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x16, "extract32(0x01234567, 4, 5) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_extract64() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 64, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Extract all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
RzILOpBitVector *start = rz_il_op_new_bitv_from_ut64(64, 0);
|
||||
RzILOpBitVector *len = rz_il_op_new_bitv_from_ut64(32, 64);
|
||||
RzILOpBitVector *result = rz_il_extract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0123456789abcdef, "extract64(0x0123456789abcdef, 0, 64) resulting value mismatch.");
|
||||
|
||||
// Extract none
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
start = rz_il_op_new_bitv_from_ut64(64, 0);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
result = rz_il_extract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0, "extract64(0x0123456789abcdef, 0, 0) resulting value mismatch.");
|
||||
|
||||
// Extract within
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
start = rz_il_op_new_bitv_from_ut64(64, 4);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 5);
|
||||
result = rz_il_extract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x1e, "extract64(0x0123456789abcdef, 4, 5) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_sextract64() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 64, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Extract all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
RzILOpBitVector *start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
RzILOpBitVector *len = rz_il_op_new_bitv_from_ut64(32, 64);
|
||||
RzILOpBitVector *result = rz_il_sextract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0123456789abcdef, "sextract64(0x0123456789abcdef, 0, 64) resulting value mismatch.");
|
||||
|
||||
// Extract none
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
result = rz_il_sextract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0, "sextract64(0x0123456789abcdef, 0, 0) resulting value mismatch.");
|
||||
|
||||
// Extract within
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 28);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 4);
|
||||
result = rz_il_sextract64(val, start, len);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xfffffffffffffff8, "extract64(0x0123456789abcdef, 28, 4) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_deposit32() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Deposit all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(32, 0x00000000);
|
||||
RzILOpBitVector *field = rz_il_op_new_bitv_from_ut64(32, 0xffffffff);
|
||||
RzILOpBitVector *start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
RzILOpBitVector *len = rz_il_op_new_bitv_from_ut64(32, 32);
|
||||
RzILOpBitVector *result = rz_il_deposit32(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xffffffff, "deposit32(0x00000000, 0, 32, 0xffffffff) resulting value mismatch.");
|
||||
|
||||
// Deposit none
|
||||
val = rz_il_op_new_bitv_from_ut64(32, 0x00000000);
|
||||
field = rz_il_op_new_bitv_from_ut64(32, 0xffffffff);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
result = rz_il_deposit32(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0, "deposit32(0x00000000, 0, 0, 0xffffffff) resulting value mismatch.");
|
||||
|
||||
// Deposit within
|
||||
val = rz_il_op_new_bitv_from_ut64(32, 0xffffffff);
|
||||
field = rz_il_op_new_bitv_from_ut64(32, 0x0);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 8);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 7);
|
||||
result = rz_il_deposit32(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xffff80ff, "deposit32(0xffffffff, 8, 7, 0xffff80ff) resulting value mismatch.");
|
||||
|
||||
// Deposit no wrap around
|
||||
val = rz_il_op_new_bitv_from_ut64(32, 0xffffffff);
|
||||
field = rz_il_op_new_bitv_from_ut64(32, 0x0);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 30);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 9);
|
||||
result = rz_il_deposit32(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x3fffffff, "deposit32(0xffffffff, 30, 9, 0x0) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_deposit64() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Deposit all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(64, 0x0);
|
||||
RzILOpBitVector *field = rz_il_op_new_bitv_from_ut64(64, 0xffffffffffffffff);
|
||||
RzILOpBitVector *start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
RzILOpBitVector *len = rz_il_op_new_bitv_from_ut64(32, 64);
|
||||
RzILOpBitVector *result = rz_il_deposit64(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xffffffffffffffff, "deposit64(0x00000000, 0, 64, 0xffffffffffffffff) resulting value mismatch.");
|
||||
|
||||
// Deposit none
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0x0);
|
||||
field = rz_il_op_new_bitv_from_ut64(64, 0xffffffffffffffff);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 0);
|
||||
result = rz_il_deposit64(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x0, "deposit64(0x00000000, 0, 0, 0xffffffffffffffff) resulting value mismatch.");
|
||||
|
||||
// Deposit within
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0xffffffffffffffff);
|
||||
field = rz_il_op_new_bitv_from_ut64(64, 0x0);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 8);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 7);
|
||||
result = rz_il_deposit64(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xffffffffffff80ff, "deposit64(0xffffffffffffffff, 8, 7, 0xffff80ff) resulting value mismatch.");
|
||||
|
||||
// Deposit no wrap around
|
||||
val = rz_il_op_new_bitv_from_ut64(64, 0xffffffffffffffff);
|
||||
field = rz_il_op_new_bitv_from_ut64(64, 0x0);
|
||||
start = rz_il_op_new_bitv_from_ut64(32, 62);
|
||||
len = rz_il_op_new_bitv_from_ut64(32, 9);
|
||||
result = rz_il_deposit64(val, start, len, field);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x3fffffffffffffff, "deposit64(0xffffffffffffffff, 62, 9, 0x0) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_bswap16() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Deposit all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(16, 0x0123);
|
||||
RzILOpBitVector *result = rz_il_bswap16(val);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x2301, "bswap16(0x0123) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_bswap32() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Deposit all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(32, 0x01234567);
|
||||
RzILOpBitVector *result = rz_il_bswap32(val);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0x67452301, "bswap32(0x01234567) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
static bool test_il_bswap64() {
|
||||
RzILSortPure sort;
|
||||
RzILValidateReport report;
|
||||
RzILValidateGlobalContext *ctx = rz_il_validate_global_context_new_empty(24);
|
||||
bool valid = false;
|
||||
RzILVM *vm = rz_il_vm_new(0, 32, false);
|
||||
RzILVal *vm_result = NULL;
|
||||
|
||||
// Deposit all
|
||||
RzILOpBitVector *val = rz_il_op_new_bitv_from_ut64(64, 0x0123456789abcdef);
|
||||
RzILOpBitVector *result = rz_il_bswap64(val);
|
||||
|
||||
valid = rz_il_validate_pure(result, ctx, &sort, &report);
|
||||
mu_assert_true(valid, "invalid pure");
|
||||
vm_result = rz_il_evaluate_val(vm, result);
|
||||
mu_assert_eq(vm_result->data.bv->bits.small_u, 0xefcdab8967452301, "bswap64(0x0123456789abcdef) resulting value mismatch.");
|
||||
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool all_tests() {
|
||||
mu_run_test(test_il_extract32);
|
||||
mu_run_test(test_il_extract64);
|
||||
mu_run_test(test_il_sextract64);
|
||||
mu_run_test(test_il_deposit32);
|
||||
mu_run_test(test_il_deposit64);
|
||||
mu_run_test(test_il_bswap16);
|
||||
mu_run_test(test_il_bswap32);
|
||||
mu_run_test(test_il_bswap64);
|
||||
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
mu_main(all_tests)
|
||||
Loading…
Reference in a new issue