Rizin
unix-like reverse engineering framework and cli tools
vmenus.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <string.h>
5 
6 #include <rz_core.h>
7 #include <rz_util.h>
8 
9 #include "../core_private.h"
10 #include <rz_asm.h>
11 #include <rz_util/rz_print.h>
12 #include <rz_util/rz_strbuf.h>
13 
14 #define MAX_FORMAT 3
15 
16 enum {
20  RZ_QWORD_DATA = 8
21 };
22 
23 enum {
27 };
28 
29 // TODO: move this helper into rz_cons
30 static char *prompt(const char *str, const char *txt) {
31  char cmd[1024];
32  char *res = NULL;
33  char *oprompt = strdup(rz_cons_singleton()->line->prompt);
34  rz_cons_show_cursor(true);
35  if (txt && *txt) {
36  free(rz_cons_singleton()->line->contents);
38  } else {
39  RZ_FREE(rz_cons_singleton()->line->contents);
40  }
41  *cmd = '\0';
43  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
44  *cmd = '\0';
45  }
46  // line[strlen(line)-1]='\0';
47  if (*cmd) {
48  res = strdup(cmd);
49  }
50  rz_line_set_prompt(oprompt);
51  free(oprompt);
52  RZ_FREE(rz_cons_singleton()->line->contents);
53  return res;
54 }
55 
56 static int rotate_nibble(const ut8 b, int dir) {
57  if (dir > 0) {
58  bool high = b >> 7;
59  return (b << 1) | high;
60  }
61  bool lower = b & 1;
62  return (b >> 1) | (lower << 7);
63 }
64 
65 static int wordpos(const char *esil, int n) {
66  const char *w = esil;
67  if (n < 1) {
68  n = 0;
69  }
70  while (w && n--) {
71  const char *nw = strchr(w + 1, ',');
72  if (!nw) {
73  return strlen(esil);
74  }
75  w = nw;
76  }
77  if (!w && n > 0) {
78  return strlen(esil);
79  }
80  return (size_t)(w - esil);
81 }
82 
83 static void showreg(RzAnalysisEsil *esil, const char *rn, const char *desc) {
84  ut64 nm = 0;
85  int sz = 0;
86  rz_cons_printf("%s 0x%08" PFMT64x " (%d) ; %s\n", rn, nm, sz, desc);
87 }
88 
90  const int nbits = sizeof(ut64) * 8;
91  char *word = NULL;
92  int x = 0;
93  RzAsmOp asmop;
95  ut8 buf[sizeof(ut64)];
96  unsigned int addrsize = rz_config_get_i(core->config, "esil.addr.size");
97 
98  if (core->blocksize < sizeof(ut64)) {
99  return false;
100  }
101  memcpy(buf, core->block, sizeof(ut64));
102  RzAnalysisEsil *esil = rz_analysis_esil_new(20, 0, addrsize);
103  esil->analysis = core->analysis;
104  rz_analysis_esil_set_pc(esil, core->offset);
105  for (;;) {
106  rz_cons_clear00();
107  // bool use_color = core->print->flags & RZ_PRINT_FLAGS_COLOR;
108  (void)rz_asm_disassemble(core->rasm, &asmop, buf, sizeof(ut64));
109  analop.type = -1;
110  (void)rz_analysis_op(core->analysis, &analop, core->offset, buf, sizeof(ut64), RZ_ANALYSIS_OP_MASK_ESIL);
111  rz_cons_printf("rizin's esil debugger:\n\n");
112  rz_cons_printf("pos: %d\n", x);
113  {
114  char *op_hex = rz_asm_op_get_hex(&asmop);
115  char *res = rz_print_hexpair(core->print, op_hex, -1);
116  rz_cons_printf("hex: %s\n" Color_RESET, res);
117  free(res);
118  free(op_hex);
119  }
120  {
121  RzStrBuf *colored_asm;
123  colored_asm = rz_asm_colorize_asm_str(&asmop.buf_asm, core->print, param, asmop.asm_toks);
124  free(param);
125  rz_cons_printf(Color_RESET "asm: %s\n" Color_RESET, rz_strbuf_get(colored_asm));
126  rz_strbuf_free(colored_asm);
127  }
128  {
129  const char *expr = rz_strbuf_get(&analop.esil);
131  int wp = wordpos(expr, x);
132  char *pas = strdup(rz_str_pad(' ', wp ? wp + 1 : 0));
133  int wp2 = wordpos(expr, x + 1);
134  free(word);
135  word = rz_str_ndup(expr + (wp ? (wp + 1) : 0), (wp2 - wp) - (wp ? 1 : 0));
136  if (wp == wp2) {
137  // x --;
138  eprintf("Done\n");
139  x = 0;
140  rz_sys_sleep(1);
141  free(pas);
142  continue;
143  }
144  const char *pad = rz_str_pad('-', wp2 - ((wp > 0) ? wp + 1 : 0));
145  rz_cons_printf(Color_RESET " %s%s\n" Color_RESET, pas, pad);
146  free(pas);
147  // free (pad);
148  }
149  rz_cons_printf("esil regs:\n");
150  showreg(esil, "$$", "address");
151  showreg(esil, "$z", "zero");
152  showreg(esil, "$b", "borrow");
153  showreg(esil, "$c", "carry");
154  showreg(esil, "$o", "overflow");
155  showreg(esil, "$p", "parity");
156  showreg(esil, "$r", "regsize");
157  showreg(esil, "$s", "sign");
158  showreg(esil, "$d", "delay");
159  showreg(esil, "$j", "jump");
160 
161  rz_cons_printf("regs:\n");
162  char *r = rz_core_cmd_str(core, "dr=");
163  if (r) {
164  rz_cons_printf("%s", r);
165  free(r);
166  }
167  rz_cons_printf("esil stack:\n");
170  rz_cons_newline();
172 
173  int ch = rz_cons_readchar();
174  if (ch == -1 || ch == 4) {
175  break;
176  }
177  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
178  switch (ch) {
179  case 'Q':
180  case 'q':
181  goto beach;
182  case 's':
183  eprintf("step ((%s))\n", word);
184  rz_sys_usleep(500);
185  x = RZ_MIN(x + 1, nbits - 1);
186  rz_analysis_esil_runword(esil, word);
187  break;
188  case 'S':
189  eprintf("esil step over :D\n");
190  rz_sys_usleep(500);
191  break;
192  case 'r':
193  case 'h':
194  x = 0; // RZ_MAX (x - 1, 0);
195  break;
196  case '?':
197  rz_cons_clear00();
199  "Vd1?: Visual Bit Editor Help:\n\n"
200  " q - quit the bit editor\n"
201  " h/r - reset / go back (reinitialize esil state)\n"
202  " s - esil step in\n"
203  " j/k - toggle bit value (same as space key)\n"
204  " : - enter command\n");
205  rz_cons_flush();
207  break;
208  case ':': // TODO: move this into a separate helper function
209  {
210  char cmd[1024];
211  rz_cons_show_cursor(true);
212  rz_cons_set_raw(0);
213  *cmd = 0;
214  rz_line_set_prompt(":> ");
215  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
216  cmd[0] = '\0';
217  }
218  rz_core_cmd0(core, cmd);
219  rz_cons_set_raw(1);
220  rz_cons_show_cursor(false);
221  if (cmd[0]) {
223  }
224  rz_cons_clear();
225  } break;
226  }
227  }
228 beach:
229  rz_analysis_esil_free(esil);
230  free(word);
231  return true;
232 }
233 
235  const int nbits = sizeof(ut64) * 8;
236  bool colorBits = false;
237  int i, j, x = 0;
238  RzAsmOp asmop;
240  ut8 buf[sizeof(ut64)];
241  bool bitsInLine = false;
242 
243  if (core->blocksize < sizeof(ut64)) {
244  return false;
245  }
246  int cur = 0;
247  if (core->print->cur != -1) {
248  cur = core->print->cur;
249  }
250  memcpy(buf, core->block + cur, sizeof(ut64));
251  for (;;) {
252  rz_cons_clear00();
253  bool use_color = core->print->flags & RZ_PRINT_FLAGS_COLOR;
254  (void)rz_asm_disassemble(core->rasm, &asmop, buf, sizeof(ut64));
255  analop.type = -1;
256  (void)rz_analysis_op(core->analysis, &analop, core->offset, buf, sizeof(ut64), RZ_ANALYSIS_OP_MASK_ESIL);
257  rz_cons_printf("rizin's bit editor:\n\n");
258  rz_cons_printf("offset: 0x%08" PFMT64x "\n" Color_RESET, core->offset + cur);
259  {
260  char *op_hex = rz_asm_op_get_hex(&asmop);
261  char *res = rz_print_hexpair(core->print, op_hex, -1);
262  rz_cons_printf("hex: %s\n" Color_RESET, res);
263  free(res);
264  free(op_hex);
265  }
266  rz_cons_printf("len: %d\n", asmop.size);
267  {
268  ut32 word = (x % 32);
269  rz_cons_printf("shift: >> %d << %d\n", word, (asmop.size * 8) - word - 1);
270  }
271  {
273  RzStrBuf *colored_asm = rz_asm_colorize_asm_str(&asmop.buf_asm, core->print, param, asmop.asm_toks);
274  free(param);
275  rz_cons_printf(Color_RESET "asm: %s\n" Color_RESET, rz_strbuf_get(colored_asm));
276  rz_strbuf_free(colored_asm);
277  }
280  rz_cons_printf("chr:");
281  for (i = 0; i < 8; i++) {
282  const ut8 *byte = buf + i;
283  char ch = IS_PRINTABLE(*byte) ? *byte : '?';
284  if (i == 4) {
285  rz_cons_print(" |");
286  }
287  if (use_color) {
288  rz_cons_printf(" %5s'%s%c" Color_RESET "'", " ", core->cons->context->pal.btext, ch);
289  } else {
290  rz_cons_printf(" %5s'%c'", " ", ch);
291  }
292  }
293  rz_cons_printf("\ndec:");
294  for (i = 0; i < 8; i++) {
295  const ut8 *byte = buf + i;
296  if (i == 4) {
297  rz_cons_print(" |");
298  }
299  rz_cons_printf(" %8d", *byte);
300  }
301  rz_cons_printf("\nhex:");
302  for (i = 0; i < 8; i++) {
303  const ut8 *byte = buf + i;
304  if (i == 4) {
305  rz_cons_print(" |");
306  }
307  rz_cons_printf(" 0x%02x", *byte);
308  }
309  if (bitsInLine) {
310  rz_cons_printf("\nbit: ");
311  for (i = 0; i < 8; i++) {
312  ut8 *byte = buf + i;
313  if (i == 4) {
314  rz_cons_print("| ");
315  }
316  if (colorBits && i >= asmop.size) {
317  rz_cons_print(Color_RESET);
318  colorBits = false;
319  }
320  for (j = 0; j < 8; j++) {
321  bool bit = RZ_BIT_CHK(byte, 7 - j);
322  rz_cons_printf("%d", bit ? 1 : 0);
323  }
324  rz_cons_print(" ");
325  }
326  } else {
327  int set;
328  const char *ws = rz_config_get_i(core->config, "scr.utf8") ? "·" : " ";
329  for (set = 1; set >= 0; set--) {
330  rz_cons_printf("\nbit: ");
331  for (i = 0; i < 8; i++) {
332  ut8 *byte = buf + i;
333  if (i == 4) {
334  rz_cons_print("| ");
335  }
336  if (colorBits && i >= asmop.size) {
337  rz_cons_print(Color_RESET);
338  colorBits = false;
339  }
340  for (j = 0; j < 8; j++) {
341  bool bit = RZ_BIT_CHK(byte, 7 - j);
342  if (set && bit) {
343  rz_cons_print("1");
344  } else if (!set && !bit) {
345  rz_cons_print("0");
346  } else {
347  rz_cons_print(ws);
348  }
349  }
350  rz_cons_print(" ");
351  }
352  }
353  }
354  rz_cons_newline();
355  char str_pos[128];
356  memset(str_pos, '-', nbits + 9);
357  int pos = x;
358  if (pos > 31) {
359  pos += 2;
360  }
361  str_pos[pos + (x / 8)] = '^';
362  str_pos[nbits + 9] = 0;
363  str_pos[8] = ' ';
364  str_pos[17] = ' ';
365  str_pos[26] = ' ';
366  str_pos[35] = ' ';
367  str_pos[36] = ' ';
368  str_pos[37] = ' ';
369  str_pos[46] = ' ';
370  str_pos[55] = ' ';
371  str_pos[64] = ' ';
372  rz_cons_printf("pos: %s\n", str_pos);
373  rz_cons_newline();
375 
376  int ch = rz_cons_readchar();
377  if (ch == -1 || ch == 4) {
378  break;
379  }
380  if (ch != 10) {
381  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
382  }
383  switch (ch) {
384  case 'Q':
385  case 'q': {
386  char *op_hex = rz_asm_op_get_hex(&asmop);
387  char *res = rz_print_hexpair(core->print, op_hex, -1);
388  rz_core_write_at(core, core->offset, buf, 4);
389  free(res);
390  free(op_hex);
391  }
392  return false;
393  case 'H': {
394  int y = RZ_MAX(x - 8, 0);
395  x = y - y % 8;
396  } break;
397  case 'L':
398  case 9: {
399  int y = RZ_MIN(x + 8, nbits - 8);
400  x = y - y % 8;
401  } break;
402  case 'j':
403  case 'k':
404  case 10:
405  case ' ':
406  // togglebit();
407  {
408  const int nbyte = x / 8;
409  const int nbit = 7 - (x - (nbyte * 8));
410  ut8 *byte = buf + nbyte;
411  bool bit = RZ_BIT_CHK(byte, nbit);
412  if (bit) {
413  RZ_BIT_UNSET(byte, nbit);
414  } else {
415  RZ_BIT_SET(byte, nbit);
416  }
417  }
418  break;
419  case '>':
420  buf[x / 8] = rotate_nibble(buf[(x / 8)], -1);
421  break;
422  case '<':
423  buf[x / 8] = rotate_nibble(buf[(x / 8)], 1);
424  break;
425  case 'i': {
426  rz_line_set_prompt("> ");
427  const char *line = rz_line_readline();
428  ut64 num = rz_num_math(core->num, line);
429  if (num || (!num && *line == '0')) {
430  buf[x / 8] = num;
431  }
432  } break;
433  case 'R':
434  if (rz_config_get_b(core->config, "scr.randpal")) {
436  } else {
437  rz_core_theme_nextpal(core, 'n');
438  }
439  break;
440  case '+':
441  buf[(x / 8)]++;
442  break;
443  case '-':
444  buf[(x / 8)]--;
445  break;
446  case 'h':
447  x = RZ_MAX(x - 1, 0);
448  break;
449  case 'l':
450  x = RZ_MIN(x + 1, nbits - 1);
451  break;
452  case 'b':
453  bitsInLine = !bitsInLine;
454  break;
455  case '?':
456  rz_cons_clear00();
458  "Vd1?: Visual Bit Editor Help:\n\n"
459  " q - quit the bit editor\n"
460  " R - randomize color palette\n"
461  " b - toggle bitsInLine\n"
462  " j/k - toggle bit value (same as space key)\n"
463  " h/l - select next/previous bit\n"
464  " +/- - increment or decrement byte value\n"
465  " </> - rotate left/right byte value\n"
466  " i - insert numeric value of byte\n"
467  " : - enter command\n");
468  rz_cons_flush();
470  break;
471  case ':': // TODO: move this into a separate helper function
472  {
473  char cmd[1024];
474  rz_cons_show_cursor(true);
475  rz_cons_set_raw(0);
476  cmd[0] = '\0';
477  rz_line_set_prompt(":> ");
478  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
479  cmd[0] = '\0';
480  }
481  rz_core_cmd(core, cmd, 1);
482  rz_cons_set_raw(1);
483  rz_cons_show_cursor(false);
484  if (cmd[0]) {
486  }
487  rz_cons_clear();
488  } break;
489  }
490  }
491  return true;
492 }
493 
495  RzListIter *iter, *iter2;
496  RzBinClass *c;
497  RzBinField *f;
498  RzBinSymbol *m;
499  ut64 addr;
500  char *res;
501  RzList *list = rz_list_new();
502  if (!list) {
503  return false;
504  }
505  list->free = free;
507  rz_list_foreach (classes, iter, c) {
508  rz_list_foreach (c->fields, iter2, f) {
509  rz_list_append(list, rz_str_newf("0x%08" PFMT64x " %s %s", f->vaddr, c->name, f->name));
510  }
511  rz_list_foreach (c->methods, iter2, m) {
512  const char *name = m->dname ? m->dname : m->name;
513  rz_list_append(list, rz_str_newf("0x%08" PFMT64x " %s %s", m->vaddr, c->name, name));
514  }
515  }
516  res = rz_cons_hud(list, NULL);
517  if (res) {
518  char *p = strchr(res, ' ');
519  if (p) {
520  *p = 0;
521  }
522  addr = rz_num_get(NULL, res);
523  rz_core_seek(core, addr, true);
524  free(res);
525  }
527  return res != NULL;
528 }
529 
530 static bool hudstuff_append(RzFlagItem *fi, void *user) {
531  RzList *list = (RzList *)user;
532  char *s = rz_str_newf("0x%08" PFMT64x " %s", fi->offset, fi->name);
533  if (s) {
535  }
536  return true;
537 }
538 
540  ut64 addr;
541  char *res;
542  RzList *list = rz_list_new();
543  if (!list) {
544  return false;
545  }
546  list->free = free;
550  rz_interval_tree_foreach (&core->analysis->meta, it, mi) {
551  if (mi->type == RZ_META_TYPE_COMMENT) {
552  char *s = rz_str_newf("0x%08" PFMT64x " %s", rz_interval_tree_iter_get(&it)->start, mi->str);
553  if (s) {
554  rz_list_push(list, s);
555  }
556  }
557  }
558  res = rz_cons_hud(list, NULL);
559  if (res) {
560  char *p = strchr(res, ' ');
561  if (p) {
562  *p = 0;
563  }
564  addr = rz_num_get(NULL, res);
565  rz_core_seek(core, addr, true);
566  free(res);
567  }
569  return res != NULL;
570 }
571 
572 static bool rz_core_visual_config_hud(RzCore *core) {
573  RzListIter *iter;
574  RzConfigNode *bt;
575  RzList *list = rz_list_new();
576  if (!list) {
577  return false;
578  }
579  list->free = free;
580  rz_list_foreach (core->config->nodes, iter, bt) {
581  rz_list_append(list, rz_str_newf("%s %s", bt->name, bt->value));
582  }
583  char *res = rz_cons_hud(list, NULL);
584  if (res) {
585  const char *oldvalue = NULL;
586  char cmd[512];
587  char *p = strchr(res, ' ');
588  if (p) {
589  *p = 0;
590  }
591  oldvalue = rz_config_get(core->config, res);
592  rz_cons_show_cursor(true);
593  rz_cons_set_raw(false);
594  cmd[0] = '\0';
595  eprintf("Set new value for %s (old=%s)\n", res, oldvalue);
596  rz_line_set_prompt(":> ");
597  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
598  cmd[0] = '\0';
599  }
600  rz_config_set(core->config, res, cmd);
601  rz_cons_set_raw(true);
602  rz_cons_show_cursor(false);
603  }
605  return true;
606 }
607 
608 // TODO: skip N first elements
609 // TODO: show only N elements of the list
610 // TODO: wrap index when out of boundaries
611 // TODO: Add support to show class fields too
612 // Segfaults - stack overflow, because of recursion
613 static void *show_class(RzCore *core, int mode, int *idx, RzBinClass *_c, const char *grep, RzList *list) {
614  bool show_color = rz_config_get_i(core->config, "scr.color");
615  RzListIter *iter;
616  RzBinClass *c, *cur = NULL;
617  RzBinSymbol *m, *mur = NULL;
618  RzBinField *f, *fur = NULL;
619  int i = 0;
620  int skip = *idx - 10;
621  bool found = false;
622 
623  switch (mode) {
624  case 'c':
625  rz_cons_printf("[hjkl_/Cfm]> classes:\n\n");
626  rz_list_foreach (list, iter, c) {
627  if (grep) {
628  if (!rz_str_casestr(c->name, grep)) {
629  i++;
630  continue;
631  }
632  } else {
633  if (*idx > 10) {
634  skip--;
635  if (skip > 0) {
636  i++;
637  continue;
638  }
639  }
640  }
641  if (show_color) {
642  if (i == *idx) {
643  const char *clr = Color_BLUE;
645  i, clr, c->addr, c->name);
646  } else {
647  rz_cons_printf("- %02d %s0x%08" PFMT64x Color_RESET " %s\n",
648  i, core->cons->context->pal.offset, c->addr, c->name);
649  }
650  } else {
651  rz_cons_printf("%s %02d 0x%08" PFMT64x " %s\n",
652  (i == *idx) ? ">>" : "- ", i, c->addr, c->name);
653  }
654  if (i++ == *idx) {
655  cur = c;
656  }
657  found = true;
658  }
659  if (!cur) {
660  *idx = i - 1;
661  if (!found) {
662  return NULL;
663  }
664  // rz_cons_clear00 ();
665  return NULL; // show_class (core, mode, idx, _c, "", list);
666  }
667  return cur;
668  case 'f':
669  // show fields
670  rz_cons_printf("[hjkl_/cFm]> fields of %s:\n\n", _c->name);
671  rz_list_foreach (_c->fields, iter, f) {
672  const char *name = f->name;
673  if (grep) {
674  if (!rz_str_casestr(name, grep)) {
675  i++;
676  continue;
677  }
678  } else {
679  if (*idx > 10) {
680  skip--;
681  if (skip > 0) {
682  i++;
683  continue;
684  }
685  }
686  }
687 
688  char *mflags = strdup("");
689 
690  if (rz_str_startswith(name, _c->name)) {
691  name += strlen(_c->name);
692  }
693  if (show_color) {
694  if (i == *idx) {
695  const char *clr = Color_BLUE;
696  rz_cons_printf(Color_GREEN ">>" Color_RESET " %02d %s0x%08" PFMT64x Color_YELLOW " %s %s\n" Color_RESET,
697  i, clr, f->vaddr, mflags, name);
698  } else {
699  rz_cons_printf("- %02d %s0x%08" PFMT64x Color_RESET " %s %s\n",
700  i, core->cons->context->pal.offset, f->vaddr, mflags, name);
701  }
702  } else {
703  rz_cons_printf("%s %02d 0x%08" PFMT64x " %s %s\n",
704  (i == *idx) ? ">>" : "- ", i, f->vaddr, mflags, name);
705  }
706 
707  RZ_FREE(mflags);
708 
709  if (i++ == *idx) {
710  fur = f;
711  }
712  }
713  if (!fur) {
714  *idx = i - 1;
715  if (rz_list_empty(_c->fields)) {
716  return NULL;
717  }
718  // rz_cons_clear00 ();
719  return NULL; // show_class (core, mode, idx, _c, grep, list);
720  }
721  return fur;
722  break;
723  case 'm':
724  // show methods
725  if (!_c) {
726  eprintf("No class selected.\n");
727  return mur;
728  }
729  rz_cons_printf("[hjkl_/cfM]> methods of %s\n\n", _c->name);
730  rz_list_foreach (_c->methods, iter, m) {
731  const char *name = m->dname ? m->dname : m->name;
732  char *mflags;
733  if (grep) {
734  if (!rz_str_casestr(name, grep)) {
735  i++;
736  continue;
737  }
738  } else {
739  if (*idx > 10) {
740  skip--;
741  if (skip > 0) {
742  i++;
743  continue;
744  }
745  }
746  }
747 
748  mflags = rz_core_bin_method_flags_str(m->method_flags, 0);
749 
750  if (show_color) {
751  if (rz_str_startswith(name, _c->name)) {
752  name += strlen(_c->name);
753  }
754  if (i == *idx) {
755  const char *clr = Color_BLUE;
756  rz_cons_printf(Color_GREEN ">>" Color_RESET " %02d %s0x%08" PFMT64x Color_YELLOW " %s %s\n" Color_RESET,
757  i, clr, m->vaddr, mflags, name);
758  } else {
759  rz_cons_printf("- %02d %s0x%08" PFMT64x Color_RESET " %s %s\n",
760  i, core->cons->context->pal.offset, m->vaddr, mflags, name);
761  }
762  } else {
763  rz_cons_printf("%s %02d 0x%08" PFMT64x " %s %s\n",
764  (i == *idx) ? ">>" : "- ", i, m->vaddr, mflags, name);
765  }
766 
767  RZ_FREE(mflags);
768 
769  if (i++ == *idx) {
770  mur = m;
771  }
772  }
773  if (!mur) {
774  *idx = i - 1;
775  if (rz_list_empty(_c->methods)) {
776  return NULL;
777  }
778  // rz_cons_clear00 ();
779  return NULL; // show_class (core, mode, idx, _c, grep, list);
780  }
781  return mur;
782  }
783  return NULL;
784 }
785 
787  int ch, index = 0;
788  char cmd[1024];
789  int mode = 'c';
790  RzBinClass *cur = NULL;
791  RzBinSymbol *mur = NULL;
792  RzBinField *fur = NULL;
793  void *ptr;
794  int oldcur = 0;
795  char *grep = NULL;
796  bool grepmode = false;
797  RzList *list = rz_bin_get_classes(core->bin);
798  if (rz_list_empty(list)) {
799  rz_cons_message("No Classes");
800  return false;
801  }
802  for (;;) {
803  int cols;
804  rz_cons_clear00();
805  if (grepmode) {
806  rz_cons_printf("Grep: %s\n", grep ? grep : "");
807  }
808  ptr = show_class(core, mode, &index, cur, grep, list);
809  switch (mode) {
810  case 'f':
811  fur = (RzBinField *)ptr;
812  break;
813  case 'm':
814  mur = (RzBinSymbol *)ptr;
815  break;
816  case 'c':
817  cur = (RzBinClass *)ptr;
818  break;
819  }
820 
821  /* update terminal size */
822  (void)rz_cons_get_size(&cols);
824  ch = rz_cons_readchar();
825  if (ch == -1 || ch == 4) {
826  RZ_FREE(grep);
827  return false;
828  }
829 
830  if (grepmode) {
831  switch (ch) {
832  case 127:
833  if (grep) {
834  int len = strlen(grep);
835  if (len < 1) {
836  grepmode = false;
837  } else {
838  grep[len - 1] = 0;
839  }
840  }
841  break;
842  case ' ':
843  case '\r':
844  case '\n':
845  RZ_FREE(grep);
846  grepmode = false;
847  break;
848  default:
849  grep = grep
850  ? rz_str_appendf(grep, "%c", ch)
851  : rz_str_newf("%c", ch);
852  break;
853  }
854  continue;
855  }
856 
857  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
858  switch (ch) {
859  case 'C':
860  rz_config_toggle(core->config, "scr.color");
861  break;
862  case '_':
863  if (rz_core_visual_hudclasses(core)) {
864  return true;
865  }
866  break;
867  case 'J': index += 10; break;
868  case 'j': index++; break;
869  case 'k':
870  if (--index < 0) {
871  index = 0;
872  }
873  break;
874  case 'K':
875  index -= 10;
876  if (index < 0) {
877  index = 0;
878  }
879  break;
880  case 'g':
881  index = 0;
882  break;
883  case 'G':
884  index = rz_list_length(list) - 1;
885  break;
886  case 'i': {
887  char *num = prompt("Index:", NULL);
888  if (num) {
889  index = atoi(num);
890  free(num);
891  }
892  } break;
893  case 'p':
894  if (mode == 'm' && mur) {
895  rz_core_seek(core, mur->vaddr, true);
896  rz_core_analysis_function_add(core, NULL, core->offset, false);
897  rz_core_cmd0(core, "pdf~..");
898  }
899  break;
900  case 'm': // methods
901  mode = 'm';
902  break;
903  case 'f': // fields
904  mode = 'f';
905  break;
906  case 'h':
907  case 127: // backspace
908  case 'b': // back
909  case 'Q':
910  case 'c':
911  case 'q':
912  if (mode == 'c') {
913  return true;
914  }
915  mode = 'c';
916  index = oldcur;
917  break;
918  case '/':
919  grepmode = true;
920  break;
921  case 'l':
922  case ' ':
923  case '\r':
924  case '\n':
925  if (mur && mode == 'm') {
926  rz_core_seek(core, mur->vaddr, true);
927  return true;
928  }
929  if (fur) {
930  rz_core_seek(core, fur->vaddr, true);
931  return true;
932  }
933  if (cur) {
934  oldcur = index;
935  index = 0;
936  mode = 'm';
937  }
938  break;
939  case '?':
940  rz_cons_clear00();
942  "\nVF: Visual Classes help:\n\n"
943  " q - quit menu\n"
944  " j/k - down/up keys\n"
945  " h/b - go back\n"
946  " g/G - go first/last item\n"
947  " i - specify index\n"
948  " / - grep mode\n"
949  " C - toggle colors\n"
950  " f - show class fields\n"
951  " m - show class methods\n"
952  " l/' ' - accept current selection\n"
953  " p - preview method disasm with less\n"
954  " : - enter command\n");
955  rz_cons_flush();
957  break;
958  case ':':
959  rz_cons_show_cursor(true);
960  rz_cons_set_raw(0);
961  cmd[0] = '\0';
962  rz_line_set_prompt(":> ");
963  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
964  cmd[0] = '\0';
965  }
966  // line[strlen(line)-1]='\0';
967  rz_core_cmd(core, cmd, 1);
968  rz_cons_set_raw(1);
969  rz_cons_show_cursor(false);
970  if (cmd[0]) {
972  }
973  // cons_gotoxy(0,0);
974  rz_cons_clear();
975  break;
976  }
977  }
978  return true;
979 }
980 
981 static void analysis_class_print(RzAnalysis *analysis, const char *class_name) {
982  RzVector *bases = rz_analysis_class_base_get_all(analysis, class_name);
983  RzVector *vtables = rz_analysis_class_vtable_get_all(analysis, class_name);
984  RzVector *methods = rz_analysis_class_method_get_all(analysis, class_name);
985 
986  rz_cons_print(class_name);
987  if (bases) {
988  RzAnalysisBaseClass *base;
989  bool first = true;
990  rz_vector_foreach(bases, base) {
991  if (first) {
992  rz_cons_print(": ");
993  first = false;
994  } else {
995  rz_cons_print(", ");
996  }
997  rz_cons_print(base->class_name);
998  }
999  rz_vector_free(bases);
1000  }
1001 
1002  rz_cons_print("\n");
1003 
1004  if (vtables) {
1005  RzAnalysisVTable *vtable;
1006  rz_vector_foreach(vtables, vtable) {
1007  rz_cons_printf(" %2s vtable 0x%" PFMT64x " @ +0x%" PFMT64x " size:+0x%" PFMT64x "\n", vtable->id, vtable->addr, vtable->offset, vtable->size);
1008  }
1009  rz_vector_free(vtables);
1010  }
1011 
1012  rz_cons_print("\n");
1013 
1014  if (methods) {
1015  RzAnalysisMethod *meth;
1016  rz_vector_foreach(methods, meth) {
1017  rz_cons_printf(" %s @ 0x%" PFMT64x, meth->name, meth->addr);
1018  if (meth->vtable_offset >= 0) {
1019  rz_cons_printf(" (vtable + 0x%" PFMT64x ")\n", (ut64)meth->vtable_offset);
1020  } else {
1021  rz_cons_print("\n");
1022  }
1023  }
1024  rz_vector_free(methods);
1025  }
1026 }
1027 
1028 static const char *show_analysis_classes(RzCore *core, char mode, int *idx, SdbList *list, const char *class_name) {
1029  bool show_color = rz_config_get_i(core->config, "scr.color");
1030  SdbListIter *iter;
1031  SdbKv *kv;
1032  int i = 0;
1033  int skip = *idx - 10;
1034  const char *cur_class = NULL;
1035  rz_cons_printf("[hjkl_/Cfm]> analysis classes:\n\n");
1036 
1037  if (mode == 'd' && class_name) {
1038  analysis_class_print(core->analysis, class_name);
1039  return class_name;
1040  }
1041 
1042  ls_foreach (list, iter, kv) {
1043  if (*idx > 10) {
1044  skip--;
1045  if (skip > 0) {
1046  i++;
1047  continue;
1048  }
1049  }
1050  class_name = sdbkv_key(kv);
1051 
1052  if (show_color) {
1053  const char *pointer = "- ";
1054  const char *txt_clr = "";
1055 
1056  if (i == *idx) {
1057  pointer = Color_GREEN ">>";
1058  txt_clr = Color_YELLOW;
1059  cur_class = class_name;
1060  }
1061  rz_cons_printf("%s" Color_RESET " %02d"
1062  " %s%s\n" Color_RESET,
1063  pointer, i, txt_clr, class_name);
1064  } else {
1065  rz_cons_printf("%s %02d %s\n", (i == *idx) ? ">>" : "- ", i, class_name);
1066  }
1067 
1068  i++;
1069  }
1070 
1071  return cur_class;
1072 }
1073 // TODO add other commands that Vbc has
1074 // Should the classes be refreshed after command execution with :
1075 // in case new class information would be added?
1076 // Add grep?
1078  int ch, index = 0;
1079  char command[1024];
1081  int oldcur = 0;
1082  char mode = ' ';
1083  const char *class_name = "";
1084 
1085  if (rz_list_empty(list)) {
1086  rz_cons_message("No Classes");
1087  goto cleanup;
1088  }
1089  for (;;) {
1090  int cols;
1091  rz_cons_clear00();
1092 
1093  class_name = show_analysis_classes(core, mode, &index, list, class_name);
1094 
1095  /* update terminal size */
1096  (void)rz_cons_get_size(&cols);
1098  ch = rz_cons_readchar();
1099  if (ch == -1 || ch == 4) {
1100  goto cleanup;
1101  }
1102 
1103  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
1104  switch (ch) {
1105  case 'C':
1106  rz_config_toggle(core->config, "scr.color");
1107  break;
1108  case 'J':
1109  index += 10;
1110  if (index >= list->length) {
1111  index = list->length - 1;
1112  }
1113  break;
1114  case 'j':
1115  if (++index >= list->length) {
1116  index = 0;
1117  }
1118  break;
1119  case 'k':
1120  if (--index < 0) {
1121  index = list->length - 1;
1122  }
1123  break;
1124  case 'K':
1125  index -= 10;
1126  if (index < 0) {
1127  index = 0;
1128  }
1129  break;
1130  case 'g':
1131  index = 0;
1132  break;
1133  case 'G':
1134  index = list->length - 1;
1135  break;
1136  case 'h':
1137  case 127: // backspace
1138  case 'b': // back
1139  case 'Q':
1140  case 'c':
1141  case 'q':
1142  if (mode == ' ') {
1143  goto cleanup;
1144  }
1145  mode = ' ';
1146  index = oldcur;
1147  break;
1148  case 'l':
1149  case ' ':
1150  case '\r':
1151  case '\n':
1152  mode = 'd';
1153  break;
1154  case '?':
1155  rz_cons_clear00();
1157  "\nVF: Visual Classes help:\n\n"
1158  " q - quit menu\n"
1159  " j/k - down/up keys\n"
1160  " h/b - go back\n"
1161  " g/G - go first/last item\n"
1162  " l/' ' - accept current selection\n"
1163  " : - enter command\n");
1164  rz_cons_flush();
1166  break;
1167  case ':':
1168  rz_cons_show_cursor(true);
1169  rz_cons_set_raw(0);
1170  command[0] = '\0';
1171  rz_line_set_prompt(":> ");
1172  if (rz_cons_fgets(command, sizeof(command), 0, NULL) < 0) {
1173  command[0] = '\0';
1174  }
1175  // line[strlen(line)-1]='\0';
1176  rz_core_cmd(core, command, 1);
1177  rz_cons_set_raw(1);
1178  rz_cons_show_cursor(false);
1179  if (command[0]) {
1181  }
1182  // cons_gotoxy(0,0);
1183  rz_cons_clear();
1184  break;
1185  }
1186  }
1187 cleanup:
1188  ls_free(list);
1189  return true;
1190 }
1191 
1192 static int flag_name_sort(const void *a, const void *b) {
1193  const RzFlagItem *fa = (const RzFlagItem *)a;
1194  const RzFlagItem *fb = (const RzFlagItem *)b;
1195  return strcmp(fa->name, fb->name);
1196 }
1197 
1198 static int flag_offset_sort(const void *a, const void *b) {
1199  const RzFlagItem *fa = (const RzFlagItem *)a;
1200  const RzFlagItem *fb = (const RzFlagItem *)b;
1201  if (fa->offset < fb->offset) {
1202  return -1;
1203  }
1204  if (fa->offset > fb->offset) {
1205  return 1;
1206  }
1207  return 0;
1208 }
1209 
1210 static void sort_flags(RzList *l, int sort) {
1211  switch (sort) {
1212  case SORT_NAME:
1214  break;
1215  case SORT_OFFSET:
1217  break;
1218  case SORT_NONE:
1219  default:
1220  break;
1221  }
1222 }
1223 
1224 // TODO: remove this statement, should be a separate .o
1225 
1226 static char *print_rop(void *_core, void *_item, bool selected) {
1227  char *line = _item;
1228  // TODO: trim if too long
1229  return rz_str_newf("%c %s\n", selected ? '>' : ' ', line);
1230 }
1231 
1233  RzListIter *iter;
1234  const int rows = 7;
1235  int cur = 0;
1236 
1237  rz_line_set_prompt("rop regexp: ");
1238  const char *line = rz_line_readline();
1239 
1240  int scr_h, scr_w = rz_cons_get_size(&scr_h);
1241 
1242  if (!line || !*line) {
1243  return false;
1244  }
1245  // maybe store in RzCore, so we can save it in project and use it outside visual
1246 
1247  eprintf("Searching ROP gadgets...\n");
1248  char *ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", line);
1249  RzList *rops = rz_str_split_list(ropstr, "\n", 0);
1250  int delta = 0;
1251  bool show_color = core->print->flags & RZ_PRINT_FLAGS_COLOR;
1252  bool forceaddr = false;
1253  ut64 addr = UT64_MAX;
1254  char *cursearch = strdup(line);
1255  while (true) {
1256  rz_cons_clear00();
1257  rz_cons_printf("[0x%08" PFMT64x "]-[visual-rzrop] %s (see pdp command)\n",
1258  (addr == UT64_MAX) ? 0 : addr + delta, cursearch);
1259 
1260  // compute chain
1261  RzStrBuf *sb = rz_strbuf_new("");
1262  char *msg;
1263  rz_list_foreach (core->ropchain, iter, msg) {
1264  if (core->rasm->bits == 64) {
1265  ut64 n = rz_num_get(NULL, msg);
1266  n = rz_read_be64(&n);
1267  rz_strbuf_appendf(sb, "%016" PFMT64x, n);
1268  } else {
1269  ut32 n = rz_num_get(NULL, msg);
1270  n = rz_read_be32(&n);
1271  rz_strbuf_appendf(sb, "%08x", n);
1272  }
1273  }
1274  char *chainstr = rz_strbuf_drain(sb);
1275 
1276  char *wlist = rz_str_widget_list(core, rops, rows, cur, print_rop);
1277  rz_cons_printf("%s", wlist);
1278  free(wlist);
1279  char *curline = rz_str_dup(NULL, rz_str_trim_head_ro(rz_str_widget_list(core, rops, rows, cur, print_rop)));
1280  if (curline) {
1281  char *sp = strchr(curline, ' ');
1282  if (sp) {
1283  *sp = 0;
1284  if (!forceaddr) {
1285  addr = rz_num_math(NULL, curline);
1286  }
1287  *sp = ' ';
1288  }
1289  if (addr != UT64_MAX) {
1290  rz_cons_printf("Gadget:");
1291  // get comment
1292  char *output = rz_core_cmd_strf(core, "piu 10 @ 0x%08" PFMT64x, addr + delta);
1293  if (output) {
1294  rz_cons_strcat_at(output, 0, 10, scr_w, 10);
1295  free(output);
1296  }
1297  }
1298  }
1299  int count = 0;
1300  rz_cons_flush();
1301  rz_cons_gotoxy(0, 20);
1302  rz_cons_printf("ROPChain:\n %s\n", chainstr ? chainstr : "");
1303  int chainstrlen = chainstr ? strlen(chainstr) : 0;
1304  rz_list_foreach (core->ropchain, iter, msg) {
1305  int extra = chainstrlen / scr_w;
1306  rz_cons_gotoxy(0, extra + 22 + count);
1308  const char *cmt = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, rz_num_get(NULL, msg));
1309  if (cmt) {
1310  rz_cons_strcat(cmt);
1311  }
1312  count++;
1313  }
1314  rz_cons_flush();
1315  int ch = rz_cons_readchar();
1316  if (ch == -1 || ch == 4) {
1317  free(curline);
1318  free(cursearch);
1319  RZ_FREE(chainstr);
1320  return false;
1321  }
1322 #define NEWTYPE(x, y) rz_mem_dup(&(y), sizeof(x));
1323  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
1324  switch (ch) {
1325  case 127:
1326  free(rz_list_pop(core->ropchain));
1327  break;
1328  case '?':
1329  rz_cons_clear00();
1330  rz_cons_printf("[rzrop-visual] Help\n"
1331  " jk - select next/prev rop gadget\n"
1332  " JK - scroll next/prev page from list\n"
1333  " hl - increase/decrease delta offset in disasm\n"
1334  " \\n - enter key or dot will add the current offset into the chain\n"
1335  " i - enter a number to be pushed into the chain\n"
1336  " : - run rizin command\n"
1337  " ; - add comment in current offset\n"
1338  " <- - backspace - delete last gadget from the chain\n"
1339  " / - highlight given word\n"
1340  " y - yank current rop chain into the clipboard (y?)\n"
1341  " o - seek to given offset\n"
1342  " r - run /R again\n"
1343  " ? - show this help message\n"
1344  " q - quit this view\n");
1345  rz_cons_flush();
1347  break;
1348  case ':': // TODO: move this into a separate helper function
1349  rz_cons_show_cursor(true);
1350  rz_cons_set_raw(0);
1351  while (true) {
1352  char cmd[1024];
1353  cmd[0] = '\0';
1354  rz_line_set_prompt(":> ");
1355  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
1356  cmd[0] = '\0';
1357  }
1358  if (!*cmd || *cmd == 'q') {
1359  break;
1360  }
1361  ut64 oseek = core->offset;
1362  rz_core_seek(core, addr + delta, false);
1363  rz_core_cmd(core, cmd, 1);
1364  rz_core_seek(core, oseek, false);
1365  rz_cons_flush();
1366  }
1367  rz_cons_set_raw(1);
1368  rz_cons_show_cursor(false);
1369  break;
1370  case 'y':
1371  rz_core_yank_hexpair(core, chainstr);
1372  break;
1373  case 'o': {
1374  rz_line_set_prompt("offset: ");
1375  const char *line = rz_line_readline();
1376  if (line && *line) {
1377  ut64 off = rz_num_math(core->num, line);
1378  rz_core_seek(core, off, true);
1379  addr = off;
1380  forceaddr = true;
1381  delta = 0;
1382  }
1383  } break;
1384  case 'r': {
1385  rz_line_set_prompt("rop regexp: ");
1386  const char *line = rz_line_readline();
1387  if (line && *line) {
1388  free(cursearch);
1389  delta = 0;
1390  addr = UT64_MAX;
1391  cur = 0;
1392  cursearch = strdup(line);
1393  free(ropstr);
1394  ropstr = rz_core_cmd_strf(core, "\"/Rl %s\" @e:scr.color=0", line);
1395  rz_list_free(rops);
1396  rops = rz_str_split_list(ropstr, "\n", 0);
1397  }
1398  } break;
1399  case '/':
1400  rz_core_cmd0(core, "?i highlight;e scr.highlight=`yp`");
1401  break;
1402  case 'i': {
1403  rz_line_set_prompt("insert value: ");
1404  const char *line = rz_line_readline();
1405  if (line && *line) {
1406  ut64 n = rz_num_math(core->num, line);
1407  rz_list_push(core->ropchain, rz_str_newf("0x%08" PFMT64x, n));
1408  }
1409  } break;
1410  case ';': {
1411  rz_line_set_prompt("comment: ");
1412  const char *line = rz_line_readline();
1413  if (line && *line) {
1415  }
1416  } break;
1417  case '.':
1418  case '\n':
1419  case '\r':
1420  if (curline && *curline) {
1421  char *line = rz_core_cmd_strf(core, "piuq@0x%08" PFMT64x, addr + delta);
1422  rz_str_replace_char(line, '\n', ';');
1423  if (show_color) {
1424  // XXX parsing fails to read this ansi-offset
1425  // const char *offsetColor = rz_cons_singleton ()->context->pal.offset; // TODO etooslow. must cache
1426  // rz_list_push (core->ropchain, rz_str_newf ("%s0x%08"PFMT64x""Color_RESET" %s", offsetColor, addr + delta, line));
1427  rz_list_push(core->ropchain, rz_str_newf("0x%08" PFMT64x " %s", addr + delta, line));
1428  } else {
1429  rz_list_push(core->ropchain, rz_str_newf("0x%08" PFMT64x " %s", addr + delta, line));
1430  }
1431  free(line);
1432  }
1433  break;
1434  case 'h':
1435  delta--;
1436  break;
1437  case 'l':
1438  delta++;
1439  break;
1440  case 'J':
1441  cur += 10;
1442  forceaddr = false;
1443  delta = 0;
1444  break;
1445  case 'K':
1446  delta = 0;
1447  forceaddr = false;
1448  if (cur > 10) {
1449  cur -= 10;
1450  } else {
1451  cur = 0;
1452  }
1453  break;
1454  case '0':
1455  delta = 0;
1456  cur = 0;
1457  break;
1458  case 'j':
1459  delta = 0;
1460  cur++;
1461  forceaddr = false;
1462  break;
1463  case 'k':
1464  delta = 0;
1465  forceaddr = false;
1466  if (cur > 0) {
1467  cur--;
1468  } else {
1469  cur = 0;
1470  }
1471  break;
1472  case 'q':
1473  free(curline);
1474  free(cursearch);
1475  RZ_FREE(chainstr);
1476  return true;
1477  }
1478  RZ_FREE(chainstr);
1479  free(curline);
1480  }
1481  free(cursearch);
1482  return false;
1483 }
1484 
1486  const char *fs = NULL, *fs2 = NULL;
1487  int hit, i, j, ch;
1488  int _option = 0;
1489  int option = 0;
1490  char cmd[1024];
1491  int format = 0;
1492  int delta = 7;
1493  int menu = 0;
1494  int sort = SORT_NONE;
1495 
1496  if (rz_flag_space_is_empty(core->flags)) {
1497  menu = 1;
1498  }
1499  for (;;) {
1500  bool hasColor = rz_config_get_i(core->config, "scr.color");
1501  rz_cons_clear00();
1502 
1503  if (menu) {
1504  rz_cons_printf("Flags in flagspace '%s'. Press '?' for help.\n\n",
1505  rz_flag_space_cur_name(core->flags));
1506  hit = 0;
1507  i = j = 0;
1508  RzList *l = rz_flag_all_list(core->flags, true);
1509  RzListIter *iter;
1510  RzFlagItem *fi;
1511  sort_flags(l, sort);
1512  rz_list_foreach (l, iter, fi) {
1513  if (option == i) {
1514  fs2 = fi->name;
1515  hit = 1;
1516  }
1517  if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
1518  bool cur = option == i;
1519  if (cur && hasColor) {
1521  }
1522  rz_cons_printf(" %c %03d 0x%08" PFMT64x " %4" PFMT64d " %s\n",
1523  cur ? '>' : ' ', i, fi->offset, fi->size, fi->name);
1524  if (cur && hasColor) {
1526  }
1527  j++;
1528  }
1529  i++;
1530  }
1531  rz_list_free(l);
1532 
1533  if (!hit && i > 0) {
1534  option = i - 1;
1535  continue;
1536  }
1537  if (fs2) {
1538  int cols, rows = rz_cons_get_size(&cols);
1539  // int rows = 20;
1540  rows -= 12;
1541  rz_cons_printf("\n Selected: %s\n\n", fs2);
1542  // Honor MAX_FORMATS here
1543  switch (format) {
1544  case 0:
1545  snprintf(cmd, sizeof(cmd), "px %d @ %s!64", rows * 16, fs2);
1546  core->printidx = 0;
1547  break;
1548  case 1:
1549  snprintf(cmd, sizeof(cmd), "pd %d @ %s!64", rows, fs2);
1550  core->printidx = 1;
1551  break;
1552  case 2:
1553  snprintf(cmd, sizeof(cmd), "ps @ %s!64", fs2);
1554  core->printidx = 5;
1555  break;
1556  case 3: strcpy(cmd, "f="); break;
1557  default: format = 0; continue;
1558  }
1559  if (*cmd) {
1560  rz_core_cmd(core, cmd, 0);
1561  }
1562  } else {
1563  rz_cons_printf("(no flags)\n");
1564  }
1565  } else {
1566  rz_cons_printf("Flag spaces:\n\n");
1567  hit = 0;
1568  RzSpaceIter it;
1569  const RzSpace *s, *cur = rz_flag_space_cur(core->flags);
1570  int i = 0;
1571  rz_flag_space_foreach(core->flags, it, s) {
1572  if (option == i) {
1573  fs = s->name;
1574  hit = 1;
1575  }
1576  if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
1577  rz_cons_printf(" %c %c %s\n",
1578  (option == i) ? '>' : ' ',
1579  (s == cur) ? '*' : ' ',
1580  s->name);
1581  }
1582  i++;
1583  }
1584  if (option == i) {
1585  fs = "*";
1586  hit = 1;
1587  }
1588  rz_cons_printf(" %c %c %s\n", (option == i) ? '>' : ' ',
1589  !cur ? '*' : ' ', "*");
1590  i++;
1591  if (!hit && i > 0) {
1592  option = i - 1;
1593  continue;
1594  }
1595  }
1597  ch = rz_cons_readchar();
1598  if (ch == -1 || ch == 4) {
1599  return false;
1600  }
1601  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
1602  switch (ch) {
1603  case 'C':
1604  rz_config_toggle(core->config, "scr.color");
1605  break;
1606  case '_':
1607  if (rz_core_visual_hudstuff(core)) {
1608  return true;
1609  }
1610  break;
1611  case 'J': option += 10; break;
1612  case 'o': sort = SORT_OFFSET; break;
1613  case 'n': sort = SORT_NAME; break;
1614  case 'j': option++; break;
1615  case 'k':
1616  if (--option < 0) {
1617  option = 0;
1618  }
1619  break;
1620  case 'K':
1621  option -= 10;
1622  if (option < 0) {
1623  option = 0;
1624  }
1625  break;
1626  case 'h':
1627  case 'b': // back
1628  case 'Q':
1629  case 'q':
1630  if (menu <= 0) {
1631  return true;
1632  }
1633  menu--;
1634  option = _option;
1635  if (menu == 0) {
1636  rz_flag_space_set(core->flags, NULL);
1637  // if no flagspaces, just quit
1638  if (rz_flag_space_is_empty(core->flags)) {
1639  return true;
1640  }
1641  }
1642  break;
1643  case 'a':
1644  switch (menu) {
1645  case 0: // new flag space
1646  rz_cons_show_cursor(true);
1647  rz_line_set_prompt("add flagspace: ");
1648  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) {
1649  rz_flag_space_set(core->flags, cmd);
1650  rz_cons_set_raw(1);
1651  rz_cons_show_cursor(false);
1652  }
1653  break;
1654  case 1: // new flag
1655  rz_cons_show_cursor(true);
1656  rz_line_set_prompt("add flag: ");
1657  strcpy(cmd, "f ");
1658  if (rz_cons_fgets(cmd + 2, sizeof(cmd) - 2, 0, NULL) > 0) {
1659  rz_core_cmd(core, cmd, 0);
1660  rz_cons_set_raw(1);
1661  rz_cons_show_cursor(false);
1662  }
1663  break;
1664  }
1665  break;
1666  case 'd':
1667  rz_flag_unset_name(core->flags, fs2);
1668  break;
1669  case 'e':
1670  /* TODO: prompt for addr, size, name */
1671  eprintf("TODO\n");
1672  rz_sys_sleep(1);
1673  break;
1674  case '*':
1675  rz_core_block_size(core, core->blocksize + 16);
1676  break;
1677  case '/':
1678  rz_core_block_size(core, core->blocksize - 16);
1679  break;
1680  case '+':
1681  if (menu == 1) {
1682  rz_core_cmdf(core, "f %s @ %s+1", fs2, fs2);
1683  } else {
1684  rz_core_block_size(core, core->blocksize + 1);
1685  }
1686  break;
1687  case '-':
1688  if (menu == 1) {
1689  rz_core_cmdf(core, "f %s @ %s-1", fs2, fs2);
1690  } else {
1691  rz_core_block_size(core, core->blocksize - 1);
1692  }
1693  break;
1694  case 'r': // "Vtr"
1695  if (menu == 1) {
1696  int len;
1697  rz_cons_show_cursor(true);
1698  rz_cons_set_raw(0);
1699  // TODO: use rz_flag_rename or fail?..`fr` doesn't uses this..
1700  snprintf(cmd, sizeof(cmd), "fr %s ", fs2);
1701  len = strlen(cmd);
1702  eprintf("Rename flag '%s' as:\n", fs2);
1703  rz_line_set_prompt(":> ");
1704  if (rz_cons_fgets(cmd + len, sizeof(cmd) - len, 0, NULL) < 0) {
1705  cmd[0] = '\0';
1706  }
1707  rz_core_cmd(core, cmd, 0);
1708  rz_cons_set_raw(1);
1709  rz_cons_show_cursor(false);
1710  }
1711  break;
1712  case 'R':
1713  if (menu == 1) {
1714  char line[1024];
1715  rz_cons_show_cursor(true);
1716  rz_cons_set_raw(0);
1717  eprintf("Rename function '%s' as:\n", fs2);
1718  rz_line_set_prompt(":> ");
1719  if (rz_cons_fgets(line, sizeof(line), 0, NULL) < 0) {
1720  cmd[0] = '\0';
1721  }
1722  ut64 addr = rz_num_math(core->num, line);
1723  rz_core_analysis_function_add(core, fs2, addr, true);
1724  rz_cons_set_raw(1);
1725  rz_cons_show_cursor(false);
1726  }
1727  break;
1728  case 'P':
1729  if (--format < 0) {
1730  format = MAX_FORMAT;
1731  }
1732  break;
1733  // = (format<=0)? MAX_FORMAT: format-1; break;
1734  case 'p': format++; break;
1735  case 'l':
1736  case ' ':
1737  case '\r':
1738  case '\n':
1739  if (menu == 1) {
1740  ut64 addr = rz_num_math(core->num, fs2);
1741  rz_core_seek_and_save(core, addr, true);
1742  return true;
1743  }
1744  rz_flag_space_set(core->flags, fs);
1745  menu = 1;
1746  _option = option;
1747  option = 0;
1748  break;
1749  case '?':
1750  rz_cons_clear00();
1752  "\nVF: Visual Flags help:\n\n"
1753  " q - quit menu\n"
1754  " j/k - line down/up keys\n"
1755  " J/K - page down/up keys\n"
1756  " h/b - go back\n"
1757  " C - toggle colors\n"
1758  " l/' ' - accept current selection\n"
1759  " a/d/e - add/delete/edit flag\n"
1760  " +/- - increase/decrease block size\n"
1761  " o - sort flags by offset\n"
1762  " r/R - rename flag / Rename function\n"
1763  " n - sort flags by name\n"
1764  " p/P - rotate print format\n"
1765  " _ - hud for flags and comments\n"
1766  " : - enter command\n");
1767  rz_cons_flush();
1769  break;
1770  case ':':
1771  rz_cons_show_cursor(true);
1772  rz_cons_set_raw(0);
1773  *cmd = 0;
1774  rz_line_set_prompt(":> ");
1775  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) < 0) {
1776  *cmd = 0;
1777  }
1778  cmd[sizeof(cmd) - 1] = 0;
1779  rz_core_cmd0(core, cmd);
1780  rz_cons_set_raw(1);
1781  rz_cons_show_cursor(false);
1782  if (*cmd) {
1784  }
1785  // cons_gotoxy(0,0);
1786  rz_cons_clear();
1787  continue;
1788  }
1789  }
1790  return true;
1791 }
1792 
1794  char *str;
1795  char cmd[512], *p = NULL;
1796  int ch, option = 0;
1797  int format = 0, i = 0;
1798  ut64 addr, from = 0, size = 0;
1799 
1800  for (;;) {
1801  rz_cons_clear00();
1802  rz_cons_strcat("Comments:\n");
1803  RzIntervalTreeIter it;
1804  RzAnalysisMetaItem *item;
1805  i = 0;
1806  rz_interval_tree_foreach (&core->analysis->meta, it, item) {
1807  if (item->type != RZ_META_TYPE_COMMENT) {
1808  continue;
1809  }
1810  str = item->str;
1812  if (option == i) {
1813  from = addr;
1814  size = 1; // XXX: remove this thing size for comments is useless d->size;
1815  free(p);
1816  p = strdup(str);
1817  rz_cons_printf(" > %s\n", str);
1818  } else {
1819  rz_cons_printf(" %s\n", str);
1820  }
1821  i++;
1822  }
1823  if (!i) {
1824  if (--option < 0) {
1825  rz_cons_any_key("No comments");
1826  break;
1827  }
1828  continue;
1829  }
1830  rz_cons_newline();
1831 
1832  switch (format) {
1833  case 0:
1834  sprintf(cmd, "px @ 0x%" PFMT64x ":64", from);
1835  core->printidx = 0;
1836  break;
1837  case 1:
1838  sprintf(cmd, "pd 12 @ 0x%" PFMT64x ":64", from);
1839  core->printidx = 1;
1840  break;
1841  case 2:
1842  sprintf(cmd, "ps @ 0x%" PFMT64x ":64", from);
1843  core->printidx = 5;
1844  break;
1845  default: format = 0; continue;
1846  }
1847  if (*cmd) {
1848  rz_core_cmd(core, cmd, 0);
1849  }
1851  ch = rz_cons_readchar();
1852  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
1853  switch (ch) {
1854  case 'a':
1855  // TODO
1856  break;
1857  case 'e':
1858  // TODO
1859  break;
1860  case 'd':
1861  if (p) {
1863  }
1864  break;
1865  case 'P':
1866  if (--format < 0) {
1867  format = MAX_FORMAT;
1868  }
1869  break;
1870  case 'p':
1871  format++;
1872  break;
1873  case 'J':
1874  option += 10;
1875  break;
1876  case 'j':
1877  option++;
1878  break;
1879  case 'k':
1880  if (--option < 0) {
1881  option = 0;
1882  }
1883  break;
1884  case 'K':
1885  option -= 10;
1886  if (option < 0) {
1887  option = 0;
1888  }
1889  break;
1890  case 'l':
1891  case ' ':
1892  case '\r':
1893  case '\n':
1894  rz_core_seek_and_save(core, from, true);
1895  RZ_FREE(p);
1896  return true;
1897  case 'Q':
1898  case 'q':
1899  RZ_FREE(p);
1900  return true;
1901  case '?':
1902  case 'h':
1903  rz_cons_clear00();
1905  "\nVT: Visual Comments/Analysis help:\n\n"
1906  " q - quit menu\n"
1907  " j/k - down/up keys\n"
1908  " h/b - go back\n"
1909  " l/' ' - accept current selection\n"
1910  " a/d/e - add/delete/edit comment/analysis symbol\n"
1911  " p/P - rotate print format\n");
1912  rz_cons_flush();
1914  break;
1915  }
1916  RZ_FREE(p);
1917  }
1918  return true;
1919 }
1920 
1921 static void config_visual_hit_i(RzCore *core, const char *name, int delta) {
1922  struct rz_config_node_t *node;
1923  node = rz_config_node_get(core->config, name);
1924  if (node && rz_config_node_is_int(node)) {
1925  int hitDelta = rz_config_get_i(core->config, name) + delta;
1926  (void)rz_config_set_i(core->config, name, hitDelta);
1927  }
1928 }
1929 
1930 /* Visually activate the config variable */
1931 static void config_visual_hit(RzCore *core, const char *name, int editor) {
1932  char buf[1024];
1933  RzConfigNode *node;
1934 
1935  if (!(node = rz_config_node_get(core->config, name))) {
1936  return;
1937  }
1938  if (rz_config_node_is_bool(node)) {
1939  rz_config_set_i(core->config, name, node->i_value ? 0 : 1);
1940  } else {
1941  // XXX: must use config_set () to run callbacks!
1942  if (editor) {
1943  char *buf = rz_core_editor(core, NULL, node->value);
1944  node->value = rz_str_dup(node->value, buf);
1945  free(buf);
1946  } else {
1947  // FGETS AND SO
1948  rz_cons_printf("New value (old=%s): \n", node->value);
1949  rz_cons_show_cursor(true);
1950  rz_cons_flush();
1951  rz_cons_set_raw(0);
1952  rz_line_set_prompt(":> ");
1953  rz_cons_fgets(buf, sizeof(buf), 0, 0);
1954  rz_cons_set_raw(1);
1955  rz_cons_show_cursor(false);
1956  rz_config_set(core->config, name, buf);
1957  // node->value = rz_str_dup (node->value, buf);
1958  }
1959  }
1960 }
1961 
1962 static void show_config_options(RzCore *core, const char *opt) {
1963  RzConfigNode *node = rz_config_node_get(core->config, opt);
1964  if (node && !rz_list_empty(node->options)) {
1965  int h, w = rz_cons_get_size(&h);
1966  const char *item;
1967  RzListIter *iter;
1968  RzStrBuf *sb = rz_strbuf_new(" Options: ");
1969  rz_list_foreach (node->options, iter, item) {
1970  rz_strbuf_appendf(sb, "%s%s", iter->p ? ", " : "", item);
1971  if (rz_strbuf_length(sb) + 5 >= w) {
1972  char *s = rz_strbuf_drain(sb);
1973  rz_cons_println(s);
1974  free(s);
1975  sb = rz_strbuf_new("");
1976  }
1977  }
1978  char *s = rz_strbuf_drain(sb);
1979  rz_cons_println(s);
1980  free(s);
1981  }
1982 }
1983 
1985  char *fs = NULL, *fs2 = NULL, *desc = NULL;
1986  int i, j, ch, hit, show;
1987  int option, _option = 0;
1988  RzListIter *iter;
1989  RzConfigNode *bt;
1990  char old[1024];
1991  int delta = 9;
1992  int menu = 0;
1993  old[0] = '\0';
1994 
1995  option = 0;
1996  for (;;) {
1997  rz_cons_clear00();
1999  delta /= 4;
2000 
2001  switch (menu) {
2002  case 0: // flag space
2003  rz_cons_printf("[EvalSpace]\n\n");
2004  hit = j = i = 0;
2005  rz_list_foreach (core->config->nodes, iter, bt) {
2006  if (option == i) {
2007  fs = bt->name;
2008  }
2009  if (!old[0]) {
2010  rz_str_ccpy(old, bt->name, '.');
2011  show = 1;
2012  } else if (rz_str_ccmp(old, bt->name, '.')) {
2013  rz_str_ccpy(old, bt->name, '.');
2014  show = 1;
2015  } else {
2016  show = 0;
2017  }
2018  if (show) {
2019  if (option == i) {
2020  hit = 1;
2021  }
2022  if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
2023  rz_cons_printf(" %c %s\n", (option == i) ? '>' : ' ', old);
2024  j++;
2025  }
2026  i++;
2027  }
2028  }
2029  if (!hit && j > 0) {
2030  option--;
2031  continue;
2032  }
2033  rz_cons_printf("\n Sel: %s \n\n", fs);
2034  break;
2035  case 1: // flag selection
2036  rz_cons_printf("[EvalSpace < Variables: %s]\n\n", fs);
2037  hit = 0;
2038  j = i = 0;
2039  // TODO: cut -d '.' -f 1 | sort | uniq !!!
2040  rz_list_foreach (core->config->nodes, iter, bt) {
2041  if (!rz_str_ccmp(bt->name, fs, '.')) {
2042  if (option == i) {
2043  fs2 = bt->name;
2044  desc = bt->desc;
2045  hit = 1;
2046  }
2047  if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
2048  // TODO: Better align
2049  rz_cons_printf(" %c %s = %s\n", (option == i) ? '>' : ' ', bt->name, bt->value);
2050  j++;
2051  }
2052  i++;
2053  }
2054  }
2055  if (!hit && j > 0) {
2056  option = i - 1;
2057  continue;
2058  }
2059  if (fs2) {
2060  // TODO: Break long lines.
2061  rz_cons_printf("\n Selected: %s (%s)\n", fs2, desc);
2062  show_config_options(core, fs2);
2063  rz_cons_newline();
2064  }
2065  }
2066 
2067  if (fs && !strncmp(fs, "asm.", 4)) {
2068  rz_core_cmd(core, "pd $r", 0);
2069  }
2071  ch = rz_cons_readchar();
2072  if (ch == 4 || ch == -1) {
2073  return;
2074  }
2075  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
2076 
2077  switch (ch) {
2078  case 'j': option++; break;
2079  case 'k': option = (option <= 0) ? 0 : option - 1; break;
2080  case 'J': option += 4; break;
2081  case 'K': option = (option <= 3) ? 0 : option - 4; break;
2082  case 'h':
2083  case 'b': // back
2084  menu = 0;
2085  option = _option;
2086  break;
2087  case '_':
2089  break;
2090  case 'Q':
2091  case 'q':
2092  if (menu <= 0) {
2093  return;
2094  }
2095  menu--;
2096  option = _option;
2097  break;
2098  case '$':
2101  break;
2102  case '*':
2103  case '+':
2104  fs2 ? config_visual_hit_i(core, fs2, +1) : 0;
2105  continue;
2106  case '/':
2107  case '-':
2108  fs2 ? config_visual_hit_i(core, fs2, -1) : 0;
2109  continue;
2110  case 'l':
2111  case 'E': // edit value
2112  case 'e': // edit value
2113  case ' ':
2114  case '\r':
2115  case '\n': // never happens
2116  if (menu == 1) {
2117  fs2 ? config_visual_hit(core, fs2, (ch == 'E')) : 0;
2118  } else {
2119  menu = 1;
2120  _option = option;
2121  option = 0;
2122  }
2123  break;
2124  case '?':
2125  rz_cons_clear00();
2126  rz_cons_printf("\nVe: Visual Eval help:\n\n"
2127  " q - quit menu\n"
2128  " j/k - down/up keys\n"
2129  " h/b - go back\n"
2130  " $ - same as ?$ - show values of vars\n"
2131  " e/' ' - edit/toggle current variable\n"
2132  " E - edit variable with 'cfg.editor' (vi?)\n"
2133  " +/- - increase/decrease numeric value (* and /, too)\n"
2134  " : - enter command\n");
2135  rz_cons_flush();
2137  break;
2138  case ':':
2139  rz_cons_show_cursor(true);
2140  rz_cons_set_raw(0);
2141  {
2142  char *cmd = prompt(":> ", NULL);
2143  rz_core_cmd(core, cmd, 1);
2144  free(cmd);
2145  }
2146  rz_cons_set_raw(1);
2147  rz_cons_show_cursor(false);
2149  rz_cons_clear00();
2150  continue;
2151  }
2152  }
2153 }
2154 
2155 // helper
2156 static void function_rename(RzCore *core, ut64 addr, const char *name) {
2157  RzListIter *iter;
2158  RzAnalysisFunction *fcn;
2159 
2160  rz_list_foreach (core->analysis->fcns, iter, fcn) {
2161  if (fcn->addr == addr) {
2162  rz_flag_unset_name(core->flags, fcn->name);
2163  free(fcn->name);
2164  fcn->name = strdup(name);
2166  break;
2167  }
2168  }
2169 }
2170 
2171 static void variable_rename(RzCore *core, ut64 addr, int vindex, const char *name) {
2173  ut64 a_tmp = core->offset;
2174  int i = 0;
2175  RzListIter *iter;
2177  RzAnalysisVar *var;
2178 
2179  rz_list_foreach (list, iter, var) {
2180  if (i == vindex) {
2181  rz_core_seek(core, addr, false);
2182  rz_core_analysis_var_rename(core, name, var->name);
2183  rz_core_seek(core, a_tmp, false);
2184  break;
2185  }
2186  ++i;
2187  }
2188  rz_list_free(list);
2189 }
2190 
2191 static void variable_set_type(RzCore *core, ut64 addr, int vindex, const char *type) {
2194  RzListIter *iter;
2195  RzAnalysisVar *var;
2196 
2198  rz_list_foreach (list, iter, var) {
2199  if (vindex == 0) {
2200  rz_analysis_var_set_type(var, ttype, true);
2201  break;
2202  }
2203  vindex--;
2204  }
2205  rz_list_free(list);
2206 }
2207 
2214 static RzPVector *capture_filter_keywords(char *visual_inputing) {
2215  rz_return_val_if_fail(visual_inputing, NULL);
2216  char *buf, *inputing;
2217  RzPVector *keywords = rz_pvector_new(free);
2218 
2219  if (!keywords) {
2220  return NULL;
2221  }
2222  inputing = rz_str_trim_dup(visual_inputing);
2223  buf = rz_str_new("");
2224  for (int i = 0; i < strlen(visual_inputing); i++) {
2225  if (IS_WHITESPACE(visual_inputing[i])) {
2226  if (strlen(buf)) {
2227  rz_pvector_push(keywords, buf);
2228  buf = rz_str_new("");
2229  }
2230  } else {
2231  buf = rz_str_appendch(buf, visual_inputing[i]);
2232  }
2233  }
2234  if (strlen(buf)) {
2235  rz_pvector_push(keywords, buf);
2236  } else {
2237  RZ_FREE(buf);
2238  }
2239  RZ_FREE(inputing);
2240  return keywords;
2241 }
2242 
2250 static ut32 filter_function(RzCore *core, RzList *filter_fcn, RzPVector *keywords) {
2251  rz_return_val_if_fail(core, 0);
2252  RzListIter *iter;
2253  RzAnalysisFunction *fcn;
2254  size_t num = 0;
2255 
2256  rz_list_foreach (core->analysis->fcns, iter, fcn) {
2257  bool contain = true;
2258  void **it;
2259  rz_pvector_foreach (keywords, it) {
2260  contain = contain && strstr(fcn->name, (char *)*it);
2261  }
2262  if (!contain) {
2263  continue;
2264  }
2265  if (filter_fcn) {
2266  rz_list_append(filter_fcn, fcn);
2267  }
2268  num++;
2269  }
2270 
2271  return num;
2272 }
2273 
2274 // In visual mode, display function list
2275 static ut64 var_functions_show(RzCore *core, int idx, int show, int cols) {
2276  int wdelta = (idx > 5) ? idx - 5 : 0;
2277  char *var_functions;
2278  ut64 seek = core->offset;
2279  ut64 addr = core->offset;
2280  RzAnalysisFunction *fcn;
2281  RzList *filter_fcn = core->analysis->fcns, *visual_filter = NULL;
2282  int window, i = 0, print_full_func;
2283  RzListIter *iter;
2284 
2285  // Adjust the windows size automaticaly
2286  (void)rz_cons_get_size(&window);
2287  window -= core->visual_inputing ? 10 : 8; // Size of printed things
2288  bool color = rz_config_get_i(core->config, "scr.color");
2289  const char *color_addr = core->cons->context->pal.offset;
2290  const char *color_fcn = core->cons->context->pal.fname;
2291 
2292  if (core->visual_inputing) {
2293  visual_filter = rz_list_newf(NULL);
2294  if (visual_filter) {
2296  if (keywords) {
2297  filter_function(core, visual_filter, keywords);
2298  RZ_FREE_CUSTOM(keywords, rz_pvector_free);
2299  filter_fcn = visual_filter;
2300  }
2301  }
2302  }
2303 
2304  rz_list_foreach (filter_fcn, iter, fcn) {
2305  print_full_func = true;
2306  if (i >= wdelta) {
2307  if (i > window + wdelta - 1) {
2308  rz_cons_printf("...\n");
2309  break;
2310  }
2311  if (idx == i) {
2312  addr = fcn->addr;
2313  }
2314  if (show) {
2315  char *tmp;
2316  if (color) {
2317  var_functions = rz_str_newf("%c%c %s0x%08" PFMT64x "" Color_RESET " %4" PFMT64d " %s%s" Color_RESET "",
2318  (seek == fcn->addr) ? '>' : ' ',
2319  (idx == i) ? '*' : ' ',
2320  color_addr, fcn->addr, rz_analysis_function_realsize(fcn),
2321  color_fcn, fcn->name);
2322  } else {
2323  var_functions = rz_str_newf("%c%c 0x%08" PFMT64x " %4" PFMT64d " %s",
2324  (seek == fcn->addr) ? '>' : ' ',
2325  (idx == i) ? '*' : ' ',
2326  fcn->addr, rz_analysis_function_realsize(fcn), fcn->name);
2327  }
2328  if (var_functions) {
2329  if (!rz_cons_singleton()->show_vals) {
2330  int fun_len = rz_str_ansi_len(var_functions);
2331  int columns = fun_len > cols ? cols - 2 : cols;
2332  tmp = rz_str_ansi_crop(var_functions, 0, 0, columns, window);
2333  if (rz_str_ansi_len(tmp) < fun_len) {
2334  rz_cons_printf("%s..%s\n", tmp, Color_RESET);
2335  print_full_func = false;
2336  }
2337  rz_free(tmp);
2338  }
2339  if (print_full_func) {
2340  rz_cons_println(var_functions);
2341  }
2342  rz_free(var_functions);
2343  }
2344  }
2345  }
2346  i++;
2347  }
2348  if (filter_fcn != core->analysis->fcns) {
2349  rz_list_free(filter_fcn);
2350  }
2351  return addr;
2352 }
2353 
2354 // In visual mode, display the variables.
2355 static ut64 var_variables_show(RzCore *core, int idx, int *vindex, int show, int cols) {
2356  int i = 0;
2357  const ut64 addr = var_functions_show(core, idx, 0, cols);
2359  int window;
2360  int wdelta = (idx > 5) ? idx - 5 : 0;
2361  RzListIter *iter;
2363  RzAnalysisVar *var;
2364  // Adjust the window size automatically.
2365  (void)rz_cons_get_size(&window);
2366  window -= 8; // Size of printed things.
2367 
2368  // A new line so this looks reasonable.
2369  rz_cons_newline();
2370 
2371  int llen = rz_list_length(list);
2372  if (*vindex >= llen) {
2373  *vindex = llen - 1;
2374  }
2375 
2376  rz_list_foreach (list, iter, var) {
2377  if (i >= wdelta) {
2378  if (i > window + wdelta) {
2379  rz_cons_printf("...\n");
2380  break;
2381  }
2382  if (show) {
2383  char *vartype = rz_type_as_string(core->analysis->typedb, var->type);
2384  switch (var->kind & 0xff) {
2385  case 'r': {
2386  RzRegItem *r = rz_reg_index_get(core->analysis->reg, var->delta);
2387  if (!r) {
2388  eprintf("Register not found");
2389  break;
2390  }
2391  rz_cons_printf("%sarg %s %s @ %s\n",
2392  i == *vindex ? "* " : " ",
2393  vartype, var->name,
2394  r->name);
2395  } break;
2396  case 'b':
2397  rz_cons_printf("%s%s %s %s @ %s%s0x%x\n",
2398  i == *vindex ? "* " : " ",
2399  var->delta < 0 ? "var" : "arg",
2400  vartype, var->name,
2401  core->analysis->reg->name[RZ_REG_NAME_BP],
2402  (var->kind == 'v') ? "-" : "+",
2403  var->delta);
2404  break;
2405  case 's':
2406  rz_cons_printf("%s%s %s %s @ %s%s0x%x\n",
2407  i == *vindex ? "* " : " ",
2408  var->delta < 0 ? "var" : "arg",
2409  vartype, var->name,
2410  core->analysis->reg->name[RZ_REG_NAME_BP],
2411  (var->kind == 'v') ? "-" : "+",
2412  var->delta);
2413  break;
2414  }
2415  free(vartype);
2416  }
2417  }
2418  ++i;
2419  }
2420  rz_list_free(list);
2421  return addr;
2422 }
2423 
2424 static int level = 0;
2425 static st64 delta = 0;
2426 static int option = 0;
2427 static int variable_option = 0;
2428 static int printMode = 0;
2429 static bool selectPanel = false;
2430 #define lastPrintMode 6
2431 static const char *printCmds[lastPrintMode] = {
2432  "pdf", "pd $r", "afi", "pdsf", "pdc", "pdr"
2433 };
2434 
2435 static void rz_core_visual_analysis_refresh_column(RzCore *core, int colpos) {
2436  const ut64 addr = (level != 0 && level != 1)
2437  ? core->offset
2438  : var_functions_show(core, option, 0, colpos);
2439  // RzAnalysisFunction* fcn = rz_analysis_get_fcn_in(core->analysis, addr, RZ_ANALYSIS_FCN_TYPE_NULL);
2440  int h, w = rz_cons_get_size(&h);
2441  // int sz = (fcn)? RZ_MIN (rz_analysis_fcn_size (fcn), h * 15) : 16; // max instr is 15 bytes.
2442 
2443  const char *cmd;
2444  if (printMode > 0 && printMode < lastPrintMode) {
2445  cmd = printCmds[printMode];
2446  } else {
2447  cmd = printCmds[printMode = 0];
2448  }
2449  char *cmdf = rz_str_newf("%s @ 0x%" PFMT64x, cmd, addr + delta);
2450  if (!cmdf) {
2451  return;
2452  }
2453  char *output = rz_core_cmd_str(core, cmdf);
2454  if (output) {
2455  // 'h - 2' because we have two new lines in rz_cons_printf
2456  char *out = rz_str_ansi_crop(output, 0, 0, w - colpos, h - 2);
2457  rz_cons_printf("\n%s\n", out);
2458  free(out);
2459  RZ_FREE(output);
2460  }
2461  free(cmdf);
2462 }
2463 
2464 static const char *help_fun_visual[] = {
2465  "(a)", "analyze ", "(-)", "delete ", "(x)", "xrefs to ", "(X)", "xrefs from\n",
2466  "(r)", "rename ", "(c)", "calls ", "(d)", "define ", "(:)", "shell ", "(v)", "vars\n",
2467  "(j/k)", "next/prev ", "(tab)", "column ", "(_)", "hud ", "(?)", " help\n",
2468  "(f/F)", "set/reset filter ", "(s)", "function signature ", "(q)", "quit\n\n",
2469  NULL
2470 };
2471 
2472 static const char *help_var_visual[] = {
2473  "(a)", "add ", "(x)", "xrefs ", "(r)", "rename\n",
2474  "(t)", "type ", "(g)", "go ", "(-)", "delete\n",
2475  "(q)", "quit ", "(s)", "signature\n\n",
2476  NULL
2477 };
2478 
2479 static const char *help_vv_visual[] = {
2480  "j,k", "select next/prev item or scroll if tab pressed",
2481  "J,K", "scroll next/prev page \"\"",
2482  "f,F", "set/reset filter keyword",
2483  "h,q", "go back, quit",
2484  "p,P", "switch next/prev print mode",
2485  "v", "view selected function arguments and variables",
2486  "x,X", "see xrefs to the selected function",
2487  "tab", "toggle disasm column selection (to scroll in code)",
2488  "!", "run 'afls' to sort all functions by address",
2489  ".", "seek to current function address",
2490  ":", "run rizin commands",
2491  "_", "hud mode. same as: s $(afl~...)",
2492  "enter", "enter function view (variables), xrefs",
2493  NULL
2494 };
2495 
2496 static const char *help_vv_actions_visual[] = {
2497  " functions:", "Add, Modify, Delete, Xrefs Calls Vars",
2498  " variables:", "Add, Modify, Delete",
2499  NULL
2500 };
2501 
2502 static void rz_core_vmenu_append_help(RzStrBuf *p, const char **help) {
2503  int i;
2504  RzConsContext *cons_ctx = rz_cons_singleton()->context;
2505  const char *pal_args_color = cons_ctx->color_mode ? cons_ctx->pal.args : "",
2506  *pal_help_color = cons_ctx->color_mode ? cons_ctx->pal.help : "",
2507  *pal_reset = cons_ctx->color_mode ? cons_ctx->pal.reset : "";
2508 
2509  for (i = 0; help[i]; i += 2) {
2510  rz_strbuf_appendf(p, "%s%s %s%s%s",
2511  pal_args_color, help[i],
2512  pal_help_color, help[i + 1], pal_reset);
2513  }
2514 }
2515 
2517  if (!core) {
2518  return 0LL;
2519  }
2520  ut64 addr;
2521  RzStrBuf *buf;
2522  char old[1024];
2523  bool color = rz_config_get_i(core->config, "scr.color");
2524  int h, cols = rz_cons_get_size(&h);
2525  old[0] = '\0';
2526  addr = core->offset;
2527  cols -= 50;
2528  if (cols > 60) {
2529  cols = 60;
2530  }
2531 
2532  rz_cons_clear00();
2534  if (cols > 30) {
2535  rz_cons_column(cols);
2536  }
2537  switch (level) {
2538  // Show functions list help in visual mode
2539  case 0: {
2540  buf = rz_strbuf_new("");
2541  if (color) {
2543  }
2544  if (selectPanel) {
2545  rz_cons_printf("-- functions -----------------[ %s ]-->>", printCmds[printMode]);
2546  } else {
2547  rz_cons_printf("-[ functions ]----------------- %s ---", printCmds[printMode]);
2548  }
2549  if (color) {
2551  }
2553  char *drained = rz_strbuf_drain(buf);
2554  rz_cons_printf("%s", drained);
2555  free(drained);
2556  // hints for filtered keywords
2557  if (core->visual_inputing) {
2558  if (core->visual_is_inputing) {
2559  rz_cons_printf("input keywords: %s\n\n", core->visual_inputing);
2560  } else {
2561  rz_cons_printf("keywords: %s\n\n", core->visual_inputing);
2562  }
2563  }
2564  addr = var_functions_show(core, option, 1, cols);
2565  break;
2566  }
2567  case 1: {
2568  buf = rz_strbuf_new("");
2569  if (color) {
2571  }
2572  rz_cons_printf("-[ variables ]----- 0x%08" PFMT64x "", addr);
2573  if (color) {
2575  }
2577  char *drained = rz_strbuf_drain(buf);
2578  rz_cons_printf("%s", drained);
2579  addr = var_variables_show(core, option, &variable_option, 1, cols);
2580  free(drained);
2581  // var_index_show (core->analysis, fcn, addr, option);
2582  break;
2583  }
2584  case 2: {
2585  rz_cons_printf("Press 'q' to quit call refs\n");
2586  if (color) {
2588  }
2589  rz_cons_printf("-[ calls ]----------------------- 0x%08" PFMT64x " (TODO)\n", addr);
2590  if (color) {
2592  }
2593  // TODO: filter only the callrefs. but we cant grep here
2594  sprintf(old, "afi @ 0x%08" PFMT64x, addr);
2595  char *output = rz_core_cmd_str(core, old);
2596  if (output) {
2597  // 'h - 2' because we have two new lines in rz_cons_printf
2598  if (!rz_cons_singleton()->show_vals) {
2599  char *out = rz_str_ansi_crop(output, 0, 0, cols, h - 2);
2600  rz_cons_printf("\n%s\n", out);
2601  free(out);
2602  RZ_FREE(output);
2603  } else {
2604  rz_cons_printf("\n%s\n", output);
2605  RZ_FREE(output);
2606  }
2607  }
2608  break;
2609  }
2610  default:
2612  break;
2613  }
2614  rz_cons_flush();
2615  return addr;
2616 }
2617 
2619  rz_core_task_enqueue_oneshot(&core->tasks, (RzCoreTaskOneShot)rz_core_visual_analysis_refresh, core);
2620 }
2621 
2623  rz_cons_clear00();
2625  "vbd: Visual Browse Debugtraces:\n\n"
2626  " q - quit the bit editor\n"
2627  " Q - Quit (jump into the disasm view)\n"
2628  " j/k - Select next/previous trace\n"
2629  " : - enter command\n");
2630  rz_cons_flush();
2632 }
2633 
2634 RZ_API void rz_core_visual_debugtraces(RzCore *core, const char *input) {
2635  int i, delta = 0;
2636  for (;;) {
2637  char *trace_addr_str = rz_core_cmd_strf(core, "dtdq %d", delta);
2638  ut64 trace_addr = rz_num_get(NULL, trace_addr_str);
2639  free(trace_addr_str);
2640  rz_cons_printf("[0x%08" PFMT64x "]> %d dbg.trace\n", trace_addr, delta);
2641  for (i = 0; i < delta; i++) {
2642  rz_core_cmdf(core, ".dte %d", i);
2643  }
2644  rz_core_cmd0(core, "x 64@r:SP");
2645  rz_core_debug_ri(core);
2646  // limit by rows here
2647  // int rows = rz_cons_get_size (NULL);
2648  rz_core_cmdf(core, "dtd %d", delta);
2650  char ch;
2651  if (input && *input) {
2652  ch = *input;
2653  input++;
2654  } else {
2655  ch = rz_cons_readchar();
2656  }
2657  if (ch == 4 || ch == -1) {
2658  if (level == 0) {
2659  goto beach;
2660  }
2661  level--;
2662  continue;
2663  }
2664  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
2665  switch (ch) {
2666  case 'Q': // tab
2667  {
2668  ut64 oseek = core->offset;
2669  core->vmode = false;
2670  rz_core_seek(core, trace_addr, true);
2671  rz_core_visual(core, "");
2672  rz_core_seek(core, oseek, true);
2673  } break;
2674  case 'q':
2675  goto beach;
2676  break;
2677  case ']':
2678  rz_config_set_i(core->config, "hex.cols", rz_config_get_i(core->config, "hex.cols") + 1);
2679  break;
2680  case '[':
2681  rz_config_set_i(core->config, "hex.cols", rz_config_get_i(core->config, "hex.cols") - 1);
2682  break;
2683  case 'J':
2684  delta += 10;
2685  break;
2686  case 'K':
2687  delta -= 10;
2688  if (delta < 0) {
2689  delta = 0;
2690  }
2691  break;
2692  case 'j':
2693  delta++;
2694  break;
2695  case 'k':
2696  delta--;
2697  if (delta < 0) {
2698  delta = 0;
2699  }
2700  break;
2701  case ':':
2702  rz_core_visual_prompt(core);
2704  break;
2705  case '?':
2707  break;
2708  }
2709  }
2710 beach:;
2711 }
2712 
2713 static char *__prompt(const char *msg, void *p) {
2714  char res[128];
2715  rz_cons_show_cursor(true);
2716  rz_cons_set_raw(false);
2718  res[0] = 0;
2719  if (!rz_cons_fgets(res, sizeof(res), 0, NULL)) {
2720  res[0] = 0;
2721  }
2722  return strdup(res);
2723 }
2724 
2725 static void addVar(RzCore *core, int ch, const char *msg) {
2726  char *src = __prompt(msg, NULL);
2727  char *name = __prompt("Variable Name: ", NULL);
2728  char *type = __prompt("Type of Variable (int32_t): ", NULL);
2729  char *cmd = rz_str_newf("afv%c %s %s %s", ch, src, name, type);
2730  rz_str_trim(cmd);
2731  rz_core_cmd0(core, cmd);
2732  free(cmd);
2733  free(src);
2734  free(name);
2735  free(type);
2736 }
2737 
2738 /* Like emenu but for real */
2739 RZ_API void rz_core_visual_analysis(RzCore *core, const char *input) {
2740  char old[218];
2741  int nfcns, ch, _option = 0;
2742 
2743  RzConsEvent olde = core->cons->event_resize;
2744  void *olde_user = core->cons->event_data;
2745  ut64 addr = core->offset;
2746 
2747  core->cons->event_resize = NULL; // avoid running old event with new data
2748  core->cons->event_data = core;
2750 
2751  level = 0;
2752 
2753  int asmbytes = rz_config_get_i(core->config, "asm.bytes");
2754  rz_config_set_i(core->config, "asm.bytes", 0);
2755  for (;;) {
2756  nfcns = rz_list_length(core->analysis->fcns);
2757  if (core->visual_inputing) {
2759  if (keywords) {
2760  nfcns = filter_function(core, NULL, keywords);
2761  }
2762  RZ_FREE_CUSTOM(keywords, rz_pvector_free);
2763  }
2765 
2766  // for filter on the go
2767  if (level == 0 && core->visual_is_inputing) {
2768  int ch = rz_cons_readchar();
2769  switch (ch) {
2770  case 13: // CR
2771  core->visual_is_inputing = false;
2772  if (!strlen(core->visual_inputing)) {
2773  RZ_FREE(core->visual_inputing);
2774  }
2775  break;
2776  case 127: // Backspace
2777  case 8:
2778  if (strlen(core->visual_inputing) > 0) {
2779  core->visual_inputing[strlen(core->visual_inputing) - 1] = '\0';
2780  }
2781  break;
2782  default:
2783  if (!IS_PRINTABLE(ch)) {
2784  continue;
2785  }
2786  core->visual_inputing = rz_str_appendch(core->visual_inputing, ch);
2787  break;
2788  }
2789  // mute the following switch while inputing keyword
2790  continue;
2791  }
2792 
2793  if (input && *input) {
2794  ch = *input;
2795  input++;
2796  } else {
2797  ch = rz_cons_readchar();
2798  }
2799  if (ch == 4 || ch == -1) {
2800  if (level == 0) {
2801  goto beach;
2802  }
2803  level--;
2804  continue;
2805  }
2806  ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
2807 
2808  switch (ch) {
2809  case 'f':
2810  if (level == 0) {
2811  // add new keyword
2812  core->visual_is_inputing = true;
2813  if (!core->visual_inputing) {
2814  core->visual_inputing = rz_str_new("");
2815  }
2816  option = 0;
2817  }
2818  break;
2819  case 'F':
2820  if (level == 0) {
2821  // reset all keywords
2822  RZ_FREE(core->visual_inputing);
2823  }
2824  break;
2825  case '[':
2826  rz_cons_singleton()->show_vals = true;
2827  break;
2828  case ']':
2829  rz_cons_singleton()->show_vals = false;
2830  break;
2831  case '?':
2832  rz_cons_clear00();
2833  RzStrBuf *buf = rz_strbuf_new("");
2834  rz_cons_println("|Usage: vv");
2835  rz_core_visual_append_help(buf, "Actions supported", help_vv_actions_visual);
2838  rz_cons_flush();
2840  break;
2841  case 9:
2843  if (!selectPanel) {
2844  delta = 0;
2845  printMode = 0;
2846  }
2847  break;
2848  case ':': {
2849  ut64 orig = core->offset;
2850  rz_core_seek(core, addr, false);
2851  while (rz_core_visual_prompt(core))
2852  ;
2853  rz_core_seek(core, orig, false);
2854  }
2855  continue;
2856  case '/':
2857  rz_core_cmd0(core, "?i highlight;e scr.highlight=`yp`");
2858  break;
2859  case 'a':
2860  switch (level) {
2861  case 0:
2862  // Remove the old function information
2863  rz_core_analysis_undefine(core, core->offset);
2865  rz_analysis_fcn_del(core->analysis, core->offset);
2866  // Reanalyze and create function from scratch
2867  rz_core_analysis_function_add(core, NULL, core->offset, false);
2868  break;
2869  case 1: {
2870  eprintf("Select variable source ('r'egister, 's'tackptr or 'b'aseptr): ");
2871  int type = rz_cons_readchar();
2872  switch (type) {
2873  case 'r':
2874  addVar(core, type, "Source Register Name: ");
2875  break;
2876  case 's':
2877  addVar(core, type, "BP Relative Delta: ");
2878  break;
2879  case 'b':
2880  addVar(core, type, "SP Relative Delta: ");
2881  break;
2882  }
2883  } break;
2884  }
2885  break;
2886  case 'r': {
2887  switch (level) {
2888  case 1:
2889  rz_cons_show_cursor(true);
2890  rz_cons_set_raw(false);
2891  rz_line_set_prompt("New name: ");
2892  if (rz_cons_fgets(old, sizeof(old), 0, NULL)) {
2893  if (*old) {
2894  // old[strlen (old)-1] = 0;
2895  variable_rename(core, addr, variable_option, old);
2896  }
2897  }
2898  break;
2899  default:
2900  rz_line_set_prompt("New name: ");
2901  if (rz_cons_fgets(old, sizeof(old), 0, NULL)) {
2902  if (*old) {
2903  // old[strlen (old)-1] = 0;
2904  function_rename(core, addr, old);
2905  }
2906  }
2907  break;
2908  }
2909  rz_cons_set_raw(true);
2910  rz_cons_show_cursor(false);
2911  } break;
2912  case 't':
2913  if (level == 1) {
2914  rz_cons_show_cursor(true);
2915  rz_cons_set_raw(false);
2916  rz_line_set_prompt("New type: ");
2917  if (rz_cons_fgets(old, sizeof(old), 0, NULL)) {
2918  if (*old) {
2919  // old[strlen (old)-1] = 0;
2920  variable_set_type(core, addr, variable_option, old);
2921  }
2922  }
2923  rz_cons_set_raw(true);
2924  rz_cons_show_cursor(false);
2925  }
2926  break;
2927  case '.':
2928  delta = 0;
2929  break;
2930  case 'R':
2931  rz_core_theme_nextpal(core, 'n');
2932  break;
2933  case 'p':
2934  printMode++;
2935  break;
2936  case 'P':
2937  if (printMode == 0) {
2939  } else {
2940  printMode--;
2941  }
2942  break;
2943  case 'd':
2944  rz_core_visual_define(core, "", 0);
2945  break;
2946  case '-':
2947  switch (level) {
2948  case 0:
2949  // Remove the old function information
2953  break;
2954  }
2955  break;
2956  case 'x':
2957  rz_core_visual_xrefs(core, false, true);
2958  break;
2959  case 'X':
2960  rz_core_visual_xrefs(core, true, true);
2961  break;
2962  case 's':
2964  break;
2965  case 'c':
2966  level = 2;
2967  break;
2968  case 'v':
2969  level = 1;
2970  variable_option = 0;
2971  break;
2972  case '_': {
2973  rz_core_cmd0(core, "s $(afl~...)");
2974  int n = 0;
2975  RzListIter *iter;
2976  RzAnalysisFunction *fcn;
2977  rz_list_foreach (core->analysis->fcns, iter, fcn) {
2978  if (fcn->addr == core->offset) {
2979  option = n;
2980  break;
2981  }
2982  n++;
2983  }
2984  } break;
2985  case 'j':
2986  if (selectPanel) {
2987  printMode = 1;
2988  delta += 16;
2989  } else {
2990  delta = 0;
2991  switch (level) {
2992  case 1:
2993  variable_option++;
2994  break;
2995  default:
2996  option++;
2997  if (option >= nfcns) {
2998  --option;
2999  }
3000  break;
3001  }
3002  }
3003  break;
3004  case '!':
3005  // TODO: use aflsn/aflsb/aflss/...
3006  {
3007  static int sortMode = 0;
3008  const char *sortModes[4] = { "aflsa", "aflss", "aflsb", "aflsn" };
3009  rz_core_cmd0(core, sortModes[sortMode % 4]);
3010  sortMode++;
3011  }
3012  break;
3013  case 'k':
3014  if (selectPanel) {
3015  printMode = 1;
3016  delta -= 16;
3017  } else {
3018  delta = 0;
3019  switch (level) {
3020  case 1:
3021  variable_option = (variable_option <= 0) ? 0 : variable_option - 1;
3022  break;
3023  default:
3024  option = (option <= 0) ? 0 : option - 1;
3025  break;
3026  }
3027  }
3028 
3029  break;
3030  case 'J':
3031  if (selectPanel) {
3032  printMode = 1;
3033  delta += 40;
3034  } else {
3035  int rows = 0;
3036  rz_cons_get_size(&rows);
3037  option += (rows - 5);
3038  if (option >= nfcns) {
3039  option = nfcns - 1;
3040  }
3041  }
3042  break;
3043  case 'K':
3044  if (selectPanel) {
3045  printMode = 1;
3046  delta -= 40;
3047  } else {
3048  int rows = 0;
3049  rz_cons_get_size(&rows);
3050  option -= (rows - 5);
3051  if (option < 0) {
3052  option = 0;
3053  }
3054  }
3055  break;
3056  case 'g': {
3057  rz_core_visual_showcursor(core, true);
3058  rz_core_visual_offset(core); // change the seek to selected offset
3059  RzListIter *iter; // change the current option to selected seek
3060  RzAnalysisFunction *fcn;
3061  int i = 0;
3062  rz_list_foreach (core->analysis->fcns, iter, fcn) {
3063  if (core->offset == fcn->addr) {
3064  option = i;
3065  }
3066  i++;
3067  }
3068  rz_core_visual_showcursor(core, false);
3069  } break;
3070  case 'G':
3071  rz_core_seek(core, addr, SEEK_SET);
3072  goto beach;
3073  case ' ':
3074  case '\r':
3075  case '\n':
3076  level = 0;
3077  rz_core_seek(core, addr, SEEK_SET);
3078  goto beach;
3079  break;
3080  case 'l':
3081  level = 1;
3082  _option = option;
3083  break;
3084  case 'h':
3085  case 'b': // back
3086  level = 0;
3087  option = _option;
3088  break;
3089  case 'Q':
3090  case 'q':
3091  if (level == 0) {
3092  goto beach;
3093  }
3094  level--;
3095  break;
3096  }
3097  }
3098 beach:
3099  core->cons->event_resize = NULL; // avoid running old event with new data
3100  core->cons->event_data = olde_user;
3101  core->cons->event_resize = olde;
3102  level = 0;
3103  rz_config_set_i(core->config, "asm.bytes", asmbytes);
3104 }
3105 
3106 // define the data at offset according to the type (byte, word...) n times
3107 static void define_data_ntimes(RzCore *core, ut64 off, int times, int type) {
3108  int i = 0;
3110  if (times < 0) {
3111  times = 1;
3112  }
3113  for (i = 0; i < times; i++, off += type) {
3115  }
3116 }
3117 
3118 static bool isDisasmPrint(int mode) {
3119  return (mode == 1 || mode == 2);
3120 }
3121 
3122 static void handleHints(RzCore *core) {
3123  // TODO extend for more analysis hints
3124  int i = 0;
3125  char ch[64] = RZ_EMPTY;
3126  const char *lines[] = { "[dh]- Define analysis hint:", " b [16,32,64] set bits hint", NULL };
3127  for (i = 0; lines[i]; i++) {
3129  rz_cons_printf("\r%s\n", lines[i]);
3130  }
3131  rz_cons_flush();
3132  rz_line_set_prompt("analysis hint: ");
3133  if (rz_cons_fgets(ch, sizeof(ch), 0, NULL) > 0) {
3134  switch (ch[0]) {
3135  case 'b': {
3136  char *arg = ch + 1;
3137  rz_str_trim(arg);
3138  int bits = atoi(arg);
3139  if (bits == 8 || bits == 16 || bits == 32 || bits == 64) {
3141  }
3142  } break;
3143  default:
3144  break;
3145  }
3146  }
3147 }
3148 
3149 RZ_API void rz_core_visual_define(RzCore *core, const char *args, int distance) {
3150  int plen = core->blocksize;
3151  ut64 off = core->offset;
3152  int i, h = 0, n, ch, ntotal = 0;
3153  ut8 *p = core->block;
3154  int rep = -1;
3155  char *name;
3156  int delta = 0;
3157  if (core->print->cur_enabled) {
3158  int cur = core->print->cur;
3159  if (core->print->ocur != -1) {
3160  plen = RZ_ABS(core->print->cur - core->print->ocur) + 1;
3161  if (core->print->ocur < cur) {
3162  cur = core->print->ocur;
3163  }
3164  }
3165  off += cur;
3166  p += cur;
3167  }
3168  (void)rz_cons_get_size(&h);
3169  h -= 19;
3170  if (h < 0) {
3171  h = 0;
3172  rz_cons_clear00();
3173  } else {
3174  rz_cons_gotoxy(0, 3);
3175  }
3176  const char *lines[] = { "", "[Vd]- Define current block as:", " $ define flag size", " 1 edit bits", " a assembly", " b as byte (1 byte)", " B define half word (16 bit, 2 byte size)", " c as code (unset any data / string / format) in here", " C define flag color (fc)", " d set as data", " e end of function", " f analyze function", " F format", " h define hint (for half-word, see 'B')", " i (ahi) immediate base (b(in), o(ct), d(ec), h(ex), s(tr))", " I (ahi1) immediate base (b(in), o(ct), d(ec), h(ex), s(tr))", " j merge down (join this and next functions)", " k merge up (join this and previous function)", " h define analysis hint", " m manpage for current call", " n rename flag used at cursor", " N edit function signature (afs!)", " o opcode string", " r rename function", " R find references /r", " s set string", " S set strings in current block", " t set opcode type via aht hints (call, nop, jump, ...)", " u undefine metadata here", " v rename variable at offset that matches some hex digits", " x find xrefs to current address (./r)", " w set as 32bit word", " W set as 64bit word", " q quit menu", " z zone flag", NULL };
3177  for (i = 0; lines[i]; i++) {
3179  rz_cons_printf("\r%s\n", lines[i]);
3180  }
3181  rz_cons_flush();
3182  int wordsize = 0;
3183  // get ESC+char, return 'hjkl' char
3184 repeat:
3185  if (*args) {
3186  ch = *args;
3187  args++;
3188  } else {
3190  }
3191 
3192 onemoretime:
3193  wordsize = 4;
3194  switch (ch) {
3195  case 'N':
3197  break;
3198  case 'F': {
3199  char cmd[128];
3200  rz_cons_show_cursor(true);
3201  rz_core_cmd0(core, "pf?");
3202  rz_cons_flush();
3203  rz_line_set_prompt("format: ");
3204  strcpy(cmd, "Cf 0 ");
3205  if (rz_cons_fgets(cmd + 5, sizeof(cmd) - 5, 0, NULL) > 0) {
3206  rz_core_cmdf(core, "%s @ 0x%08" PFMT64x, cmd, off);
3207  rz_cons_set_raw(1);
3208  rz_cons_show_cursor(false);
3209  }
3210  } break;
3211  case '1':
3213  break;
3214  case 't':
3215  case 'o': {
3216  char str[128];
3217  rz_cons_show_cursor(true);
3218  rz_line_set_prompt(ch == 't' ? "type: " : "opstr: ");
3219  if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) {
3220  rz_core_cmdf(core, "ah%c %s @ 0x%" PFMT64x, ch, str, off);
3221  }
3222  } break;
3223  case 'x':
3224  rz_core_cmd0(core, "/r $$");
3225  break;
3226  case 'i': {
3227  char str[128];
3228  rz_cons_show_cursor(true);
3229  rz_line_set_prompt("immbase: ");
3230  if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) {
3231  int base = rz_num_base_of_string(core->num, str);
3233  }
3234  } break;
3235  case 'I': {
3236  char str[128];
3237  rz_cons_show_cursor(true);
3238  rz_line_set_prompt("immbase: ");
3239  if (rz_cons_fgets(str, sizeof(str), 0, NULL) > 0) {
3240  rz_core_cmdf(core, "ahi1 %s @ 0x%" PFMT64x, str, off);
3241  }
3242  } break;
3243  case 'a':
3244  rz_core_visual_asm(core, off);
3245  break;
3246  case 'b':
3247  if (plen != core->blocksize) {
3248  rep = plen / 2;
3249  }
3250  define_data_ntimes(core, off, rep, RZ_BYTE_DATA);
3251  wordsize = 1;
3252  break;
3253  case 'B': // "VdB"
3254  if (plen != core->blocksize) {
3255  rep = plen / 2;
3256  }
3257  define_data_ntimes(core, off, rep, RZ_WORD_DATA);
3258  wordsize = 2;
3259  break;
3260  case 'w':
3261  if (plen != core->blocksize) {
3262  rep = plen / 4;
3263  }
3264  define_data_ntimes(core, off, rep, RZ_DWORD_DATA);
3265  wordsize = 4;
3266  break;
3267  case 'W':
3268  if (plen != core->blocksize) {
3269  rep = plen / 8;
3270  }
3271  define_data_ntimes(core, off, rep, RZ_QWORD_DATA);
3272  wordsize = 8;
3273  break;
3274  case 'm': {
3275  char *man = NULL;
3276  /* check for manpage */
3278  if (op) {
3279  if (op->jump != UT64_MAX) {
3280  RzFlagItem *item = rz_flag_get_i(core->flags, op->jump);
3281  if (item) {
3282  const char *ptr = rz_str_lchr(item->name, '.');
3283  if (ptr) {
3284  man = strdup(ptr + 1);
3285  }
3286  }
3287  }
3289  }
3290  if (man) {
3291  char *p = strstr(man, "INODE");
3292  if (p) {
3293  *p = 0;
3294  }
3295  rz_cons_clear();
3296  rz_cons_flush();
3297  rz_sys_cmdf("man %s", man);
3298  free(man);
3299  }
3301  } break;
3302  case 'n': {
3303  RzAnalysisOp op;
3304  ut64 tgt_addr = UT64_MAX;
3305  if (!isDisasmPrint(core->printidx)) {
3306  break;
3307  }
3308  // TODO: get the aligned instruction even if the cursor is in the middle of it.
3309  rz_analysis_op(core->analysis, &op, off,
3310  core->block + off - core->offset, 32, RZ_ANALYSIS_OP_MASK_BASIC);
3311 
3312  tgt_addr = op.jump != UT64_MAX ? op.jump : op.ptr;
3314  if (var) {
3315  char *newname = rz_cons_input(sdb_fmt("New variable name for '%s': ", var->name));
3316  if (newname && *newname) {
3317  rz_analysis_var_rename(var, newname, true);
3318  free(newname);
3319  }
3320  } else if (tgt_addr != UT64_MAX) {
3322  RzFlagItem *f = rz_flag_get_i(core->flags, tgt_addr);
3323  if (fcn) {
3324  char *msg = rz_str_newf("Rename function %s to: ", fcn->name);
3325  char *newname = rz_cons_input(msg);
3326  free(msg);
3327  rz_core_analysis_function_rename(core, tgt_addr, newname);
3328  free(newname);
3329  } else if (f) {
3330  char *msg = rz_str_newf("Rename flag %s to: ", f->name);
3331  char *newname = rz_cons_input(msg);
3332  free(msg);
3333  rz_flag_rename(core->flags, f, newname);
3334  free(newname);
3335  } else {
3336  char *msg = rz_str_newf("Create flag at 0x%" PFMT64x " named: ", tgt_addr);
3337  char *newname = rz_cons_input(msg);
3338  free(msg);
3339  rz_flag_set(core->flags, newname, tgt_addr, 1);
3340  free(newname);
3341  }
3342  }
3343 
3345  break;
3346  }
3347  case 'C': {
3348  RzFlagItem *item = rz_flag_get_i(core->flags, off);
3349  if (item) {
3350  char cmd[128];
3351  rz_cons_show_cursor(true);
3352  rz_cons_flush();
3353  rz_line_set_prompt("color: ");
3354  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) {
3355  rz_flag_item_set_color(item, cmd);
3356  rz_cons_set_raw(1);
3357  rz_cons_show_cursor(false);
3358  }
3359  } else {
3360  eprintf("Sorry. No flag here\n");
3362  }
3363  } break;
3364  case '$': {
3365  RzFlagItem *item = rz_flag_get_i(core->flags, off);
3366  if (item) {
3367  char cmd[128];
3368  rz_cons_printf("Current flag size is: %" PFMT64d "\n", item->size);
3369  rz_cons_show_cursor(true);
3370  rz_cons_flush();
3371  rz_line_set_prompt("new size: ");
3372  if (rz_cons_fgets(cmd, sizeof(cmd), 0, NULL) > 0) {
3373  item->size = rz_num_math(core->num, cmd);
3374  rz_cons_set_raw(1);
3375  rz_cons_show_cursor(false);
3376  }
3377  } else {
3378  eprintf("Sorry. No flag here\n");
3380  }
3381  } break;
3382  case 'e':
3383  // set function size
3384  {
3386  if (!fcn) {
3387  fcn = rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
3388  }
3389  if (fcn) {
3390  RzAnalysisOp op;
3391  ut64 size;
3392  if (rz_analysis_op(core->analysis, &op, off, core->block + delta,
3393  core->blocksize - delta, RZ_ANALYSIS_OP_MASK_BASIC) > 0) {
3394  size = off - fcn->addr + op.size;
3396  }
3397  }
3398  }
3399  break;
3400  case 'j': {
3401  ut64 addr = rz_num_math(core->num, "$$+$F");
3403  } break;
3404  case 'k':
3405  eprintf("TODO: merge up\n");
3407  break;
3408  // very weak and incomplete
3409  case 'h': // "Vdh"
3410  handleHints(core);
3411  break;
3412  case 'r': // "Vdr"
3413  rz_core_cmdf(core, "?i new function name;afn `yp` @ 0x%08" PFMT64x, off);
3414  break;
3415  case 'z': // "Vdz"
3416  rz_core_cmdf(core, "?i zone name;fz `yp` @ 0x%08" PFMT64x, off);
3417  break;
3418  case 'R': // "VdR"
3419  eprintf("Finding references to 0x%08" PFMT64x " ...\n", off);
3420  rz_core_cmdf(core, "./r 0x%08" PFMT64x " @ $S", off);
3421  break;
3422  case 'S': {
3423  int i, j;
3424  bool is_wide = false;
3425  do {
3426  n = rz_str_nlen_w((const char *)p + ntotal,
3427  plen - ntotal) +
3428  1;
3429  if (n < 2) {
3430  break;
3431  }
3432  name = malloc(n + 10);
3433  strcpy(name, "str.");
3434  for (i = 0, j = 0; i < n; i++, j++) {
3435  name[4 + i] = p[j + ntotal];
3436  if (!p[j + ntotal]) {
3437  break;
3438  }
3439  if (!p[j + 1 + ntotal]) {
3440  // check if is still wide
3441  if (j + 3 + ntotal < n) {
3442  if (p[j + 3]) {
3443  break;
3444  }
3445  }
3446  is_wide = true;
3447  j++;
3448  }
3449  }
3450  name[4 + n] = '\0';
3451  if (is_wide) {
3453  off + ntotal, (n * 2) + ntotal,
3454  (const char *)name + 4);
3455  } else {
3457  off + ntotal, n + ntotal,
3458  (const char *)name + 4);
3459  }
3460  rz_name_filter(name, n + 10, true);
3461  rz_flag_set(core->flags, name, off + ntotal, n);
3462  free(name);
3463  if (is_wide) {
3464  ntotal += n * 2 - 1;
3465  } else {
3466  ntotal += n;
3467  }
3468  } while (ntotal < plen);
3469  wordsize = ntotal;
3470  } break;
3471  case 's': {
3472  int i, j;
3473  bool is_wide = false;
3474  if (core->print->ocur != -1) {
3475  n = plen;
3476  } else {
3477  n = rz_str_nlen_w((const char *)p, plen) + 1;
3478  }
3479  name = malloc(n + 10);
3480  if (!name) {
3481  break;
3482  }
3483  strcpy(name, "str.");
3484  for (i = 0, j = 0; i < n; i++, j++) {
3485  name[4 + i] = p[j];
3486  if (!p[j + 1]) {
3487  break;
3488  }
3489  if (!p[j + 1]) {
3490  if (j + 3 < n) {
3491  if (p[j + 3]) {
3492  break;
3493  }
3494  }
3495  is_wide = true;
3496  j++;
3497  }
3498  }
3499  name[4 + n] = '\0';
3500  // handle wide strings
3501  // memcpy (name + 4, (const char *)p, n);
3502  if (is_wide) {
3504  n * 2, (const char *)name + 4);
3505  } else {
3507  n, (const char *)name + 4);
3508  }
3509  rz_name_filter(name, n + 10, true);
3510  rz_flag_set(core->flags, name, off, n);
3511  wordsize = n;
3512  free(name);
3513  } break;
3514  case 'd': // TODO: check
3515  rz_meta_del(core->analysis, RZ_META_TYPE_ANY, off, plen);
3516  rz_meta_set(core->analysis, RZ_META_TYPE_DATA, off, plen, "");
3517  break;
3518  case 'c': // TODO: check
3519  rz_meta_del(core->analysis, RZ_META_TYPE_ANY, off, plen);
3520  rz_meta_set(core->analysis, RZ_META_TYPE_CODE, off, plen, "");
3521  break;
3522  case 'u':
3524  break;
3525  case 'f': {
3526  RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
3527  if (fcn) {
3528  rz_analysis_function_resize(fcn, core->offset - fcn->addr);
3529  }
3531  // required for thumb autodetection
3532  rz_core_analysis_function_add(core, NULL, off, false);
3534  } break;
3535  case 'v': {
3536  ut64 N;
3537  char *endptr = NULL;
3538  char *end_off = rz_cons_input("Last hexadecimal digits of instruction: ");
3539  if (end_off) {
3540  N = strtoull(end_off, &endptr, 16);
3541  }
3542  if (!end_off || end_off == endptr) {
3543  eprintf("Invalid numeric input\n");
3545  free(end_off);
3546  break;
3547  }
3548  free(end_off);
3549 
3550  ut64 incr = 0x10;
3551  ut64 tmp_N = N >> 4;
3552  while (tmp_N > 0) {
3553  tmp_N = tmp_N >> 4;
3554  incr = incr << 4;
3555  }
3556  ut64 mask = incr - 1;
3557 
3558  ut64 start_off = (off & ~mask) ^ N;
3559  if ((off & mask) > N) {
3560  if (start_off > incr) {
3561  start_off -= incr;
3562  } else {
3563  start_off = N;
3564  }
3565  }
3566 
3567  ut64 try_off;
3568  RzAnalysisOp *op = NULL;
3569  RzAnalysisVar *var = NULL;
3570  for (try_off = start_off; try_off < start_off + incr * 16; try_off += incr) {
3573  if (!op) {
3574  break;
3575  }
3576  var = rz_analysis_get_used_function_var(core->analysis, op->addr);
3577  if (var) {
3578  break;
3579  }
3580  }
3581 
3582  if (var) {
3583  char *newname = rz_cons_input(sdb_fmt("New variable name for '%s': ", var->name));
3584  if (newname && *newname) {
3585  rz_analysis_var_rename(var, newname, true);
3586  free(newname);
3587  }
3588  } else {
3589  eprintf("Cannot find instruction with a variable\n");
3591  }
3592 
3594  break;
3595  }
3596  case 'Q':
3597  case 'q':
3598  default:
3599  if (IS_DIGIT(ch)) {
3600  if (rep < 0) {
3601  rep = 0;
3602  }
3603  rep = rep * 10 + atoi((char *)&ch);
3604  goto repeat;
3605  }
3606  break;
3607  }
3608  if (distance > 0) {
3609  distance--;
3610  off += wordsize;
3611  goto onemoretime;
3612  }
3613 }
3614 
3616  char *color = calloc(1, 64), cstr[32];
3617  char preview_cmd[128] = "pd $r";
3618  int ch, opt = 0, oopt = -1;
3619  bool truecolor = rz_cons_singleton()->context->color_mode == COLOR_MODE_16M;
3620  char *rgb_xxx_fmt = truecolor ? "rgb:%2.2x%2.2x%2.2x " : "rgb:%x%x%x ";
3621  const char *k;
3622  RzColor rcolor;
3623 
3624  rz_cons_show_cursor(false);
3625  rcolor = rz_cons_pal_get_i(opt);
3626  for (;;) {
3627  rz_cons_clear();
3628  rz_cons_gotoxy(0, 0);
3629  k = rz_cons_pal_get_name(opt);
3630  if (!k) {
3631  opt = 0;
3632  k = rz_cons_pal_get_name(opt);
3633  }
3634  if (!truecolor) {
3635  rcolor.r &= 0xf;
3636  rcolor.g &= 0xf;
3637  rcolor.b &= 0xf;
3638  rcolor.r2 &= 0xf;
3639  rcolor.g2 &= 0xf;
3640  rcolor.b2 &= 0xf;
3641  } else {
3642  rcolor.r &= 0xff;
3643  rcolor.g &= 0xff;
3644  rcolor.b &= 0xff;
3645  rcolor.r2 &= 0xff;
3646  rcolor.g2 &= 0xff;
3647  rcolor.b2 &= 0xff;
3648  }
3649  sprintf(color, rgb_xxx_fmt, rcolor.r, rcolor.g, rcolor.b);
3650  if (rcolor.r2 || rcolor.g2 || rcolor.b2) {
3651  color = rz_str_appendf(color, rgb_xxx_fmt, rcolor.r2, rcolor.g2, rcolor.b2);
3652  rcolor.a = ALPHA_FGBG;
3653  } else {
3654  rcolor.a = ALPHA_FG;
3655  }
3656  rz_cons_rgb_str(cstr, sizeof(cstr), &rcolor);
3657  char *esc = strchr(cstr + 1, '\x1b');
3658  char *curtheme = rz_core_theme_get(core);
3659 
3660  rz_cons_printf("# Use '.' to randomize current color and ':' to randomize palette\n");
3661  rz_cons_printf("# Press '" Color_RED "rR" Color_GREEN "gG" Color_BLUE "bB" Color_RESET
3662  "' or '" Color_BGRED "eE" Color_BGGREEN "fF" Color_BGBLUE "vV" Color_RESET
3663  "' to change foreground/background color\n");
3664  rz_cons_printf("# Export colorscheme with command 'ec* > filename'\n");
3665  rz_cons_printf("# Preview command: '%s' - Press 'c' to change it\n", preview_cmd);
3666  rz_cons_printf("# Selected colorscheme : %s - Use 'hl' or left/right arrow keys to change colorscheme\n", curtheme ? curtheme : "default");
3667  rz_cons_printf("# Selected element: %s - Use 'jk' or up/down arrow keys to change element\n", k);
3668  rz_cons_printf("# ec %s %s # %d (\\x1b%.*s)",
3669  k, color, atoi(cstr + 7), esc ? (int)(esc - cstr - 1) : (int)strlen(cstr + 1), cstr + 1);
3670  if (esc) {
3671  rz_cons_printf(" (\\x1b%s)", esc + 1);
3672  }
3673  rz_cons_newline();
3674 
3675  rz_core_cmdf(core, "ec %s %s", k, color);
3676  char *res = rz_core_cmd_str(core, preview_cmd);
3677  int h, w = rz_cons_get_size(&h);
3678  char *body = rz_str_ansi_crop(res, 0, 0, w, h - 8);
3679  if (body) {
3680  rz_cons_printf("\n%s", body);
3681  }
3682  rz_cons_flush();
3683  ch = rz_cons_readchar();
3684  ch = rz_cons_arrow_to_hjkl(ch);
3685  switch (ch) {
3686 #define CASE_RGB(x, X, y) \
3687  case x: \
3688  if ((y) > 0x00) { \
3689  (y)--; \
3690  } \
3691  break; \
3692  case X: \
3693  if ((y) < 0xff) { \
3694  (y)++; \
3695  } \
3696  break;
3697  CASE_RGB('R', 'r', rcolor.r);
3698  CASE_RGB('G', 'g', rcolor.g);
3699  CASE_RGB('B', 'b', rcolor.b);
3700  CASE_RGB('E', 'e', rcolor.r2);
3701  CASE_RGB('F', 'f', rcolor.g2);
3702  CASE_RGB('V', 'v', rcolor.b2);
3703  case 'Q':
3704  case 'q':
3705  free(body);
3706  free(color);
3707  return;
3708  case 'k':
3709  opt--;
3710  break;
3711  case 'j':
3712  opt++;
3713  break;
3714  case 'l':
3715  rz_core_theme_nextpal(core, 'n');
3716  oopt = -1;
3717  break;
3718  case 'h':
3719  rz_core_theme_nextpal(core, 'p');
3720  oopt = -1;
3721  break;
3722  case 'K':
3723  opt = 0;
3724  break;
3725  case 'J':
3726  opt = rz_cons_pal_len() - 1;
3727  break;
3728  case ':':
3730  break;
3731  case '.':
3732  rcolor.r = rz_num_rand(0xff);
3733  rcolor.g = rz_num_rand(0xff);
3734  rcolor.b = rz_num_rand(0xff);
3735  break;
3736  case 'c':
3737  rz_line_set_prompt("Preview command> ");
3738  rz_cons_show_cursor(true);
3739  rz_cons_fgets(preview_cmd, sizeof(preview_cmd), 0, NULL);
3740  rz_cons_show_cursor(false);
3741  }
3742  if (opt != oopt) {
3743  rcolor = rz_cons_pal_get_i(opt);
3744  oopt = opt;
3745  }
3746  free(body);
3747  }
3748 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API ut64 rz_analysis_function_size_from_entry(RzAnalysisFunction *fcn)
Definition: function.c:333
RZ_API ut64 rz_analysis_function_realsize(const RzAnalysisFunction *fcn)
Definition: function.c:338
static int analop(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
#define mask()
RZ_API char * rz_asm_op_get_hex(RzAsmOp *op)
Definition: aop.c:28
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
RZ_API RZ_OWN RzAsmParseParam * rz_asm_get_parse_param(RZ_NULLABLE const RzReg *reg, ut32 ana_op_type)
Does all kinds of NULL checks on the parameters and returns an initialized RzAsmParseParam or NULL on...
Definition: asm.c:1763
RZ_DEPRECATE RZ_API RZ_OWN RzStrBuf * rz_asm_colorize_asm_str(RZ_BORROW RzStrBuf *asm_str, RZ_BORROW RzPrint *p, RZ_NULLABLE const RzAsmParseParam *param, RZ_NULLABLE const RzAsmTokenString *toks)
Colors a given asm string and returns it. If toks is not NULL it uses the tokens to color the asm str...
Definition: asm.c:1741
RZ_API int rz_asm_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
Definition: asm.c:543
RZ_DEPRECATE RZ_API RZ_BORROW RzList * rz_bin_get_classes(RZ_NONNULL RzBin *bin)
Definition: bin.c:883
static RzList * classes(RzBinFile *bf)
Definition: bin_dex.c:71
static SblHeader sb
Definition: bin_mbn.c:26
static RzBinSourceLineInfo * lines(RzBinFile *bf)
Definition: bin_symbols.c:427
const char * desc
Definition: bin_vsf.c:19
int bits(struct state *s, int need)
Definition: blast.c:72
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
RZ_API RZ_OWN RzType * rz_type_parse_string_single(RzTypeParser *parser, const char *code, char **error_msg)
Parses the single C type definition.
Definition: c_cpp_parser.c:309
static RzNumCalcValue expr(RzNum *, RzNumCalc *, int)
Definition: calc.c:167
RZ_API void rz_core_analysis_fcn_merge(RzCore *core, ut64 addr, ut64 addr2)
Definition: canalysis.c:4042
RZ_API void rz_core_analysis_undefine(RzCore *core, ut64 off)
Definition: canalysis.c:4028
RZ_API bool rz_core_analysis_function_add(RzCore *core, const char *name, ut64 addr, bool analyze_recursively)
Definition: canalysis.c:5298
RZ_API RzAnalysisOp * rz_core_analysis_op(RzCore *core, ut64 addr, int mask)
Definition: canalysis.c:1033
RZ_IPI void rz_core_analysis_function_signature_editor(RzCore *core, ut64 addr)
Definition: canalysis.c:6409
RZ_API bool rz_core_analysis_function_rename(RzCore *core, ut64 addr, const char *_name)
Definition: canalysis.c:5270
RZ_IPI bool rz_core_analysis_var_rename(RzCore *core, const char *name, const char *newname)
Definition: canalysis.c:5728
RZ_API char * rz_core_bin_method_flags_str(ut64 flags, int mode)
Definition: cbin.c:4731
RZ_API bool rz_core_write_at(RzCore *core, ut64 addr, const ut8 *buf, int size)
Definition: cio.c:145
RZ_API RzVector * rz_analysis_class_base_get_all(RzAnalysis *analysis, const char *class_name)
Definition: class.c:928
RZ_API RzVector * rz_analysis_class_method_get_all(RzAnalysis *analysis, const char *class_name)
Definition: class.c:735
RZ_API SdbList * rz_analysis_class_get_all(RzAnalysis *analysis, bool sorted)
Definition: class.c:177
RZ_API RzVector * rz_analysis_class_vtable_get_all(RzAnalysis *analysis, const char *class_name)
Definition: class.c:1118
RZ_API int rz_core_cmd0(RzCore *core, const char *cmd)
Definition: cmd.c:5428
RZ_API int rz_core_cmd(RzCore *core, const char *cstr, int log)
Definition: cmd.c:5328
RZ_API char * rz_core_cmd_strf(RzCore *core, const char *fmt,...)
Definition: cmd.c:5472
RZ_API int rz_core_cmdf(RzCore *core, const char *fmt,...)
Definition: cmd.c:5413
RZ_API char * rz_core_cmd_str(RzCore *core, const char *cmd)
Executes a rizin command and returns the stdout as a string.
Definition: cmd.c:5513
RZ_API bool rz_core_esil_dumpstack(RzAnalysisEsil *esil)
static RzCore * _core
Definition: cmd_debug.c:1622
RZ_API void rz_core_debug_ri(RzCore *core)
Definition: cmd_debug.c:3616
RZ_API void rz_core_theme_nextpal(RzCore *core, RzConsPalSeekMode mode)
Definition: cmd_eval.c:148
RZ_API char * rz_core_theme_get(RzCore *core)
Definition: cmd_eval.c:103
RZ_API void rz_core_help_vars_print(RzCore *core)
Definition: cmd_help.c:370
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:142
RZ_API RzConfigNode * rz_config_set(RzConfig *cfg, RZ_NONNULL const char *name, const char *value)
Definition: config.c:267
RZ_API RZ_BORROW RzConfigNode * rz_config_node_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:48
RZ_API RzConfigNode * rz_config_set_i(RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i)
Definition: config.c:419
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API bool rz_config_toggle(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:97
RZ_API void rz_cons_clear00(void)
Definition: cons.c:778
RZ_API void rz_cons_set_raw(bool is_raw)
Definition: cons.c:1617
RZ_API int rz_cons_get_size(int *rows)
Definition: cons.c:1446
RZ_API void rz_cons_column(int c)
Definition: cons.c:1707
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_strcat(const char *str)
Definition: cons.c:1263
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_visual_flush(void)
Definition: cons.c:1067
RZ_API void rz_cons_strcat_at(const char *_str, int x, char y, int w, int h)
Definition: cons.c:260
RZ_API void rz_cons_show_cursor(int cursor)
Definition: cons.c:1581
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
RZ_API void rz_cons_fill_line(void)
Definition: cons.c:737
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
RZ_API void rz_cons_gotoxy(int x, int y)
Definition: cons.c:724
RZ_API void rz_cons_clear(void)
Definition: cons.c:787
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
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 count
Definition: sflib.h:98
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 static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
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 cmd
Definition: sflib.h:79
uint32_t ut32
RZ_API const char * rz_line_readline(void)
Definition: dietline.c:913
const char * k
Definition: dsignal.c:11
void cleanup(void)
Definition: enough.c:244
RZ_API RzAnalysisEsil * rz_analysis_esil_new(int stacksize, int iotrap, unsigned int addrsize)
Definition: esil.c:85
RZ_API bool rz_analysis_esil_set_pc(RzAnalysisEsil *esil, ut64 addr)
Definition: esil.c:155
RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil)
Definition: esil.c:163
RZ_API bool rz_analysis_esil_runword(RzAnalysisEsil *esil, const char *word)
Definition: esil.c:3095
RZ_API int rz_analysis_function_resize(RzAnalysisFunction *fcn, int newsize)
Definition: fcn.c:90
RZ_API int rz_analysis_fcn_del(RzAnalysis *a, ut64 addr)
Definition: fcn.c:1675
RZ_DEPRECATE RZ_API RzAnalysisFunction * rz_analysis_get_fcn_in(RzAnalysis *analysis, ut64 addr, int type)
Definition: fcn.c:1687
RZ_API int rz_analysis_fcn_del_locs(RzAnalysis *analysis, ut64 addr)
Definition: fcn.c:1657
RZ_API int rz_flag_rename(RzFlag *f, RzFlagItem *item, const char *name)
Definition: flag.c:587
RZ_API RzFlagItem * rz_flag_get_i(RzFlag *f, ut64 off)
Definition: flag.c:317
RZ_API const char * rz_flag_item_set_color(RzFlagItem *item, const char *color)
Definition: flag.c:578
RZ_API RzList * rz_flag_all_list(RzFlag *f, bool by_space)
Definition: flag.c:463
RZ_API RzFlagItem * rz_flag_set(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:521
RZ_API bool rz_flag_unset_name(RzFlag *f, const char *name)
Definition: flag.c:670
RZ_API void rz_flag_foreach(RzFlag *f, RzFlagItemCb cb, void *user)
Definition: flag.c:800
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
void skip(file *in, unsigned n)
Definition: gzappend.c:202
RZ_API void rz_analysis_hint_set_bits(RzAnalysis *a, ut64 addr, int bits)
Definition: hint.c:288
RZ_API void rz_analysis_hint_set_immbase(RzAnalysis *a, ut64 addr, int base)
Definition: hint.c:229
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
RZ_API void rz_cons_message(RZ_NONNULL const char *msg)
Definition: hud.c:321
RZ_API char * rz_cons_hud(RzList *list, const char *prompt)
Definition: hud.c:202
RZ_API char * rz_cons_input(const char *msg)
Definition: input.c:696
RZ_API int rz_cons_arrow_to_hjkl(int ch)
Definition: input.c:78
RZ_API int rz_cons_any_key(const char *msg)
Definition: input.c:393
RZ_API int rz_cons_fgets(char *buf, int len, int argc, const char **argv)
Definition: input.c:339
RZ_API int rz_cons_readchar(void)
Definition: input.c:619
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN char * rz_core_editor(const RzCore *core, RZ_NULLABLE const char *file, RZ_NULLABLE const char *str)
Definition: core.c:3214
RZ_API bool rz_core_block_size(RzCore *core, ut32 bsize)
Definition: core.c:2842
static int hit(RzSearchKeyword *kw, void *user, ut64 addr)
Definition: rz-find.c:58
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
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_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
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
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
RZ_API void rz_line_set_prompt(const char *prompt)
Definition: line.c:56
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd times
Definition: sflib.h:70
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
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 void ls_free(SdbList *list)
Definition: ls.c:191
#define ls_foreach(list, it, pos)
Definition: ls.h:31
@ RZ_ABS
RZ_API const char * rz_meta_get_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr)
Definition: meta.c:146
RZ_API void rz_meta_del(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, ut64 size)
Definition: meta.c:187
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
RZ_API bool rz_meta_set(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, ut64 size, const char *str)
Definition: meta.c:191
int args
Definition: mipsasm.c:18
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
line
Definition: setup.py:34
int idx
Definition: setup.py:197
const char * name
Definition: op.c:541
RZ_API void rz_analysis_op_free(void *op)
Definition: op.c:61
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
RZ_API const char * rz_cons_pal_get_name(int index)
Definition: pal.c:644
int off
Definition: pal.c:13
RzColor rcolor
Definition: pal.c:97
RZ_API RzColor rz_cons_pal_get_i(int index)
Definition: pal.c:639
RZ_API int rz_cons_pal_len(void)
Definition: pal.c:648
RZ_API void rz_cons_pal_random(void)
Definition: pal.c:270
RZ_API char * rz_print_hexpair(RzPrint *p, const char *str, int n)
Definition: print.c:172
static void pad(RzStrBuf *sb, ut32 count)
Definition: protobuf.c:36
RZ_API RzRegItem * rz_reg_index_get(RzReg *reg, int idx)
Definition: reg.c:262
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
RZ_API char * rz_cons_rgb_str(char *outstr, size_t sz, const RzColor *rcolor)
Definition: rgb.c:318
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_free(x)
Definition: rz_alloc.h:44
@ RZ_ANALYSIS_FCN_TYPE_NULL
Definition: rz_analysis.h:192
@ RZ_META_TYPE_ANY
Definition: rz_analysis.h:288
@ RZ_META_TYPE_DATA
Definition: rz_analysis.h:289
@ RZ_META_TYPE_CODE
Definition: rz_analysis.h:290
@ RZ_META_TYPE_STRING
Definition: rz_analysis.h:291
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
@ RZ_ANALYSIS_OP_MASK_ALL
Definition: rz_analysis.h:447
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static bool rz_config_node_is_bool(RzConfigNode *node)
Definition: rz_config.h:117
static bool rz_config_node_is_int(RzConfigNode *node)
Definition: rz_config.h:120
@ ALPHA_FGBG
Definition: rz_cons.h:170
@ ALPHA_FG
Definition: rz_cons.h:168
#define Color_RESET
Definition: rz_cons.h:617
@ COLOR_MODE_16M
Definition: rz_cons.h:445
void(* RzConsEvent)(void *)
Definition: rz_cons.h:346
#define Color_GREEN
Definition: rz_cons.h:627
#define Color_RED
Definition: rz_cons.h:623
#define Color_YELLOW
Definition: rz_cons.h:631
#define Color_BGGREEN
Definition: rz_cons.h:628
#define Color_BLUE
Definition: rz_cons.h:635
#define Color_BGBLUE
Definition: rz_cons.h:636
#define Color_BGRED
Definition: rz_cons.h:624
#define Color_INVERT
Definition: rz_cons.h:606
static ut64 rz_read_be64(const void *src)
Definition: rz_endian.h:108
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
static RzIntervalNode * rz_interval_tree_iter_get(RzIntervalTreeIter *it)
#define rz_interval_tree_foreach(tree, it, dat)
RZ_API bool rz_name_filter(char *name, int len, bool strict)
Definition: name.c:43
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API size_t rz_num_base_of_string(RzNum *num, RZ_NONNULL const char *str)
Convert the base suffix to the numeric value.
Definition: unum.c:935
RZ_API int rz_num_rand(int max)
Definition: unum.c:47
#define RZ_PRINT_FLAGS_COLOR
Definition: rz_print.h:15
@ RZ_REG_NAME_BP
Definition: rz_reg.h:46
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
RZ_API size_t rz_str_ansi_len(const char *str)
Definition: str.c:1945
RZ_API char * rz_str_dup(char *ptr, const char *string)
Definition: str.c:1021
RZ_API char * rz_str_trim_dup(const char *str)
Definition: str_trim.c:78
RZ_API int rz_str_ccpy(char *dst, char *orig, int ch)
Definition: str.c:991
RZ_API char RZ_API char * rz_str_appendch(char *x, char y)
Definition: str.c:1105
RZ_API char * rz_str_ansi_crop(const char *str, unsigned int x, unsigned int y, unsigned int x2, unsigned int y2)
Definition: str.c:2174
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API bool rz_str_ccmp(const char *dst, const char *orig, int ch)
Definition: str.c:941
RZ_API size_t rz_str_nlen_w(const char *s, int n)
Definition: str.c:1966
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 int rz_str_replace_char(char *s, int a, int b)
Definition: str.c:169
RZ_API const char * rz_str_casestr(const char *a, const char *b)
Definition: str.c:2757
RZ_API const char * rz_str_pad(const char ch, int len)
Definition: str.c:3236
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
#define IS_WHITESPACE(x)
Definition: rz_str_util.h:13
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
#define IS_PRINTABLE(x)
Definition: rz_str_util.h: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 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 bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
RZ_API int rz_sys_cmdf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int rz_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317
RZ_API int rz_sys_sleep(int secs)
Sleep for secs seconds.
Definition: sys.c:300
#define PFMT64d
Definition: rz_types.h:394
#define RZ_BIT_SET(x, y)
Definition: rz_types.h:311
#define RZ_BIT_CHK(x, y)
Definition: rz_types.h:316
#define RZ_BIT_UNSET(x, y)
Definition: rz_types.h:312
#define RZ_FREE_CUSTOM(x, y)
Definition: rz_types.h:375
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_EMPTY
Definition: rz_types_base.h:68
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
static char * sdbkv_key(const SdbKv *kv)
Definition: sdbht.h:21
RZ_API bool rz_core_seek_and_save(RzCore *core, ut64 addr, bool rb)
Save currently marked state in seek history and seek to addr .
Definition: seek.c:101
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb)
Seek to addr.
Definition: seek.c:116
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define h(i)
Definition: sha256.c:48
Definition: ls.h:17
Definition: ls.h:22
Definition: z80asm.h:102
Definition: getopt.h:84
ut8 r2
Definition: rz_cons.h:185
ut8 g2
Definition: rz_cons.h:186
ut8 g
Definition: rz_cons.h:183
ut8 b
Definition: rz_cons.h:184
ut8 b2
Definition: rz_cons.h:187
ut8 r
Definition: rz_cons.h:182
ut8 a
Definition: rz_cons.h:181
RzAnalysis * analysis
Definition: rz_analysis.h:1043
RzAnalysisMetaType type
Definition: rz_analysis.h:302
RzList * fcns
Definition: rz_analysis.h:565
RzIntervalTree meta
Definition: rz_analysis.h:600
RzTypeDB * typedb
Definition: rz_analysis.h:602
RzAnalysisVarKind kind
Definition: rz_analysis.h:728
RzStrBuf buf_asm
Definition: rz_asm.h:72
int size
Definition: rz_asm.h:67
RzAsmTokenString * asm_toks
Tokenized asm string.
Definition: rz_asm.h:74
int bits
Definition: rz_asm.h:100
RzList * fields
Definition: rz_bin.h:654
char * name
Definition: rz_bin.h:647
RzList * methods
Definition: rz_bin.h:653
ut64 vaddr
Definition: rz_bin.h:762
RzList * options
Definition: rz_config.h:47
RzList * nodes
Definition: rz_config.h:56
RzConsPrintablePalette pal
Definition: rz_cons.h:491
struct rz_line_t * line
Definition: rz_cons.h:553
RzConsEvent event_resize
Definition: rz_cons.h:522
void * event_data
Definition: rz_cons.h:523
RzConsContext * context
Definition: rz_cons.h:502
bool show_vals
Definition: rz_cons.h:574
bool vmode
Definition: rz_core.h:309
RzCons * cons
Definition: rz_core.h:312
RzCoreVisualMode printidx
Definition: rz_core.h:357
bool visual_is_inputing
Definition: rz_core.h:353
RzBin * bin
Definition: rz_core.h:298
ut64 offset
Definition: rz_core.h:301
RzAsm * rasm
Definition: rz_core.h:323
RzAnalysis * analysis
Definition: rz_core.h:322
RzList * ropchain
Definition: rz_core.h:387
RzNum * num
Definition: rz_core.h:316
RzCoreTaskScheduler tasks
Definition: rz_core.h:362
ut8 * block
Definition: rz_core.h:305
RzFlag * flags
Definition: rz_core.h:330
RzPrint * print
Definition: rz_core.h:327
ut32 blocksize
Definition: rz_core.h:303
char * visual_inputing
Definition: rz_core.h:354
RzConfig * config
Definition: rz_core.h:300
ut64 offset
Definition: rz_flag.h:38
char * name
Definition: rz_flag.h:35
char * contents
Definition: rz_cons.h:1111
int flags
Definition: rz_print.h:137
int ocur
Definition: rz_print.h:135
bool cur_enabled
Definition: rz_print.h:130
char * name[RZ_REG_NAME_LAST]
Definition: rz_reg.h:149
RzTypeParser * parser
Definition: rz_type.h:37
Definition: sdbht.h:14
const char * command
Definition: main.c:7
int pos
Definition: main.c:11
RZ_API void rz_core_task_enqueue_oneshot(RzCoreTaskScheduler *scheduler, RzCoreTaskOneShot func, void *user)
Definition: task.c:391
RZ_API RZ_OWN char * rz_type_as_string(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Returns the type C representation.
Definition: type.c:817
Definition: dis.c:32
RZ_DEPRECATE RZ_API RzList * rz_analysis_var_all_list(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: var.c:1135
RZ_API bool rz_analysis_var_rename(RzAnalysisVar *var, const char *new_name, bool verbose)
Definition: var.c:348
RZ_API void rz_analysis_var_set_type(RzAnalysisVar *var, RZ_OWN RzType *type, bool resolve_overlaps)
Definition: var.c:170
RZ_DEPRECATE RZ_API RzAnalysisVar * rz_analysis_get_used_function_var(RzAnalysis *analysis, ut64 addr)
Definition: var.c:398
RZ_API void rz_core_visual_asm(RzCore *core, ut64 off)
Definition: vasm.c:73
static int color
Definition: visual.c:20
RZ_API void rz_core_visual_offset(RzCore *core)
Definition: visual.c:1247
RZ_API void rz_core_visual_append_help(RzStrBuf *p, const char *title, const char **help)
Definition: visual.c:532
RZ_API int rz_core_visual_prompt(RzCore *core)
Definition: visual.c:756
RZ_API int rz_core_visual(RzCore *core, const char *input)
Definition: visual.c:3856
RZ_API int rz_core_visual_xrefs(RzCore *core, bool xref_to, bool fcnInsteadOfAddr)
Definition: visual.c:1312
RZ_API void rz_core_visual_showcursor(RzCore *core, int x)
Definition: visual.c:420
static ut64 var_variables_show(RzCore *core, int idx, int *vindex, int show, int cols)
Definition: vmenus.c:2355
static void showreg(RzAnalysisEsil *esil, const char *rn, const char *desc)
Definition: vmenus.c:83
RZ_API int rz_core_visual_comments(RzCore *core)
Definition: vmenus.c:1793
static void rz_core_visual_debugtraces_help(RzCore *core)
Definition: vmenus.c:2622
static void analysis_class_print(RzAnalysis *analysis, const char *class_name)
Definition: vmenus.c:981
static const char * help_fun_visual[]
Definition: vmenus.c:2464
static char * prompt(const char *str, const char *txt)
Definition: vmenus.c:30
static int printMode
Definition: vmenus.c:2428
RZ_API void rz_core_visual_define(RzCore *core, const char *args, int distance)
Definition: vmenus.c:3149
static char * print_rop(void *_core, void *_item, bool selected)
Definition: vmenus.c:1226
static void config_visual_hit(RzCore *core, const char *name, int editor)
Definition: vmenus.c:1931
RZ_API bool rz_core_visual_hudclasses(RzCore *core)
Definition: vmenus.c:494
#define MAX_FORMAT
Definition: vmenus.c:14
static ut64 rz_core_visual_analysis_refresh(RzCore *core)
Definition: vmenus.c:2516
static void variable_set_type(RzCore *core, ut64 addr, int vindex, const char *type)
Definition: vmenus.c:2191
RZ_API int rz_core_visual_view_rop(RzCore *core)
Definition: vmenus.c:1232
static char * __prompt(const char *msg, void *p)
Definition: vmenus.c:2713
static ut64 var_functions_show(RzCore *core, int idx, int show, int cols)
Definition: vmenus.c:2275
static void define_data_ntimes(RzCore *core, ut64 off, int times, int type)
Definition: vmenus.c:3107
RZ_API void rz_core_visual_debugtraces(RzCore *core, const char *input)
Definition: vmenus.c:2634
RZ_API void rz_core_visual_analysis(RzCore *core, const char *input)
Definition: vmenus.c:2739
static void show_config_options(RzCore *core, const char *opt)
Definition: vmenus.c:1962
#define CASE_RGB(x, X, y)
RZ_API bool rz_core_visual_esil(RzCore *core)
Definition: vmenus.c:89
static RzPVector * capture_filter_keywords(char *visual_inputing)
Convert the string visual_inputing to RzPVector, with WHITESPACE as separators.
Definition: vmenus.c:2214
static int rotate_nibble(const ut8 b, int dir)
Definition: vmenus.c:56
RZ_API void rz_core_visual_config(RzCore *core)
Definition: vmenus.c:1984
static const char * show_analysis_classes(RzCore *core, char mode, int *idx, SdbList *list, const char *class_name)
Definition: vmenus.c:1028
static void rz_core_visual_analysis_refresh_oneshot(RzCore *core)
Definition: vmenus.c:2618
static int flag_offset_sort(const void *a, const void *b)
Definition: vmenus.c:1198
static const char * help_vv_visual[]
Definition: vmenus.c:2479
#define lastPrintMode
Definition: vmenus.c:2430
static int option
Definition: vmenus.c:2426
static bool hudstuff_append(RzFlagItem *fi, void *user)
Definition: vmenus.c:530
static int flag_name_sort(const void *a, const void *b)
Definition: vmenus.c:1192
static void handleHints(RzCore *core)
Definition: vmenus.c:3122
RZ_API int rz_core_visual_trackflags(RzCore *core)
Definition: vmenus.c:1485
static int variable_option
Definition: vmenus.c:2427
@ SORT_OFFSET
Definition: vmenus.c:26
@ SORT_NONE
Definition: vmenus.c:24
@ SORT_NAME
Definition: vmenus.c:25
static void rz_core_visual_analysis_refresh_column(RzCore *core, int colpos)
Definition: vmenus.c:2435
RZ_API bool rz_core_visual_bit_editor(RzCore *core)
Definition: vmenus.c:234
RZ_API bool rz_core_visual_hudstuff(RzCore *core)
Definition: vmenus.c:539
static bool selectPanel
Definition: vmenus.c:2429
static void sort_flags(RzList *l, int sort)
Definition: vmenus.c:1210
static void config_visual_hit_i(RzCore *core, const char *name, int delta)
Definition: vmenus.c:1921
static const char * printCmds[lastPrintMode]
Definition: vmenus.c:2431
static ut32 filter_function(RzCore *core, RzList *filter_fcn, RzPVector *keywords)
Filter the functions in visual analysis mode (helper of command f)
Definition: vmenus.c:2250
static void function_rename(RzCore *core, ut64 addr, const char *name)
Definition: vmenus.c:2156
static int level
Definition: vmenus.c:2424
static void * show_class(RzCore *core, int mode, int *idx, RzBinClass *_c, const char *grep, RzList *list)
Definition: vmenus.c:613
static bool rz_core_visual_config_hud(RzCore *core)
Definition: vmenus.c:572
static void addVar(RzCore *core, int ch, const char *msg)
Definition: vmenus.c:2725
static st64 delta
Definition: vmenus.c:2425
RZ_API void rz_core_visual_colors(RzCore *core)
Definition: vmenus.c:3615
static void rz_core_vmenu_append_help(RzStrBuf *p, const char **help)
Definition: vmenus.c:2502
static const char * help_vv_actions_visual[]
Definition: vmenus.c:2496
RZ_API int rz_core_visual_analysis_classes(RzCore *core)
Definition: vmenus.c:1077
static const char * help_var_visual[]
Definition: vmenus.c:2472
static int wordpos(const char *esil, int n)
Definition: vmenus.c:65
@ RZ_WORD_DATA
Definition: vmenus.c:18
@ RZ_DWORD_DATA
Definition: vmenus.c:19
@ RZ_QWORD_DATA
Definition: vmenus.c:20
@ RZ_BYTE_DATA
Definition: vmenus.c:17
static void variable_rename(RzCore *core, ut64 addr, int vindex, const char *name)
Definition: vmenus.c:2171
static bool isDisasmPrint(int mode)
Definition: vmenus.c:3118
RZ_API int rz_core_visual_classes(RzCore *core)
Definition: vmenus.c:786
RZ_API char * rz_str_widget_list(void *user, RzList *list, int rows, int cur, PrintItemCallback cb)
Definition: vmenus_graph.c:9
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
struct _window window
RZ_API bool rz_core_yank_hexpair(RzCore *core, const char *str)
Definition: yank.c:362
static int sp
Definition: z80asm.c:91
static int addr
Definition: z80asm.c:58
#define SEEK_SET
Definition: zip.c:88
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
#define N
Definition: zip_err_str.c:8
diff_output_t output
Definition: zipcmp.c:237
static int seek(char *argv[])