Rizin
unix-like reverse engineering framework and cli tools
load.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2020 thestr4ng3r <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "rz_test.h"
5 
6 #include <assert.h>
7 
8 #define LINEFMT "%s, line %" PFMT64u ": "
9 
11  return RZ_NEW0(RzCmdTest);
12 }
13 
15  if (!test) {
16  return;
17  }
18 #define DO_KEY_STR(key, field) free(test->field.value);
20 #undef DO_KEY_STR
21  free(test);
22 }
23 
24 static char *readline(char *buf, size_t *linesz) {
25  char *end = strchr(buf, '\n');
26  if (end) {
27  size_t len = end - buf;
28  *end = '\0';
29  if (len > 0 && buf[len - 1] == '\r') {
30  buf[len - 1] = '\0';
31  len--;
32  }
33  *linesz = len;
34  return end + 1;
35  } else {
36  *linesz = strlen(buf);
37  return NULL;
38  }
39 }
40 
41 // read the (possibly multiline) string value of some key in the file
42 // e.g. for
43 //
44 // 0 CMDS=<<EOF
45 // 1 Hello
46 // 2 World
47 // 3 EOF
48 // 4 ...
49 //
50 // if nextline is at the beginning of line 1,
51 // read_string_val(&nextline, "<<EOF\0")
52 // will return "Hello\nWorld\n" with nextline being at the beginning of line 4 afterwards.
53 static char *read_string_val(char **nextline, const char *val, ut64 *linenum) {
54  if (val[0] == '\'') {
55  size_t len = strlen(val);
56  if (len > 1 && val[len - 1] == '\'') {
57  eprintf("Error: Invalid string syntax, use <<EOF instead of '...'\n");
58  return NULL;
59  }
60  }
61  if (val[0] == '<' && val[1] == '<') {
62  // <<EOF syntax
63  const char *endtoken = val + 2;
64  if (!*endtoken) {
65  eprintf("Error: Missing opening end token after <<\n");
66  return NULL;
67  }
68  if (strcmp(endtoken, "EOF") != 0) {
69  // In case there will be strings containing "EOF" inside of them, this requirement
70  // can be weakened to only apply for strings which do not contain "EOF".
71  eprintf("Error: End token must be \"EOF\", got \"%s\" instead.", endtoken);
72  return NULL;
73  }
74  RzStrBuf *buf = rz_strbuf_new("");
75  char *line = *nextline;
76  size_t linesz = 0;
77  do {
78  *nextline = readline(line, &linesz);
79  (*linenum)++;
80  char *end = strstr(line, endtoken);
81  if (end != line) {
82  // Require the EOF to be at the beginning of the line.
83  // This means makes it impossible to write multiline tests without a trailing newline.
84  // This requirement could be lifted later if necessary.
85  end = NULL;
86  }
87  if (end) {
88  *end = '\0';
89  }
91  if (end) {
92  return rz_strbuf_drain(buf);
93  } else {
94  rz_strbuf_append(buf, "\n");
95  }
96  } while ((line = *nextline));
97  eprintf("Error: Missing closing end token %s\n", endtoken);
99  return NULL;
100  }
101 
102  return strdup(val);
103 }
104 
106  char *contents = rz_file_slurp(file, NULL);
107  if (!contents) {
108  eprintf("Failed to open file \"%s\"\n", file);
109  return NULL;
110  }
111 
112  RzPVector *ret = rz_pvector_new(NULL);
113  if (!ret) {
114  free(contents);
115  return NULL;
116  }
118  if (!test) {
119  free(contents);
120  rz_pvector_free(ret);
121  return NULL;
122  }
123 
124  ut64 linenum = 0;
125  char *line = contents;
126  size_t linesz;
127  char *nextline;
128  do {
129  nextline = readline(line, &linesz);
130  linenum++;
131  if (!linesz) {
132  continue;
133  }
134  if (*line == '#') {
135  continue;
136  }
137 
138  char *val = strchr(line, '=');
139  if (val) {
140  *val = '\0';
141  val++;
142  } else if (!val && !(strcmp(line, "RUN") == 0)) {
143  eprintf("Error: No value for key \"%s\".\n", line);
144  goto fail;
145  }
146 
147  // RUN is the only cmd without value
148  if (strcmp(line, "RUN") == 0) {
149  test->run_line = linenum;
150  if (!test->cmds.value) {
151  eprintf(LINEFMT "Error: Test without CMDS key\n", file, linenum);
152  goto fail;
153  }
154  if (!(test->expect.value || test->expect_err.value)) {
155  eprintf(LINEFMT "Error: Test without EXPECT or EXPECT_ERR key"
156  " (did you forget an EOF?)\n",
157  file, linenum);
158  goto fail;
159  }
160  rz_pvector_push(ret, test);
162  if (!test) {
163  goto beach;
164  }
165  continue;
166  }
167 
168 #define DO_KEY_STR(key, field) \
169  if (strcmp(line, key) == 0) { \
170  if (test->field.value) { \
171  free(test->field.value); \
172  eprintf(LINEFMT "Warning: Duplicate key \"%s\"\n", file, linenum, key); \
173  } \
174  test->field.line_begin = linenum; \
175  test->field.value = read_string_val(&nextline, val, &linenum); \
176  test->field.line_end = linenum + 1; \
177  if (!test->field.value) { \
178  eprintf(LINEFMT "Error: Failed to read value for key \"%s\"\n", file, linenum, key); \
179  goto fail; \
180  } \
181  continue; \
182  }
183 
184 #define DO_KEY_BOOL(key, field) \
185  if (strcmp(line, key) == 0) { \
186  if (test->field.value) { \
187  eprintf(LINEFMT "Warning: Duplicate key \"%s\"\n", file, linenum, key); \
188  } \
189  test->field.set = true; \
190  /* Strip comment */ \
191  char *cmt = strchr(val, '#'); \
192  if (cmt) { \
193  *cmt = '\0'; \
194  cmt--; \
195  while (cmt > val && *cmt == ' ') { \
196  *cmt = '\0'; \
197  cmt--; \
198  } \
199  } \
200  if (!strcmp(val, "1")) { \
201  test->field.value = true; \
202  } else if (!strcmp(val, "0")) { \
203  test->field.value = false; \
204  } else { \
205  eprintf(LINEFMT "Error: Invalid value \"%s\" for boolean key \"%s\", only \"1\" or \"0\" allowed.\n", file, linenum, val, key); \
206  goto fail; \
207  } \
208  continue; \
209  }
210 
211 #define DO_KEY_NUM(key, field) \
212  if (strcmp(line, key) == 0) { \
213  if (test->field.value) { \
214  eprintf(LINEFMT "Warning: Duplicate key \"%s\"\n", file, linenum, key); \
215  } \
216  test->field.set = true; \
217  /* Strip comment */ \
218  char *cmt = strchr(val, '#'); \
219  if (cmt) { \
220  *cmt = '\0'; \
221  cmt--; \
222  while (cmt > val && *cmt == ' ') { \
223  *cmt = '\0'; \
224  cmt--; \
225  } \
226  } \
227  char *endval; \
228  test->field.value = strtol(val, &endval, 0); \
229  if (!endval || *endval) { \
230  eprintf(LINEFMT "Error: Invalid value \"%s\" for numeric key \"%s\", only numbers allowed.\n", file, linenum, val, key); \
231  goto fail; \
232  } \
233  continue; \
234  }
235 
237 #undef DO_KEY_STR
238 #undef DO_KEY_BOOL
239 #undef DO_KEY_NUM
240 
241  eprintf(LINEFMT "Unknown key \"%s\".\n", file, linenum, line);
242  } while ((line = nextline));
243 beach:
244  free(contents);
245 
246  if (test && (test->name.value || test->cmds.value || test->expect.value)) {
247  eprintf("Warning: found test tokens at the end of \"%s\" without RUN.\n", file);
248  }
250  return ret;
251 fail:
253  test = NULL;
254  rz_pvector_free(ret);
255  ret = NULL;
256  goto beach;
257 }
258 
260  return RZ_NEW0(RzAsmTest);
261 }
262 
264  if (!test) {
265  return;
266  }
267  free(test->disasm);
268  free(test->bytes);
269  free(test->il);
270  free(test);
271 }
272 
273 static bool parse_asm_path(const char *path, RzStrConstPool *strpool, const char **arch_out, const char **cpuout, int *bitsout) {
274  RzList *file_tokens = rz_str_split_duplist(path, RZ_SYS_DIR, true);
275  if (!file_tokens || rz_list_empty(file_tokens)) {
276  rz_list_free(file_tokens);
277  return false;
278  }
279 
280  // Possibilities:
281  // arm
282  // arm_32
283  // arm_cortex_32
284 
285  char *arch = rz_list_last(file_tokens);
286  if (!*arch) {
287  rz_list_free(file_tokens);
288  return false;
289  }
290  char *second = strchr(arch, '_');
291  if (second) {
292  *second = '\0';
293  second++;
294  char *third = strchr(second, '_');
295  if (third) {
296  *third = '\0';
297  third++;
298  *cpuout = rz_str_constpool_get(strpool, second);
299  *bitsout = atoi(third);
300  } else {
301  *cpuout = NULL;
302  *bitsout = atoi(second);
303  }
304  } else {
305  *cpuout = NULL;
306  *bitsout = 0;
307  }
308  *arch_out = rz_str_constpool_get(strpool, arch);
309  rz_list_free(file_tokens);
310  return true;
311 }
312 
314  const char *arch;
315  const char *cpu;
316  int bits;
317  if (!parse_asm_path(file, strpool, &arch, &cpu, &bits)) {
318  eprintf("Failed to parse arch/cpu/bits from path %s\n", file);
319  return NULL;
320  }
321 
322  char *contents = rz_file_slurp(file, NULL);
323  if (!contents) {
324  eprintf("Failed to open file \"%s\"\n", file);
325  return NULL;
326  }
327 
328  RzPVector *ret = rz_pvector_new(NULL);
329  if (!ret) {
330  return NULL;
331  }
332 
333  ut64 linenum = 0;
334  char *line = contents;
335  size_t linesz;
336  char *nextline;
337  do {
338  nextline = readline(line, &linesz);
339  linenum++;
340  if (!linesz) {
341  continue;
342  }
343  if (*line == '#') {
344  continue;
345  }
346 
347  // mode flags
348  int mode = 0;
349  while (*line && *line != ' ') {
350  switch (*line) {
351  case 'a':
353  break;
354  case 'd':
356  break;
357  case 'E':
359  break;
360  case 'B':
362  break;
363  default:
364  eprintf(LINEFMT "Warning: Invalid mode char '%c'\n", file, linenum, *line);
365  goto fail;
366  }
367  line++;
368  }
370  eprintf(LINEFMT "Warning: Mode specifies neither assemble nor disassemble.\n", file, linenum);
371  continue;
372  }
373 
374  // disasm
375  char *disasm = strchr(line, '"');
376  if (!disasm) {
377  eprintf(LINEFMT "Error: Expected \" to begin disassembly.\n", file, linenum);
378  goto fail;
379  }
380  disasm++;
381  char *hex = strchr(disasm, '"');
382  if (!hex) {
383  eprintf(LINEFMT "Error: Expected \" to end disassembly.\n", file, linenum);
384  goto fail;
385  }
386  *hex = '\0';
387  hex++;
388  rz_str_trim(disasm);
389 
390  // hex
391  while (*hex && *hex == ' ') {
392  hex++;
393  }
394 
395  // remove comment at the end of the line
396  char *latecmt = strchr(hex, '#');
397  if (latecmt) {
398  *latecmt = '\0';
399  }
400 
401  // offset (optional)
402  char *offset = strchr(hex, ' ');
403  char *il = NULL;
404  if (offset) {
405  *offset = '\0';
406  offset++;
407 
408  // IL (optional, the entire rest)
409  il = strchr(offset, ' ');
410  if (il) {
411  *il = '\0';
412  il++;
413  }
414  }
415 
416  size_t hexlen = strlen(hex);
417  if (!hexlen) {
418  eprintf(LINEFMT "Error: Expected hex chars.\n", file, linenum);
419  goto fail;
420  }
421  ut8 *bytes = malloc(hexlen);
422  if (!bytes) {
423  break;
424  }
425  int bytesz = rz_hex_str2bin(hex, bytes);
426  if (bytesz == 0) {
427  eprintf(LINEFMT "Error: Expected hex chars.\n", file, linenum);
428  free(bytes);
429  goto fail;
430  }
431  if (bytesz < 0) {
432  eprintf(LINEFMT "Error: Odd number of hex chars: %s\n", file, linenum, hex);
433  free(bytes);
434  goto fail;
435  }
436 
438  if (!test) {
439  free(bytes);
440  goto fail;
441  }
442  test->line = linenum;
443  test->bits = bits;
444  test->arch = arch;
445  test->cpu = cpu;
446  test->mode = mode;
447  char *endptr = NULL;
448  test->offset = offset ? (ut64)strtoull(offset, &endptr, 0) : 0;
449  if (endptr && *endptr) {
450  eprintf(LINEFMT "Error: Invalid offset string: \"%s\"\n", file, linenum, offset);
451  free(bytes);
452  goto fail;
453  }
454  test->disasm = strdup(disasm);
455  test->bytes = bytes;
456  test->bytes_size = (size_t)bytesz;
457  test->il = il ? strdup(il) : NULL;
458  rz_pvector_push(ret, test);
459  } while ((line = nextline));
460 
461 beach:
462  free(contents);
463  return ret;
464 fail:
465  rz_pvector_free(ret);
466  ret = NULL;
467  goto beach;
468 }
469 
471  return RZ_NEW0(RzJsonTest);
472 }
473 
475  if (!test) {
476  return;
477  }
478  free(test->cmd);
479  free(test);
480 }
481 
483  char *contents = rz_file_slurp(file, NULL);
484  if (!contents) {
485  eprintf("Failed to open file \"%s\"\n", file);
486  return NULL;
487  }
488 
489  RzPVector *ret = rz_pvector_new(NULL);
490  if (!ret) {
491  free(contents);
492  return NULL;
493  }
494 
495  ut64 linenum = 0;
496  char *line = contents;
497  size_t linesz;
498  char *nextline;
499  do {
500  nextline = readline(line, &linesz);
501  linenum++;
502  if (!linesz) {
503  continue;
504  }
505  if (*line == '#') {
506  continue;
507  }
508 
509  char *broken_token = strstr(line, "BROKEN");
510  if (broken_token) {
511  *broken_token = '\0';
512  }
513 
514  rz_str_trim(line);
515  if (!*line) {
516  // empty line
517  continue;
518  }
519 
521  if (!test) {
522  break;
523  }
524  test->line = linenum;
525  test->cmd = strdup(line);
526  if (!test->cmd) {
528  break;
529  }
530  test->broken = broken_token ? true : false;
531  rz_pvector_push(ret, test);
532  } while ((line = nextline));
533 
534  free(contents);
535  return ret;
536 }
537 
539  if (!test) {
540  return;
541  }
542  free(test->file);
543  free(test);
544 }
545 
547  if (!test) {
548  return;
549  }
550  switch (test->type) {
551  case RZ_TEST_TYPE_CMD:
552  rz_test_cmd_test_free(test->cmd_test);
553  break;
554  case RZ_TEST_TYPE_ASM:
555  rz_test_asm_test_free(test->asm_test);
556  break;
557  case RZ_TEST_TYPE_JSON:
558  rz_test_json_test_free(test->json_test);
559  break;
560  case RZ_TEST_TYPE_FUZZ:
561  rz_test_fuzz_test_free(test->fuzz_test);
562  break;
563  }
564  free(test);
565 }
566 
569  if (!db) {
570  return NULL;
571  }
574  return db;
575 }
576 
578  if (!db) {
579  return;
580  }
581  rz_pvector_clear(&db->tests);
583  free(db);
584 }
585 
586 static RzTestType test_type_for_path(const char *path, bool *load_plugins) {
588  char *pathdup = strdup(path);
589  RzList *tokens = rz_str_split_list(pathdup, RZ_SYS_DIR, 0);
590  if (!tokens) {
591  return ret;
592  }
593  if (!rz_list_empty(tokens)) {
594  rz_list_pop(tokens);
595  }
596  RzListIter *it;
597  char *token;
598  *load_plugins = false;
599  rz_list_foreach (tokens, it, token) {
600  if (!strcmp(token, "asm")) {
601  ret = RZ_TEST_TYPE_ASM;
602  continue;
603  }
604  if (!strcmp(token, "json")) {
605  ret = RZ_TEST_TYPE_JSON;
606  continue;
607  }
608  if (!strcmp(token, "extras")) {
609  *load_plugins = true;
610  }
611  }
612  rz_list_free(tokens);
613  free(pathdup);
614  return ret;
615 }
616 
617 static inline bool skip_archos(const char *subname) {
618  rz_return_val_if_fail(subname, true);
619  if (!strcmp(subname, RZ_TEST_ARCH_OS)) {
620  return false;
621  }
622  if (rz_str_startswith(subname, "not-")) {
623  const char *neg_subname = subname + strlen("not-");
624  const char *second_dash = strchr(neg_subname, '-');
625  rz_return_val_if_fail(second_dash, true);
626  if (strncmp(neg_subname, RZ_TEST_ARCH_OS, second_dash - neg_subname) &&
627  (rz_str_endswith(RZ_TEST_ARCH_OS, strrchr(subname, '-')) || rz_str_endswith(subname, "-any"))) {
628  return false;
629  }
630  } else {
631  if (rz_str_endswith(subname, "-any")) {
632  if (!strncmp(subname, RZ_TEST_ARCH_OS, strlen(subname) - strlen("-any"))) {
633  return false;
634  }
635  }
636  }
637  return true;
638 }
639 
640 static bool database_load(RzTestDatabase *db, const char *path, int depth) {
641  if (depth <= 0) {
642  eprintf("Directories for loading tests too deep: %s\n", path);
643  return false;
644  }
645  if (rz_file_is_directory(path)) {
646  RzList *dir = rz_sys_dir(path);
647  if (!dir) {
648  return false;
649  }
650  RzListIter *it;
651  const char *subname;
652  RzStrBuf subpath;
653  rz_strbuf_init(&subpath);
654  bool ret = true;
655  rz_list_foreach (dir, it, subname) {
656  if (*subname == '.') {
657  continue;
658  }
659  if (!strcmp(subname, "extras")) {
660  // Only load "extras" dirs if explicitly specified
661  eprintf("Skipping %s" RZ_SYS_DIR "%s because it requires additional dependencies.\n", path, subname);
662  continue;
663  }
664  if ((!strcmp(path, "archos") || rz_str_endswith(path, RZ_SYS_DIR "archos")) && skip_archos(subname)) {
665  eprintf("Skipping %s" RZ_SYS_DIR "%s because it does not match the current platform.\n", path, subname);
666  continue;
667  }
668  rz_strbuf_setf(&subpath, "%s%s%s", path, RZ_SYS_DIR, subname);
669  if (!database_load(db, rz_strbuf_get(&subpath), depth - 1)) {
670  ret = false;
671  break;
672  }
673  }
674  rz_strbuf_fini(&subpath);
675  rz_list_free(dir);
676  return ret;
677  }
678 
679  if (!rz_file_exists(path)) {
680  eprintf("Path \"%s\" does not exist\n", path);
681  return false;
682  }
683 
684  // Not a directory but exists, load a file
685  const char *pooled_path = rz_str_constpool_get(&db->strpool, path);
686  bool load_plugins = false;
687  RzTestType test_type = test_type_for_path(path, &load_plugins);
688  switch (test_type) {
689  case RZ_TEST_TYPE_CMD: {
691  if (!cmd_tests) {
692  return false;
693  }
694  void **it;
695  rz_pvector_foreach (cmd_tests, it) {
696  RzTest *test = RZ_NEW(RzTest);
697  if (!test) {
698  continue;
699  }
700  test->type = RZ_TEST_TYPE_CMD;
701  test->path = pooled_path;
702  test->cmd_test = *it;
703  test->cmd_test->load_plugins = load_plugins;
704  rz_pvector_push(&db->tests, test);
705  }
706  rz_pvector_free(cmd_tests);
707  break;
708  }
709  case RZ_TEST_TYPE_ASM: {
710  RzPVector *asm_tests = rz_test_load_asm_test_file(&db->strpool, path);
711  if (!asm_tests) {
712  return false;
713  }
714  void **it;
715  rz_pvector_foreach (asm_tests, it) {
716  RzTest *test = RZ_NEW(RzTest);
717  if (!test) {
718  continue;
719  }
720  test->type = RZ_TEST_TYPE_ASM;
721  test->path = pooled_path;
722  test->asm_test = *it;
723  rz_pvector_push(&db->tests, test);
724  }
725  rz_pvector_free(asm_tests);
726  break;
727  }
728  case RZ_TEST_TYPE_JSON: {
730  if (!json_tests) {
731  return false;
732  }
733  void **it;
734  rz_pvector_foreach (json_tests, it) {
735  RzTest *test = RZ_NEW(RzTest);
736  if (!test) {
737  continue;
738  }
739  test->type = RZ_TEST_TYPE_JSON;
740  test->path = pooled_path;
741  test->json_test = *it;
742  test->json_test->load_plugins = load_plugins;
743  rz_pvector_push(&db->tests, test);
744  }
745  rz_pvector_free(json_tests);
746  break;
747  }
748  case RZ_TEST_TYPE_FUZZ:
749  // shouldn't come here, fuzz tests are loaded differently
750  break;
751  }
752 
753  return true;
754 }
755 
757  return database_load(db, path, 4);
758 }
759 
760 static void database_load_fuzz_file(RzTestDatabase *db, const char *path, const char *file) {
761  RzFuzzTest *fuzz_test = RZ_NEW(RzFuzzTest);
762  if (!fuzz_test) {
763  return;
764  }
765  fuzz_test->file = strdup(file);
766  if (!fuzz_test->file) {
767  free(fuzz_test);
768  return;
769  }
770  RzTest *test = RZ_NEW(RzTest);
771  if (!test) {
772  free(fuzz_test->file);
773  free(fuzz_test);
774  return;
775  }
776  test->type = RZ_TEST_TYPE_FUZZ;
777  test->fuzz_test = fuzz_test;
778  test->path = rz_str_constpool_get(&db->strpool, path);
779  rz_pvector_push(&db->tests, test);
780 }
781 
783  if (rz_file_is_directory(path)) {
784  RzList *dir = rz_sys_dir(path);
785  if (!dir) {
786  return false;
787  }
788  RzListIter *it;
789  const char *subname;
790  RzStrBuf subpath;
791  rz_strbuf_init(&subpath);
792  bool ret = true;
793  rz_list_foreach (dir, it, subname) {
794  if (*subname == '.') {
795  continue;
796  }
797  rz_strbuf_setf(&subpath, "%s%s%s", path, RZ_SYS_DIR, subname);
798  if (rz_file_is_directory(rz_strbuf_get(&subpath))) {
799  // only load 1 level deep
800  continue;
801  }
803  }
804  rz_strbuf_fini(&subpath);
805  rz_list_free(dir);
806  return ret;
807  }
808 
809  if (!rz_file_exists(path)) {
810  eprintf("Path \"%s\" does not exist\n", path);
811  return false;
812  }
813 
814  // Just a single file
816  return true;
817 }
size_t len
Definition: 6502dis.c:15
static ut32 cpu[32]
Definition: analysis_or1k.c:21
ut16 val
Definition: armass64_const.h:6
static ut8 bytes[32]
Definition: asm_arc.c:23
int bits(struct state *s, int need)
Definition: blast.c:72
#define RZ_API
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
#define true
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
RZ_API RZ_BORROW void * rz_list_last(RZ_NONNULL const RzList *list)
Returns the last element of the list.
Definition: list.c:86
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
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")
static bool database_load(RzTestDatabase *db, const char *path, int depth)
Definition: load.c:640
static char * readline(char *buf, size_t *linesz)
Definition: load.c:24
static char * read_string_val(char **nextline, const char *val, ut64 *linenum)
Definition: load.c:53
#define LINEFMT
Definition: load.c:8
RZ_API RzJsonTest * rz_test_json_test_new(void)
Definition: load.c:470
static void database_load_fuzz_file(RzTestDatabase *db, const char *path, const char *file)
Definition: load.c:760
static RzTestType test_type_for_path(const char *path, bool *load_plugins)
Definition: load.c:586
RZ_API RzPVector * rz_test_load_cmd_test_file(const char *file)
Definition: load.c:105
RZ_API bool rz_test_test_database_load(RzTestDatabase *db, const char *path)
Definition: load.c:756
RZ_API RzTestDatabase * rz_test_test_database_new(void)
Definition: load.c:567
static bool skip_archos(const char *subname)
Definition: load.c:617
RZ_API void rz_test_test_database_free(RzTestDatabase *db)
Definition: load.c:577
RZ_API RzCmdTest * rz_test_cmd_test_new(void)
Definition: load.c:10
#define DO_KEY_NUM(key, field)
RZ_API RzPVector * rz_test_load_json_test_file(const char *file)
Definition: load.c:482
RZ_API void rz_test_fuzz_test_free(RzFuzzTest *test)
Definition: load.c:538
RZ_API void rz_test_test_free(RzTest *test)
Definition: load.c:546
RZ_API bool rz_test_test_database_load_fuzz(RzTestDatabase *db, const char *path)
Definition: load.c:782
RZ_API RzAsmTest * rz_test_asm_test_new(void)
Definition: load.c:259
RZ_API void rz_test_json_test_free(RzJsonTest *test)
Definition: load.c:474
RZ_API void rz_test_cmd_test_free(RzCmdTest *test)
Definition: load.c:14
RZ_API RzPVector * rz_test_load_asm_test_file(RzStrConstPool *strpool, const char *file)
Definition: load.c:313
static bool parse_asm_path(const char *path, RzStrConstPool *strpool, const char **arch_out, const char **cpuout, int *bitsout)
Definition: load.c:273
#define DO_KEY_STR(key, field)
#define DO_KEY_BOOL(key, field)
RZ_API void rz_test_asm_test_free(RzAsmTest *test)
Definition: load.c:263
line
Definition: setup.py:34
-lz4-versions
static const char hex[16]
Definition: print.c:21
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API RzList * rz_str_split_duplist(const char *str, const char *c, bool trim)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3464
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.
Definition: str_trim.c:190
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)
Definition: str.c:3286
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
RZ_API const char * rz_str_constpool_get(RzStrConstPool *pool, const char *str)
Definition: str_constpool.c:19
RZ_API void rz_str_constpool_fini(RzStrConstPool *pool)
Definition: str_constpool.c:15
RZ_API bool rz_str_constpool_init(RzStrConstPool *pool)
Definition: str_constpool.c:10
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API RzList * rz_sys_dir(const char *path)
Definition: sys.c:216
enum rz_test_test_type_t RzTestType
#define RZ_CMD_TEST_FOREACH_RECORD_NOP(name, field)
Definition: rz_test.h:73
#define RZ_TEST_ARCH_OS
Definition: rz_test.h:33
@ RZ_TEST_TYPE_JSON
Definition: rz_test.h:122
@ RZ_TEST_TYPE_ASM
Definition: rz_test.h:121
@ RZ_TEST_TYPE_FUZZ
Definition: rz_test.h:123
@ RZ_TEST_TYPE_CMD
Definition: rz_test.h:120
#define RZ_CMD_TEST_FOREACH_RECORD(macro_str, macro_bool, macro_int)
Definition: rz_test.h:74
@ RZ_ASM_TEST_MODE_BIG_ENDIAN
Definition: rz_test.h:91
@ RZ_ASM_TEST_MODE_BROKEN
Definition: rz_test.h:92
@ RZ_ASM_TEST_MODE_ASSEMBLE
Definition: rz_test.h:89
@ RZ_ASM_TEST_MODE_DISASSEMBLE
Definition: rz_test.h:90
#define RZ_SYS_DIR
Definition: rz_types.h:218
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEW(x)
Definition: rz_types.h:285
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
int size_t
Definition: sftypes.h:40
Definition: gzappend.c:170
RzStrConstPool strpool
Definition: rz_test.h:139
#define fail(test)
Definition: tests.h:29
ut64(WINAPI *w32_GetEnabledXStateFeatures)()