Add several common bit operations to RzIL. (#3977)

This commit is contained in:
Rot127 2023-12-03 16:23:41 +00:00 committed by GitHub
parent 6b9d56282c
commit 1ec21a8d32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 583 additions and 9 deletions

View file

@ -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
View 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;
}

View file

@ -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',

View file

@ -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

View file

@ -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

View file

@ -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 //

View file

@ -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
View 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)