Files
ircolib/external/capstone/suite/cstest/src/test_detail.c
T

428 lines
11 KiB
C

// Copyright © 2024 Rot127 <unisono@quyllur.org>
// SPDX-License-Identifier: BSD-3
#include "test_detail.h"
#include "test_compare.h"
#include <capstone/capstone.h>
TestDetail *test_detail_new()
{
return cs_mem_calloc(sizeof(TestDetail), 1);
}
TestDetail *test_detail_clone(TestDetail *detail)
{
assert(detail);
TestDetail *clone = test_detail_new();
clone->regs_read =
detail->regs_read_count > 0 ?
cs_mem_calloc(sizeof(char *), detail->regs_read_count) :
NULL;
clone->regs_read_count = detail->regs_read_count;
for (size_t i = 0; i < detail->regs_read_count; ++i) {
clone->regs_read[i] = strdup(detail->regs_read[i]);
}
clone->regs_write = detail->regs_write_count > 0 ?
cs_mem_calloc(sizeof(char *),
detail->regs_write_count) :
NULL;
clone->regs_write_count = detail->regs_write_count;
for (size_t i = 0; i < detail->regs_write_count; ++i) {
clone->regs_write[i] = strdup(detail->regs_write[i]);
}
clone->regs_impl_read =
detail->regs_impl_read_count > 0 ?
cs_mem_calloc(sizeof(char *),
detail->regs_impl_read_count) :
NULL;
clone->regs_impl_read_count = detail->regs_impl_read_count;
for (size_t i = 0; i < detail->regs_impl_read_count; ++i) {
clone->regs_impl_read[i] = strdup(detail->regs_impl_read[i]);
}
clone->regs_impl_write =
detail->regs_impl_write_count > 0 ?
cs_mem_calloc(sizeof(char *),
detail->regs_impl_write_count) :
NULL;
clone->regs_impl_write_count = detail->regs_impl_write_count;
for (size_t i = 0; i < detail->regs_impl_write_count; ++i) {
clone->regs_impl_write[i] = strdup(detail->regs_impl_write[i]);
}
clone->groups =
detail->groups_count > 0 ?
cs_mem_calloc(sizeof(char *), detail->groups_count) :
NULL;
clone->groups_count = detail->groups_count;
for (size_t i = 0; i < detail->groups_count; ++i) {
clone->groups[i] = strdup(detail->groups[i]);
}
if (detail->aarch64) {
clone->aarch64 = test_detail_aarch64_clone(detail->aarch64);
}
if (detail->arm) {
clone->arm = test_detail_arm_clone(detail->arm);
}
if (detail->ppc) {
clone->ppc = test_detail_ppc_clone(detail->ppc);
}
if (detail->tricore) {
clone->tricore = test_detail_tricore_clone(detail->tricore);
}
if (detail->alpha) {
clone->alpha = test_detail_alpha_clone(detail->alpha);
}
if (detail->bpf) {
clone->bpf = test_detail_bpf_clone(detail->bpf);
}
if (detail->hppa) {
clone->hppa = test_detail_hppa_clone(detail->hppa);
}
if (detail->xcore) {
clone->xcore = test_detail_xcore_clone(detail->xcore);
}
if (detail->systemz) {
clone->systemz = test_detail_systemz_clone(detail->systemz);
}
if (detail->sparc) {
clone->sparc = test_detail_sparc_clone(detail->sparc);
}
if (detail->sh) {
clone->sh = test_detail_sh_clone(detail->sh);
}
if (detail->mips) {
clone->mips = test_detail_mips_clone(detail->mips);
}
if (detail->riscv) {
clone->riscv = test_detail_riscv_clone(detail->riscv);
}
if (detail->m680x) {
clone->m680x = test_detail_m680x_clone(detail->m680x);
}
if (detail->tms320c64x) {
clone->tms320c64x =
test_detail_tms320c64x_clone(detail->tms320c64x);
}
if (detail->mos65xx) {
clone->mos65xx = test_detail_mos65xx_clone(detail->mos65xx);
}
if (detail->evm) {
clone->evm = test_detail_evm_clone(detail->evm);
}
if (detail->loongarch) {
clone->loongarch =
test_detail_loongarch_clone(detail->loongarch);
}
if (detail->wasm) {
clone->wasm = test_detail_wasm_clone(detail->wasm);
}
if (detail->x86) {
clone->x86 = test_detail_x86_clone(detail->x86);
}
if (detail->m68k) {
clone->m68k = test_detail_m68k_clone(detail->m68k);
}
if (detail->xtensa) {
clone->xtensa = test_detail_xtensa_clone(detail->xtensa);
}
if (detail->arc) {
clone->arc = test_detail_arc_clone(detail->arc);
}
return clone;
}
void test_detail_free(TestDetail *detail)
{
if (!detail) {
return;
}
for (size_t i = 0; i < detail->regs_read_count; ++i) {
cs_mem_free(detail->regs_read[i]);
}
cs_mem_free(detail->regs_read);
for (size_t i = 0; i < detail->regs_write_count; ++i) {
cs_mem_free(detail->regs_write[i]);
}
cs_mem_free(detail->regs_write);
for (size_t i = 0; i < detail->regs_impl_read_count; ++i) {
cs_mem_free(detail->regs_impl_read[i]);
}
cs_mem_free(detail->regs_impl_read);
for (size_t i = 0; i < detail->regs_impl_write_count; ++i) {
cs_mem_free(detail->regs_impl_write[i]);
}
cs_mem_free(detail->regs_impl_write);
for (size_t i = 0; i < detail->groups_count; ++i) {
cs_mem_free(detail->groups[i]);
}
cs_mem_free(detail->groups);
if (detail->aarch64) {
test_detail_aarch64_free(detail->aarch64);
}
if (detail->arm) {
test_detail_arm_free(detail->arm);
}
if (detail->ppc) {
test_detail_ppc_free(detail->ppc);
}
if (detail->tricore) {
test_detail_tricore_free(detail->tricore);
}
if (detail->alpha) {
test_detail_alpha_free(detail->alpha);
}
if (detail->hppa) {
test_detail_hppa_free(detail->hppa);
}
if (detail->bpf) {
test_detail_bpf_free(detail->bpf);
}
if (detail->xcore) {
test_detail_xcore_free(detail->xcore);
}
if (detail->systemz) {
test_detail_systemz_free(detail->systemz);
}
if (detail->sparc) {
test_detail_sparc_free(detail->sparc);
}
if (detail->sh) {
test_detail_sh_free(detail->sh);
}
if (detail->mips) {
test_detail_mips_free(detail->mips);
}
if (detail->riscv) {
test_detail_riscv_free(detail->riscv);
}
if (detail->m680x) {
test_detail_m680x_free(detail->m680x);
}
if (detail->tms320c64x) {
test_detail_tms320c64x_free(detail->tms320c64x);
}
if (detail->mos65xx) {
test_detail_mos65xx_free(detail->mos65xx);
}
if (detail->evm) {
test_detail_evm_free(detail->evm);
}
if (detail->loongarch) {
test_detail_loongarch_free(detail->loongarch);
}
if (detail->wasm) {
test_detail_wasm_free(detail->wasm);
}
if (detail->x86) {
test_detail_x86_free(detail->x86);
}
if (detail->m68k) {
test_detail_m68k_free(detail->m68k);
}
if (detail->xtensa) {
test_detail_xtensa_free(detail->xtensa);
}
if (detail->arc) {
test_detail_arc_free(detail->arc);
}
cs_mem_free(detail);
}
static bool test_reg_rw_access(csh *handle, const cs_insn *insn,
TestDetail *expected)
{
assert(handle && insn && expected);
if (expected->regs_read_count <= 0 && expected->regs_write_count <= 0) {
return true;
}
cs_regs regs_read, regs_write;
uint8_t regs_read_count, regs_write_count;
cs_err err = cs_regs_access(*handle, insn, regs_read, &regs_read_count,
regs_write, &regs_write_count);
if (err != CS_ERR_OK) {
fprintf(stderr, "cs_regs_access() failed with '%s'\n",
cs_strerror(err));
return false;
}
if (expected->regs_read_count > 0) {
compare_uint32_ret(regs_read_count, expected->regs_read_count,
false);
for (size_t i = 0; i < regs_read_count; ++i) {
compare_reg_ret(*handle, regs_read[i],
expected->regs_read[i], false);
}
}
if (expected->regs_write_count > 0) {
compare_uint32_ret(regs_write_count, expected->regs_write_count,
false);
for (size_t i = 0; i < regs_write_count; ++i) {
compare_reg_ret(*handle, regs_write[i],
expected->regs_write[i], false);
}
}
return true;
}
static bool test_impl_reg_rw_access(csh *handle, const cs_insn *insn,
TestDetail *expected)
{
assert(handle && insn && expected);
if (expected->regs_impl_read_count <= 0 &&
expected->regs_impl_write_count <= 0) {
return true;
}
cs_detail *actual = insn->detail;
// Test exclusively the implicitly read or written register.
if (expected->regs_impl_read_count > 0) {
compare_uint32_ret(actual->regs_read_count,
expected->regs_impl_read_count, false);
for (size_t i = 0; i < actual->regs_read_count; ++i) {
compare_reg_ret(*handle, actual->regs_read[i],
expected->regs_impl_read[i], false);
}
}
if (expected->regs_impl_write_count > 0) {
compare_uint32_ret(actual->regs_write_count,
expected->regs_impl_write_count, false);
for (size_t i = 0; i < actual->regs_write_count; ++i) {
compare_reg_ret(*handle, actual->regs_write[i],
expected->regs_impl_write[i], false);
}
}
return true;
}
bool test_expected_detail(csh *handle, const cs_insn *insn,
TestDetail *expected)
{
assert(handle && insn && insn->detail && expected);
cs_detail *actual = insn->detail;
if (!test_reg_rw_access(handle, insn, expected)) {
return false;
}
if (!test_impl_reg_rw_access(handle, insn, expected)) {
return false;
}
if (expected->groups_count > 0) {
compare_uint32_ret(actual->groups_count, expected->groups_count,
false);
for (size_t i = 0; i < actual->groups_count; ++i) {
if (strings_match(cs_group_name(*handle,
actual->groups[i]),
expected->groups[i])) {
continue;
}
compare_enum_ret(actual->groups[i], expected->groups[i],
false);
}
}
if (expected->aarch64) {
return test_expected_aarch64(handle, &actual->aarch64,
expected->aarch64);
}
if (expected->arm) {
return test_expected_arm(handle, &actual->arm, expected->arm);
}
if (expected->ppc) {
return test_expected_ppc(handle, &actual->ppc, expected->ppc);
}
if (expected->tricore) {
return test_expected_tricore(handle, &actual->tricore,
expected->tricore);
}
if (expected->alpha) {
return test_expected_alpha(handle, &actual->alpha,
expected->alpha);
}
if (expected->bpf) {
return test_expected_bpf(handle, &actual->bpf, expected->bpf);
}
if (expected->hppa) {
return test_expected_hppa(handle, &actual->hppa,
expected->hppa);
}
if (expected->xcore) {
return test_expected_xcore(handle, &actual->xcore,
expected->xcore);
}
if (expected->systemz) {
return test_expected_systemz(handle, &actual->systemz,
expected->systemz);
}
if (expected->sparc) {
return test_expected_sparc(handle, &actual->sparc,
expected->sparc);
}
if (expected->sh) {
return test_expected_sh(handle, &actual->sh, expected->sh);
}
if (expected->mips) {
return test_expected_mips(handle, &actual->mips,
expected->mips);
}
if (expected->riscv) {
return test_expected_riscv(handle, &actual->riscv,
expected->riscv);
}
if (expected->m680x) {
return test_expected_m680x(handle, &actual->m680x,
expected->m680x);
}
if (expected->tms320c64x) {
return test_expected_tms320c64x(handle, &actual->tms320c64x,
expected->tms320c64x);
}
if (expected->mos65xx) {
return test_expected_mos65xx(handle, &actual->mos65xx,
expected->mos65xx);
}
if (expected->evm) {
return test_expected_evm(handle, &actual->evm, expected->evm);
}
if (expected->loongarch) {
return test_expected_loongarch(handle, &actual->loongarch,
expected->loongarch);
}
if (expected->wasm) {
return test_expected_wasm(handle, &actual->wasm,
expected->wasm);
}
if (expected->x86) {
return test_expected_x86(handle, &actual->x86, expected->x86);
}
if (expected->m68k) {
return test_expected_m68k(handle, &actual->m68k,
expected->m68k);
}
if (expected->xtensa) {
return test_expected_xtensa(handle, &actual->xtensa,
expected->xtensa);
}
if (expected->arc) {
return test_expected_arc(handle, &actual->arc, expected->arc);
}
return true;
}