10 #define Color_INSERT Color_BGREEN
11 #define Color_DELETE Color_BRED
12 #define Color_BGINSERT "\x1b[48;5;22m"
13 #define Color_BGDELETE "\x1b[48;5;52m"
14 #define Color_HLINSERT Color_BGINSERT Color_INSERT
15 #define Color_HLDELETE Color_BGDELETE Color_DELETE
17 #define WORKERS_DEFAULT 8
18 #define RIZIN_CMD_DEFAULT "rizin"
19 #define RZ_ASM_CMD_DEFAULT "rz-asm"
20 #define JSON_TEST_FILE_DEFAULT "bins/elf/crackme0x00b"
21 #define TIMEOUT_DEFAULT 960
24 #define STR(x) STRV(x)
25 #define WORKERS_DEFAULT_STR STR(WORKERS_DEFAULT)
26 #define TIMEOUT_DEFAULT_STR STR(TIMEOUT_DEFAULT)
63 printf(
"Usage: rz-test [-qvVnL] [-j threads] [test file/dir | @test-type]\n");
66 " -h print this help\n"
70 " -i interactive mode\n"
71 " -n do nothing (don't run any test, just load/parse them)\n"
72 " -L log mode (better printing for CI, logfiles, etc.)\n"
73 " -F [dir] run fuzz tests (open and default analysis) on all files in the given dir\n"
74 " -j [threads] how many threads to use for running tests concurrently (default is " WORKERS_DEFAULT_STR ")\n"
78 " -C [dir] chdir before running rz-test (default follows executable symlink + test/new\n"
80 " -o [file] output test run information in JSON format to file\n"
81 " -e [dir] exclude a particular directory while testing (this option can appear many times)\n"
82 " -s [num] number of expected successful tests\n"
83 " -x [num] number of expected failed tests"
85 "Supported test types: @json @unit @fuzz @cmds\n"
101 char src_path[PATH_MAX];
105 ssize_t linklen =
readlink(rz_test_path, src_path,
sizeof(src_path) - 1);
107 src_path[linklen] =
'\0';
113 if (
chdir(src_path) != -1) {
114 eprintf(
"Running from %s\n", src_path);
117 eprintf(
"Cannot find '%s' directory\n", src_path);
122 eprintf(
"Cannot follow the link %s\n", src_path);
136 if (!test_path || *test_path ==
'@') {
146 if (
chdir(abs_test_path) == -1) {
153 char *old_cwd =
NULL;
156 if (old_cwd && !strcmp(old_cwd,
cwd)) {
176 if (
chdir(
"..") == -1) {
192 bool interactive =
false;
193 char *rizin_cmd =
NULL;
194 char *rz_asm_cmd =
NULL;
195 char *json_test_file =
NULL;
196 char *output_file =
NULL;
197 char *fuzz_dir =
NULL;
199 const char *rz_test_dir =
NULL;
201 st64 expect_succ = -1;
202 st64 expect_fail = -1;
212 UINT old_cp = GetConsoleOutputCP();
214 HANDLE streams[] = { GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE) };
261 workers_count = atoi(opt.
arg);
262 if (workers_count <= 0) {
263 eprintf(
"Invalid thread count\n");
273 rz_test_dir = opt.
arg;
283 free(json_test_file);
287 timeout_sec = strtoull(opt.
arg,
NULL, 0);
303 RZ_LOG_ERROR(
"Number of expected successful tests is invalid\n");
310 RZ_LOG_ERROR(
"Number of expected failed tests is invalid\n");
322 if (
chdir(rz_test_dir) == -1) {
323 eprintf(
"Cannot find %s directory.\n", rz_test_dir);
328 bool dir_found = (opt.
ind < argc &&
argv[opt.
ind][0] !=
'.')
332 eprintf(
"Cannot find db/ directory related to the given test.\n");
339 char *
tmp = fuzz_dir;
345 eprintf(
"Subprocess init failed\n");
361 state.run_config.rz_cmd = rizin_cmd;
362 state.run_config.rz_asm_cmd = rz_asm_cmd;
389 if (opt.
ind < argc) {
392 for (
i = opt.
ind;
i < argc;
i++) {
394 char *alloc_arg =
NULL;
398 if (!strcmp(
arg,
"unit")) {
404 }
else if (!strcmp(
arg,
"fuzz")) {
406 eprintf(
"No fuzz dir given. Use -F [dir]\n");
411 eprintf(
"Failed to load fuzz tests from \"%s\"\n", fuzz_dir);
414 }
else if (!strcmp(
arg,
"json")) {
416 }
else if (!strcmp(
arg,
"dasm")) {
418 }
else if (!strcmp(
arg,
"cmds")) {
426 eprintf(
"Failed to load tests from \"%s\"\n", tf);
439 eprintf(
"Failed to load tests from ./db\n");
445 eprintf(
"Failed to load fuzz tests from \"%s\"\n", fuzz_dir);
473 printf(
"Loaded %u tests.\n", loaded_tests);
480 eprintf(
"Skipping json tests because jq is not available.\n");
496 eprintf(
"No tests discovered\n");
503 if (
state.path_left) {
510 ht_pp_insert(
state.path_left,
test->path, counts);
522 for (
i = 0;
i < workers_count;
i++) {
525 eprintf(
"Failed to start thread.\n");
533 ut64 prev_paths_completed = 0;
538 }
else if (completed != prev_completed) {
541 prev_completed = completed;
564 ut64 minutes = seconds / 60;
566 seconds -= (minutes * 60);
581 if (expect_succ > 0 && expect_succ !=
state.ok_count) {
585 if (expect_fail > 0 && expect_fail !=
state.xx_count) {
589 if (expect_fail < 0 && expect_succ < 0 &&
state.xx_count) {
600 ht_pp_free(
state.path_left);
605 free(json_test_file);
610 (void)SetConsoleOutputCP(old_cp);
623 switch (
test->type) {
626 pj_ks(pj,
"name",
test->cmd_test->name.value);
640 pj_ks(pj,
"file",
test->fuzz_test->file);
693 if (
state->path_left) {
722 static void print_diff(
const char *actual,
const char *expected,
const char *regexp) {
725 const char *
output = actual;
753 const char *envvars[],
const char *envvals[],
size_t env_size,
ut64 timeout_ms,
void *user) {
755 for (
i = 0;
i < env_size;
i++) {
756 printf(
"%s=%s ", envvars[
i], envvals[
i]);
759 for (
i = 0;
i < args_size;
i++) {
761 if (strpbrk(
str,
"\n \'\"")) {
808 expect_hex ? expect_hex :
"",
809 test->il ?
" ---> <IL>" :
"");
812 const char *actual =
out->disasm;
814 printf(
"-- disassembly\n");
820 if (
out->bytes && (
out->bytes_size !=
test->bytes_size || memcmp(
out->bytes,
test->bytes,
out->bytes_size))) {
822 print_diff(actual ? actual :
"", expect_hex ? expect_hex :
"",
NULL);
828 const char *actual =
out->il;
829 const char *report =
out->il_report;
830 bool il_printed =
false;
831 const char *hdr =
"-- IL\n";
865 for (
i = prev_completed;
i < completed;
i++) {
867 if (
state->test_results) {
910 setvbuf(stdout,
NULL, _IOFBF, 8192);
917 while (
w >= 0 &&
w < 20) {
925 setvbuf(stdout,
NULL, _IONBF, 0);
932 for (; prev_paths_completed < paths_completed; prev_paths_completed++) {
935 name =
"unknown path. something is very wrong.";
938 if (
state->path_left) {
968 (void)SetConsoleOutputCP(65001);
971 printf(
"#####################\n");
981 printf(
"#####################\n\n");
994 if (!fgets(
buf,
sizeof(
buf), stdin)) {
997 if (strlen(
buf) != 2) {
1003 printf(
"This test has failed too hard to be fixed.\n");
1013 if (have_commands) {
1033 if (strchr(
val,
'\n')) {
1042 const char *begin =
src;
1045 begin = strchr(begin,
'\n');
1056 const char *
end = begin;
1085 if (result->
test->
path != edited_file) {
1091 #define DO_KEY_STR(key, field) \
1092 if (test->field.value) { \
1093 if (test->field.line_begin >= start_line) { \
1094 test->field.line_begin += delta; \
1096 if (test->field.line_end >= start_line) { \
1097 test->field.line_end += delta; \
1101 #define DO_KEY_BOOL(key, field) \
1102 if (test->field.set && test->field.line >= start_line) { \
1103 test->field.line += delta; \
1106 #define DO_KEY_NUM(key, field) \
1107 if (test->field.set && test->field.line >= start_line) { \
1108 test->field.line += delta; \
1142 char *newc =
replace_lines(content, line_begin, line_end, kv);
1147 size_t lines_before = line_end - line_begin;
1149 if (line_end == line_begin) {
1177 if (
test->expect.value &&
out->out) {
1180 if (
test->expect_err.value &&
out->err) {
1191 char *newc =
replace_lines(content, line_idx, line_idx + 1, line_new);
1206 char offset_str[0x20];
1215 disasm,
hex, offset_str, il ?
" " :
"", il ? il :
"");
1234 if (
out->disasm && !strcmp(
test->disasm,
out->disasm)) {
1238 if (
out->bytes &&
out->bytes_size ==
test->bytes_size && !memcmp(
out->bytes,
test->bytes,
test->bytes_size)) {
1259 bytes_sz =
out->bytes_size;
1262 bytes_sz =
test->bytes_size;
1273 if (
test->il && (
out->il_failed || !
out->il)) {
1298 if (
test->broken.set) {
1299 line_begin =
test->broken.set;
1300 line_end = line_begin + 1;
1302 line_begin = line_end =
test->run_line;
1330 if (!
test->cmds.value) {
1337 eprintf(
"Failed to open tmp file\n");
1340 size_t cmds_sz = strlen(
test->cmds.value);
1341 if (
write(
fd,
test->cmds.value, cmds_sz) != cmds_sz) {
1342 eprintf(
"Failed to write to tmp file\n");
1350 if (!editor || !*editor) {
1363 eprintf(
"Failed to read edited command file\n");
1370 if (strchr(newcmds,
'\n')) {
1371 char *
tmp = newcmds;
1387 int ret =
rz_test_main(argc, (
const char **)utf8_argv);
RZ_API RzTestResultInfo * rz_test_run_test(RzTestRunConfig *config, RzTest *test)
RZ_API RzSubprocessOutput * rz_test_run_cmd_test(RzTestRunConfig *config, RzCmdTest *test, RzTestCmdRunner runner, void *user)
RZ_API bool rz_test_check_jq_available(void)
RZ_API bool rz_test_cmp_cmd_output(const char *output, const char *expect, const char *regexp)
RZ_API RzSubprocessOutput * rz_test_run_fuzz_test(RzTestRunConfig *config, RzFuzzTest *test, RzTestCmdRunner runner, void *user)
RZ_API void rz_test_test_result_info_free(RzTestResultInfo *result)
RZ_API char * rz_test_test_name(RzTest *test)
const lzma_allocator const uint8_t size_t uint8_t * out
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
static static fork const void static count static fd const char const char static newpath const char static path const char path
static static fork const void static count static fd const char const char static newpath chdir
static static fork const void static count close
static static sync static getppid static getegid const char static filename char static len readlink
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
RZ_API RZ_OWN RzDiff * rz_diff_lines_new(RZ_BORROW const char *a, RZ_BORROW const char *b, RZ_NULLABLE RzDiffIgnoreLine ignore)
Returns the structure needed to diff lines.
RZ_API void rz_diff_free(RZ_NULLABLE RzDiff *diff)
frees the diff structure
RZ_API void Ht_() free(HtName_(Ht) *ht)
RZ_API const KEY_TYPE bool * found
RZ_API RZ_OWN char * rz_list_to_str(RZ_NONNULL RzList *list, char ch)
Casts a RzList containg strings into a concatenated string.
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
RZ_API RZ_OWN RzThread * rz_th_new(RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
Creates and starts a new thread.
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
void * calloc(size_t number, size_t size)
static static fork const void static count static fd const char const char static newpath char char argv
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API bool rz_test_test_database_load(RzTestDatabase *db, const char *path)
RZ_API RzTestDatabase * rz_test_test_database_new(void)
RZ_API void rz_test_test_database_free(RzTestDatabase *db)
RZ_API void rz_test_test_free(RzTest *test)
RZ_API bool rz_test_test_database_load_fuzz(RzTestDatabase *db, const char *path)
#define expect(expr, value)
assert(limit<=UINT32_MAX/2)
static const char hex[16]
static char * replace_cmd_kv(const char *path, const char *content, size_t line_begin, size_t line_end, const char *key, const char *value, RzPVector *fixup_results)
#define WORKERS_DEFAULT_STR
static void print_result_diff(RzTestRunConfig *config, RzTestResultInfo *result)
static int help(bool verbose)
static bool interact_fix_cmd(RzTestResultInfo *result, RzPVector *fixup_results)
static bool interact_fix_asm(RzTestResultInfo *result)
static void path_left_free_kv(HtPPKv *kv)
#define RIZIN_CMD_DEFAULT
static void interact_break(RzTestResultInfo *result, RzPVector *fixup_results)
#define RZ_ASM_CMD_DEFAULT
static void save_test_file_for_fix(const char *path, const char *newc)
struct rz_test_state_t RzTestState
struct rz_testfile_counts_t RzTestFileCounts
static char * format_cmd_kv(const char *key, const char *val)
static void test_result_to_json(PJ *pj, RzTestResultInfo *result)
static void print_new_results(RzTestState *state, ut64 prev_completed)
#define DO_KEY_NUM(key, field)
static void interact(RzTestState *state)
static char * read_test_file_for_fix(const char *path)
static bool rz_test_chdir(const char *argv0)
static void replace_file_line(const char *path, ut64 line_idx, const char *line_new)
static void print_log(RzTestState *state, ut64 prev_completed, ut64 prev_paths_completed)
static void replace_asm_test(RZ_NONNULL const char *path, ut64 line_idx, int mode, RZ_NONNULL const char *disasm, RZ_NONNULL const ut8 *bytes, size_t bytes_sz, ut64 offset, RZ_NULLABLE const char *il)
static char * replace_lines(const char *src, size_t from, size_t to, const char *news)
static void print_diff(const char *actual, const char *expected, const char *regexp)
static void replace_cmd_kv_file(const char *path, ut64 line_begin, ut64 line_end, const char *key, const char *value, RzPVector *fixup_results)
#define TIMEOUT_DEFAULT_STR
int rz_test_main(int argc, const char **argv)
static bool rz_test_test_run_unit(void)
#define JSON_TEST_FILE_DEFAULT
static void print_state(RzTestState *state, ut64 prev_completed)
static void fixup_tests(RzPVector *results, const char *edited_file, ut64 start_line, st64 delta)
static void interact_commands(RzTestResultInfo *result, RzPVector *fixup_results)
static bool asm_test_failed_both_ways(RzAsmTest *test, RzAsmTestOutput *out)
static bool rz_test_chdir_fromtest(const char *test_path)
static void interact_break_cmd(RzTestResultInfo *result, RzPVector *fixup_results)
static void interact_break_asm(RzTestResultInfo *result)
static RzSubprocessOutput * print_runner(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user)
static void * worker_th(RzTestState *state)
#define DO_KEY_STR(key, field)
int MAIN_NAME(int argc, const ARGV_TYPE **argv)
#define DO_KEY_BOOL(key, field)
static bool interact_fix(RzTestResultInfo *result, RzPVector *fixup_results)
static void print_state_counts(RzTestState *state)
#define rz_return_if_fail(expr)
#define RZ_CONS_CLEAR_LINE
#define UTF8_POLICE_CARS_REVOLVING_LIGHT
#define RZ_CONS_CURSOR_UP
#define UTF8_SEE_NO_EVIL_MONKEY
#define UTF8_WHITE_HEAVY_CHECK_MARK
#define UTF8_SKULL_AND_CROSSBONES
RZ_API bool rz_file_is_directory(const char *str)
RZ_API bool rz_file_is_abspath(const char *file)
RZ_API char * rz_file_abspath(const char *file)
RZ_API int rz_file_mkstemp(RZ_NULLABLE const char *prefix, char **oname)
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
RZ_API bool rz_file_dump(const char *file, const ut8 *buf, int len, bool append)
RZ_API char * rz_file_path(const char *bin)
RZ_API char * rz_file_abspath_rel(const char *cwd, const char *file)
RZ_API void rz_getopt_init(RzGetopt *go, int argc, const char **argv, const char *ostr)
RZ_API int rz_getopt_next(RzGetopt *opt)
RZ_API char * rz_hex_bin2strdup(const ut8 *in, int len)
#define RZ_LOG_ERROR(fmtstr,...)
#define ARGV_TYPE_TO_UTF8(argc, argv)
#define FREE_UTF8_ARGV(argc, utf8_argv)
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
RZ_API int rz_num_is_valid_input(RzNum *num, const char *input_value)
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
RZ_API char * pj_drain(PJ *j)
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
RZ_API PJ * pj_k(PJ *j, const char *k)
RZ_API PJ * pj_end(PJ *j)
RZ_API PJ * pj_s(PJ *j, const char *k)
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
RZ_API RzList * rz_regex_get_match_list(const char *pattern, const char *flags, const char *text)
RZ_API int rz_str_char_count(const char *string, char ch)
RZ_API const char * rz_str_lchr(const char *str, char chr)
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
RZ_API char * rz_str_version(const char *program)
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
RZ_API bool rz_strbuf_append_n(RzStrBuf *sb, const char *s, size_t l)
RZ_API void rz_subprocess_fini(void)
RZ_API bool rz_subprocess_init(void)
RZ_API int rz_sys_cmdf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
RZ_API int rz_sys_setenv(const char *key, const char *value)
Set an environment variable in the calling process.
RZ_API bool rz_sys_chdir(RZ_NONNULL const char *s)
Change current directory to s, taking care of home expansion ~.
RZ_API int rz_sys_system(const char *command)
RZ_API char * rz_sys_getdir(void)
Get current working directory.
#define RZ_CMD_TEST_FOREACH_RECORD(macro_str, macro_bool, macro_int)
@ RZ_ASM_TEST_MODE_BIG_ENDIAN
@ RZ_ASM_TEST_MODE_BROKEN
@ RZ_ASM_TEST_MODE_ASSEMBLE
@ RZ_ASM_TEST_MODE_DISASSEMBLE
void *(* RzThreadFunction)(void *user)
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
RZ_API void * rz_pvector_pop(RzPVector *vec)
static void ** rz_pvector_insert_range(RzPVector *vec, size_t index, void **first, size_t count)
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
static size_t rz_pvector_len(const RzPVector *vec)
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
void(* RzPVectorFree)(void *e)
static bool rz_pvector_empty(RzPVector *vec)
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
static void ** rz_pvector_push(RzPVector *vec, void *x)
RZ_API void rz_pvector_free(RzPVector *vec)
RZ_API void rz_pvector_clear(RzPVector *vec)
static void * rz_pvector_at(const RzPVector *vec, size_t index)
#define rz_pvector_foreach(vec, it)
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
ut8 * out
< Output generated by the process
int ret
True if the process has exited because of a timeout.
ut8 * err
Number of bytes in the err field.
RzCmdTestStringRecord expect
RzCmdTestStringRecord regexp_out
RzCmdTestStringRecord regexp_err
RzCmdTestStringRecord expect_err
RzTestRunConfig run_config
RzPVector completed_paths
RzAsmTestOutput * asm_out
RzSubprocessOutput * proc_out
struct child_worker * workers
RZ_API void rz_th_cond_free(RZ_NULLABLE RzThreadCond *cond)
Frees a RzThreadCond struct.
RZ_API void rz_th_cond_signal(RZ_NONNULL RzThreadCond *cond)
This function shall unblock at least one of the threads that are blocked on the specified condition.
RZ_API void rz_th_cond_wait(RZ_NONNULL RzThreadCond *cond, RZ_NONNULL RzThreadLock *lock)
The function shall block on a condition variable and shall be called with RzThreadLock locked by the ...
RZ_API RZ_OWN RzThreadCond * rz_th_cond_new(void)
Condition variables are intended to be used to communicate changes in the state of data shared betwee...
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
RZ_API RZ_OWN char * rz_diff_unified_text(RZ_NONNULL RzDiff *diff, RZ_NULLABLE const char *from, RZ_NULLABLE const char *to, bool show_time, bool color)
Produces a diff output with A and B inputs presented immediately adjacent to each other.
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING
if(dbg->bits==RZ_SYS_BITS_64)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static void nothing(void)
static const z80_opcode fd[]