Skip to content

Commit

Permalink
cstool: fix cstool cstest
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Jun 9, 2024
1 parent 0953700 commit 7570795
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 62 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -893,9 +893,9 @@ if(CAPSTONE_BUILD_CSTEST)
GIT_REPOSITORY "https://git.cryptomilk.org/projects/cmocka.git"
GIT_TAG "origin/stable-1.1"
GIT_SHALLOW true
CONFIGURE_COMMAND cmake -DBUILD_SHARED_LIBS=OFF ../cmocka_ext/
CONFIGURE_COMMAND cmake -DBUILD_SHARED_LIBS=ON ../cmocka_ext/
BUILD_BYPRODUCTS ${CMOCKA_LIB_DIR}/libcmocka.a
BUILD_COMMAND cmake --build . --config Release
BUILD_COMMAND cmake --build . --config Debug
INSTALL_COMMAND ""
)
add_library(cmocka STATIC IMPORTED)
Expand Down
81 changes: 63 additions & 18 deletions cstool/cstool.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,55 @@
#include <ctype.h>

#include <capstone/capstone.h>
#include "../SStream.h"
#include "../cs_priv.h"
#include "../utils.h"

typedef struct {
char *ptr;
size_t index;
size_t size;
} Stringbuf;

typedef struct {
bool is_stdout;
SStream ss;
Stringbuf ss;
} Stream;

static inline void stream_init_stdout(Stream *s)
static inline void stream_init(Stream *s)
{
assert(s);
memset(s, 0, sizeof(Stream));
}

static inline void stream_init_stream(Stream *s)
{
stream_init(s);
s->ss.ptr = malloc(512);
s->ss.size = 512;
}

static inline void stream_init_stdout(Stream *s)
{
stream_init(s);
s->is_stdout = true;
}

static inline void stream_init_sstream(Stream *s)
static inline char *stringbuf_back(Stringbuf *s)
{
assert(s);
SStream_Init(&s->ss);
return s->ptr + s->index;
}

static inline bool stringbuf_grow(Stringbuf *s, size_t size)
{
assert(s && size > 0);
char *ptr = realloc(s->ptr, size);
if (ptr) {
s->ptr = ptr;
s->size = size;
return true;
}
return false;
}

static inline void stream_printf(Stream *s, const char *fmt, ...)
Expand All @@ -32,13 +63,20 @@ static inline void stream_printf(Stream *s, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
if (s->is_stdout) {
vprintf(fmt, ap);
int res = vprintf(fmt, ap);
s->ss.index += res;
} else {
SStream *ss = &s->ss;
SSTREAM_RETURN_IF_CLOSED(ss);
int ret = cs_vsnprintf(ss->buffer + ss->index,
sizeof(ss->buffer) - (ss->index + 1),
fmt, ap);
Stringbuf *ss = &s->ss;
int ret = cs_vsnprintf(stringbuf_back(&s->ss),
ss->size - ss->index, fmt, ap);
if (ret >= ss->size - ss->index) {
if (!stringbuf_grow(ss, (ss->index + ret) * 2)) {
assert(0);
return;
}
ret = cs_vsnprintf(stringbuf_back(&s->ss), ret + 1, fmt,
ap);
}
ss->index += ret;
}
va_end(ap);
Expand All @@ -50,28 +88,35 @@ static inline void stream_print(Stream *s, const char *x)
if (s->is_stdout) {
printf("%s", x);
} else {
SSTREAM_RETURN_IF_CLOSED(&s->ss);
SStream_concat0(&s->ss, x);
size_t len = strlen(x);
if (s->ss.size <= len + s->ss.index + 1) {
if (!stringbuf_grow(&s->ss, (s->ss.size + len) * 2)) {
assert(0);
return;
}
}
memcpy(stringbuf_back(&s->ss), x, len);
s->ss.index += len;
}
}

static inline void stream_close(Stream *s)
{
assert(s);
if (!s->is_stdout) {
SSTREAM_RETURN_IF_CLOSED(&s->ss);
SStream_Close(&s->ss);
free(s->ss.ptr);
}
stream_init(s);
}

static inline char *stream_as_str(Stream *s)
{
assert(s && !s->is_stdout);
return s->ss.buffer;
return s->ss.ptr;
}

static inline void stream_print_string_hex(Stream *s, const char *comment,
unsigned char *str, size_t len)
unsigned char *str, size_t len)
{
assert(s);
unsigned char *c;
Expand All @@ -86,7 +131,7 @@ static inline void stream_print_string_hex(Stream *s, const char *comment,
static inline void stream_rtrim(Stream *s)
{
assert(s && !s->is_stdout);
char *back = s->ss.buffer+s->ss.index;
char *back = stringbuf_back(&s->ss);
while (isspace(*--back))
;
*(back + 1) = '\0';
Expand Down
14 changes: 7 additions & 7 deletions cstool/cstool_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ void print_insn_detail_aarch64(csh handle, cs_insn *ins, Stream *steam)
case AArch64_OP_MEM:
printf("\t\toperands[%u].type: MEM\n", i);
if (op->mem.base != AArch64_REG_INVALID)
printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
printf("\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
if (op->mem.index != AArch64_REG_INVALID)
printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
printf("\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
if (op->mem.disp != 0)
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
printf("\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
if (ins->detail->aarch64.post_index)
printf("\t\t\tpost-indexed: true\n");
printf("\t\tpost-indexed: true\n");

break;
case AArch64_OP_SME_MATRIX:
Expand Down Expand Up @@ -192,13 +192,13 @@ void print_insn_detail_aarch64(csh handle, cs_insn *ins, Stream *steam)
op->shift.type, op->shift.value);

if (op->ext != AArch64_EXT_INVALID)
printf("\t\t\tExt: %u\n", op->ext);
printf("\t\tExt: %u\n", op->ext);

if (op->vas != AArch64Layout_Invalid)
printf("\t\t\tVector Arrangement Specifier: 0x%x\n", op->vas);
printf("\t\toperands[%u].vas: 0x%x\n", i, op->vas);

if (op->vector_index != -1)
printf("\t\t\tVector Index: %u\n", op->vector_index);
printf("\t\toperands[%u].vector_index: %u\n", i, op->vector_index);
}

if (aarch64->update_flags)
Expand Down
6 changes: 5 additions & 1 deletion cstool/cstool_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ void print_insn_detail(csh handle, cs_arch arch, cs_mode md, cs_insn *ins,
break;
}

print_detail(handle, ins, steam);
if (print_detail) {
print_detail(handle, ins, steam);
} else {
assert(0);
}

if (ins->detail && ins->detail->groups_count) {
int j;
Expand Down
1 change: 1 addition & 0 deletions cstool/cstool_x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <capstone/capstone.h>
#include "cstool.h"
#include "priv.h"

static const char *get_eflag_name(uint64_t flag)
{
Expand Down
4 changes: 2 additions & 2 deletions suite/cstest/Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
SOURCE = src
INCLUDE = include ../../include
INCLUDE = include ../../include ../../cstool
BUILD = build
LIBRARY = -lcapstone -L../..

all:
rm -rf $(BUILD)
mkdir $(BUILD)
$(CC) $(SOURCE)/*.c $(INCLUDE:%=-I %) -g -o $(BUILD)/cstest $(LIBRARY) $(shell pkg-config --libs cmocka) $(shell pkg-config --cflags cmocka)
$(CC) $(SOURCE)/*.c ../../cstool/cstool_*.c $(INCLUDE:%=-I %) -g -o $(BUILD)/cstest $(LIBRARY) $(shell pkg-config --libs cmocka) $(shell pkg-config --cflags cmocka)
cstest:
$(BUILD)/cstest -d ../MC
clean:
Expand Down
75 changes: 50 additions & 25 deletions suite/cstest/src/capstone_test.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* Capstone testing regression */
/* By Do Minh Tuan <[email protected]>, 02-2019 */


#include "../../../cs_priv.h"
#include "cstool.h"
#include "capstone_test.h"
Expand Down Expand Up @@ -39,28 +38,35 @@ void test_single_MC(csh *handle, int mc_mode, char *line)
code[i] = (unsigned char)strtol(list_byte[i], NULL, 16);
}

((struct cs_struct *)(uintptr_t)*handle)->PrintBranchImmNotAsAddress = true;
((struct cs_struct *)(uintptr_t)*handle)->PrintBranchImmNotAsAddress =
true;
count = cs_disasm(*handle, code, size_byte, offset, 0, &insn);
if (count == 0) {
fprintf(stderr, "[ ERROR ] --- %s --- Failed to disassemble given code!\n", list_part[0]);
fprintf(stderr,
"[ ERROR ] --- %s --- Failed to disassemble given code!\n",
list_part[0]);
free_strs(list_part, size_part);
free_strs(offset_opcode, size_offset_opcode);
free_strs(list_byte, size_byte);
free(code);
_fail(__FILE__, __LINE__);
}
if (count > 1) {
fprintf(stderr, "[ ERROR ] --- %s --- Multiple instructions(%d) disassembling doesn't support!\n", list_part[0], count);
fprintf(stderr,
"[ ERROR ] --- %s --- Multiple instructions(%d) disassembling doesn't support!\n",
list_part[0], count);
free_strs(list_part, size_part);
free_strs(offset_opcode, size_offset_opcode);
free_strs(list_byte, size_byte);
free(code);
_fail(__FILE__, __LINE__);
}

for (p = list_part[1]; *p; ++p) *p = tolower(*p);
for (p = list_part[1]; *p; ++p)
if (*p == '\t') *p = ' ';
*p = tolower(*p);
for (p = list_part[1]; *p; ++p)
if (*p == '\t')
*p = ' ';
trim_str(list_part[1]);
strcpy(tmp_mc, list_part[1]);
replace_hex(tmp_mc);
Expand All @@ -78,7 +84,8 @@ void test_single_MC(csh *handle, int mc_mode, char *line)
replace_hex(tmp);
replace_negative(tmp, mc_mode);
replace_tabs(tmp);
for (p = tmp; *p; ++p) *p = tolower(*p);
for (p = tmp; *p; ++p)
*p = tolower(*p);

// Skip ARM because the duplicate disassembly messes with the IT/VPT states
// and laeds to wrong results.
Expand All @@ -89,15 +96,19 @@ void test_single_MC(csh *handle, int mc_mode, char *line)
strcpy(tmp_noreg, insn[0].mnemonic);
if (strlen(insn[0].op_str) > 0) {
tmp_noreg[strlen(insn[0].mnemonic)] = ' ';
strcpy(tmp_noreg + strlen(insn[0].mnemonic) + 1, insn[0].op_str);
strcpy(tmp_noreg + strlen(insn[0].mnemonic) + 1,
insn[0].op_str);
}

trim_str(tmp_noreg);
replace_hex(tmp_noreg);
replace_negative(tmp_noreg, mc_mode);

if (strcmp(tmp, tmp_mc) && strcmp(tmp_noreg, tmp_mc)) {
fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" and \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc, tmp_noreg, tmp_mc);
fprintf(stderr,
"[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" and \"%s\" != \"%s\" )\n",
list_part[0], origin, list_part[1], tmp, tmp_mc,
tmp_noreg, tmp_mc);
free_strs(list_part, size_part);
free_strs(offset_opcode, size_offset_opcode);
free_strs(list_byte, size_byte);
Expand All @@ -106,7 +117,9 @@ void test_single_MC(csh *handle, int mc_mode, char *line)
_fail(__FILE__, __LINE__);
}
} else if (strcmp(tmp, tmp_mc)) {
fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" )\n", list_part[0], origin, list_part[1], tmp, tmp_mc);
fprintf(stderr,
"[ ERROR ] --- %s --- \"%s\" != \"%s\" ( \"%s\" != \"%s\" )\n",
list_part[0], origin, list_part[1], tmp, tmp_mc);
free_strs(list_part, size_part);
free_strs(offset_opcode, size_offset_opcode);
free_strs(list_byte, size_byte);
Expand Down Expand Up @@ -155,8 +168,8 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
int size_offset_opcode;
unsigned long offset;

Stream steam = {0};
stream_init_sstream(&steam);
Stream steam = { 0 };
stream_init_stream(&steam);
list_part = split(line, " == ", &size_part);

offset_opcode = split(list_part[0], ": ", &size_offset_opcode);
Expand All @@ -177,39 +190,51 @@ void test_single_issue(csh *handle, cs_mode mode, char *line, int detail)
for (i = 0; i < count; ++i) {
stream_print(&steam, insn[i].mnemonic);
if (strlen(insn[i].op_str) > 0) {
stream_print(&steam, " ");
stream_print(&steam, insn[i].op_str);
stream_printf(&steam, " %s", insn[i].op_str);
}
if (detail && insn->detail) {
stream_print(&steam, "\n");
print_insn_detail(*handle, ((cs_struct *)*handle)->arch,
((cs_struct *)*handle)->mode,
insn + i, &steam);
}
}

if (detail == 1) {
print_insn_detail(*handle, ((cs_struct*)handle)->arch, ((cs_struct*)handle)->mode, insn, &steam);

if (detail == 1 && insn->detail) {
if (insn->detail->groups_count) {
stream_print(&steam, " ; Groups: ");
for (j = 0; j < insn->detail->groups_count; j++) {
stream_printf(&steam, "%s ", cs_group_name(*handle, insn->detail->groups[j]));
stream_printf(
&steam, "%s ",
cs_group_name(*handle,
insn->detail->groups[j]));
}
}
}

stream_rtrim(&steam);
// list_part_cs_result = split(cs_result, " ; ", &size_part_cs_result);
for (p = list_part[1]; *p; ++p) if (*p == '\t') *p = ' ';
list_part_issue_result = split(list_part[1], " ; ", &size_part_issue_result);
for (p = list_part[1]; *p; ++p)
if (*p == '\t')
*p = ' ';
list_part_issue_result =
split(list_part[1], " ; ", &size_part_issue_result);

for (i = 0; i < size_part_issue_result; ++i) {
trim_str(list_part_issue_result[i]);

if ((strstr(stream_as_str(&steam), list_part_issue_result[i])) == NULL) {
fprintf(stderr, "[ ERROR ] --- %s --- \"%s\" not in \"%s\"\n",
list_part[0], list_part_issue_result[i], stream_as_str(&steam));
if ((strstr(stream_as_str(&steam),
list_part_issue_result[i])) == NULL) {
fprintf(stderr,
"[ ERROR ] --- %s --- \"%s\" not in \"%s\"\n",
list_part[0], list_part_issue_result[i],
stream_as_str(&steam));
cs_free(insn, count);
free_strs(list_part, size_part);
free_strs(list_byte, size_byte);
stream_close(&steam);
// free_strs(list_part_cs_result, size_part_cs_result);
free_strs(list_part_issue_result, size_part_issue_result);
free_strs(list_part_issue_result,
size_part_issue_result);
_fail(__FILE__, __LINE__);
}
}
Expand Down
Loading

0 comments on commit 7570795

Please sign in to comment.