blob: 06a8e2b8403a05c53768ec89d2ee8b8f01e03bd9 [file] [log] [blame]
// Copyright © 2024 Rot127 <unisono@quyllur.org>
// SPDX-License-Identifier: BSD-3
#include "test_compare.h"
#include "test_detail_x86.h"
#include <capstone/capstone.h>
#include <stdio.h>
#include <string.h>
TestDetailX86 *test_detail_x86_new()
{
return cs_mem_calloc(sizeof(TestDetailX86), 1);
}
void test_detail_x86_free(TestDetailX86 *detail)
{
if (!detail) {
return;
}
if (detail->prefix[0]) {
for (size_t i = 0; i < ARR_SIZE(detail->prefix); ++i) {
cs_mem_free(detail->prefix[i]);
}
}
for (size_t i = 0; i < detail->eflags_count; ++i) {
cs_mem_free(detail->eflags[i]);
}
cs_mem_free(detail->eflags);
for (size_t i = 0; i < detail->fpu_flags_count; ++i) {
cs_mem_free(detail->fpu_flags[i]);
}
cs_mem_free(detail->fpu_flags);
for (size_t i = 0; i < detail->operands_count; ++i) {
test_detail_x86_op_free(detail->operands[i]);
}
cs_mem_free(detail->operands);
cs_mem_free(detail->sib_index);
cs_mem_free(detail->sib_base);
cs_mem_free(detail->xop_cc);
cs_mem_free(detail->sse_cc);
cs_mem_free(detail->avx_cc);
cs_mem_free(detail->avx_rm);
cs_mem_free(detail);
}
TestDetailX86 *test_detail_x86_clone(TestDetailX86 *detail)
{
TestDetailX86 *clone = test_detail_x86_new();
clone->sib_index = detail->sib_index ? strdup(detail->sib_index) : NULL;
clone->sib_base = detail->sib_base ? strdup(detail->sib_base) : NULL;
clone->xop_cc = detail->xop_cc ? strdup(detail->xop_cc) : NULL;
clone->sse_cc = detail->sse_cc ? strdup(detail->sse_cc) : NULL;
clone->avx_cc = detail->avx_cc ? strdup(detail->avx_cc) : NULL;
clone->avx_rm = detail->avx_rm ? strdup(detail->avx_rm) : NULL;
if (detail->prefix[0]) {
for (size_t i = 0; i < ARR_SIZE(clone->prefix); ++i) {
clone->prefix[i] = strdup(detail->prefix[i]);
}
}
memcpy(clone->opcode, detail->opcode, sizeof(clone->opcode));
clone->rex = detail->rex;
clone->addr_size = detail->addr_size;
clone->modrm = detail->modrm;
clone->sib = detail->sib;
clone->disp = detail->disp;
clone->sib_scale = detail->sib_scale;
clone->avx_sae = detail->avx_sae;
clone->enc_modrm_offset = detail->enc_modrm_offset;
clone->enc_disp_offset = detail->enc_disp_offset;
clone->enc_disp_size = detail->enc_disp_size;
clone->enc_imm_offset = detail->enc_imm_offset;
clone->enc_imm_size = detail->enc_imm_size;
clone->eflags_count = detail->eflags_count;
clone->eflags = detail->eflags ? cs_mem_calloc(sizeof(char *),
detail->eflags_count) :
NULL;
for (size_t i = 0; clone->eflags && i < detail->eflags_count; ++i) {
clone->eflags[i] =
detail->eflags[i] ? strdup(detail->eflags[i]) : NULL;
}
clone->fpu_flags_count = detail->fpu_flags_count;
clone->fpu_flags =
detail->fpu_flags ?
cs_mem_calloc(sizeof(char *), detail->fpu_flags_count) :
NULL;
for (size_t i = 0; clone->fpu_flags && i < detail->fpu_flags_count;
++i) {
clone->fpu_flags[i] = detail->fpu_flags[i] ?
strdup(detail->fpu_flags[i]) :
NULL;
}
clone->operands_count = detail->operands_count;
clone->operands = detail->operands_count > 0 ?
cs_mem_calloc(sizeof(TestDetailX86Op *),
detail->operands_count) :
NULL;
for (size_t i = 0; i < detail->operands_count; ++i) {
clone->operands[i] =
test_detail_x86_op_clone(detail->operands[i]);
}
return clone;
}
TestDetailX86Op *test_detail_x86_op_new()
{
return cs_mem_calloc(sizeof(TestDetailX86Op), 1);
}
TestDetailX86Op *test_detail_x86_op_clone(TestDetailX86Op *op)
{
TestDetailX86Op *clone = test_detail_x86_op_new();
clone->size = op->size;
clone->type = op->type ? strdup(op->type) : NULL;
clone->access = op->access ? strdup(op->access) : NULL;
clone->reg = op->reg ? strdup(op->reg) : NULL;
clone->imm = op->imm;
clone->mem_segment = op->mem_segment ? strdup(op->mem_segment) : NULL;
clone->mem_base = op->mem_base ? strdup(op->mem_base) : NULL;
clone->mem_index = op->mem_index ? strdup(op->mem_index) : NULL;
clone->mem_scale = op->mem_scale;
clone->mem_disp = op->mem_disp;
clone->avx_bcast = op->avx_bcast ? strdup(op->avx_bcast) : NULL;
clone->avx_zero_opmask = op->avx_zero_opmask;
return clone;
}
void test_detail_x86_op_free(TestDetailX86Op *op)
{
if (!op) {
return;
}
cs_mem_free(op->type);
cs_mem_free(op->access);
cs_mem_free(op->reg);
cs_mem_free(op->mem_segment);
cs_mem_free(op->mem_base);
cs_mem_free(op->mem_index);
cs_mem_free(op->avx_bcast);
cs_mem_free(op);
}
bool test_expected_x86(csh *handle, cs_x86 *actual, TestDetailX86 *expected)
{
assert(handle && actual && expected);
compare_reg_ret(*handle, actual->sib_index, expected->sib_index, false);
compare_reg_ret(*handle, actual->sib_base, expected->sib_base, false);
compare_enum_ret(actual->xop_cc, expected->xop_cc, false);
compare_enum_ret(actual->sse_cc, expected->sse_cc, false);
compare_enum_ret(actual->avx_cc, expected->avx_cc, false);
compare_enum_ret(actual->avx_rm, expected->avx_rm, false);
if (expected->rex) {
compare_uint8_ret(actual->rex, expected->rex, false);
}
if (expected->addr_size) {
compare_uint8_ret(actual->addr_size, expected->addr_size,
false);
}
if (expected->modrm) {
compare_uint8_ret(actual->modrm, expected->modrm, false);
}
if (expected->sib) {
compare_uint8_ret(actual->sib, expected->sib, false);
}
if (expected->disp) {
compare_int64_ret(actual->disp, expected->disp, false);
}
if (expected->sib_scale) {
compare_int8_ret(actual->sib_scale, expected->sib_scale, false);
}
compare_tbool_ret(actual->avx_sae, expected->avx_sae, false);
for (size_t i = 0; i < ARR_SIZE(actual->prefix); ++i) {
compare_enum_ret(actual->prefix[i], expected->prefix[i], false);
}
for (size_t i = 0; i < ARR_SIZE(actual->opcode); ++i) {
if (expected->opcode[i] != 0) {
compare_uint8_ret(actual->opcode[i],
expected->opcode[i], false);
}
}
compare_bit_flags_64_ret(actual->eflags, expected->eflags,
expected->eflags_count, false);
compare_bit_flags_64_ret(actual->fpu_flags, expected->fpu_flags,
expected->fpu_flags_count, false);
if (expected->enc_modrm_offset) {
compare_uint8_ret(actual->encoding.modrm_offset,
expected->enc_modrm_offset, false);
}
if (expected->enc_disp_offset) {
compare_uint8_ret(actual->encoding.disp_offset,
expected->enc_disp_offset, false);
}
if (expected->enc_disp_size) {
compare_uint8_ret(actual->encoding.disp_size,
expected->enc_disp_size, false);
}
if (expected->enc_imm_offset) {
compare_uint8_ret(actual->encoding.imm_offset,
expected->enc_imm_offset, false);
}
if (expected->enc_imm_size) {
compare_uint8_ret(actual->encoding.imm_size,
expected->enc_imm_size, false);
}
if (expected->operands_count == 0) {
return true;
}
compare_uint8_ret(actual->op_count, expected->operands_count, false);
for (size_t i = 0; i < actual->op_count; ++i) {
cs_x86_op *op = &actual->operands[i];
TestDetailX86Op *eop = expected->operands[i];
compare_enum_ret(op->type, eop->type, false);
if (eop->size) {
compare_uint8_ret(op->size, eop->size, false);
}
compare_enum_ret(op->access, eop->access, false);
compare_enum_ret(op->avx_bcast, eop->avx_bcast, false);
compare_tbool_ret(op->avx_zero_opmask, eop->avx_zero_opmask,
false);
switch (op->type) {
default:
fprintf(stderr,
"arm op type %" PRId32 " not handled.\n",
op->type);
return false;
case X86_OP_REG:
compare_reg_ret(*handle, op->reg, eop->reg, false);
break;
case X86_OP_IMM:
compare_int64_ret(op->imm, eop->imm, false);
break;
case X86_OP_MEM:
compare_reg_ret(*handle, op->mem.segment,
eop->mem_segment, false);
compare_reg_ret(*handle, op->mem.base, eop->mem_base,
false);
compare_reg_ret(*handle, op->mem.index, eop->mem_index,
false);
if (eop->mem_disp) {
compare_int64_ret(op->mem.disp, eop->mem_disp,
false);
}
if (eop->mem_scale) {
compare_int_ret(op->mem.scale, eop->mem_scale,
false);
}
break;
}
}
return true;
}