Rizin
unix-like reverse engineering framework and cli tools
visual.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 <rz_core.h>
5 #include <rz_cons.h>
6 #include <rz_windows.h>
7 #include "../core_private.h"
8 
9 #define NPF 5
10 #define PIDX (RZ_ABS(core->printidx % NPF))
11 
12 static void visual_refresh(RzCore *core);
13 
14 static int obs = 0;
15 static int blocksize = 0;
16 static bool autoblocksize = true;
17 static int disMode = 0;
18 static int hexMode = 0;
19 static int printMode = 0;
20 static int color = 1;
21 static int debug = 1;
22 static int zoom = 0;
23 
24 typedef struct {
25  int x;
26  int y;
27 } Snow;
28 
29 #define KEY_ALTQ 0xc5
30 
31 #define CMD_REGISTERS "?== true `e cfg.debug`; ?! dr=; ?? ar=" // select dr= or ar= depending on cfg.debug
32 #define CMD_REGISTERS_REFS "?== true `e cfg.debug`; ?! drr; ?? arr" // select drr or arr depending on cfg.debug
33 
34 static const char *printfmtSingle[NPF] = {
35  "xc", // HEXDUMP
36  "pd $r", // ASSEMBLY
37  ("pxw 64@r:SP;" CMD_REGISTERS ";pd $r"), // DEBUGGER
38  "prc", // OVERVIEW
39  "pss", // PC// copypasteable views
40 };
41 
42 static const char *printfmtColumns[NPF] = {
43  "pCx", // HEXDUMP // + pCw
44  "pCd $r-1", // ASSEMBLY
45  "pCD", // DEBUGGER
46  "pCA", // OVERVIEW
47  "pCc", // PC// copypasteable views
48 };
49 
50 // to print the stack in the debugger view
51 #define PRINT_HEX_FORMATS 10
52 #define PRINT_3_FORMATS 2
53 #define PRINT_4_FORMATS 7
54 #define PRINT_5_FORMATS 8
55 
56 static int currentFormat = 0;
57 static int current0format = 0;
58 static const char *printHexFormats[PRINT_HEX_FORMATS] = {
59  "px",
60  "pxa",
61  "pxr",
62  "prx",
63  "pxb",
64  "pxh",
65  "pxw",
66  "pxq",
67  "pxd",
68  "pxr",
69 };
70 static int current3format = 0;
71 static const char *print3Formats[PRINT_3_FORMATS] = { // not used at all. its handled by the pd format
72  "pxw 64@r:SP;" CMD_REGISTERS ";pd $r", // DEBUGGER
73  "pCD"
74 };
75 static int current4format = 0;
76 static const char *print4Formats[PRINT_4_FORMATS] = {
77  "prc", "prc=a", "pxAv", "pxx", "p=e $r-2", "pk 64"
78 };
79 static int current5format = 0;
80 static const char *print5Formats[PRINT_5_FORMATS] = {
81  "pca", "pcA", "p8", "pcc", "pss", "pcp", "pcd", "pcj"
82 };
83 
86  switch (currentFormat) {
87  case 0: /* px */
88  case 3: /* prx */
89  case 6: /* pxw */
90  case 9: /* pxr */
91  rz_config_set(core->config, "hex.compact", "false");
92  rz_config_set(core->config, "hex.comments", "true");
93  break;
94  case 1: /* pxa */
95  case 4: /* pxb */
96  case 7: /* pxq */
97  rz_config_set(core->config, "hex.compact", "true");
98  rz_config_set(core->config, "hex.comments", "true");
99  break;
100  case 2: /* pxr */
101  case 5: /* pxh */
102  case 8: /* pxd */
103  rz_config_set(core->config, "hex.compact", "false");
104  rz_config_set(core->config, "hex.comments", "false");
105  break;
106  }
107 }
108 
110  if (rz_config_get_b(core->config, "asm.hint.call")) {
111  rz_config_toggle(core->config, "asm.hint.call");
112  rz_config_set_b(core->config, "asm.hint.jmp", true);
113  } else if (rz_config_get_b(core->config, "asm.hint.jmp")) {
114  rz_config_toggle(core->config, "asm.hint.jmp");
115  rz_config_set_b(core->config, "asm.hint.emu", true);
116  } else if (rz_config_get_b(core->config, "asm.hint.emu")) {
117  rz_config_toggle(core->config, "asm.hint.emu");
118  rz_config_set_b(core->config, "asm.hint.lea", true);
119  } else if (rz_config_get_b(core->config, "asm.hint.lea")) {
120  rz_config_toggle(core->config, "asm.hint.lea");
121  rz_config_set_b(core->config, "asm.hint.call", true);
122  } else {
123  rz_config_set_b(core->config, "asm.hint.call", true);
124  }
125 }
126 
127 RZ_API void rz_core_visual_toggle_decompiler_disasm(RzCore *core, bool for_graph, bool reset) {
128  static RzConfigHold *hold = NULL; // should be a tab-specific var
129  if (hold) {
131  rz_config_hold_free(hold);
132  hold = NULL;
133  return;
134  }
135  if (reset) {
136  return;
137  }
138  hold = rz_config_hold_new(core->config);
139  rz_config_hold_s(hold, "asm.hint.pos", "asm.cmt.col", "asm.offset", "asm.lines",
140  "asm.indent", "asm.bytes", "asm.comments", "asm.dwarf", "asm.usercomments", "asm.instr", NULL);
141  if (for_graph) {
142  rz_config_set(core->config, "asm.hint.pos", "-2");
143  rz_config_set(core->config, "asm.lines", "false");
144  rz_config_set(core->config, "asm.indent", "false");
145  } else {
146  rz_config_set(core->config, "asm.hint.pos", "0");
147  rz_config_set(core->config, "asm.indent", "true");
148  rz_config_set(core->config, "asm.lines", "true");
149  }
150  rz_config_set(core->config, "asm.cmt.col", "0");
151  rz_config_set(core->config, "asm.offset", "false");
152  rz_config_set(core->config, "asm.dwarf", "true");
153  rz_config_set(core->config, "asm.bytes", "false");
154  rz_config_set(core->config, "asm.comments", "false");
155  rz_config_set(core->config, "asm.usercomments", "true");
156  rz_config_set(core->config, "asm.instr", "false");
157 }
158 
159 static void setcursor(RzCore *core, bool cur) {
160  int flags = core->print->flags;
161  if (core->print->cur_enabled) {
163  } else {
165  }
166  core->print->cur_enabled = cur;
167  if (core->print->cur == -1) {
168  core->print->cur = 0;
169  }
171  core->print->col = core->print->cur_enabled ? 1 : 0;
172 }
173 
176  switch (currentFormat) {
177  case 0:
178  rz_config_set(core->config, "asm.pseudo", "false");
179  rz_config_set(core->config, "asm.bytes", "true");
180  rz_config_set(core->config, "asm.esil", "false");
181  rz_config_set(core->config, "emu.str", "false");
182  rz_config_set(core->config, "asm.emu", "false");
183  break;
184  case 1:
185  rz_config_set(core->config, "asm.pseudo", "false");
186  rz_config_set(core->config, "asm.bytes", "true");
187  rz_config_set(core->config, "asm.esil", "false");
188  rz_config_set(core->config, "asm.emu", "false");
189  rz_config_set(core->config, "emu.str", "true");
190  break;
191  case 2:
192  rz_config_set(core->config, "asm.pseudo", "true");
193  rz_config_set(core->config, "asm.bytes", "true");
194  rz_config_set(core->config, "asm.esil", "true");
195  rz_config_set(core->config, "emu.str", "true");
196  rz_config_set(core->config, "asm.emu", "true");
197  break;
198  case 3:
199  rz_config_set(core->config, "asm.pseudo", "false");
200  rz_config_set(core->config, "asm.bytes", "false");
201  rz_config_set(core->config, "asm.esil", "false");
202  rz_config_set(core->config, "asm.emu", "false");
203  rz_config_set(core->config, "emu.str", "true");
204  break;
205  case 4:
206  rz_config_set(core->config, "asm.pseudo", "true");
207  rz_config_set(core->config, "asm.bytes", "false");
208  rz_config_set(core->config, "asm.esil", "false");
209  rz_config_set(core->config, "asm.emu", "false");
210  rz_config_set(core->config, "emu.str", "true");
211  break;
212  }
213 }
214 
215 static void nextPrintCommand(void) {
216  current0format++;
219 }
220 
221 static void prevPrintCommand(void) {
222  current0format--;
223  if (current0format < 0) {
224  current0format = 0;
225  }
227 }
228 
229 static const char *stackPrintCommand(RzCore *core) {
230  if (current0format == 0) {
231  if (rz_config_get_b(core->config, "dbg.slow")) {
232  return "pxr";
233  }
234  if (rz_config_get_b(core->config, "stack.bytes")) {
235  return "px";
236  }
237  switch (core->rasm->bits) {
238  case 64: return "pxq"; break;
239  case 32: return "pxw"; break;
240  }
241  return "px";
242  }
244 }
245 
246 static const char *__core_visual_print_command(RzCore *core) {
247  if (core->visual.tabs) {
249  if (tab && tab->name[0] == ':') {
250  return tab->name + 1;
251  }
252  }
253  if (rz_config_get_i(core->config, "scr.dumpcols")) {
254  free(core->stkcmd);
255  core->stkcmd = rz_str_new(stackPrintCommand(core));
256  return printfmtColumns[PIDX];
257  }
258  return printfmtSingle[PIDX];
259 }
260 
261 static bool __core_visual_gogo(RzCore *core, int ch) {
262  RzIOMap *map;
263  switch (ch) {
264  case 'g':
265  if (core->io->va) {
266  RzIOMap *map = rz_io_map_get(core->io, core->offset);
267  RzPVector *maps = rz_io_maps(core->io);
268  if (!map && !rz_pvector_empty(maps)) {
270  }
271  if (map) {
272  rz_core_seek_and_save(core, rz_itv_begin(map->itv), true);
273  }
274  } else {
275  rz_core_seek_and_save(core, 0, true);
276  }
277  return true;
278  case 'G': {
279  map = rz_io_map_get(core->io, core->offset);
280  RzPVector *maps = rz_io_maps(core->io);
281  if (!map && !rz_pvector_empty(maps)) {
282  map = rz_pvector_at(maps, 0);
283  }
284  if (map) {
285  RzPrint *p = core->print;
286  int scr_rows;
287  if (!p->consbind.get_size) {
288  break;
289  }
290  (void)p->consbind.get_size(&scr_rows);
291  ut64 scols = rz_config_get_i(core->config, "hex.cols");
292  rz_core_seek_and_save(core, rz_itv_end(map->itv) - (scr_rows - 2) * scols, true);
293  }
294  return true;
295  }
296  }
297  return false;
298 }
299 
300 static const char *help_visual[] = {
301  "?", "full help",
302  "!", "enter panels",
303  "a", "code analysis",
304  "c", "toggle cursor",
305  "d", "debugger / emulator",
306  "e", "toggle configurations",
307  "i", "insert / write",
308  "m", "moving around (seeking)",
309  "p", "print commands and modes",
310  "v", "view management",
311  NULL
312 };
313 
314 static const char *help_msg_visual[] = {
315  "?", "show visual help menu",
316  "??", "show this help",
317  "$", "set the program counter to the current offset + cursor",
318  "&", "rotate asm.bits between 8, 16, 32 and 64 applying hints",
319  "%", "in cursor mode finds matching pair, otherwise toggle autoblocksz",
320  "^", "seek to the beginning of the function",
321  "!", "enter into the visual panels mode",
322  "TAB", "switch to the next print mode (or element in cursor mode)",
323  "_", "enter the flag/comment/functions/.. hud (same as VF_)",
324  "=", "set cmd.vprompt (top row)",
325  "|", "set cmd.cprompt (right column)",
326  ".", "seek to program counter",
327  "#", "toggle decompiler comments in disasm (see pdd* from jsdec)",
328  "\\", "toggle visual split mode",
329  "\"", "toggle the column mode (uses pC..)",
330  "/", "in cursor mode search in current block",
331  "(", "toggle snow",
332  ")", "toggle emu.str",
333  ":cmd", "run rizin command",
334  ";[-]cmt", "add/remove comment",
335  "0", "seek to beginning of current function",
336  "[1-9]", "follow jmp/call identified by shortcut (like ;[1])",
337  ",file", "add a link to the text file",
338  "/*+-[]", "change block size, [] = resize hex.cols",
339  "<,>", "seek aligned to block size (in cursor slurp or dump files)",
340  "a/A", "(a)ssemble code, visual (A)ssembler",
341  "b", "browse evals, symbols, flags, mountpoints, evals, classes, ...",
342  "B", "toggle breakpoint",
343  "c/C", "toggle (c)ursor and (C)olors",
344  "d[f?]", "define function, data, code, ..",
345  "D", "enter visual diff mode (set diff.from/to)",
346  "f/F", "set/unset or browse flags. f- to unset, F to browse, ..",
347  "hjkl", "move around (or HJKL) (left-down-up-right)",
348  "i", "insert hex or string (in hexdump) use tab to toggle",
349  "I", "insert hexpair block ",
350  "mK/'K", "mark/go to Key (any key)",
351  "n/N", "seek next/prev function/flag/hit (scr.nkey)",
352  "g", "go/seek to given offset (g[g/G]<enter> to seek begin/end of file)",
353  "O", "toggle asm.pseudo and asm.esil",
354  "p/P", "rotate print modes (hex, disasm, debug, words, buf)",
355  "q", "back to rizin shell",
356  "r", "toggle call/jmp/lea hints",
357  "R", "randomize color palette (ecr)",
358  "sS", "step / step over",
359  "tT", "tt new tab, t[1-9] switch to nth tab, t= name tab, t- close tab",
360  "uU", "undo/redo seek",
361  "v", "visual function/vars code analysis menu",
362  "V", "(V)iew interactive ascii art graph (agfv)",
363  "wW", "seek cursor to next/prev word",
364  "xX", "show xrefs/refs of current function from/to data/code",
365  "yY", "copy and paste selection",
366  "Z", "shift-tab rotate print modes", // ctoggle zoom mode",
367  "Enter", "follow address of jump/call",
368  NULL
369 };
370 
371 static const char *help_msg_visual_fn[] = {
372  "F2", "toggle breakpoint",
373  "F4", "run to cursor",
374  "F7", "single step",
375  "F8", "step over",
376  "F9", "continue",
377  NULL
378 };
379 
380 static bool splitView = false;
382 
383 #undef USE_THREADS
384 #define USE_THREADS 1
385 
386 static void rotateAsmBits(RzCore *core) {
387  RzAnalysisHint *hint = rz_analysis_hint_get(core->analysis, core->offset);
388  int bits = hint ? hint->bits : rz_config_get_i(core->config, "asm.bits");
389  int retries = 4;
390  while (retries > 0) {
391  int nb = bits == 64 ? 8 : bits == 32 ? 64
392  : bits == 16 ? 32
393  : bits == 8 ? 16
394  : bits;
395  if ((core->rasm->cur->bits & nb) == nb) {
396  rz_analysis_hint_set_bits(core->analysis, core->offset, nb);
397  break;
398  }
399  bits = nb;
400  retries--;
401  }
402  rz_analysis_hint_free(hint);
403 }
404 
405 static const char *rotateAsmemu(RzCore *core) {
406  const bool isEmuStr = rz_config_get_b(core->config, "emu.str");
407  const bool isEmu = rz_config_get_b(core->config, "asm.emu");
408  if (isEmu) {
409  if (isEmuStr) {
410  rz_config_set(core->config, "emu.str", "false");
411  } else {
412  rz_config_set(core->config, "asm.emu", "false");
413  }
414  } else {
415  rz_config_set(core->config, "emu.str", "true");
416  }
417  return "pd";
418 }
419 
421  if (core && core->vmode) {
423  rz_cons_enable_mouse(rz_config_get_b(core->config, "scr.wheel"));
424  } else {
425  rz_cons_enable_mouse(false);
426  }
427  rz_cons_flush();
428 }
429 
430 static void printFormat(RzCore *core, const int next) {
431  switch (core->printidx) {
432  case RZ_CORE_VISUAL_MODE_PX: // 0 // xc
433  hexMode += next;
436  break;
437  case RZ_CORE_VISUAL_MODE_PD: // pd
438  disMode += next;
440  printfmtSingle[1] = rotateAsmemu(core);
441  break;
442  case RZ_CORE_VISUAL_MODE_DB: // debugger
443  disMode += next;
445  printfmtSingle[1] = rotateAsmemu(core);
446  current3format += next;
449  break;
450  case RZ_CORE_VISUAL_MODE_OV: // overview
451  current4format += next;
454  break;
455  case RZ_CORE_VISUAL_MODE_CD: // code
456  current5format += next;
459  break;
460  }
461 }
462 
463 static inline void nextPrintFormat(RzCore *core) {
464  printFormat(core, 1);
465 }
466 
467 static inline void prevPrintFormat(RzCore *core) {
468  printFormat(core, -1);
469 }
470 
472  const char *c = rz_config_get(core->config, "hud.path");
473  char *system_hud_dir = rz_path_system(RZ_HUD);
474  char *f = rz_file_path_join(system_hud_dir, "main");
475  free(system_hud_dir);
476  int use_color = core->print->flags & RZ_PRINT_FLAGS_COLOR;
477  char *homehud = rz_path_home_prefix(RZ_HUD);
478  char *res = NULL;
479  char *p = 0;
480  rz_cons_singleton()->context->color_mode = use_color;
481 
482  rz_core_visual_showcursor(core, true);
483  if (c && *c && rz_file_exists(c)) {
484  res = rz_cons_hud_file(c);
485  }
486  if (!res && homehud) {
487  res = rz_cons_hud_file(homehud);
488  }
489  if (!res && rz_file_exists(f)) {
490  res = rz_cons_hud_file(f);
491  }
492  if (!res) {
493  rz_cons_message("Cannot find hud file");
494  return false;
495  }
496 
497  rz_cons_clear();
498  if (res) {
499  p = strchr(res, ';');
500  rz_cons_println(res);
501  rz_cons_flush();
502  if (p) {
503  rz_core_cmd0(core, p + 1);
504  }
505  free(res);
506  }
507  rz_core_visual_showcursor(core, false);
508  rz_cons_flush();
509  free(homehud);
510  free(f);
511  return true;
512 }
513 
515  char chbuf[2];
516  ut64 off;
517  chbuf[0] = ch;
518  chbuf[1] = '\0';
519  off = rz_core_get_asmqjmps(core, chbuf);
520  if (off != UT64_MAX) {
521  int delta = RZ_ABS((st64)off - (st64)core->offset);
522  if (core->print->cur_enabled && delta < 100) {
523  core->print->cur = delta;
524  } else {
526  core->print->cur = 0;
527  }
528  rz_core_block_read(core);
529  }
530 }
531 
532 RZ_API void rz_core_visual_append_help(RzStrBuf *p, const char *title, const char **help) {
533  int i, max_length = 0, padding = 0;
534  RzConsContext *cons_ctx = rz_cons_singleton()->context;
535  const char *pal_args_color = cons_ctx->color_mode ? cons_ctx->pal.args : "",
536  *pal_help_color = cons_ctx->color_mode ? cons_ctx->pal.help : "",
537  *pal_reset = cons_ctx->color_mode ? cons_ctx->pal.reset : "";
538  for (i = 0; help[i]; i += 2) {
539  max_length = RZ_MAX(max_length, strlen(help[i]));
540  }
541  rz_strbuf_appendf(p, "|%s:\n", title);
542 
543  for (i = 0; help[i]; i += 2) {
544  padding = max_length - (strlen(help[i]));
545  rz_strbuf_appendf(p, "| %s%s%*s %s%s%s\n",
546  pal_args_color, help[i],
547  padding, "",
548  pal_help_color, help[i + 1], pal_reset);
549  }
550 }
551 
552 static int visual_help(RzCore *core) {
553  int ret = 0;
554  RzStrBuf *p, *q;
555 repeat:
556  p = rz_strbuf_new(NULL);
557  q = rz_strbuf_new(NULL);
558  if (!p) {
559  return 0;
560  }
561  rz_cons_clear00();
562  rz_core_visual_append_help(q, "Visual Help", help_visual);
563  rz_cons_printf("%s", rz_strbuf_get(q));
564  rz_cons_flush();
565  switch (rz_cons_readchar()) {
566  case 'q':
567  rz_strbuf_free(p);
568  rz_strbuf_free(q);
569  return ret;
570  case '!':
572  break;
573  case '?':
574  rz_core_visual_append_help(p, "Visual mode help", help_msg_visual);
575  rz_core_visual_append_help(p, "Function Keys: (See 'e key.'), defaults to", help_msg_visual_fn);
576  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
577  break;
578  case 'v':
579  rz_strbuf_appendf(p, "Visual Views:\n\n");
581  " \\ toggle horizonal split mode\n"
582  " tt create a new tab (same as t+)\n"
583  " t= give a name to the current tab\n"
584  " t- close current tab\n"
585  " th select previous tab (same as tj)\n"
586  " tl select next tab (same as tk)\n"
587  " t[1-9] select nth tab\n"
588  " C -> rotate scr.color=0,1,2,3\n"
589  " R -> rotate color theme with ecr command which honors scr.randpal\n");
590  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
591  break;
592  case 'p':
593  rz_strbuf_appendf(p, "Visual Print Modes:\n\n");
595  " pP -> change to the next/previous print mode (hex, dis, ..)\n"
596  " TAB -> rotate between all the configurations for the current print mode\n");
597  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
598  break;
599  case 'e':
600  rz_strbuf_appendf(p, "Visual Evals:\n\n");
602  " E toggle asm.hint.lea\n"
603  " & rotate asm.bits=16,32,64\n");
604  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
605  break;
606  case 'c':
607  setcursor(core, !core->print->cur_enabled);
608  rz_strbuf_free(p);
609  rz_strbuf_free(q);
610  return ret;
611  case 'i':
612  rz_strbuf_appendf(p, "Visual Insertion Help:\n\n");
614  " i -> insert bits, bytes or text depending on view\n"
615  " a -> assemble instruction and write the bytes in the current offset\n"
616  " A -> visual assembler\n"
617  " + -> increment value of byte\n"
618  " - -> decrement value of byte\n");
619  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
620  break;
621  case 'd':
622  rz_strbuf_appendf(p, "Visual Debugger Help:\n\n");
624  " $ -> set the program counter (PC register)\n"
625  " s -> step in\n"
626  " S -> step over\n"
627  " B -> toggle breakpoint\n"
628  " :dc -> continue\n");
629  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
630  break;
631  case 'm':
632  rz_strbuf_appendf(p, "Visual Moving Around:\n\n");
634  " g type flag/offset/register name to seek\n"
635  " hl seek to the next/previous byte\n"
636  " jk seek to the next row (core.offset += hex.cols)\n"
637  " JK seek one page down\n"
638  " ^ seek to the beginning of the current map\n"
639  " $ seek to the end of the current map\n"
640  " c toggle cursor mode (use hjkl to move and HJKL to select a range)\n"
641  " mK/'K mark/go to Key (any key)\n");
642  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
643  break;
644  case 'a':
645  rz_strbuf_appendf(p, "Visual Analysis:\n\n");
647  " df -> define function\n"
648  " du -> undefine function\n"
649  " dc -> define as code\n"
650  " dw -> define as dword (32bit)\n"
651  " dw -> define as qword (64bit)\n"
652  " dd -> define current block or selected bytes as data\n"
653  " V -> view graph (same as press the 'space' key)\n");
654  ret = rz_cons_less_str(rz_strbuf_get(p), "?");
655  break;
656  }
657  rz_strbuf_free(p);
658  rz_strbuf_free(q);
659  goto repeat;
660 }
661 
662 static void prompt_read(const char *p, char *buf, int buflen) {
663  if (!buf || buflen < 1) {
664  return;
665  }
666  *buf = 0;
671 }
672 
673 static void reset_print_cur(RzPrint *p) {
674  p->cur = 0;
675  p->ocur = -1;
676 }
677 
678 static bool __holdMouseState(RzCore *core) {
679  bool m = rz_cons_singleton()->mouse;
680  rz_cons_enable_mouse(false);
681  return m;
682 }
683 
684 static void backup_current_addr(RzCore *core, ut64 *addr, ut64 *bsze, ut64 *newaddr, int *cur) {
685  *addr = core->offset;
686  *bsze = core->blocksize;
687  *cur = core->print->cur_enabled ? core->print->cur : 0;
688  if (core->print->cur_enabled) {
689  if (core->print->ocur != -1) {
690  int newsz = core->print->cur - core->print->ocur;
691  *newaddr = core->offset + core->print->ocur;
692  rz_core_block_size(core, newsz);
693  } else {
694  *newaddr = core->offset + core->print->cur;
695  }
696  rz_core_seek(core, *newaddr, true);
697  core->print->cur = 0;
698  }
699 }
700 
701 static void restore_current_addr(RzCore *core, ut64 addr, ut64 bsze, ut64 newaddr, int cur) {
702  bool restore_seek = true;
703  bool cursor_moved = false;
704  if (core->offset != newaddr) {
705  // when new address is in the screen bounds, just move
706  // the cursor if enabled and restore seek
707  if (core->print->cur_enabled && core->print->screen_bounds > 1) {
708  if (core->offset >= addr &&
709  core->offset < core->print->screen_bounds) {
710  core->print->ocur = -1;
711  core->print->cur = core->offset - addr;
712  cursor_moved = true;
713  }
714  }
715 
716  if (!cursor_moved) {
717  restore_seek = false;
718  reset_print_cur(core->print);
719  }
720  }
721 
722  if (core->print->cur_enabled) {
723  if (restore_seek) {
724  rz_core_seek(core, addr, true);
725  rz_core_block_size(core, bsze);
726  if (!cursor_moved) {
727  core->print->cur = cur;
728  }
729  }
730  }
731 }
732 
734  ut64 addr, bsze, newaddr = 0LL;
735  int ret, h, cur;
736  (void)rz_cons_get_size(&h);
737  bool mouse_state = __holdMouseState(core);
738  rz_cons_gotoxy(0, h);
740  // rz_cons_printf ("\nPress <enter> to return to Visual mode.\n");
741  rz_cons_show_cursor(true);
742  core->vmode = false;
743 
744  backup_current_addr(core, &addr, &bsze, &newaddr, &cur);
745  do {
746  ret = rz_core_visual_prompt(core);
747  } while (ret);
748  restore_current_addr(core, addr, bsze, newaddr, cur);
749 
750  rz_cons_show_cursor(false);
751  core->vmode = true;
752  rz_cons_enable_mouse(mouse_state && rz_config_get_b(core->config, "scr.wheel"));
753  rz_cons_show_cursor(true);
754 }
755 
757  char buf[1024];
758  int ret;
759  if (PIDX != 2) {
760  core->seltab = 0;
761  }
762 #if __UNIX__
764 #else
765  rz_line_set_prompt(":> ");
766 #endif
767  rz_core_visual_showcursor(core, true);
768  rz_cons_fgets(buf, sizeof(buf), 0, NULL);
769  if (!strcmp(buf, "q")) {
770  ret = false;
771  } else if (*buf) {
773  rz_core_cmd(core, buf, 0);
775  rz_cons_flush();
776  ret = true;
777  if (rz_config_get_b(core->config, "cfg.debug")) {
779  }
780  } else {
781  ret = false;
782  // rz_cons_any_key (NULL);
783  rz_cons_clear00();
784  rz_core_visual_showcursor(core, false);
785  }
786  return ret;
787 }
788 
789 static void visual_breakpoint(RzCore *core) {
791 }
792 
793 static int visual_nkey(RzCore *core, int ch) {
794  const char *cmd;
795  ut64 oseek = UT64_MAX;
796  if (core->print->ocur == -1) {
797  oseek = core->offset;
798  rz_core_seek(core, core->offset + core->print->cur, false);
799  }
800 
801  switch (ch) {
802  case RZ_CONS_KEY_F1:
803  cmd = rz_config_get(core->config, "key.f1");
804  if (cmd && *cmd) {
805  ch = rz_core_cmd0(core, cmd);
806  } else {
807  visual_help(core);
808  }
809  break;
810  case RZ_CONS_KEY_F2:
811  cmd = rz_config_get(core->config, "key.f2");
812  if (cmd && *cmd) {
813  ch = rz_core_cmd0(core, cmd);
814  } else {
815  visual_breakpoint(core);
816  }
817  break;
818  case RZ_CONS_KEY_F3:
819  cmd = rz_config_get(core->config, "key.f3");
820  if (cmd && *cmd) {
821  ch = rz_core_cmd0(core, cmd);
822  }
823  break;
824  case RZ_CONS_KEY_F4:
825  cmd = rz_config_get(core->config, "key.f4");
826  if (cmd && *cmd) {
827  ch = rz_core_cmd0(core, cmd);
828  } else {
829  if (core->print->cur_enabled) {
830  rz_core_debug_continue_until(core, core->offset, core->offset + core->print->cur);
831  core->print->cur_enabled = 0;
832  }
833  }
834  break;
835  case RZ_CONS_KEY_F5:
836  cmd = rz_config_get(core->config, "key.f5");
837  if (cmd && *cmd) {
838  ch = rz_core_cmd0(core, cmd);
839  }
840  break;
841  case RZ_CONS_KEY_F6:
842  cmd = rz_config_get(core->config, "key.f6");
843  if (cmd && *cmd) {
844  ch = rz_core_cmd0(core, cmd);
845  }
846  break;
847  case RZ_CONS_KEY_F7:
848  cmd = rz_config_get(core->config, "key.f7");
849  if (cmd && *cmd) {
850  ch = rz_core_cmd0(core, cmd);
851  } else {
853  }
854  break;
855  case RZ_CONS_KEY_F8:
856  cmd = rz_config_get(core->config, "key.f8");
857  if (cmd && *cmd) {
858  ch = rz_core_cmd0(core, cmd);
859  } else {
861  }
862  break;
863  case RZ_CONS_KEY_F9:
864  cmd = rz_config_get(core->config, "key.f9");
865  if (cmd && *cmd) {
866  ch = rz_core_cmd0(core, cmd);
867  } else {
869  }
870  break;
871  case RZ_CONS_KEY_F10:
872  cmd = rz_config_get(core->config, "key.f10");
873  if (cmd && *cmd) {
874  ch = rz_core_cmd0(core, cmd);
875  }
876  break;
877  case RZ_CONS_KEY_F11:
878  cmd = rz_config_get(core->config, "key.f11");
879  if (cmd && *cmd) {
880  ch = rz_core_cmd0(core, cmd);
881  }
882  break;
883  case RZ_CONS_KEY_F12:
884  cmd = rz_config_get(core->config, "key.f12");
885  if (cmd && *cmd) {
886  ch = rz_core_cmd0(core, cmd);
887  }
888  break;
889  }
890  if (oseek != UT64_MAX) {
891  rz_core_seek(core, oseek, false);
892  }
893  return ch;
894 }
895 
896 static void setdiff(RzCore *core) {
897  char from[64], to[64];
898  prompt_read("diff from: ", from, sizeof(from));
899  rz_config_set(core->config, "diff.from", from);
900  prompt_read("diff to: ", to, sizeof(to));
901  rz_config_set(core->config, "diff.to", to);
902 }
903 
904 static void findPair(RzCore *core) {
905  ut8 buf[256];
906  int i, len, d = core->print->cur + 1;
907  int delta = 0;
908  const ut8 *p, *q = NULL;
909  const char *keys = "{}[]()<>";
910  ut8 ch = core->block[core->print->cur];
911 
912  p = (const ut8 *)strchr(keys, ch);
913  if (p) {
914  char p_1 = 0;
915  if ((const char *)p > keys) {
916  p_1 = p[-1];
917  }
918  delta = (size_t)(p - (const ut8 *)keys);
919  ch = (delta % 2 && p != (const ut8 *)keys) ? p_1 : p[1];
920  }
921  len = 1;
922  buf[0] = ch;
923 
924  if (p && (delta % 2)) {
925  for (i = d - 1; i >= 0; i--) {
926  if (core->block[i] == ch) {
927  q = core->block + i;
928  break;
929  }
930  }
931  } else {
932  q = rz_mem_mem(core->block + d, core->blocksize - d,
933  (const ut8 *)buf, len);
934  if (!q) {
935  q = rz_mem_mem(core->block, RZ_MIN(core->blocksize, d),
936  (const ut8 *)buf, len);
937  }
938  }
939  if (q) {
940  core->print->cur = (int)(size_t)(q - core->block);
941  core->print->ocur = -1;
942  rz_core_visual_showcursor(core, true);
943  }
944 }
945 
946 static void findNextWord(RzCore *core) {
947  int i, d = core->print->cur_enabled ? core->print->cur : 0;
948  for (i = d + 1; i < core->blocksize; i++) {
949  switch (core->block[i]) {
950  case ' ':
951  case '.':
952  case '\t':
953  case '\n':
954  if (core->print->cur_enabled) {
955  core->print->cur = i + 1;
956  core->print->ocur = -1;
957  rz_core_visual_showcursor(core, true);
958  } else {
959  rz_core_seek_and_save(core, core->offset + i + 1, true);
960  }
961  return;
962  }
963  }
964 }
965 
966 static int isSpace(char ch) {
967  switch (ch) {
968  case ' ':
969  case '.':
970  case ',':
971  case '\t':
972  case '\n':
973  return 1;
974  }
975  return 0;
976 }
977 
978 static void findPrevWord(RzCore *core) {
979  int i = core->print->cur_enabled ? core->print->cur : 0;
980  while (i > 1) {
981  if (isSpace(core->block[i])) {
982  i--;
983  } else if (isSpace(core->block[i - 1])) {
984  i -= 2;
985  } else {
986  break;
987  }
988  }
989  for (; i >= 0; i--) {
990  if (isSpace(core->block[i])) {
991  if (core->print->cur_enabled) {
992  core->print->cur = i + 1;
993  core->print->ocur = -1;
994  rz_core_visual_showcursor(core, true);
995  }
996  break;
997  }
998  }
999 }
1000 
1001 // TODO: integrate in '/' command with search.inblock ?
1002 static void visual_search(RzCore *core) {
1003  const ut8 *p;
1004  int len, d = core->print->cur;
1005  char str[128], buf[sizeof(str) * 2 + 1];
1006 
1007  rz_line_set_prompt("search byte/string in block: ");
1008  rz_cons_fgets(str, sizeof(str), 0, NULL);
1009  len = rz_hex_str2bin(str, (ut8 *)buf);
1010  if (*str == '"') {
1011  rz_str_ncpy(buf, str + 1, sizeof(buf));
1012  len = strlen(buf);
1013  char *e = buf + len - 1;
1014  if (e > buf && *e == '"') {
1015  *e = 0;
1016  len--;
1017  }
1018  } else if (len < 1) {
1019  rz_str_ncpy(buf, str, sizeof(buf));
1020  len = strlen(buf);
1021  }
1022  p = rz_mem_mem(core->block + d, core->blocksize - d,
1023  (const ut8 *)buf, len);
1024  if (p) {
1025  core->print->cur = (int)(size_t)(p - core->block);
1026  if (len > 1) {
1027  core->print->ocur = core->print->cur + len - 1;
1028  } else {
1029  core->print->ocur = -1;
1030  }
1031  rz_core_visual_showcursor(core, true);
1032  eprintf("Found in offset 0x%08" PFMT64x " + %d\n", core->offset, core->print->cur);
1034  } else {
1035  eprintf("Cannot find bytes.\n");
1037  rz_cons_clear00();
1038  }
1039 }
1040 
1042  if (rz_config_get_i(core->config, "scr.feedback") < 2) {
1043  return;
1044  }
1045  if (!IS_PRINTABLE(ch)) {
1046  return;
1047  }
1048  rz_cons_gotoxy(1, 2);
1049  rz_cons_printf(".---.\n");
1050  rz_cons_printf("| %c |\n", ch);
1051  rz_cons_printf("'---'\n");
1052  rz_cons_flush();
1053  rz_sys_sleep(1);
1054 }
1055 
1056 static void visual_seek_animation(RzCore *core, ut64 addr) {
1057  if (rz_config_get_i(core->config, "scr.feedback") < 1) {
1058  return;
1059  }
1060  if (core->offset == addr) {
1061  return;
1062  }
1063  rz_cons_gotoxy(1, 2);
1064  if (addr > core->offset) {
1065  rz_cons_printf(".----.\n");
1066  rz_cons_printf("| \\/ |\n");
1067  rz_cons_printf("'----'\n");
1068  } else {
1069  rz_cons_printf(".----.\n");
1070  rz_cons_printf("| /\\ |\n");
1071  rz_cons_printf("'----'\n");
1072  }
1073  rz_cons_flush();
1074  rz_sys_usleep(90000);
1075 }
1076 
1078  rz_core_seek_and_save(core, addr, true);
1079  visual_seek_animation(core, addr);
1080 }
1081 
1083  if (rz_core_seek_redo(core)) {
1084  visual_seek_animation(core, core->offset);
1085  }
1086 }
1087 
1089  if (rz_core_seek_undo(core)) {
1090  visual_seek_animation(core, core->offset);
1091  }
1092 }
1093 
1094 static void setprintmode(RzCore *core, int n) {
1095  rz_config_set_i(core->config, "scr.visual.mode", core->printidx + n);
1096  RzAsmOp op;
1097 
1098  switch (core->printidx) {
1101  rz_asm_op_init(&op);
1102  rz_asm_disassemble(core->rasm, &op, core->block, RZ_MIN(32, core->blocksize));
1103  rz_asm_op_fini(&op);
1104  break;
1105  default:
1106  break;
1107  }
1108 }
1109 
1110 #define OPDELTA 32
1111 static ut64 prevop_addr(RzCore *core, ut64 addr) {
1112  ut8 buf[OPDELTA * 2];
1113  ut64 target, base;
1114  RzAnalysisBlock *bb;
1115  RzAnalysisOp op;
1116  int len, ret, i;
1119 
1120  if (minop == maxop) {
1121  if (minop == -1) {
1122  return addr - 4;
1123  }
1124  return addr - minop;
1125  }
1126 
1127  // let's see if we can use analysis info to get the previous instruction
1128  // TODO: look in the current basicblock, then in the current function
1129  // and search in all functions only as a last chance, to try to speed
1130  // up the process.
1132  if (bb) {
1133  ut64 res = rz_analysis_block_get_op_addr_in(bb, addr - minop);
1134  if (res != UT64_MAX) {
1135  return res;
1136  }
1137  }
1138  // if we analysis info didn't help then fallback to the dumb solution.
1139  int midflags = rz_config_get_i(core->config, "asm.flags.middle");
1140  target = addr;
1141  base = target > OPDELTA ? target - OPDELTA : 0;
1142  rz_io_read_at(core->io, base, buf, sizeof(buf));
1143  for (i = 0; i < sizeof(buf); i++) {
1144  ret = rz_analysis_op(core->analysis, &op, base + i,
1145  buf + i, sizeof(buf) - i, RZ_ANALYSIS_OP_MASK_BASIC);
1146  if (ret > 0) {
1147  len = op.size;
1148  if (len < 1) {
1149  len = 1;
1150  }
1151  rz_analysis_op_fini(&op); // XXX
1152  if (midflags >= RZ_MIDFLAGS_REALIGN) {
1153  int skip_bytes = rz_core_flag_in_middle(core, base + i, len, &midflags);
1154  if (skip_bytes && base + i + skip_bytes < target) {
1155  i += skip_bytes - 1;
1156  continue;
1157  }
1158  }
1159  } else {
1160  len = 1;
1161  }
1162  if (target <= base + i + len) {
1163  return base + i;
1164  }
1165  i += len - 1;
1166  }
1167  return target > 4 ? target - 4 : 0;
1168 }
1169 
1170 // Returns true if we can use analysis to find the previous operation address,
1171 // sets prev_addr to the value of the instruction numinstrs back.
1172 // If we can't use the analysis, then set prev_addr to UT64_MAX and return false;
1173 RZ_API bool rz_core_prevop_addr(RzCore *core, ut64 start_addr, int numinstrs, ut64 *prev_addr) {
1174  RzAnalysisBlock *bb;
1175  int i;
1176  // Check that we're in a bb, otherwise this prevop stuff won't work.
1177  bb = rz_analysis_find_most_relevant_block_in(core->analysis, start_addr);
1178  if (bb) {
1179  if (rz_analysis_block_get_op_addr_in(bb, start_addr) != UT64_MAX) {
1180  // Do some analysis looping.
1181  for (i = 0; i < numinstrs; i++) {
1182  *prev_addr = prevop_addr(core, start_addr);
1183  start_addr = *prev_addr;
1184  }
1185  return true;
1186  }
1187  }
1188  // Dang! not in a bb, return false and fallback to other methods.
1189  *prev_addr = UT64_MAX;
1190  return false;
1191 }
1192 
1193 // Like rz_core_prevop_addr(), but also uses fallback from prevop_addr() if
1194 // no analysis info is available.
1195 RZ_API ut64 rz_core_prevop_addr_force(RzCore *core, ut64 start_addr, int numinstrs) {
1196  int i;
1197  for (i = 0; i < numinstrs; i++) {
1198  start_addr = prevop_addr(core, start_addr);
1199  }
1200  return start_addr;
1201 }
1202 
1203 static bool fill_hist_offset(RzCore *core, RzLine *line, RzCoreSeekItem *csi) {
1204  ut64 off = csi->offset;
1205  RzFlagItem *f = rz_flag_get_at(core->flags, off, false);
1206  char *command = NULL;
1207  if (f && f->offset == off && f->offset > 0) {
1208  command = rz_str_newf("%s", f->name);
1209  } else {
1210  command = rz_str_newf("0x%" PFMT64x, off);
1211  }
1212  if (!command) {
1213  return false;
1214  }
1215 
1216  strncpy(line->buffer.data, command, RZ_LINE_BUFSIZE - 1);
1217  line->buffer.index = line->buffer.length = strlen(line->buffer.data);
1218  free(command);
1219  return true;
1220 }
1221 
1223  RzCore *core = (RzCore *)line->user;
1224  RzCoreSeekItem *csi = rz_core_seek_peek(core, line->offset_hist_index - 1);
1225  if (!csi) {
1226  return false;
1227  }
1228 
1229  line->offset_hist_index--;
1230  bool res = fill_hist_offset(core, line, csi);
1232  return res;
1233 }
1234 
1236  RzCore *core = (RzCore *)line->user;
1237  RzCoreSeekItem *csi = rz_core_seek_peek(core, line->offset_hist_index + 1);
1238  if (!csi) {
1239  return false;
1240  }
1241  line->offset_hist_index++;
1242  bool res = fill_hist_offset(core, line, csi);
1244  return res;
1245 }
1246 
1248  char buf[256];
1249 
1254  rz_line_set_prompt("[offset]> ");
1255  if (rz_cons_fgets(buf, sizeof(buf) - 1, 0, NULL) > 0) {
1256  if (!strcmp(buf, "g") || !strcmp(buf, "G")) {
1257  __core_visual_gogo(core, buf[0]);
1258  } else {
1259  if (buf[0] == '.') {
1260  rz_core_seek_base(core, buf + 1, true);
1261  } else {
1262  ut64 addr = rz_num_math(core->num, buf);
1263  rz_core_seek_and_save(core, addr, true);
1264  }
1265  }
1266  reset_print_cur(core->print);
1267  }
1270 }
1271 
1273  ut64 prev_addr = prevop_addr(core, addr);
1274  return addr - prev_addr;
1275 }
1276 
1277 static void add_comment(RzCore *core, ut64 addr, const char *prompt) {
1278  char buf[1024];
1279  rz_cons_print(prompt);
1280  rz_core_visual_showcursor(core, true);
1281  rz_cons_flush();
1282  rz_cons_set_raw(false);
1283  rz_line_set_prompt(":> ");
1284  rz_cons_enable_mouse(false);
1285  if (rz_cons_fgets(buf, sizeof(buf), 0, NULL) < 0) {
1286  buf[0] = '\0';
1287  }
1288  if (!strcmp(buf, "-")) {
1290  } else if (!strcmp(buf, "!")) {
1292  } else {
1294  }
1295  rz_core_visual_showcursor(core, false);
1296  rz_cons_set_raw(true);
1297 }
1298 
1299 static int follow_ref(RzCore *core, RzList *xrefs, int choice, bool xref_to) {
1300  RzAnalysisXRef *xrefi = rz_list_get_n(xrefs, choice);
1301  if (xrefi) {
1302  if (core->print->cur_enabled) {
1303  core->print->cur = 0;
1304  }
1305  ut64 addr = xref_to ? xrefi->from : xrefi->to;
1306  rz_core_seek_and_save(core, addr, true);
1307  return 1;
1308  }
1309  return 0;
1310 }
1311 
1312 RZ_API int rz_core_visual_xrefs(RzCore *core, bool xref_to, bool fcnInsteadOfAddr) {
1313  ut64 cur_ref_addr = UT64_MAX;
1314  int ret = 0;
1315  char ch;
1316  int count = 0;
1317  RzList *xrefs = NULL;
1318  RzAnalysisXRef *xrefi;
1319  RzListIter *iter;
1320  int skip = 0;
1321  int idx = 0;
1322  char cstr[32];
1323  ut64 addr = core->offset;
1324  bool xrefsMode = fcnInsteadOfAddr;
1325  int lastPrintMode = 3;
1326  if (core->print->cur_enabled) {
1327  addr += core->print->cur;
1328  }
1329 repeat:
1330  rz_list_free(xrefs);
1331  if (xrefsMode) {
1333  if (fun) {
1334  if (xref_to) { // function xrefs
1335  xrefs = rz_analysis_xrefs_get_to(core->analysis, addr);
1336  // XXX xrefs = rz_analysis_function_get_xrefs_to(core->analysis, fun);
1337  // this function is buggy so we must get the xrefs of the addr
1338  } else { // functon refs
1340  }
1341  } else {
1342  xrefs = NULL;
1343  }
1344  } else {
1345  if (xref_to) { // address xrefs
1346  xrefs = rz_analysis_xrefs_get_to(core->analysis, addr);
1347  } else { // address refs
1348  xrefs = rz_analysis_xrefs_get_from(core->analysis, addr);
1349  }
1350  }
1351 
1352  rz_cons_clear00();
1353  rz_cons_gotoxy(1, 1);
1354  {
1355  char *address = (core->dbg->bits & RZ_SYS_BITS_64)
1356  ? rz_str_newf("0x%016" PFMT64x, addr)
1357  : rz_str_newf("0x%08" PFMT64x, addr);
1358  rz_cons_printf("[%s%srefs]> %s # (TAB/jk/q/?) ",
1359  xrefsMode ? "fcn." : "addr.", xref_to ? "x" : "", address);
1360  free(address);
1361  }
1362  if (!xrefs || rz_list_empty(xrefs)) {
1363  rz_list_free(xrefs);
1364  xrefs = NULL;
1365  rz_cons_printf("\n\n(no %srefs)\n", xref_to ? "x" : "");
1366  } else {
1367  int h, w = rz_cons_get_size(&h);
1368  bool asm_bytes = rz_config_get_b(core->config, "asm.bytes");
1369  rz_config_set_b(core->config, "asm.bytes", false);
1372  return RZ_CMD_STATUS_INVALID;
1373  }
1374  rz_core_flag_describe(core, core->offset, false, &state);
1376  int maxcount = 9;
1377  int rows, cols = rz_cons_get_size(&rows);
1378  count = 0;
1379  char *dis = NULL;
1380  rows -= 4;
1381  idx = 0;
1382  ut64 curat = UT64_MAX;
1383  rz_list_foreach (xrefs, iter, xrefi) {
1384  ut64 xaddr1 = xref_to ? xrefi->from : xrefi->to;
1385  ut64 xaddr2 = xref_to ? xrefi->to : xrefi->from;
1386  if (idx - skip > maxcount) {
1387  rz_cons_printf("...");
1388  break;
1389  }
1390  if (!iter->n && idx < skip) {
1391  skip = idx;
1392  }
1393  if (idx >= skip) {
1394  if (count > maxcount) {
1395  strcpy(cstr, "?");
1396  } else {
1397  snprintf(cstr, sizeof(cstr), "%d", count);
1398  }
1399  if (idx == skip) {
1400  cur_ref_addr = xaddr1;
1401  }
1403  char *name;
1404  if (fun) {
1405  name = strdup(fun->name);
1406  } else {
1407  RzFlagItem *f = rz_flag_get_at(core->flags, xaddr1, true);
1408  if (f) {
1409  name = rz_str_newf("%s + %" PFMT64d, f->name, xaddr1 - f->offset);
1410  } else {
1411  name = strdup("unk");
1412  }
1413  }
1414  if (w > 45) {
1415  if (strlen(name) > w - 45) {
1416  name[w - 45] = 0;
1417  }
1418  } else {
1419  name[0] = 0;
1420  }
1421 
1422  const char *cmt = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, xaddr1);
1423  if (cmt) {
1424  cmt = rz_str_trim_head_ro(cmt);
1425  rz_cons_printf(" %d [%s] 0x%08" PFMT64x " 0x%08" PFMT64x " %s %sref (%s) ; %s\n",
1426  idx, cstr, xaddr2, xaddr1,
1428  xref_to ? "x" : "", name, cmt);
1429  }
1430  free(name);
1431  if (idx == skip) {
1432  free(dis);
1433  curat = xaddr1;
1434  char *res = rz_core_cmd_strf(core, "pd 4 @ 0x%08" PFMT64x "@e:asm.flags.limit=1", xaddr2);
1435  // TODO: show disasm with context. not seek addr
1436  // dis = rz_core_cmd_strf (core, "pd $r-4 @ 0x%08"PFMT64x, xaddr);
1437  dis = NULL;
1438  res = rz_str_appendf(res, "; ---------------------------\n");
1439  switch (printMode) {
1440  case 0:
1441  dis = rz_core_cmd_strf(core, "pd $r-4 @ 0x%08" PFMT64x, xaddr1);
1442  break;
1443  case 1:
1444  dis = rz_core_cmd_strf(core, "pd @ 0x%08" PFMT64x "-32", xaddr1);
1445  break;
1446  case 2:
1447  dis = rz_core_cmd_strf(core, "px @ 0x%08" PFMT64x, xaddr1);
1448  break;
1449  case 3:
1450  dis = rz_core_cmd_strf(core, "pds @ 0x%08" PFMT64x, xaddr1);
1451  break;
1452  }
1453  if (dis) {
1454  res = rz_str_append(res, dis);
1455  free(dis);
1456  }
1457  dis = res;
1458  }
1459  if (++count >= rows) {
1460  rz_cons_printf("...");
1461  break;
1462  }
1463  }
1464  idx++;
1465  }
1466  if (dis) {
1467  if (count < rows) {
1468  rz_cons_newline();
1469  }
1470  int i = count;
1471  for (; i < 9; i++) {
1472  rz_cons_newline();
1473  }
1474  /* prepare highlight */
1475  char *cmd = strdup(rz_config_get(core->config, "scr.highlight"));
1476  char *ats = rz_str_newf("%" PFMT64x, curat);
1477  if (ats && !*cmd) {
1478  (void)rz_config_set(core->config, "scr.highlight", ats);
1479  }
1480  /* print disasm */
1481  char *d = rz_str_ansi_crop(dis, 0, 0, cols, rows - 9);
1482  if (d) {
1483  rz_cons_printf("%s", d);
1484  free(d);
1485  }
1486  /* flush and restore highlight */
1487  rz_cons_flush();
1488  rz_config_set(core->config, "scr.highlight", cmd);
1489  free(ats);
1490  free(cmd);
1491  free(dis);
1492  dis = NULL;
1493  }
1494  rz_config_set_b(core->config, "asm.bytes", asm_bytes);
1495  }
1496  rz_cons_flush();
1497  rz_cons_enable_mouse(rz_config_get_b(core->config, "scr.wheel"));
1498  ch = rz_cons_readchar();
1499  ch = rz_cons_arrow_to_hjkl(ch);
1500  if (ch == ':') {
1502  goto repeat;
1503  } else if (ch == '?') {
1504  rz_cons_clear00();
1505  rz_cons_printf("Usage: Visual Xrefs\n"
1506  " jk - select next or previous item (use arrows)\n"
1507  " JK - step 10 rows\n"
1508  " pP - rotate between various print modes\n"
1509  " : - run rizin command\n"
1510  " / - highlight given word\n"
1511  " ? - show this help message\n"
1512  " <> - '<' for xrefs and '>' for refs\n"
1513  " TAB - toggle between address and function references\n"
1514  " xX - switch to refs or xrefs\n"
1515  " q - quit this view\n"
1516  " \\n - seek to this xref");
1517  rz_cons_flush();
1519  goto repeat;
1520  } else if (ch == 9) { // TAB
1521  xrefsMode = !xrefsMode;
1522  rz_core_visual_toggle_decompiler_disasm(core, false, true);
1523  goto repeat;
1524  } else if (ch == 'p') {
1525  rz_core_visual_toggle_decompiler_disasm(core, false, true);
1526  printMode++;
1527  if (printMode > lastPrintMode) {
1528  printMode = 0;
1529  }
1530  goto repeat;
1531  } else if (ch == 'P') {
1532  rz_core_visual_toggle_decompiler_disasm(core, false, true);
1533  printMode--;
1534  if (printMode < 0) {
1536  }
1537  goto repeat;
1538  } else if (ch == '/') {
1539  rz_core_cmd0(core, "?i highlight;e scr.highlight=`yp`");
1540  goto repeat;
1541  } else if (ch == 'x' || ch == '<') {
1542  xref_to = true;
1543  xrefsMode = !xrefsMode;
1544  goto repeat;
1545  } else if (ch == 'X' || ch == '>') {
1546  xref_to = false;
1547  xrefsMode = !xrefsMode;
1548  goto repeat;
1549  } else if (ch == 'J') {
1550  skip += 10;
1551  goto repeat;
1552  } else if (ch == 'g') {
1553  skip = 0;
1554  goto repeat;
1555  } else if (ch == 'G') {
1556  skip = 9999;
1557  goto repeat;
1558  } else if (ch == ';') {
1559  add_comment(core, cur_ref_addr, "\nEnter comment for reference:\n");
1560  goto repeat;
1561  } else if (ch == '.') {
1562  skip = 0;
1563  goto repeat;
1564  } else if (ch == 'j') {
1565  skip++;
1566  goto repeat;
1567  } else if (ch == 'K') {
1568  skip = (skip < 10) ? 0 : skip - 10;
1569  goto repeat;
1570  } else if (ch == 'k') {
1571  skip--;
1572  if (skip < 0) {
1573  skip = 0;
1574  }
1575  goto repeat;
1576  } else if (ch == ' ' || ch == '\n' || ch == '\r' || ch == 'l') {
1577  ret = follow_ref(core, xrefs, skip, xref_to);
1578  } else if (IS_DIGIT(ch)) {
1579  ret = follow_ref(core, xrefs, ch - 0x30, xref_to);
1580  } else if (ch != 'q' && ch != 'Q' && ch != 'h') {
1581  goto repeat;
1582  }
1583  rz_list_free(xrefs);
1584 
1585  return ret;
1586 }
1587 
1588 #if __WINDOWS__
1589 void SetWindow(int Width, int Height) {
1590  COORD coord;
1591  coord.X = Width;
1592  coord.Y = Height;
1593 
1594  SMALL_RECT Rect;
1595  Rect.Top = 0;
1596  Rect.Left = 0;
1597  Rect.Bottom = Height - 1;
1598  Rect.Right = Width - 1;
1599 
1600  HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
1601  SetConsoleScreenBufferSize(Handle, coord);
1602  SetConsoleWindowInfo(Handle, TRUE, &Rect);
1603 }
1604 #endif
1605 
1606 // unnecesarily public
1607 char *getcommapath(RzCore *core) {
1608  char *cwd;
1609  const char *dir = rz_config_get(core->config, "dir.projects");
1610  const char *prj = rz_config_get(core->config, "prj.name");
1611  if (dir && *dir && prj && *prj) {
1612  char *abspath = rz_file_abspath(dir);
1613  /* use prjdir as base directory for comma-ent files */
1614  cwd = rz_str_newf("%s" RZ_SYS_DIR "%s.d", abspath, prj);
1615  free(abspath);
1616  } else {
1617  /* use cwd as base directory for comma-ent files */
1618  cwd = rz_sys_getdir();
1619  }
1620  return cwd;
1621 }
1622 
1623 static void visual_comma(RzCore *core) {
1624  bool mouse_state = __holdMouseState(core);
1625  ut64 addr = core->offset + (core->print->cur_enabled ? core->print->cur : 0);
1626  char *comment, *cwd, *cmtfile;
1627  const char *prev_cmt = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, addr);
1628  comment = prev_cmt ? strdup(prev_cmt) : NULL;
1629  cmtfile = rz_str_between(comment, ",(", ")");
1630  cwd = getcommapath(core);
1631  if (!cmtfile) {
1632  char *fn;
1633  fn = rz_cons_input("<comment-file> ");
1634  if (fn && *fn) {
1635  cmtfile = strdup(fn);
1636  if (!comment || !*comment) {
1637  comment = rz_str_newf(",(%s)", fn);
1639  } else {
1640  // append filename in current comment
1641  char *nc = rz_str_newf("%s ,(%s)", comment, fn);
1643  free(nc);
1644  }
1645  }
1646  free(fn);
1647  }
1648  if (cmtfile) {
1649  char *cwf = rz_str_newf("%s" RZ_SYS_DIR "%s", cwd, cmtfile);
1650  char *odata = rz_file_slurp(cwf, NULL);
1651  if (!odata) {
1652  eprintf("Could not open '%s'.\n", cwf);
1653  free(cwf);
1654  goto beach;
1655  }
1656  char *data = rz_core_editor(core, NULL, odata);
1657  rz_file_dump(cwf, (const ut8 *)data, -1, 0);
1658  free(data);
1659  free(odata);
1660  free(cwf);
1661  } else {
1662  eprintf("No commafile found.\n");
1663  }
1664 beach:
1665  free(comment);
1666  rz_cons_enable_mouse(mouse_state && rz_config_get_b(core->config, "scr.wheel"));
1667 }
1668 
1669 static bool isDisasmPrint(int mode) {
1671 }
1672 
1673 static void cursor_ocur(RzCore *core, bool use_ocur) {
1674  RzPrint *p = core->print;
1675  if (use_ocur && p->ocur == -1) {
1676  p->ocur = p->cur;
1677  } else if (!use_ocur) {
1678  p->ocur = -1;
1679  }
1680 }
1681 
1682 static void nextOpcode(RzCore *core) {
1684  RzPrint *p = core->print;
1685  if (aop) {
1686  p->cur += aop->size;
1687  rz_analysis_op_free(aop);
1688  } else {
1689  p->cur += 4;
1690  }
1691 }
1692 
1693 static void prevOpcode(RzCore *core) {
1694  RzPrint *p = core->print;
1695  ut64 addr, oaddr = core->offset + core->print->cur;
1696  if (rz_core_prevop_addr(core, oaddr, 1, &addr)) {
1697  const int delta = oaddr - addr;
1698  p->cur -= delta;
1699  } else {
1700  p->cur -= 4;
1701  }
1702 }
1703 
1704 static void cursor_nextrow(RzCore *core, bool use_ocur) {
1705  RzPrint *p = core->print;
1706  ut32 roff, next_roff;
1707  int row, sz, delta;
1708  RzAsmOp op;
1709 
1710  cursor_ocur(core, use_ocur);
1711  if (PIDX == 1) { // DISASM
1712  nextOpcode(core);
1713  return;
1714  }
1715 
1716  if (PIDX == 7 || !strcmp("prc", rz_config_get(core->config, "cmd.visual"))) {
1717  p->cur += rz_config_get_i(core->config, "hex.cols");
1718  return;
1719  }
1720  if (splitView) {
1721  int w = rz_config_get_i(core->config, "hex.cols");
1722  if (w < 1) {
1723  w = 16;
1724  }
1725  if (core->seltab == 0) {
1726  splitPtr += w;
1727  } else {
1728  core->offset += w;
1729  }
1730  return;
1731  }
1732  if (PIDX == RZ_CORE_VISUAL_MODE_DB) {
1733  const int cols = core->dbg->regcols;
1734  int w = rz_config_get_i(core->config, "hex.cols");
1735  switch (core->seltab) {
1736  case 0:
1737  if (w < 1) {
1738  w = 16;
1739  }
1740  rz_config_set_i(core->config, "stack.delta",
1741  rz_config_get_i(core->config, "stack.delta") - w);
1742  return;
1743  case 1:
1744  p->cur += cols > 0 ? cols : 3;
1745  return;
1746  default:
1747  nextOpcode(core);
1748  return;
1749  }
1750  }
1751  if (p->row_offsets) {
1752  // FIXME: cache the current row
1753  row = rz_print_row_at_off(p, p->cur);
1754  roff = rz_print_rowoff(p, row);
1755  if (roff == -1) {
1756  p->cur++;
1757  return;
1758  }
1759  next_roff = rz_print_rowoff(p, row + 1);
1760  if (next_roff == UT32_MAX) {
1761  p->cur++;
1762  return;
1763  }
1764  if (next_roff > core->blocksize) {
1765  p->cur += 32; // XXX workaround to "fix" cursor nextrow far away scrolling issue
1766  return;
1767  }
1768  if (next_roff + 32 < core->blocksize) {
1769  sz = rz_asm_disassemble(core->rasm, &op,
1770  core->block + next_roff, 32);
1771  if (sz < 1) {
1772  sz = 1;
1773  }
1774  } else {
1775  sz = 1;
1776  }
1777  delta = p->cur - roff;
1778  p->cur = next_roff + RZ_MIN(delta, sz - 1);
1779  } else {
1780  p->cur += RZ_MAX(1, p->cols);
1781  }
1782 }
1783 
1784 static void cursor_prevrow(RzCore *core, bool use_ocur) {
1785  RzPrint *p = core->print;
1786  ut32 roff, prev_roff;
1787  int row;
1788 
1789  cursor_ocur(core, use_ocur);
1790  if (PIDX == 1) { // DISASM
1791  prevOpcode(core);
1792  return;
1793  }
1794 
1795  if (PIDX == 7 || !strcmp("prc", rz_config_get(core->config, "cmd.visual"))) {
1796  int cols = rz_config_get_i(core->config, "hex.cols");
1797  p->cur -= RZ_MAX(cols, 0);
1798  return;
1799  }
1800 
1801  if (splitView) {
1802  int w = rz_config_get_i(core->config, "hex.cols");
1803  if (w < 1) {
1804  w = 16;
1805  }
1806  if (core->seltab == 0) {
1807  splitPtr -= w;
1808  } else {
1809  core->offset -= w;
1810  }
1811  return;
1812  }
1813  if (PIDX == RZ_CORE_VISUAL_MODE_DB) {
1814  switch (core->seltab) {
1815  case 0: {
1816  int w = rz_config_get_i(core->config, "hex.cols");
1817  if (w < 1) {
1818  w = 16;
1819  }
1820  rz_config_set_i(core->config, "stack.delta",
1821  rz_config_get_i(core->config, "stack.delta") + w);
1822  }
1823  return;
1824  case 1: {
1825  const int cols = core->dbg->regcols;
1826  p->cur -= cols > 0 ? cols : 4;
1827  return;
1828  }
1829  default:
1830  prevOpcode(core);
1831  return;
1832  }
1833  }
1834  if (p->row_offsets) {
1835  int delta, prev_sz;
1836 
1837  // FIXME: cache the current row
1838  row = rz_print_row_at_off(p, p->cur);
1839  roff = rz_print_rowoff(p, row);
1840  if (roff == UT32_MAX) {
1841  p->cur--;
1842  return;
1843  }
1844  prev_roff = row > 0 ? rz_print_rowoff(p, row - 1) : UT32_MAX;
1845  delta = p->cur - roff;
1846  if (prev_roff == UT32_MAX) {
1847  ut64 prev_addr = prevop_addr(core, core->offset + roff);
1848  if (prev_addr > core->offset) {
1849  prev_roff = 0;
1850  prev_sz = 1;
1851  } else {
1852  RzAsmOp op;
1853  prev_roff = 0;
1854  rz_core_seek(core, prev_addr, true);
1855  prev_sz = rz_asm_disassemble(core->rasm, &op,
1856  core->block, 32);
1857  }
1858  } else {
1859  prev_sz = roff - prev_roff;
1860  }
1861  int res = RZ_MIN(delta, prev_sz - 1);
1862  ut64 cur = prev_roff + res;
1863  if (cur == p->cur) {
1864  if (p->cur > 0) {
1865  p->cur--;
1866  }
1867  } else {
1868  p->cur = prev_roff + delta; // res;
1869  }
1870  } else {
1871  p->cur -= p->cols;
1872  }
1873 }
1874 
1875 static void cursor_left(RzCore *core, bool use_ocur) {
1876  if (PIDX == 2) {
1877  if (core->seltab == 1) {
1878  core->print->cur--;
1879  return;
1880  }
1881  }
1882  cursor_ocur(core, use_ocur);
1883  core->print->cur--;
1884 }
1885 
1886 static void cursor_right(RzCore *core, bool use_ocur) {
1887  if (PIDX == 2) {
1888  if (core->seltab == 1) {
1889  core->print->cur++;
1890  return;
1891  }
1892  }
1893  cursor_ocur(core, use_ocur);
1894  core->print->cur++;
1895 }
1896 
1897 static bool fix_cursor(RzCore *core) {
1898  RzPrint *p = core->print;
1899  int offscreen = (core->cons->rows - 3) * p->cols;
1900  bool res = false;
1901 
1902  if (!core->print->cur_enabled) {
1903  return false;
1904  }
1905  if (core->print->screen_bounds > 1) {
1906  bool off_is_visible = core->offset < core->print->screen_bounds;
1907  bool cur_is_visible = core->offset + p->cur < core->print->screen_bounds;
1908  bool is_close = core->offset + p->cur < core->print->screen_bounds + 32;
1909 
1910  if ((!cur_is_visible && !is_close) || (!cur_is_visible && p->cur == 0)) {
1911  // when the cursor is not visible and it's far from the
1912  // last visible byte, just seek there.
1913  rz_core_seek_delta(core, p->cur, false);
1914  reset_print_cur(p);
1915  } else if ((!cur_is_visible && is_close) || !off_is_visible) {
1916  RzAsmOp op;
1917  int sz = rz_asm_disassemble(core->rasm,
1918  &op, core->block, 32);
1919  if (sz < 1) {
1920  sz = 1;
1921  }
1922  rz_core_seek_delta(core, sz, false);
1923  p->cur = RZ_MAX(p->cur - sz, 0);
1924  if (p->ocur != -1) {
1925  p->ocur = RZ_MAX(p->ocur - sz, 0);
1926  }
1927  res |= off_is_visible;
1928  }
1929  } else if (core->print->cur >= offscreen) {
1930  rz_core_seek(core, core->offset + p->cols, true);
1931  p->cur -= p->cols;
1932  if (p->ocur != -1) {
1933  p->ocur -= p->cols;
1934  }
1935  }
1936 
1937  if (p->cur < 0) {
1938  int sz = p->cols;
1939  if (isDisasmPrint(core->printidx)) {
1940  sz = rz_core_visual_prevopsz(core, core->offset + p->cur);
1941  if (sz < 1) {
1942  sz = 1;
1943  }
1944  }
1945  rz_core_seek_delta(core, -sz, false);
1946  p->cur += sz;
1947  if (p->ocur != -1) {
1948  p->ocur += sz;
1949  }
1950  }
1951  return res;
1952 }
1953 
1954 static bool __ime = false;
1955 static int __nib = -1;
1956 
1957 static bool insert_mode_enabled(RzCore *core) {
1958  if (!__ime) {
1959  return false;
1960  }
1961  char ch = (ut8)rz_cons_readchar();
1962  if ((ut8)ch == KEY_ALTQ) {
1963  (void)rz_cons_readchar();
1964  __ime = false;
1965  return true;
1966  }
1967  char arrows = rz_cons_arrow_to_hjkl(ch);
1968  switch (ch) {
1969  case 127:
1970  core->print->cur = RZ_MAX(0, core->print->cur - 1);
1971  return true;
1972  case 9: // tab "tab" TAB
1973  core->print->col = core->print->col == 1 ? 2 : 1;
1974  break;
1975  }
1976  if (ch != 'h' && arrows == 'h') {
1977  core->print->cur = RZ_MAX(0, core->print->cur - 1);
1978  return true;
1979  } else if (ch != 'l' && arrows == 'l') {
1980  core->print->cur = core->print->cur + 1;
1981  return true;
1982  } else if (ch != 'j' && arrows == 'j') {
1983  cursor_nextrow(core, false);
1984  return true;
1985  } else if (ch != 'k' && arrows == 'k') {
1986  cursor_prevrow(core, false);
1987  return true;
1988  }
1989  if (core->print->col == 2) {
1990  /* ascii column */
1991  if (IS_PRINTABLE(ch)) {
1992  ut8 chs[2] = { ch, 0 };
1993  if (rz_core_write_at(core, core->offset + core->print->cur, chs, 1)) {
1994  core->print->cur++;
1995  }
1996  }
1997  return true;
1998  }
1999  ch = arrows;
2000  /* hex column */
2001  switch (ch) {
2002  case '0':
2003  case '1':
2004  case '2':
2005  case '3':
2006  case '4':
2007  case '5':
2008  case '6':
2009  case '7':
2010  case '8':
2011  case '9':
2012  case 'a':
2013  case 'b':
2014  case 'c':
2015  case 'd':
2016  case 'e':
2017  case 'f':
2018  if (__nib != -1) {
2019  char hexpair[3] = { __nib, ch, 0 };
2020  rz_core_write_hexpair(core, core->offset + core->print->cur, hexpair);
2021  core->print->cur++;
2022  __nib = -1;
2023  } else {
2024  __nib = ch;
2025  }
2026  break;
2027  case 'r': // "r -1"
2028  rz_core_file_resize_delta(core, -1);
2029  break;
2030  case 'R': // "r +1"
2031  rz_core_file_resize_delta(core, +1);
2032  break;
2033  case 'h':
2034  core->print->cur = RZ_MAX(0, core->print->cur - 1);
2035  break;
2036  case 'l':
2037  core->print->cur = core->print->cur + 1;
2038  break;
2039  case 'j':
2040  cursor_nextrow(core, false);
2041  break;
2042  case 'k':
2043  cursor_prevrow(core, false);
2044  break;
2045  case 'Q':
2046  case 'q':
2047  __ime = false;
2048  break;
2049  case '?':
2050  rz_cons_less_str("\nVisual Insert Mode:\n\n"
2051  " tab - toggle between ascii and hex columns\n"
2052  " q (or alt-q) - quit insert mode\n"
2053  "\nHex column:\n"
2054  " r - remove byte in cursor\n"
2055  " R - insert byte in cursor\n"
2056  " [0-9a-f] - insert hexpairs in hex column\n"
2057  " hjkl - move around\n"
2058  "\nAscii column:\n"
2059  " arrows - move around\n"
2060  " alt-q - quit insert mode\n",
2061  "?");
2062  break;
2063  }
2064  return true;
2065 }
2066 
2067 RZ_API void rz_core_visual_browse(RzCore *core, const char *input) {
2068  const char *browsemsg =
2069  "Browse stuff:\n"
2070  "-------------\n"
2071  " _ hud mode (V_)\n"
2072  " 1 bit editor (vd1)\n"
2073  " b blocks\n"
2074  " a analysis classes\n"
2075  " c classes\n"
2076  " C comments\n"
2077  " d debug traces\n"
2078  " e eval var configurations\n"
2079  " E esil debugger mode\n"
2080  " f flags\n"
2081  " F functions\n"
2082  " g graph\n"
2083  " h history\n"
2084  " i imports\n"
2085  " m maps\n"
2086  " M mountpoints\n"
2087  " p pids/threads\n"
2088  " q quit\n"
2089  " r ROP gadgets\n"
2090  " s symbols\n"
2091  " T themes\n"
2092  " v vars\n"
2093  " x xrefs\n"
2094  " X refs\n"
2095  " : run command\n";
2096  for (;;) {
2097  rz_cons_clear00();
2098  rz_cons_printf("%s\n", browsemsg);
2099  rz_cons_flush();
2100  char ch = 0;
2101  if (input && *input) {
2102  ch = *input;
2103  input++;
2104  } else {
2105  ch = rz_cons_readchar();
2106  }
2107  ch = rz_cons_arrow_to_hjkl(ch);
2108  switch (ch) {
2109  case '1':
2111  break;
2112  case 'g': // "vbg"
2113  if (rz_core_visual_view_graph(core)) {
2114  return;
2115  }
2116  break;
2117  case 'r': // "vbr"
2119  break;
2120  case 'f': // "vbf"
2122  break;
2123  case 'F': // "vbF"
2125  break;
2126  case 'd': // "vbd"
2128  break;
2129  case 'v': // "vbv"
2130  rz_core_visual_analysis(core, "v");
2131  break;
2132  case 'e': // "vbe"
2133  rz_core_visual_config(core);
2134  break;
2135  case 'E': // "vbe"
2136  rz_core_visual_esil(core);
2137  break;
2138  case 'c': // "vbc"
2139  rz_core_visual_classes(core);
2140  break;
2141  case 'a': // "vba"
2143  break;
2144  case 'C': // "vbC"
2146  break;
2147  case 'T': // "vbT"
2148  rz_core_cmd0(core, "eco $(eco~...)");
2149  break;
2150  case 'p':
2151  rz_core_cmd0(core, "dpt=$(dpt~[1-])");
2152  break;
2153  case 'b':
2154  rz_core_cmd0(core, "s $(afb~...)");
2155  break;
2156  case 'i':
2157  // XXX ii shows index first and iiq shows no offset :(
2158  rz_core_cmd0(core, "s $(ii~...)");
2159  break;
2160  case 's':
2161  rz_core_cmd0(core, "s $(isq~...)");
2162  break;
2163  case 'm':
2164  rz_core_cmd0(core, "s $(dm~...)");
2165  break;
2166  case 'x':
2167  rz_core_visual_xrefs(core, true, true);
2168  break;
2169  case 'X':
2170  rz_core_visual_xrefs(core, false, true);
2171  break;
2172  case 'h': // seek history
2173  rz_core_cmdf(core, "sh~...");
2174  break;
2175  case '_':
2177  break;
2178  case ':':
2180  break;
2181  case 127: // backspace
2182  case 'q':
2183  return;
2184  }
2185  }
2186 }
2187 
2188 #include "visual_tabs.inc"
2189 
2190 static bool isNumber(RzCore *core, int ch) {
2191  if (ch > '0' && ch <= '9') {
2192  return true;
2193  }
2194  if (core->print->cur_enabled) {
2195  return ch == '0';
2196  }
2197  return false;
2198 }
2199 
2200 static char numbuf[32] = { 0 };
2201 static int numbuf_i = 0;
2202 
2203 static void numbuf_append(int ch) {
2204  if (numbuf_i >= sizeof(numbuf) - 1) {
2205  numbuf_i = 0;
2206  }
2207  numbuf[numbuf_i++] = ch;
2208  numbuf[numbuf_i] = 0;
2209 }
2210 
2211 static int numbuf_pull(void) {
2212  int distance = 1;
2213  if (numbuf_i) {
2214  numbuf[numbuf_i] = 0;
2215  distance = atoi(numbuf);
2216  if (!distance) {
2217  distance = 1;
2218  }
2219  numbuf_i = 0;
2220  }
2221  return distance;
2222 }
2223 
2224 static bool canWrite(RzCore *core, ut64 addr) {
2225  if (rz_config_get_b(core->config, "io.cache")) {
2226  return true;
2227  }
2228  RzIOMap *map = rz_io_map_get(core->io, addr);
2229  return (map && (map->perm & RZ_PERM_W));
2230 }
2231 
2232 RZ_API int rz_core_visual_cmd(RzCore *core, const char *arg) {
2233  ut8 och = arg[0];
2234  RzAsmOp op;
2235  ut64 offset = core->offset;
2236  char buf[4096];
2237  const char *key_s;
2238  int i, cols = core->print->cols;
2239  int wheelspeed;
2240  int ch = och;
2241  if ((ut8)ch == KEY_ALTQ) {
2242  rz_cons_readchar();
2243  ch = 'q';
2244  }
2245  ch = rz_cons_arrow_to_hjkl(ch);
2246  ch = visual_nkey(core, ch);
2247  if (ch < 2) {
2248  int x, y;
2249  if (rz_cons_get_click(&x, &y)) {
2250  if (y == 1) {
2251  if (x < 15) {
2252  ch = '_';
2253  } else if (x < 20) {
2254  ch = 'p';
2255  } else if (x < 24) {
2256  ch = 9;
2257  }
2258  } else if (y == 2) {
2259  if (x < 2) {
2260  visual_closetab(core);
2261  } else if (x < 5) {
2262  visual_newtab(core);
2263  } else {
2264  visual_nexttab(core);
2265  }
2266  return 1;
2267  } else {
2268  ch = 0; //'c';
2269  }
2270  } else {
2271  return 1;
2272  }
2273  }
2274  if (rz_cons_singleton()->mouse_event) {
2275  wheelspeed = rz_config_get_i(core->config, "scr.wheel.speed");
2276  } else {
2277  wheelspeed = 1;
2278  }
2279 
2280  if (ch == 'l' && och == 6) {
2281  ch = 'J';
2282  } else if (ch == 'h' && och == 2) {
2283  ch = 'K';
2284  }
2285 
2286  // do we need hotkeys for data references? not only calls?
2287  // '0' is handled to seek at the beginning of the function
2288  // unless the cursor is set, then, the 0 is captured here
2289  if (isNumber(core, ch)) {
2290  // only in disasm and debug prints..
2291  if (isDisasmPrint(core->printidx)) {
2292  if (rz_config_get_b(core->config, "asm.hints") && (rz_config_get_b(core->config, "asm.hint.jmp") || rz_config_get_b(core->config, "asm.hint.lea") || rz_config_get_b(core->config, "asm.hint.emu") || rz_config_get_b(core->config, "asm.hint.call"))) {
2293  rz_core_visual_jump(core, ch);
2294  } else {
2295  numbuf_append(ch);
2296  }
2297  } else {
2298  numbuf_append(ch);
2299  }
2300  } else {
2301  switch (ch) {
2302 #if __WINDOWS__
2303  case 0xf5:
2304  SetWindow(81, 25);
2305  break;
2306  case 0xcf5:
2307  SetWindow(81, 40);
2308  break;
2309 #endif
2310  case 0x0d: // "enter" "\\n" "newline"
2311  {
2312  RzAnalysisOp *op;
2313  bool wheel = rz_config_get_b(core->config, "scr.wheel");
2314  if (wheel) {
2315  rz_cons_enable_mouse(true);
2316  }
2317  do {
2319  if (op) {
2320  if (op->type == RZ_ANALYSIS_OP_TYPE_JMP ||
2321  op->type == RZ_ANALYSIS_OP_TYPE_CJMP ||
2322  op->type == RZ_ANALYSIS_OP_TYPE_CALL ||
2323  op->type == RZ_ANALYSIS_OP_TYPE_CCALL) {
2324  if (core->print->cur_enabled) {
2325  int delta = RZ_ABS((st64)op->jump - (st64)offset);
2326  if (op->jump < core->offset || op->jump >= core->print->screen_bounds) {
2327  rz_core_visual_seek_animation(core, op->jump);
2328  core->print->cur = 0;
2329  } else {
2330  core->print->cur = delta;
2331  }
2332  } else {
2333  rz_core_visual_seek_animation(core, op->jump);
2334  }
2335  }
2336  }
2338  } while (--wheelspeed > 0);
2339  } break;
2340  case 'o': // tab TAB
2341  nextPrintFormat(core);
2342  break;
2343  case 'O': // tab TAB
2344  case 9: // tab TAB
2345  rz_core_visual_toggle_decompiler_disasm(core, false, true);
2346  if (splitView) {
2347  // this split view is kind of useless imho, we should kill it or merge it into tabs
2348  core->print->cur = 0;
2349  core->curtab = 0;
2350  core->seltab++;
2351  if (core->seltab > 1) {
2352  core->seltab = 0;
2353  }
2354  } else {
2355  if (core->print->cur_enabled) {
2356  core->curtab = 0;
2357  if (core->printidx == RZ_CORE_VISUAL_MODE_DB) {
2358  core->print->cur = 0;
2359  core->seltab++;
2360  if (core->seltab > 2) {
2361  core->seltab = 0;
2362  }
2363  } else {
2364  core->seltab = 0;
2365  ut64 f = rz_config_get_i(core->config, "diff.from");
2366  ut64 t = rz_config_get_i(core->config, "diff.to");
2367  if (f == t && f == 0) {
2368  core->print->col = core->print->col == 1 ? 2 : 1;
2369  }
2370  }
2371  } else {
2372  prevPrintFormat(core);
2373  }
2374  }
2375  break;
2376  case '&':
2377  rotateAsmBits(core);
2378  break;
2379  case 'a': {
2380  {
2381  ut64 addr = core->offset;
2382  if (PIDX == 2) {
2383  if (core->seltab == 0) {
2384  addr = rz_debug_reg_get(core->dbg, "SP");
2385  }
2386  }
2387  if (!canWrite(core, addr)) {
2388  rz_cons_printf("\nFile has been opened in read-only mode. Use -w flag, oo+ or e io.cache=true\n");
2390  return true;
2391  }
2392  }
2393  rz_cons_printf("Enter assembler opcodes separated with ';':\n");
2394  rz_core_visual_showcursor(core, true);
2395  rz_cons_flush();
2396  rz_cons_set_raw(false);
2397  strcpy(buf, "\"wa ");
2398  rz_line_set_prompt(":> ");
2399  rz_cons_enable_mouse(false);
2400  if (rz_cons_fgets(buf + 4, sizeof(buf) - 4, 0, NULL) < 0) {
2401  buf[0] = '\0';
2402  }
2403  strcat(buf, "\"");
2404  bool wheel = rz_config_get_b(core->config, "scr.wheel");
2405  if (wheel) {
2406  rz_cons_enable_mouse(true);
2407  }
2408  if (*buf) {
2409  if (core->print->cur_enabled) {
2410  int t = core->offset + core->print->cur;
2411  rz_core_seek(core, t, false);
2412  }
2413  rz_core_cmd(core, buf, true);
2414  if (core->print->cur_enabled) {
2415  int t = core->offset - core->print->cur;
2416  rz_core_seek(core, t, true);
2417  }
2418  }
2419  rz_core_visual_showcursor(core, false);
2420  rz_cons_set_raw(true);
2421  } break;
2422  case '=': { // TODO: edit
2423  rz_core_visual_showcursor(core, true);
2424  const char *buf = NULL;
2425 #define I core->cons
2426  const char *cmd = rz_config_get(core->config, "cmd.vprompt");
2427  rz_line_set_prompt("cmd.vprompt> ");
2428  I->line->contents = strdup(cmd);
2429  buf = rz_line_readline();
2430  I->line->contents = NULL;
2431  (void)rz_config_set(core->config, "cmd.vprompt", buf);
2432  rz_core_visual_showcursor(core, false);
2433  } break;
2434  case '|': { // TODO: edit
2435  rz_core_visual_showcursor(core, true);
2436  const char *buf = NULL;
2437 #define I core->cons
2438  const char *cmd = rz_config_get(core->config, "cmd.cprompt");
2439  rz_line_set_prompt("cmd.cprompt> ");
2440  I->line->contents = strdup(cmd);
2441  buf = rz_line_readline();
2442  if (buf && !strcmp(buf, "|")) {
2443  RZ_FREE(I->line->contents);
2444  core->print->cur_enabled = true;
2445  core->print->cur = 0;
2446  (void)rz_config_set(core->config, "cmd.cprompt", "p=e $r-2");
2447  } else {
2448  RZ_FREE(I->line->contents);
2449  (void)rz_config_set(core->config, "cmd.cprompt", buf ? buf : "");
2450  }
2451  rz_core_visual_showcursor(core, false);
2452  } break;
2453  case '!':
2455  break;
2456  case 'g':
2457  rz_core_visual_showcursor(core, true);
2458  rz_core_visual_offset(core);
2459  rz_core_visual_showcursor(core, false);
2460  break;
2461  case 'G':
2462  __core_visual_gogo(core, 'G');
2463  break;
2464  case 'A': {
2465  const int oce = core->print->cur_enabled;
2466  const int oco = core->print->ocur;
2467  const int occ = core->print->cur;
2468  ut64 off = oce ? core->offset + core->print->cur : core->offset;
2469  core->print->cur_enabled = 0;
2470  rz_cons_enable_mouse(false);
2471  rz_core_visual_asm(core, off);
2472  core->print->cur_enabled = oce;
2473  core->print->cur = occ;
2474  core->print->ocur = oco;
2475  if (rz_config_get_b(core->config, "scr.wheel")) {
2476  rz_cons_enable_mouse(true);
2477  }
2478  } break;
2479  case '\\':
2480  if (splitPtr == UT64_MAX) {
2481  splitPtr = core->offset;
2482  }
2483  splitView = !splitView;
2484  setcursor(core, splitView);
2485  break;
2486  case 'c':
2487  setcursor(core, !core->print->cur_enabled);
2488  break;
2489  case '$':
2490  if (core->print->cur_enabled) {
2491  rz_core_reg_set_by_role_or_name(core, "PC", core->offset + core->print->cur);
2492  } else {
2493  rz_core_reg_set_by_role_or_name(core, "PC", core->offset);
2494  }
2495  break;
2496  case '@':
2497  if (core->print->cur_enabled) {
2498  char buf[128];
2499  prompt_read("cursor at:", buf, sizeof(buf));
2500  core->print->cur = (st64)rz_num_math(core->num, buf);
2501  }
2502  break;
2503  case 'C':
2504  if (++color > 3) {
2505  color = 0;
2506  }
2507  rz_config_set_i(core->config, "scr.color", color);
2508  break;
2509  case 'd': {
2510  bool mouse_state = __holdMouseState(core);
2511  rz_core_visual_showcursor(core, true);
2512  int distance = numbuf_pull();
2513  rz_core_visual_define(core, arg + 1, distance - 1);
2514  rz_core_visual_showcursor(core, false);
2515  rz_cons_enable_mouse(mouse_state && rz_config_get_b(core->config, "scr.wheel"));
2516  } break;
2517  case 'D':
2518  setdiff(core);
2519  break;
2520  case 'f': {
2521  bool mouse_state = __holdMouseState(core);
2522  int range, min, max;
2523  char name[256], *n;
2524  rz_line_set_prompt("flag name: ");
2525  rz_core_visual_showcursor(core, true);
2526  if (rz_cons_fgets(name, sizeof(name), 0, NULL) >= 0 && *name) {
2527  n = name;
2528  rz_str_trim(n);
2529  if (core->print->ocur != -1) {
2530  min = RZ_MIN(core->print->cur, core->print->ocur);
2531  max = RZ_MAX(core->print->cur, core->print->ocur);
2532  } else {
2533  min = max = core->print->cur;
2534  }
2535  range = max - min + 1;
2536  if (!strcmp(n, "-")) {
2537  rz_flag_unset_off(core->flags, core->offset + core->print->cur);
2538  } else if (*n == '.') {
2539  RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, core->offset + min, 0);
2540  if (fcn) {
2541  if (n[1] == '-') {
2542  // Unset the local label (flag)
2544  } else {
2545  rz_analysis_function_set_label(fcn, n + 1, core->offset + min);
2546  }
2547  } else {
2548  eprintf("Cannot find function at 0x%08" PFMT64x "\n", core->offset + min);
2549  }
2550  } else if (*n == '-') {
2551  if (*n) {
2552  rz_flag_unset_name(core->flags, n + 1);
2553  }
2554  } else {
2555  if (range < 1) {
2556  range = 1;
2557  }
2558  if (*n) {
2559  rz_flag_set(core->flags, n, core->offset + min, range);
2560  }
2561  }
2562  }
2563  rz_cons_enable_mouse(mouse_state && rz_config_get_b(core->config, "scr.wheel"));
2564  rz_core_visual_showcursor(core, false);
2565  } break;
2566  case ',':
2567  visual_comma(core);
2568  break;
2569  case 't': {
2570  rz_cons_gotoxy(0, 0);
2571  if (core->visual.tabs) {
2572  rz_cons_printf("[tnp:=+-] ");
2573  } else {
2574  rz_cons_printf("[t] ");
2575  }
2576  rz_cons_flush();
2577  int ch = rz_cons_readchar();
2578  if (isdigit(ch)) {
2579  visual_nthtab(core, ch - '0' - 1);
2580  }
2581  switch (ch) {
2582  case 'h':
2583  case 'k':
2584  case 'p':
2585  visual_prevtab(core);
2586  break;
2587  case 9: // t-TAB
2588  case 'l':
2589  case 'j':
2590  case 'n':
2591  visual_nexttab(core);
2592  break;
2593  case '=':
2594  visual_tabname(core);
2595  break;
2596  case '-':
2597  visual_closetab(core);
2598  break;
2599  case ':': {
2600  RzCoreVisualTab *tab = visual_newtab(core);
2601  if (tab) {
2602  tab->name[0] = ':';
2603  rz_cons_fgets(tab->name + 1, sizeof(tab->name) - 1, 0, NULL);
2604  }
2605  } break;
2606  case '+':
2607  case 't':
2608  case 'a':
2609  visual_newtab(core);
2610  break;
2611  }
2612  } break;
2613  case 'T':
2614  visual_closetab(core);
2615  break;
2616  case 'n':
2617  rz_core_seek_next(core, rz_config_get(core->config, "scr.nkey"), true);
2618  break;
2619  case 'N':
2620  rz_core_seek_prev(core, rz_config_get(core->config, "scr.nkey"), true);
2621  break;
2622  case 'i':
2623  case 'I': {
2624  ut64 oaddr = core->offset;
2625  int delta = (core->print->ocur != -1) ? RZ_MIN(core->print->cur, core->print->ocur) : core->print->cur;
2626  ut64 addr = core->offset + delta;
2627  if (PIDX == 0) {
2628  if (strstr(printfmtSingle[0], "pxb")) {
2629  rz_core_visual_define(core, "1", 1);
2630  return true;
2631  }
2632  if (core->print->ocur == -1) {
2633  __ime = true;
2634  core->print->cur_enabled = true;
2635  return true;
2636  }
2637  } else if (PIDX == 2) {
2638  if (core->seltab == 0) {
2639  addr = rz_debug_reg_get(core->dbg, "SP") + delta;
2640  } else if (core->seltab == 1) {
2641  // regs, writing in here not implemented
2642  return true;
2643  }
2644  }
2645  if (!canWrite(core, addr)) {
2646  rz_cons_printf("\nFile has been opened in read-only mode. Use -w flag, oo+ or e io.cache=true\n");
2648  return true;
2649  }
2650  rz_core_visual_showcursor(core, true);
2651  rz_cons_flush();
2652  rz_cons_set_raw(0);
2653  if (ch == 'I') {
2654  strcpy(buf, "wow ");
2655  rz_line_set_prompt("insert hexpair block: ");
2656  if (rz_cons_fgets(buf + 4, sizeof(buf) - 4, 0, NULL) < 0) {
2657  buf[0] = '\0';
2658  }
2659  char *p = strdup(buf);
2660  int cur = core->print->cur;
2661  if (cur >= core->blocksize) {
2662  cur = core->print->cur - 1;
2663  }
2664  snprintf(buf, sizeof(buf), "%s @ $$0!%i", p,
2665  core->blocksize - cur);
2666  rz_core_cmd(core, buf, 0);
2667  free(p);
2668  break;
2669  }
2670  if (core->print->col == 2) {
2671  strcpy(buf, "\"w ");
2672  rz_line_set_prompt("insert string: ");
2673  if (rz_cons_fgets(buf + 3, sizeof(buf) - 3, 0, NULL) < 0) {
2674  buf[0] = '\0';
2675  }
2676  strcat(buf, "\"");
2677  } else {
2678  rz_line_set_prompt("insert hex: ");
2679  if (core->print->ocur != -1) {
2680  int bs = RZ_ABS(core->print->cur - core->print->ocur) + 1;
2681  core->blocksize = bs;
2682  strcpy(buf, "wow ");
2683  } else {
2684  strcpy(buf, "wx ");
2685  }
2686  if (rz_cons_fgets(buf + strlen(buf), sizeof(buf) - strlen(buf), 0, NULL) < 0) {
2687  buf[0] = '\0';
2688  }
2689  }
2690  if (core->print->cur_enabled) {
2691  rz_core_seek(core, addr, false);
2692  }
2693  rz_core_cmd(core, buf, 1);
2694  if (core->print->cur_enabled) {
2695  rz_core_seek(core, addr, true);
2696  }
2697  rz_cons_set_raw(1);
2698  rz_core_visual_showcursor(core, false);
2699  rz_core_seek(core, oaddr, true);
2700  } break;
2701  case 'R':
2702  if (rz_config_get_b(core->config, "scr.randpal")) {
2704  } else {
2705  rz_core_theme_nextpal(core, 'n');
2706  }
2707  break;
2708  case 'e':
2709  rz_core_visual_config(core);
2710  break;
2711  case '^': {
2712  RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
2713  if (fcn) {
2714  rz_core_seek_and_save(core, fcn->addr, false);
2715  } else {
2716  __core_visual_gogo(core, 'g');
2717  }
2718  } break;
2719  case 'E':
2720  rz_core_visual_colors(core);
2721  break;
2722  case 'x':
2723  rz_core_visual_xrefs(core, true, false);
2724  break;
2725  case 'X':
2726  rz_core_visual_xrefs(core, false, false);
2727  break;
2728  case 'r':
2729  // TODO: toggle shortcut hotkeys
2731  visual_refresh(core);
2732  break;
2733  case ' ':
2734  case 'V': {
2736  int ocolor = rz_config_get_i(core->config, "scr.color");
2737  if (!fun) {
2738  rz_cons_message("Not in a function. Type 'df' to define it here");
2739  break;
2740  } else if (rz_list_empty(fun->bbs)) {
2741  rz_cons_message("No basic blocks in this function. You may want to use 'afb+'.");
2742  break;
2743  }
2744  reset_print_cur(core->print);
2745  eprintf("\rRendering graph...");
2746  rz_core_visual_graph(core, NULL, NULL, true);
2747  rz_config_set_i(core->config, "scr.color", ocolor);
2748  } break;
2749  case 'v':
2751  break;
2752  case 'h':
2753  case 'l': {
2754  int distance = numbuf_pull();
2755  if (core->print->cur_enabled) {
2756  if (ch == 'h') {
2757  for (i = 0; i < distance; i++) {
2758  cursor_left(core, false);
2759  }
2760  } else {
2761  for (i = 0; i < distance; i++) {
2762  cursor_right(core, false);
2763  }
2764  }
2765  } else {
2766  if (ch == 'h') {
2767  distance = -distance;
2768  }
2769  rz_core_seek_delta(core, distance, false);
2770  }
2771  } break;
2772  case 'L':
2773  case 'H': {
2774  int distance = numbuf_pull();
2775  if (core->print->cur_enabled) {
2776  if (ch == 'H') {
2777  for (i = 0; i < distance; i++) {
2778  cursor_left(core, true);
2779  }
2780  } else {
2781  for (i = 0; i < distance; i++) {
2782  cursor_right(core, true);
2783  }
2784  }
2785  } else {
2786  if (ch == 'H') {
2787  distance = -distance;
2788  }
2789  rz_core_seek_delta(core, distance * 2, false);
2790  }
2791  } break;
2792  case 'j':
2793  if (core->print->cur_enabled) {
2794  int distance = numbuf_pull();
2795  for (i = 0; i < distance; i++) {
2796  cursor_nextrow(core, false);
2797  }
2798  } else {
2799  if (rz_config_get_b(core->config, "scr.wheel.nkey")) {
2800  int i, distance = numbuf_pull();
2801  if (distance < 1) {
2802  distance = 1;
2803  }
2804  for (i = 0; i < distance; i++) {
2805  const char *nkey = rz_config_get(core->config, "scr.nkey");
2806  rz_core_seek_next(core, nkey, true);
2807  }
2808  } else {
2809  int times = RZ_MAX(1, wheelspeed);
2810  // Check if we have a data annotation.
2811  ut64 amisize;
2812  RzAnalysisMetaItem *ami = rz_meta_get_at(core->analysis, core->offset, RZ_META_TYPE_DATA, &amisize);
2813  if (!ami) {
2814  ami = rz_meta_get_at(core->analysis, core->offset, RZ_META_TYPE_STRING, &amisize);
2815  }
2816  if (ami) {
2817  rz_core_seek_delta(core, amisize, false);
2818  } else {
2819  int distance = numbuf_pull();
2820  if (distance > 1) {
2821  times = distance;
2822  }
2823  while (times--) {
2824  if (isDisasmPrint(core->printidx)) {
2825  rz_core_visual_disasm_down(core, &op, &cols);
2826  } else if (!strcmp(__core_visual_print_command(core),
2827  "prc")) {
2828  cols = rz_config_get_i(core->config, "hex.cols");
2829  }
2830  rz_core_seek(core, core->offset + cols, true);
2831  }
2832  }
2833  }
2834  }
2835  break;
2836  case 'J':
2837  if (core->print->cur_enabled) {
2838  int distance = numbuf_pull();
2839  for (i = 0; i < distance; i++) {
2840  cursor_nextrow(core, true);
2841  }
2842  } else {
2843  if (core->print->screen_bounds > 1 && core->print->screen_bounds >= core->offset) {
2844  ut64 addr = UT64_MAX;
2845  if (isDisasmPrint(core->printidx)) {
2846  if (core->print->screen_bounds == core->offset) {
2847  rz_asm_disassemble(core->rasm, &op, core->block, 32);
2848  }
2849  if (addr == core->offset || addr == UT64_MAX) {
2850  addr = core->offset + 48;
2851  }
2852  } else {
2853  int h;
2854  int hexCols = rz_config_get_i(core->config, "hex.cols");
2855  if (hexCols < 1) {
2856  hexCols = 16;
2857  }
2858  (void)rz_cons_get_size(&h);
2859  int delta = hexCols * (h / 4);
2860  addr = core->offset + delta;
2861  }
2862  rz_core_seek(core, addr, true);
2863  } else {
2864  rz_core_seek(core, core->offset + obs, true);
2865  }
2866  }
2867  break;
2868  case 'k':
2869  if (core->print->cur_enabled) {
2870  int distance = numbuf_pull();
2871  for (i = 0; i < distance; i++) {
2872  cursor_prevrow(core, false);
2873  }
2874  } else {
2875  if (rz_config_get_b(core->config, "scr.wheel.nkey")) {
2876  int i, distance = numbuf_pull();
2877  if (distance < 1) {
2878  distance = 1;
2879  }
2880  for (i = 0; i < distance; i++) {
2881  rz_core_seek_prev(core, rz_config_get(core->config, "scr.nkey"), true);
2882  }
2883  } else {
2884  int times = wheelspeed;
2885  if (times < 1) {
2886  times = 1;
2887  }
2888  int distance = numbuf_pull();
2889  if (distance > 1) {
2890  times = distance;
2891  }
2892  while (times--) {
2893  if (isDisasmPrint(core->printidx)) {
2894  rz_core_visual_disasm_up(core, &cols);
2895  } else if (!strcmp(__core_visual_print_command(core), "prc")) {
2896  cols = rz_config_get_i(core->config, "hex.cols");
2897  }
2898  rz_core_seek_delta(core, -cols, false);
2899  }
2900  }
2901  }
2902  break;
2903  case 'K':
2904  if (core->print->cur_enabled) {
2905  int distance = numbuf_pull();
2906  for (i = 0; i < distance; i++) {
2907  cursor_prevrow(core, true);
2908  }
2909  } else {
2910  if (core->print->screen_bounds > 1 && core->print->screen_bounds > core->offset) {
2911  int delta = (core->print->screen_bounds - core->offset);
2912  if (core->offset >= delta) {
2913  rz_core_seek(core, core->offset - delta, true);
2914  } else {
2915  rz_core_seek(core, 0, true);
2916  }
2917  } else {
2918  ut64 at = (core->offset > obs) ? core->offset - obs : 0;
2919  if (core->offset > obs) {
2920  rz_core_seek(core, at, true);
2921  } else {
2922  rz_core_seek(core, 0, true);
2923  }
2924  }
2925  }
2926  break;
2927  case '[':
2928  // comments column
2929  if (core->print->cur_enabled &&
2930  (core->printidx == RZ_CORE_VISUAL_MODE_PD ||
2931  (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->seltab == 2))) {
2932  int cmtcol = rz_config_get_i(core->config, "asm.cmt.col");
2933  if (cmtcol > 2) {
2934  rz_config_set_i(core->config, "asm.cmt.col", cmtcol - 2);
2935  }
2936  }
2937  // hex column
2938  if ((core->printidx != RZ_CORE_VISUAL_MODE_PD && core->printidx != RZ_CORE_VISUAL_MODE_DB) ||
2939  (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->seltab != 2)) {
2940  int scrcols = rz_config_get_i(core->config, "hex.cols");
2941  if (scrcols > 1) {
2942  rz_config_set_i(core->config, "hex.cols", scrcols - 1);
2943  }
2944  }
2945  break;
2946  case ']':
2947  // comments column
2948  if (core->print->cur_enabled &&
2949  (core->printidx == RZ_CORE_VISUAL_MODE_PD ||
2950  (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->seltab == 2))) {
2951  int cmtcol = rz_config_get_i(core->config, "asm.cmt.col");
2952  rz_config_set_i(core->config, "asm.cmt.col", cmtcol + 2);
2953  }
2954  // hex column
2955  if ((core->printidx != RZ_CORE_VISUAL_MODE_PD && core->printidx != RZ_CORE_VISUAL_MODE_DB) ||
2956  (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->seltab != 2)) {
2957  int scrcols = rz_config_get_i(core->config, "hex.cols");
2958  rz_config_set_i(core->config, "hex.cols", scrcols + 1);
2959  }
2960  break;
2961  case 's':
2962  key_s = rz_config_get(core->config, "key.s");
2963  if (key_s && *key_s) {
2964  rz_core_cmd0(core, key_s);
2965  } else {
2967  }
2968  break;
2969  case 'S':
2970  key_s = rz_config_get(core->config, "key.S");
2971  if (key_s && *key_s) {
2972  rz_core_cmd0(core, key_s);
2973  } else {
2975  }
2976  break;
2977  case '"':
2978  rz_config_toggle(core->config, "scr.dumpcols");
2979  break;
2980  case 'p':
2981  rz_core_visual_toggle_decompiler_disasm(core, false, true);
2982  if (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->print->cur_enabled) {
2983  nextPrintCommand();
2984  } else {
2985  setprintmode(core, 1);
2986  }
2987  break;
2988  case 'P':
2989  if (core->printidx == RZ_CORE_VISUAL_MODE_DB && core->print->cur_enabled) {
2990  prevPrintCommand();
2991  } else {
2992  setprintmode(core, -1);
2993  }
2994  break;
2995  case '%':
2996  if (core->print->cur_enabled) {
2997  findPair(core);
2998  } else {
2999  /* do nothing? */
3001  if (autoblocksize) {
3002  obs = core->blocksize;
3003  } else {
3004  rz_core_block_size(core, obs);
3005  }
3006  rz_cons_clear();
3007  }
3008  break;
3009  case 'w':
3010  findNextWord(core);
3011  break;
3012  case 'W':
3013  findPrevWord(core);
3014  break;
3015  case 'm': {
3016  rz_cons_gotoxy(0, 0);
3017  rz_cons_printf(RZ_CONS_CLEAR_LINE "Set shortcut key for 0x%" PFMT64x "\n", core->offset);
3018  rz_cons_flush();
3019  int ch = rz_cons_readchar();
3020  rz_core_visual_mark(core, ch);
3021  } break;
3022  case 'M': {
3023  rz_cons_gotoxy(0, 0);
3024  if (rz_core_visual_mark_dump(core)) {
3025  rz_cons_printf(RZ_CONS_CLEAR_LINE "Remove a shortcut key from the list\n");
3026  rz_cons_flush();
3027  int ch = rz_cons_readchar();
3028  rz_core_visual_mark_del(core, ch);
3029  }
3030  } break;
3031  case '\'': {
3032  rz_cons_gotoxy(0, 0);
3033  if (rz_core_visual_mark_dump(core)) {
3034  rz_cons_flush();
3035  int ch = rz_cons_readchar();
3036  rz_core_visual_mark_seek(core, ch);
3037  }
3038  } break;
3039  case 'y':
3040  if (core->print->ocur == -1) {
3041  rz_core_yank(core, core->offset + core->print->cur, 1);
3042  } else {
3043  rz_core_yank(core, core->offset + ((core->print->ocur < core->print->cur) ? core->print->ocur : core->print->cur), RZ_ABS(core->print->cur - core->print->ocur) + 1);
3044  }
3045  break;
3046  case 'Y':
3047  if (!core->yank_buf) {
3048  rz_cons_strcat("Cannot paste, clipboard is empty.\n");
3049  rz_cons_flush();
3051  rz_cons_clear00();
3052  } else {
3053  rz_core_yank_paste(core, core->offset + core->print->cur, 0);
3054  }
3055  break;
3056  case '0': {
3058  if (fcn) {
3059  rz_core_seek_and_save(core, fcn->addr, true);
3060  }
3061  } break;
3062  case '-':
3063  if (core->print->cur_enabled) {
3064  if (core->printidx == RZ_CORE_VISUAL_MODE_DB) {
3065  if (!core->seltab) {
3066  // stack view
3067  int w = rz_config_get_i(core->config, "hex.cols");
3068  rz_config_set_i(core->config, "stack.size",
3069  rz_config_get_i(core->config, "stack.size") - w);
3070  }
3071  } else {
3072  if (core->print->ocur == -1) {
3073  sprintf(buf, "wos 01 @ $$+%i @!1", core->print->cur);
3074  } else {
3075  sprintf(buf, "wos 01 @ $$+%i @!%i", core->print->cur < core->print->ocur ? core->print->cur : core->print->ocur,
3076  RZ_ABS(core->print->ocur - core->print->cur) + 1);
3077  }
3078  rz_core_cmd(core, buf, 0);
3079  }
3080  } else {
3081  if (!autoblocksize) {
3082  rz_core_block_size(core, core->blocksize - 1);
3083  }
3084  }
3085  break;
3086  case '+':
3087  if (core->print->cur_enabled) {
3088  if (core->printidx == RZ_CORE_VISUAL_MODE_DB) {
3089  if (!core->seltab) {
3090  // stack view
3091  int w = rz_config_get_i(core->config, "hex.cols");
3092  rz_config_set_i(core->config, "stack.size",
3093  rz_config_get_i(core->config, "stack.size") + w);
3094  }
3095  } else {
3096  if (core->print->ocur == -1) {
3097  sprintf(buf, "woa 01 @ $$+%i @!1", core->print->cur);
3098  } else {
3099  sprintf(buf, "woa 01 @ $$+%i @!%i", core->print->cur < core->print->ocur ? core->print->cur : core->print->ocur,
3100  RZ_ABS(core->print->ocur - core->print->cur) + 1);
3101  }
3102  rz_core_cmd(core, buf, 0);
3103  }
3104  } else {
3105  if (!autoblocksize) {
3106  rz_core_block_size(core, core->blocksize + 1);
3107  }
3108  }
3109  break;
3110  case '/': {
3111  bool mouse_state = __holdMouseState(core);
3112  if (core->print->cur_enabled) {
3113  visual_search(core);
3114  } else {
3115  if (autoblocksize) {
3116  rz_core_cmd0(core, "?i highlight;e scr.highlight=`yp`");
3117  } else {
3118  rz_core_block_size(core, core->blocksize - cols);
3119  }
3120  }
3121  rz_cons_enable_mouse(mouse_state && rz_config_get_i(core->config, "scr.wheel"));
3122  } break;
3123  case ')':
3124  rotateAsmemu(core);
3125  break;
3126  case '#':
3127  if (core->printidx == 1) {
3128  rz_core_visual_toggle_decompiler_disasm(core, false, false);
3129  } else {
3130  // do nothing for now :?, px vs pxa?
3131  }
3132  break;
3133  case '*':
3134  if (core->print->cur_enabled) {
3135  rz_core_reg_set_by_role_or_name(core, "PC", core->offset + core->print->cur);
3136  } else if (!autoblocksize) {
3137  rz_core_block_size(core, core->blocksize + cols);
3138  }
3139  break;
3140  case '>':
3141  if (core->print->cur_enabled) {
3142  if (core->print->ocur == -1) {
3143  eprintf("No range selected. Use HJKL.\n");
3145  break;
3146  }
3147  char buf[128];
3148  // TODO autocomplete filenames
3149  prompt_read("dump to file: ", buf, sizeof(buf));
3150  if (buf[0]) {
3151  ut64 from = core->offset + core->print->ocur;
3152  ut64 size = RZ_ABS(core->print->cur - core->print->ocur) + 1;
3153  rz_core_dump(core, buf, from, size, false);
3154  }
3155  } else {
3156  rz_core_seek_and_save(core, core->offset + core->blocksize, false);
3157  }
3158  break;
3159  case '<': // "V<"
3160  if (core->print->cur_enabled) {
3161  char buf[128];
3162  // TODO autocomplete filenames
3163  prompt_read("load from file: ", buf, sizeof(buf));
3164  if (buf[0]) {
3165  size_t sz;
3166  char *data = rz_file_slurp(buf, &sz);
3167  if (data) {
3168  int cur;
3169  if (core->print->ocur != -1) {
3170  cur = RZ_MIN(core->print->cur, core->print->ocur);
3171  } else {
3172  cur = core->print->cur;
3173  }
3174  ut64 from = core->offset + cur;
3175  ut64 size = RZ_ABS(core->print->cur - core->print->ocur) + 1;
3176  ut64 s = RZ_MIN(size, (ut64)sz);
3177  rz_io_write_at(core->io, from, (const ut8 *)data, s);
3178  }
3179  }
3180  } else {
3181  rz_core_seek_and_save(core, core->offset - core->blocksize, false);
3182  }
3183  break;
3184  case '.': // "V."
3185  if (core->print->cur_enabled) {
3186  rz_config_set_i(core->config, "stack.delta", 0);
3187  rz_core_seek_and_save(core, core->offset + core->print->cur, true);
3188  core->print->cur = 0;
3189  } else {
3190  ut64 addr = rz_debug_reg_get(core->dbg, "PC");
3191  if (addr && addr != UT64_MAX) {
3192  rz_core_seek_and_save(core, addr, true);
3193  rz_core_analysis_set_reg(core, "PC", addr);
3194  } else {
3195  ut64 entry = rz_num_get(core->num, "entry0");
3196  if (!entry || entry == UT64_MAX) {
3197  RzBinObject *o = rz_bin_cur_object(core->bin);
3198  RzBinSection *s = o ? rz_bin_get_section_at(o, addr, core->io->va) : NULL;
3199  if (s) {
3200  entry = s->vaddr;
3201  } else {
3202  RzPVector *maps = rz_io_maps(core->io);
3204  if (map) {
3205  entry = map->itv.addr;
3206  } else {
3207  entry = rz_config_get_i(core->config, "bin.baddr");
3208  }
3210  }
3211  }
3212  if (entry != UT64_MAX) {
3213  rz_core_seek_and_save(core, entry, true);
3214  }
3215  }
3216  }
3217  break;
3218  case ':':
3220  break;
3221  case '_':
3223  break;
3224  case ';':
3225  rz_cons_gotoxy(0, 0);
3226  add_comment(core, core->offset, "Enter a comment: ('-' to remove, '!' to use cfg.editor)\n");
3227  break;
3228  case 'b':
3229  rz_core_visual_browse(core, arg + 1);
3230  break;
3231  case 'B': {
3232  ut64 addr = core->print->cur_enabled ? core->offset + core->print->cur : core->offset;
3234  } break;
3235  case 'u':
3237  break;
3238  case 'U':
3240  break;
3241  case '?':
3242  if (visual_help(core) == '?') {
3243  rz_core_visual_hud(core);
3244  }
3245  break;
3246  case 0x1b:
3247  case 'q':
3248  case 'Q':
3249  setcursor(core, false);
3250  return false;
3251  }
3252  numbuf_i = 0;
3253  }
3254  rz_core_block_read(core);
3255  return true;
3256 }
3257 
3258 static void visual_flagzone(RzCore *core) {
3259  const char *a, *b;
3260  int a_len = 0;
3261  int w = rz_cons_get_size(NULL);
3262  rz_flag_zone_around(core->flags, core->offset, &a, &b);
3263  if (a) {
3264  rz_cons_printf("[<< %s]", a);
3265  a_len = strlen(a) + 4;
3266  }
3267  int padsize = (w / 2) - a_len;
3268  int title_size = 12;
3269  if (a || b) {
3270  char *title = rz_str_newf("[ 0x%08" PFMT64x " ]", core->offset);
3271  title_size = strlen(title);
3272  padsize -= strlen(title) / 2;
3273  const char *halfpad = rz_str_pad(' ', padsize);
3274  rz_cons_printf("%s%s", halfpad, title);
3275  free(title);
3276  }
3277  if (b) {
3278  padsize = (w / 2) - title_size - strlen(b) - 4;
3279  const char *halfpad = padsize > 1 ? rz_str_pad(' ', padsize) : "";
3280  rz_cons_printf("%s[%s >>]", halfpad, b);
3281  }
3282  if (a || b) {
3283  rz_cons_newline();
3284  }
3285 }
3286 
3288  bool showDelta = rz_config_get_b(core->config, "scr.slow");
3289  static ut64 oldpc = 0;
3290  const char *BEGIN = core->cons->context->pal.prompt;
3291  const char *filename;
3292  char pos[512], bar[512], pcs[32];
3293  if (!oldpc) {
3294  oldpc = rz_debug_reg_get(core->dbg, "PC");
3295  }
3296  /* automatic block size */
3297  int pc, hexcols = rz_config_get_i(core->config, "hex.cols");
3298  if (autoblocksize) {
3299  switch (core->printidx) {
3300  case RZ_CORE_VISUAL_MODE_PX: // x
3301  if (currentFormat == 3 || currentFormat == 9 || currentFormat == 5) { // prx
3302  rz_core_block_size(core, (int)(core->cons->rows * hexcols * 4));
3303  } else if ((RZ_ABS(hexMode) % 3) == 0) { // prx
3304  rz_core_block_size(core, (int)(core->cons->rows * hexcols));
3305  } else {
3306  rz_core_block_size(core, (int)(core->cons->rows * hexcols * 2));
3307  }
3308  break;
3311  rz_core_block_size(core, (int)(core->cons->rows * hexcols * 2));
3312  break;
3313  case RZ_CORE_VISUAL_MODE_PD: // pd
3314  case RZ_CORE_VISUAL_MODE_DB: // pd+dbg
3315  {
3316  int bsize = core->cons->rows * 5;
3317 
3318  if (core->print->screen_bounds > 1) {
3319  // estimate new blocksize with the size of the last
3320  // printed instructions
3321  int new_sz = core->print->screen_bounds - core->offset + 32;
3322  new_sz = RZ_MIN(new_sz, 16 * 1024);
3323  if (new_sz > bsize) {
3324  bsize = new_sz;
3325  }
3326  }
3327  rz_core_block_size(core, bsize);
3328  break;
3329  }
3330  }
3331  }
3332  if (rz_config_get_i(core->config, "scr.scrollbar") == 2) {
3333  visual_flagzone(core);
3334  }
3335  if (rz_config_get_b(core->config, "cfg.debug")) {
3336  ut64 curpc = rz_debug_reg_get(core->dbg, "PC");
3337  if (curpc && curpc != UT64_MAX && curpc != oldpc) {
3338  // check dbg.follow here
3339  int follow = (int)(st64)rz_config_get_i(core->config, "dbg.follow");
3340  if (follow > 0) {
3341  if ((curpc < core->offset) || (curpc > (core->offset + follow))) {
3342  rz_core_seek(core, curpc, true);
3343  }
3344  } else if (follow < 0) {
3345  rz_core_seek(core, curpc + follow, true);
3346  }
3348  oldpc = curpc;
3349  }
3350  }
3351  RzIOMap *map = rz_io_map_get(core->io, core->offset);
3352  RzIODesc *desc = map
3353  ? rz_io_desc_get(core->io, map->fd)
3354  : core->file ? rz_io_desc_get(core->io, core->file->fd)
3355  : NULL;
3356  filename = desc ? desc->name : "";
3357 
3358  { /* get flag with delta */
3359  ut64 addr = core->offset + (core->print->cur_enabled ? core->print->cur : 0);
3360  /* TODO: we need a helper into rz_flags to do that */
3361  RzFlagItem *f = NULL;
3362  if (rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS)) {
3363  f = rz_flag_get_at(core->flags, addr, showDelta);
3364  rz_flag_space_pop(core->flags);
3365  }
3366  if (!f) {
3367  f = rz_flag_get_at(core->flags, addr, showDelta);
3368  }
3369  if (f) {
3370  if (f->offset == addr || !f->offset) {
3371  snprintf(pos, sizeof(pos), "@ %s", f->name);
3372  } else {
3373  snprintf(pos, sizeof(pos), "@ %s+%d # 0x%" PFMT64x,
3374  f->name, (int)(addr - f->offset), addr);
3375  }
3376  } else {
3378  if (fcn) {
3379  int delta = addr - fcn->addr;
3380  if (delta > 0) {
3381  snprintf(pos, sizeof(pos), "@ %s+%d", fcn->name, delta);
3382  } else if (delta < 0) {
3383  snprintf(pos, sizeof(pos), "@ %s%d", fcn->name, delta);
3384  } else {
3385  snprintf(pos, sizeof(pos), "@ %s", fcn->name);
3386  }
3387  } else {
3388  pos[0] = 0;
3389  }
3390  }
3391  }
3392 
3393  if (core->print->cur < 0) {
3394  core->print->cur = 0;
3395  }
3396 
3397  if (color) {
3398  rz_cons_strcat(BEGIN);
3399  }
3400  const char *cmd_visual = rz_config_get(core->config, "cmd.visual");
3401  if (cmd_visual && *cmd_visual) {
3402  rz_str_ncpy(bar, cmd_visual, sizeof(bar) - 1);
3403  bar[10] = '.'; // chop cmdfmt
3404  bar[11] = '.'; // chop cmdfmt
3405  bar[12] = 0; // chop cmdfmt
3406  } else {
3407  const char *cmd = __core_visual_print_command(core);
3408  if (cmd) {
3409  rz_str_ncpy(bar, cmd, sizeof(bar) - 1);
3410  bar[10] = '.'; // chop cmdfmt
3411  bar[11] = '.'; // chop cmdfmt
3412  bar[12] = 0; // chop cmdfmt
3413  }
3414  }
3415  {
3416  ut64 sz = rz_io_size(core->io);
3417  ut64 pa = core->offset;
3418  {
3419  RzIOMap *map = rz_io_map_get(core->io, core->offset);
3420  if (map) {
3421  pa = map->delta;
3422  }
3423  }
3424  if (sz == UT64_MAX) {
3425  pcs[0] = 0;
3426  } else {
3427  if (!sz || pa > sz) {
3428  pc = 0;
3429  } else {
3430  pc = (pa * 100) / sz;
3431  }
3432  sprintf(pcs, "%d%% ", pc);
3433  }
3434  }
3435  {
3436  char *title;
3437  char *address = (core->print->wide_offsets && core->dbg->bits & RZ_SYS_BITS_64)
3438  ? rz_str_newf("0x%016" PFMT64x, core->offset)
3439  : rz_str_newf("0x%08" PFMT64x, core->offset);
3440  if (__ime) {
3441  title = rz_str_newf("[%s + %d> * INSERT MODE *\n",
3442  address, core->print->cur);
3443  } else {
3444  char pm[32] = "[XADVC]";
3445  int i;
3446  for (i = 0; i < 6; i++) {
3447  if (core->printidx == i) {
3448  pm[i + 1] = toupper(pm[i + 1]);
3449  } else {
3450  pm[i + 1] = tolower(pm[i + 1]);
3451  }
3452  }
3453  if (core->print->cur_enabled) {
3454  if (core->print->ocur == -1) {
3455  title = rz_str_newf("[%s *0x%08" PFMT64x " %s%d ($$+0x%x)]> %s %s\n",
3456  address, core->offset + core->print->cur,
3457  pm, currentFormat, core->print->cur,
3458  bar, pos);
3459  } else {
3460  title = rz_str_newf("[%s 0x%08" PFMT64x " %s%d [0x%x..0x%x] %d]> %s %s\n",
3461  address, core->offset + core->print->cur,
3462  pm, currentFormat, core->print->ocur, core->print->cur,
3463  RZ_ABS(core->print->cur - core->print->ocur) + 1,
3464  bar, pos);
3465  }
3466  } else {
3467  title = rz_str_newf("[%s %s%d %s%d %s]> %s %s\n",
3468  address, pm, currentFormat, pcs, core->blocksize, filename, bar, pos);
3469  }
3470  }
3471  const int tabsCount = __core_visual_tab_count(core);
3472  if (tabsCount > 0) {
3473  const char *kolor = core->cons->context->pal.prompt;
3474  char *tabstring = __core_visual_tab_string(core, kolor);
3475  if (tabstring) {
3476  title = rz_str_append(title, tabstring);
3477  free(tabstring);
3478  }
3479 #if 0
3480  // TODO: add an option to show this tab mode instead?
3481  const int curTab = core->visual.tab;
3482  rz_cons_printf ("[");
3483  int i;
3484  for (i = 0; i < tabsCount; i++) {
3485  if (i == curTab) {
3486  rz_cons_printf ("%d", curTab + 1);
3487  } else {
3488  rz_cons_printf (".");
3489  }
3490  }
3491  rz_cons_printf ("]");
3492  rz_cons_printf ("[tab:%d/%d]", core->visual.tab, tabsCount);
3493 #endif
3494  }
3495  rz_cons_print(title);
3496  free(title);
3497  free(address);
3498  }
3499  if (color) {
3501  }
3502 }
3503 
3504 static int visual_responsive(RzCore *core) {
3505  int h, w = rz_cons_get_size(&h);
3506  if (rz_config_get_b(core->config, "scr.responsive")) {
3507  if (w < 110) {
3508  rz_config_set_b(core->config, "asm.cmt.right", false);
3509  } else {
3510  rz_config_set_b(core->config, "asm.cmt.right", true);
3511  }
3512  if (w < 68) {
3513  rz_config_set_i(core->config, "hex.cols", (int)(w / 5.2));
3514  } else {
3515  rz_config_set_i(core->config, "hex.cols", 16);
3516  }
3517  if (w < 25) {
3518  rz_config_set_b(core->config, "asm.offset", false);
3519  } else {
3520  rz_config_set_b(core->config, "asm.offset", true);
3521  }
3522  if (w > 80) {
3523  rz_config_set_i(core->config, "asm.lines.width", 14);
3524  rz_config_set_i(core->config, "asm.lines.width", w - (int)(w / 1.2));
3525  rz_config_set_i(core->config, "asm.cmt.col", w - (int)(w / 2.5));
3526  } else {
3527  rz_config_set_i(core->config, "asm.lines.width", 7);
3528  }
3529  if (w < 70) {
3530  rz_config_set_i(core->config, "asm.lines.width", 1);
3531  rz_config_set_b(core->config, "asm.bytes", false);
3532  } else {
3533  rz_config_set_b(core->config, "asm.bytes", true);
3534  }
3535  }
3536  return w;
3537 }
3538 
3539 // TODO: use colors
3540 // TODO: find better name
3542  int i, h, w = rz_cons_get_size(&h);
3543 
3544  int scrollbar = rz_config_get_i(core->config, "scr.scrollbar");
3545  if (scrollbar == 2) {
3546  // already handled by the visual_flagzone()
3547  return;
3548  }
3549  if (scrollbar > 2) {
3551  return;
3552  }
3553 
3554  if (w < 10 || h < 3) {
3555  return;
3556  }
3557  ut64 from = 0;
3558  ut64 to = UT64_MAX;
3559  if (rz_config_get_b(core->config, "cfg.debug")) {
3560  from = rz_num_math(core->num, "$D");
3561  to = rz_num_math(core->num, "$D+$DD");
3562  } else if (rz_config_get_b(core->config, "io.va")) {
3563  from = rz_num_math(core->num, "$S");
3564  to = rz_num_math(core->num, "$S+$SS");
3565  } else {
3566  to = rz_num_math(core->num, "$s");
3567  }
3568  char *s = rz_str_newf("[0x%08" PFMT64x "]", from);
3569  rz_cons_gotoxy(w - strlen(s) + 1, 2);
3570  rz_cons_strcat(s);
3571  free(s);
3572 
3573  ut64 block = (to - from) / h;
3574 
3575  RzList *words = rz_flag_zone_barlist(core->flags, from, block, h);
3576 
3577  bool hadMatch = false;
3578  for (i = 0; i < h; i++) {
3579  const char *word = rz_list_pop_head(words);
3580  if (word && *word) {
3581  rz_cons_gotoxy(w - strlen(word) - 1, i + 3);
3582  rz_cons_printf("%s>", word);
3583  }
3584  rz_cons_gotoxy(w, i + 3);
3585  if (hadMatch) {
3586  rz_cons_printf("|");
3587  } else {
3588  ut64 cur = from + (block * i);
3589  ut64 nex = from + (block * (i + 1));
3590  if (RZ_BETWEEN(cur, core->offset, nex)) {
3592  hadMatch = true;
3593  } else {
3594  rz_cons_printf("|");
3595  }
3596  }
3597  }
3598  s = rz_str_newf("[0x%08" PFMT64x "]", to);
3599  if (s) {
3600  rz_cons_gotoxy(w - strlen(s) + 1, h + 1);
3601  rz_cons_strcat(s);
3602  free(s);
3603  }
3604  rz_list_free(words);
3605  rz_cons_flush();
3606 }
3607 
3609  int i, h, w = rz_cons_get_size(&h);
3610 
3611  if (w < 10 || h < 4) {
3612  return;
3613  }
3614  ut64 from = 0;
3615  ut64 to = UT64_MAX;
3616  if (rz_config_get_b(core->config, "cfg.debug")) {
3617  from = rz_num_math(core->num, "$D");
3618  to = rz_num_math(core->num, "$D+$DD");
3619  } else if (rz_config_get_b(core->config, "io.va")) {
3620  from = rz_num_math(core->num, "$S");
3621  to = rz_num_math(core->num, "$S+$SS");
3622  } else {
3623  to = rz_num_math(core->num, "$s");
3624  }
3625  char *s = rz_str_newf("[0x%08" PFMT64x "]", from);
3626  int slen = strlen(s) + 1;
3627  rz_cons_gotoxy(0, h + 1);
3628  rz_cons_strcat(s);
3629  free(s);
3630 
3631  int linew = (w - (slen * 2)) + 1;
3632  ut64 block = (to - from) / linew;
3633 
3634  RzList *words = rz_flag_zone_barlist(core->flags, from, block, h);
3635 
3636  bool hadMatch = false;
3637  for (i = 0; i < linew + 1; i++) {
3638  rz_cons_gotoxy(i + slen, h + 1);
3639  if (hadMatch) {
3640  rz_cons_strcat("-");
3641  } else {
3642  ut64 cur = from + (block * i);
3643  ut64 nex = from + (block * (i + 2));
3644  if (RZ_BETWEEN(cur, core->offset, nex)) {
3646  hadMatch = true;
3647  } else {
3648  rz_cons_strcat("-");
3649  }
3650  }
3651  }
3652  for (i = 0; i < linew; i++) {
3653  const char *word = rz_list_pop_head(words);
3654  if (word && *word) {
3655  ut64 cur = from + (block * i);
3656  ut64 nex = from + (block * (i + strlen(word) + 1));
3657  rz_cons_gotoxy(i + slen - 1, h);
3658  if (RZ_BETWEEN(cur, core->offset, nex)) {
3659  rz_cons_printf(Color_INVERT "{%s}" Color_RESET, word);
3660  } else {
3661  rz_cons_printf("{%s}", word);
3662  }
3663  }
3664  }
3665  s = rz_str_newf("[0x%08" PFMT64x "]", to);
3666  if (s) {
3667  rz_cons_gotoxy(linew + slen + 1, h + 1);
3668  rz_cons_strcat(s);
3669  free(s);
3670  }
3671  rz_list_free(words);
3672  rz_cons_flush();
3673 }
3674 
3675 static void visual_refresh(RzCore *core) {
3676  static ut64 oseek = UT64_MAX;
3677  const char *vi, *vcmd, *cmd_str;
3678  if (!core) {
3679  return;
3680  }
3681  rz_print_set_cursor(core->print, core->print->cur_enabled, core->print->ocur, core->print->cur);
3682  core->cons->blankline = true;
3683 
3684  int w = visual_responsive(core);
3685 
3686  if (!autoblocksize) {
3687  rz_cons_clear();
3688  }
3690  rz_cons_flush();
3691 
3692  int hex_cols = rz_config_get_i(core->config, "hex.cols");
3693  int split_w = 12 + 4 + hex_cols + (hex_cols * 3);
3694  bool ce = core->print->cur_enabled;
3695 
3696  vi = rz_config_get(core->config, "cmd.cprompt");
3697  bool vsplit = (vi && *vi);
3698 
3699  if (vsplit) {
3700  // XXX: slow
3701  core->cons->blankline = false;
3702  if (split_w > w) {
3703  // do not show column contents
3704  } else {
3705  rz_cons_clear();
3706  rz_cons_printf("[cmd.cprompt=%s]\n", vi);
3707  if (oseek != UT64_MAX) {
3708  rz_core_seek(core, oseek, true);
3709  }
3710  rz_core_cmd0(core, vi);
3711  rz_cons_column(split_w + 1);
3712  if (!strncmp(vi, "p=", 2) && core->print->cur_enabled) {
3713  oseek = core->offset;
3714  core->print->cur_enabled = false;
3715  rz_core_seek(core, core->num->value, true);
3716  } else {
3717  oseek = UT64_MAX;
3718  }
3719  }
3720  rz_cons_gotoxy(0, 0);
3721  }
3722  vi = rz_config_get(core->config, "cmd.vprompt");
3723  if (vi && *vi) {
3724  rz_core_cmd0(core, vi);
3725  }
3726  rz_core_visual_title(core, color);
3727  vcmd = rz_config_get(core->config, "cmd.visual");
3728  if (vcmd && *vcmd) {
3729  // disable screen bounds when it's a user-defined command
3730  // because it can cause some issues
3731  core->print->screen_bounds = 0;
3732  cmd_str = vcmd;
3733  } else {
3734  if (splitView) {
3735  static char debugstr[512];
3736  const char *pxw = NULL;
3737  int h = rz_num_get(core->num, "$r");
3738  int size = (h * 16) / 2;
3739  switch (core->printidx) {
3740  case 1:
3741  size = (h - 2) / 2;
3742  pxw = "pd";
3743  break;
3744  default:
3745  pxw = stackPrintCommand(core);
3746  break;
3747  }
3748  snprintf(debugstr, sizeof(debugstr),
3749  "?0;%s %d @ %" PFMT64d ";cl;"
3750  "?1;%s %d @ %" PFMT64d ";",
3751  pxw, size, splitPtr,
3752  pxw, size, core->offset);
3753  core->print->screen_bounds = 1LL;
3754  cmd_str = debugstr;
3755  } else {
3756  core->print->screen_bounds = 1LL;
3757  cmd_str = (zoom ? "pz" : __core_visual_print_command(core));
3758  }
3759  }
3760  if (cmd_str && *cmd_str) {
3761  if (vsplit) {
3762  char *cmd_result = rz_core_cmd_str(core, cmd_str);
3763  cmd_result = rz_str_ansi_crop(cmd_result, 0, 0, split_w, -1);
3764  rz_cons_strcat(cmd_result);
3765  } else {
3766  rz_core_cmd0(core, cmd_str);
3767  }
3768  }
3769  core->print->cur_enabled = ce;
3770 #if 0
3771  if (core->print->screen_bounds != 1LL) {
3772  rz_cons_printf ("[0x%08"PFMT64x "..0x%08"PFMT64x "]\n",
3773  core->offset, core->print->screen_bounds);
3774  }
3775 #endif
3776  blocksize = core->num->value ? core->num->value : core->blocksize;
3777 
3778  /* this is why there's flickering */
3779  if (core->print->vflush) {
3781  } else {
3782  rz_cons_reset();
3783  }
3784  if (core->scr_gadgets) {
3785  rz_core_gadget_print(core);
3786  rz_cons_flush();
3787  }
3788  core->cons->blankline = false;
3789  core->cons->blankline = true;
3790  core->curtab = 0; // which command are we focusing
3791  // core->seltab = 0; // user selected tab
3792 
3793  if (rz_config_get_i(core->config, "scr.scrollbar")) {
3795  }
3796 }
3797 
3798 static void visual_refresh_oneshot(RzCore *core) {
3799  rz_core_task_enqueue_oneshot(&core->tasks, (RzCoreTaskOneShot)visual_refresh, core);
3800 }
3801 
3802 RZ_API void rz_core_visual_disasm_up(RzCore *core, int *cols) {
3803  *cols = rz_core_visual_prevopsz(core, core->offset);
3804 }
3805 
3807  int midflags = rz_config_get_i(core->config, "asm.flags.middle");
3808  const bool midbb = rz_config_get_b(core->config, "asm.bb.middle");
3809  op->size = 1;
3810  rz_asm_set_pc(core->rasm, core->offset);
3811  *cols = rz_asm_disassemble(core->rasm,
3812  op, core->block, 32);
3813  if (midflags || midbb) {
3814  int skip_bytes_flag = 0, skip_bytes_bb = 0;
3815  if (midflags >= RZ_MIDFLAGS_REALIGN) {
3816  skip_bytes_flag = rz_core_flag_in_middle(core, core->offset, *cols, &midflags);
3817  }
3818  if (midbb) {
3819  skip_bytes_bb = rz_core_bb_starts_in_middle(core, core->offset, *cols);
3820  }
3821  if (skip_bytes_flag) {
3822  *cols = skip_bytes_flag;
3823  }
3824  if (skip_bytes_bb && skip_bytes_bb < *cols) {
3825  *cols = skip_bytes_bb;
3826  }
3827  }
3828  if (*cols < 1) {
3829  *cols = op->size > 1 ? op->size : 1;
3830  }
3831 }
3832 
3833 #ifdef __WINDOWS__
3834 
3835 static bool is_mintty(RzCons *cons) {
3836  return cons->term_xterm;
3837 }
3838 
3839 static void flush_stdin(void) {
3840  while (rz_cons_readchar_timeout(1) != -1)
3841  ;
3842 }
3843 
3844 #else
3845 
3846 static bool is_mintty(RzCons *cons) {
3847  return false;
3848 }
3849 
3850 static void flush_stdin(void) {
3851  tcflush(STDIN_FILENO, TCIFLUSH);
3852 }
3853 
3854 #endif
3855 
3856 RZ_API int rz_core_visual(RzCore *core, const char *input) {
3857  const char *teefile;
3858  ut64 scrseek;
3859  int flags, ch;
3860  bool skip;
3861  char arg[2] = {
3862  input[0], 0
3863  };
3864 
3865  splitPtr = UT64_MAX;
3866 
3867  if (rz_cons_get_size(&ch) < 1 || ch < 1) {
3868  eprintf("Cannot create Visual context. Use scr.fix_{columns|rows}\n");
3869  return 0;
3870  }
3871 
3872  obs = core->blocksize;
3873  // rz_cons_set_cup (true);
3874 
3875  core->vmode = false;
3876  /* honor vim */
3877  if (!strncmp(input, "im", 2)) {
3878  char *cmd = rz_str_newf("!v%s", input);
3879  int ret = rz_core_cmd0(core, cmd);
3880  free(cmd);
3881  return ret;
3882  }
3883  while (*input) {
3884  int len = *input == 'd' ? 2 : 1;
3885  if (!rz_core_visual_cmd(core, input)) {
3886  return 0;
3887  }
3888  input += len;
3889  }
3890  core->vmode = true;
3891 
3892  // disable tee in cons
3893  teefile = rz_cons_singleton()->teefile;
3894  rz_cons_singleton()->teefile = "";
3895 
3896  static char debugstr[512];
3898  do {
3899  dodo:
3900  rz_core_visual_tab_update(core);
3901  // update the cursor when it's not visible anymore
3902  skip = fix_cursor(core);
3903  rz_cons_show_cursor(false);
3904  rz_cons_set_raw(1);
3905  const int ref = rz_config_get_b(core->config, "dbg.slow");
3906 #if 1
3907  // This is why multiple debug views dont work
3908  if (core->printidx == RZ_CORE_VISUAL_MODE_DB) {
3909  const bool pxa = rz_config_get_b(core->config, "stack.anotated"); // stack.anotated
3910  const char *reg = rz_config_get(core->config, "stack.reg");
3911  const int size = rz_config_get_i(core->config, "stack.size");
3912  const int delta = rz_config_get_i(core->config, "stack.delta");
3913  const char *cmdvhex = rz_config_get(core->config, "cmd.stack");
3914 
3915  if (cmdvhex && *cmdvhex) {
3916  rz_strf(debugstr,
3917  "?0 ; f+ tmp ; sr %s @e: cfg.seek.silent=true ; %s ; ?1 ; %s ; ?1 ; "
3918  "s tmp @e: cfg.seek.silent=true ; f- tmp ; pd $r",
3919  reg, cmdvhex,
3921  debugstr[sizeof(debugstr) - 1] = 0;
3922  } else {
3923  const char *pxw = stackPrintCommand(core);
3924  const char sign = (delta < 0) ? '+' : '-';
3925  const int absdelta = RZ_ABS(delta);
3926  rz_strf(debugstr,
3927  "diq ; ?0 ; f+ tmp ; sr %s @e: cfg.seek.silent=true ; %s %d @ $$%c%d;"
3928  "?1 ; %s;"
3929  "?1 ; s tmp @e: cfg.seek.silent=true ; f- tmp ; afal ; pd $r",
3930  reg, pxa ? "pxa" : pxw, size, sign, absdelta,
3932  }
3933  printfmtSingle[2] = debugstr;
3934  }
3935 #endif
3936  rz_cons_enable_mouse(rz_config_get_b(core->config, "scr.wheel"));
3937  core->cons->event_resize = NULL; // avoid running old event with new data
3938  core->cons->event_data = core;
3940  flags = core->print->flags;
3941  color = rz_config_get_i(core->config, "scr.color");
3942  if (color) {
3944  }
3945  debug = rz_config_get_b(core->config, "cfg.debug");
3947  rz_print_set_flags(core->print, flags);
3948  scrseek = rz_num_math(core->num,
3949  rz_config_get(core->config, "scr.seek"));
3950  if (scrseek != 0LL) {
3951  rz_core_seek(core, scrseek, true);
3952  }
3953  if (debug) {
3955  }
3956  core->print->vflush = !skip;
3957  visual_refresh(core);
3958  if (insert_mode_enabled(core)) {
3959  goto dodo;
3960  }
3961  if (!skip) {
3962  ch = rz_cons_readchar();
3963 
3964  if (I->vtmode == RZ_VIRT_TERM_MODE_COMPLETE && !is_mintty(core->cons)) {
3965  // Prevent runaway scrolling
3966  if (IS_PRINTABLE(ch) || ch == '\t' || ch == '\n') {
3967  flush_stdin();
3968  } else if (ch == 0x1b) {
3969  char chrs[2];
3970  int chrs_read = 1;
3971  chrs[0] = rz_cons_readchar();
3972  if (chrs[0] == '[') {
3973  chrs[1] = rz_cons_readchar();
3974  chrs_read++;
3975  if (chrs[1] >= 'A' && chrs[1] <= 'D') { // arrow keys
3976  flush_stdin();
3977 #ifndef __WINDOWS__
3978  // Following seems to fix an issue where scrolling slows
3979  // down to a crawl for some terminals after some time
3980  // mashing the up and down arrow keys
3981  rz_cons_set_raw(false);
3982  rz_cons_set_raw(true);
3983 #endif
3984  }
3985  }
3986  (void)rz_cons_readpush(chrs, chrs_read);
3987  }
3988  }
3989  if (rz_cons_is_breaked()) {
3990  break;
3991  }
3992  rz_core_visual_show_char(core, ch);
3993  if (ch == -1 || ch == 4) {
3994  break; // error or eof
3995  }
3996  arg[0] = ch;
3997  arg[1] = 0;
3998  }
3999  } while (skip || (*arg && rz_core_visual_cmd(core, arg)));
4000 
4001  rz_cons_enable_mouse(false);
4002  if (color) {
4004  }
4005  rz_config_set_i(core->config, "scr.color", color);
4006  core->print->cur_enabled = false;
4007  if (autoblocksize) {
4008  rz_core_block_size(core, obs);
4009  }
4010  rz_cons_singleton()->teefile = teefile;
4011  rz_cons_set_cup(false);
4012  rz_cons_clear00();
4013  core->vmode = false;
4014  core->cons->event_resize = NULL;
4015  core->cons->event_data = NULL;
4016  rz_cons_show_cursor(true);
4017  return 0;
4018 }
4019 
4020 RZ_API RzListInfo *rz_listinfo_new(const char *name, RzInterval pitv, RzInterval vitv, int perm, const char *extra) {
4022  if (info) {
4023  info->name = name ? strdup(name) : NULL;
4024  info->pitv = pitv;
4025  info->vitv = vitv;
4026  info->perm = perm;
4027  info->extra = extra ? strdup(extra) : NULL;
4028  }
4029  return info;
4030 }
4031 
4033  if (!info) {
4034  return;
4035  }
4036  free(info->name);
4037  free(info->extra);
4038  free(info);
4039 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
RZ_API int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_fcn, int is_interactive)
Definition: agraph.c:4114
RZ_API int rz_analysis_archinfo(RzAnalysis *analysis, int query)
Definition: analysis.c:449
#define e(frag)
RZ_API void rz_asm_op_fini(RzAsmOp *op)
Definition: aop.c:21
RZ_API void rz_asm_op_init(RzAsmOp *op)
Definition: aop.c:15
lzma_index ** i
Definition: index.h:629
RZ_API int rz_asm_set_pc(RzAsm *a, ut64 pc)
Definition: asm.c:533
RZ_API int rz_asm_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
Definition: asm.c:543
static int dis(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
Definition: asm_snes.c:12
RZ_API RzBinObject * rz_bin_cur_object(RzBin *bin)
Definition: bin.c:900
RZ_API RZ_BORROW RzBinSection * rz_bin_get_section_at(RzBinObject *o, ut64 off, int va)
Find the binary section at offset off.
Definition: bin.c:611
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
const char * desc
Definition: bin_vsf.c:19
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API ut64 rz_analysis_block_get_op_addr_in(RzAnalysisBlock *bb, ut64 off)
Definition: block.c:1048
RZ_API RzAnalysisBlock * rz_analysis_find_most_relevant_block_in(RzAnalysis *analysis, ut64 off)
Definition: block.c:997
RZ_API RzAnalysisOp * rz_core_analysis_op(RzCore *core, ut64 addr, int mask)
Definition: canalysis.c:1033
RZ_API void rz_core_debug_breakpoint_toggle(RZ_NONNULL RzCore *core, ut64 addr)
Toggle breakpoint.
Definition: cdebug.c:235
RZ_IPI void rz_core_debug_continue(RzCore *core)
Definition: cdebug.c:81
RZ_IPI void rz_core_debug_sync_bits(RzCore *core)
Definition: cdebug.c:184
RZ_API bool rz_core_debug_continue_until(RzCore *core, ut64 addr, ut64 to)
Definition: cdebug.c:98
RZ_IPI void rz_core_debug_single_step_in(RzCore *core)
Definition: cdebug.c:193
RZ_IPI void rz_core_debug_single_step_over(RzCore *core)
Definition: cdebug.c:207
RZ_API bool rz_core_file_resize_delta(RzCore *core, st64 delta)
Definition: cfile.c:522
RZ_IPI int rz_core_analysis_set_reg(RzCore *core, const char *regname, ut64 val)
Definition: cil.c:389
RZ_API int rz_core_write_hexpair(RzCore *core, ut64 addr, const char *pairs)
Definition: cio.c:268
RZ_API bool rz_core_write_at(RzCore *core, ut64 addr, const ut8 *buf, int size)
Definition: cio.c:145
RZ_API int rz_core_block_read(RzCore *core)
Definition: cio.c:243
RZ_API bool rz_core_dump(RzCore *core, const char *file, ut64 addr, ut64 size, int append)
Definition: cio.c:50
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_cmd_state_output_init(RZ_NONNULL RzCmdStateOutput *state, RzOutputMode mode)
Initialize a RzCmdStateOutput structure and its inner fields based on the provided mode.
Definition: cmd_api.c:2634
RZ_API void rz_cmd_state_output_fini(RZ_NONNULL RzCmdStateOutput *state)
Clear the inner fields of RzCmdStateOutput structure, but do not free it.
Definition: cmd_api.c:2603
RZ_API void rz_core_theme_nextpal(RzCore *core, RzConsPalSeekMode mode)
Definition: cmd_eval.c:148
RZ_IPI void rz_core_flag_describe(RzCore *core, ut64 addr, bool strict_offset, RzCmdStateOutput *state)
Definition: cmd_flag.c:327
RZ_API void rz_core_gadget_print(RzCore *core)
Prints or displays the print gadgets while in visual mode.
Definition: cmd_print.c:1185
RZ_IPI void rz_core_meta_editor(RzCore *core, RzAnalysisMetaType mtype, ut64 addr)
Definition: cmeta.c:394
RZ_IPI void rz_core_meta_append(RzCore *core, const char *newcomment, RzAnalysisMetaType mtype, ut64 addr)
Definition: cmeta.c:376
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 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 RzConfigNode * rz_config_set_b(RzConfig *cfg, RZ_NONNULL const char *name, bool value)
Definition: config.c:201
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 bool rz_cons_set_cup(bool enable)
Definition: cons.c:1672
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 bool rz_cons_enable_mouse(const bool enable)
Definition: cons.c:500
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 int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_reset_colors(void)
Definition: cons.c:783
RZ_API void rz_cons_echo(const char *msg)
Definition: cons.c:939
RZ_API void rz_cons_visual_flush(void)
Definition: cons.c:1067
RZ_API bool rz_cons_get_click(int *x, int *y)
Definition: cons.c:484
RZ_API void rz_cons_goto_origin_reset(void)
Definition: cons.c:732
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 bool rz_cons_is_breaked(void)
Definition: cons.c:373
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
RZ_API void rz_cons_reset(void)
Definition: cons.c:804
#define RZ_API
RZ_API void rz_core_reg_update_flags(RzCore *core)
Update or create flags for all registers where it makes sense.
Definition: creg.c:106
RZ_API bool rz_core_reg_set_by_role_or_name(RzCore *core, const char *name, ut64 num)
set on rz_core_reg_default()
Definition: creg.c:39
#define NULL
Definition: cris-opc.c:27
#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 cmd
Definition: sflib.h:79
#define ut8
Definition: dcpu16.h:8
uint32_t ut32
RZ_API int rz_line_hist_cmd_down(RzLine *line)
Definition: dietline.c:346
RZ_API const char * rz_line_readline(void)
Definition: dietline.c:913
RZ_API int rz_line_hist_cmd_up(RzLine *line)
Definition: dietline.c:316
RZ_API int rz_line_set_hist_callback(RzLine *line, RzLineHistoryUpCb up, RzLineHistoryDownCb down)
Definition: dietline.c:292
RZ_API int rz_line_hist_add(const char *line)
Definition: dietline.c:382
RZ_API int rz_core_flag_in_middle(RzCore *core, ut64 at, int oplen, int *midflags)
Definition: disasm.c:1702
RZ_API int rz_core_bb_starts_in_middle(RzCore *core, ut64 at, int oplen)
Definition: disasm.c:1714
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name)
Definition: dreg.c:99
int max
Definition: enough.c:225
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_DEPRECATE RZ_API RzAnalysisFunction * rz_analysis_get_fcn_in(RzAnalysis *analysis, ut64 addr, int type)
Definition: fcn.c:1687
RZ_API RzFlagItem * rz_flag_get_at(RzFlag *f, ut64 off, bool closest)
Definition: flag.c:404
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 bool rz_flag_unset_off(RzFlag *f, ut64 off)
Definition: flag.c:608
void skip(file *in, unsigned n)
Definition: gzappend.c:202
RZ_API RzAnalysisHint * rz_analysis_hint_get(RzAnalysis *a, ut64 addr)
Definition: hint.c:506
RZ_API void rz_analysis_hint_set_bits(RzAnalysis *a, ut64 addr, int bits)
Definition: hint.c:288
RZ_API void rz_analysis_hint_free(RzAnalysisHint *h)
Definition: hint.c:371
RZ_API void rz_config_hold_restore(RzConfigHold *h)
Restore whatever config options were previously saved in h.
Definition: hold.c:132
RZ_API RzConfigHold * rz_config_hold_new(RzConfig *cfg)
Create an opaque object to save/restore some configuration options.
Definition: hold.c:116
RZ_API bool rz_config_hold_s(RzConfigHold *h,...)
Save the current values of a list of config options that have string values.
Definition: hold.c:40
RZ_API void rz_config_hold_free(RzConfigHold *h)
Free a RzConfigHold object h.
Definition: hold.c:152
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API void rz_cons_message(RZ_NONNULL const char *msg)
Definition: hud.c:321
RZ_API char * rz_cons_hud_file(const char *f)
Definition: hud.c:10
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_readchar_timeout(ut32 usec)
Definition: input.c:560
RZ_API bool rz_cons_readpush(const char *str, int len)
Definition: input.c:585
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 * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
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
RZ_API bool rz_analysis_function_delete_label(RzAnalysisFunction *fcn, const char *name)
Definition: labels.c:34
RZ_API bool rz_analysis_function_set_label(RzAnalysisFunction *fcn, const char *name, ut64 addr)
Definition: labels.c:20
#define reg(n)
RZ_API int rz_cons_less_str(const char *str, const char *exitkeys)
Definition: less.c:10
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
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 ut64 rz_core_get_asmqjmps(RzCore *core, const char *str)
Definition: core.c:203
RZ_API bool rz_core_block_size(RzCore *core, ut32 bsize)
Definition: core.c:2842
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
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 const char struct stat static buf struct stat static buf static idle const char static path static fd const char static len const void static prot const char struct module static image struct kernel_sym static table unsigned char static buf static fsuid unsigned struct dirent unsigned static count const struct iovec static count static pid const void static len static flags const struct sched_param static p static pid static policy struct timespec static tp static suid unsigned fn
Definition: sflib.h:186
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_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 RzAnalysisMetaItem * rz_meta_get_at(RzAnalysis *a, ut64 addr, RzAnalysisMetaType type, RZ_OUT RZ_NULLABLE ut64 *size)
Definition: meta.c:207
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
#define TRUE
Definition: mybfd.h:103
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
static struct @218 keys[]
int off
Definition: pal.c:13
RZ_API void rz_cons_pal_random(void)
Definition: pal.c:270
RZ_API bool rz_core_visual_panels_root(RzCore *core, RzPanelsRoot *panels_root)
Definition: panels.c:5947
RZ_API void rz_print_set_flags(RzPrint *p, int _flags)
Definition: print.c:117
RZ_API int rz_print_row_at_off(RzPrint *p, ut32 offset)
Definition: print.c:1562
RZ_API ut32 rz_print_rowoff(RzPrint *p, int i)
Definition: print.c:1553
RZ_API void rz_print_set_cursor(RzPrint *p, int enable, int ocursor, int cursor)
Definition: print.c:121
#define min(a, b)
Definition: qsort.h:83
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
@ RZ_ANALYSIS_FCN_TYPE_NULL
Definition: rz_analysis.h:192
#define RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE
Definition: rz_analysis.h:99
@ RZ_META_TYPE_DATA
Definition: rz_analysis.h:289
@ RZ_META_TYPE_STRING
Definition: rz_analysis.h:291
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
#define RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE
Definition: rz_analysis.h:98
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_CCALL
Definition: rz_analysis.h:383
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_CMD_STATUS_INVALID
command could not be executed (e.g. shell level error, bad expression, etc.)
Definition: rz_cmd.h:27
#define RZ_CONS_KEY_F12
Definition: rz_cons.h:589
#define RZ_CONS_KEY_F11
Definition: rz_cons.h:588
@ RZ_VIRT_TERM_MODE_COMPLETE
All the sequences goes through VT (Windows Terminal, mintty, all OSs)
Definition: rz_cons.h:451
#define RZ_CONS_CLEAR_LINE
Definition: rz_cons.h:593
#define RZ_CONS_KEY_F10
Definition: rz_cons.h:587
#define Color_RESET
Definition: rz_cons.h:617
#define RZ_CONS_KEY_F6
Definition: rz_cons.h:583
#define RZ_CONS_KEY_F7
Definition: rz_cons.h:584
#define RZ_CONS_KEY_F3
Definition: rz_cons.h:580
#define RZ_CONS_KEY_F2
Definition: rz_cons.h:579
void(* RzConsEvent)(void *)
Definition: rz_cons.h:346
#define RZ_CONS_KEY_F1
Definition: rz_cons.h:578
#define RZ_CONS_KEY_F5
Definition: rz_cons.h:582
#define RZ_CONS_KEY_F4
Definition: rz_cons.h:581
@ RZ_LINE_PROMPT_DEFAULT
Definition: rz_cons.h:1037
@ RZ_LINE_PROMPT_OFFSET
Definition: rz_cons.h:1038
#define RZ_CONS_KEY_F9
Definition: rz_cons.h:586
#define RZ_LINE_BUFSIZE
Definition: rz_cons.h:991
#define Color_INVERT
Definition: rz_cons.h:606
#define RZ_CONS_KEY_F8
Definition: rz_cons.h:585
#define RZ_FLAGS_FS_SYMBOLS
Definition: rz_core.h:67
@ RZ_CORE_VISUAL_MODE_PD
Disassembly view.
Definition: rz_core.h:99
@ RZ_CORE_VISUAL_MODE_OV
Color blocks (entropy)
Definition: rz_core.h:101
@ RZ_CORE_VISUAL_MODE_CD
Print in string format.
Definition: rz_core.h:102
@ RZ_CORE_VISUAL_MODE_DB
Debug mode.
Definition: rz_core.h:100
@ RZ_CORE_VISUAL_MODE_PX
Hexadecimal view.
Definition: rz_core.h:98
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API char * rz_file_abspath(const char *file)
Definition: file.c:267
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API bool rz_file_dump(const char *file, const ut8 *buf, int len, bool append)
Definition: file.c:838
RZ_API RZ_OWN char * rz_file_path_join(RZ_NONNULL const char *s1, RZ_NULLABLE const char *s2)
Concatenate two paths to create a new one with s1+s2 with the correct path separator.
Definition: file.c:1312
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API bool rz_io_read_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:300
RZ_API ut64 rz_io_size(RzIO *io)
Definition: io.c:399
RZ_API RzIOMap * rz_io_map_get(RzIO *io, ut64 addr)
Definition: io_map.c:176
RZ_API RzIODesc * rz_io_desc_get(RzIO *io, int fd)
Definition: io_desc.c:73
RZ_API RZ_BORROW RzPVector * rz_io_maps(RzIO *io)
Returns the pointer to vector containing maps list.
Definition: io_map.c:435
RZ_API bool rz_io_write_at(RzIO *io, ut64 addr, const ut8 *buf, int len)
Definition: io.c:358
static ut64 rz_itv_begin(RzInterval itv)
Definition: rz_itv.h:34
static ut64 rz_itv_end(RzInterval itv)
Definition: rz_itv.h:42
RZ_API const ut8 * rz_mem_mem(const ut8 *haystack, int hlen, const ut8 *needle, int nlen)
Definition: mem.c:246
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 RZ_OWN char * rz_path_home_prefix(RZ_NULLABLE const char *path)
Return path prefixed by the home prefix.
Definition: path.c:182
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
#define RZ_PRINT_FLAGS_CURSOR
Definition: rz_print.h:17
#define RZ_PRINT_FLAGS_COLOR
Definition: rz_print.h:15
#define RZ_PRINT_FLAGS_ADDRMOD
Definition: rz_print.h:16
#define RZ_PRINT_FLAGS_HEADER
Definition: rz_print.h:18
RZ_API char * rz_str_between(const char *str, const char *prefix, const char *suffix)
Definition: str.c:3264
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_append(char *ptr, const char *string)
Definition: str.c:1063
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
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 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 const char * rz_str_pad(const char ch, int len)
Definition: str.c:3236
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
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_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317
RZ_API char * rz_sys_getdir(void)
Get current working directory.
Definition: sys.c:521
RZ_API int rz_sys_sleep(int secs)
Sleep for secs seconds.
Definition: sys.c:300
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
#define RZ_SYS_DIR
Definition: rz_types.h:218
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_PERM_W
Definition: rz_types.h:94
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_BETWEEN(x, y, z)
#define RZ_HUD
Definition: rz_userconf.h:79
RZ_API void * rz_pvector_pop(RzPVector *vec)
Definition: vector.c:372
static void ** rz_pvector_push_front(RzPVector *vec, void *x)
Definition: rz_vector.h:305
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define tolower(c)
Definition: safe-ctype.h:149
#define isdigit(c)
Definition: safe-ctype.h:131
#define toupper(c)
Definition: safe-ctype.h:147
RZ_API bool rz_core_seek_redo(RzCore *core)
Definition: seek.c:316
RZ_API RzCoreSeekItem * rz_core_seek_peek(RzCore *core, int idx)
Return a element in the undo/redo list.
Definition: seek.c:361
RZ_API bool rz_core_seek_delta(RzCore *core, st64 delta, bool save)
Seek relative to current offset and optionally save the current offset in seek history.
Definition: seek.c:152
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_next(RzCore *core, const char *type, bool save)
Seek to the next type of item from current offset.
Definition: seek.c:203
RZ_API int rz_core_seek_base(RzCore *core, const char *hex, bool save)
Seek to a new address composed of current offset with last hex digits replaced with those of hex.
Definition: seek.c:171
RZ_API bool rz_core_seek_prev(RzCore *core, const char *type, bool save)
Seek to the previous type of item from current offset.
Definition: seek.c:241
RZ_API bool rz_core_seek_undo(RzCore *core)
Definition: seek.c:301
RZ_API void rz_core_seek_item_free(RzCoreSeekItem *item)
Definition: seek.c:7
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 static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
#define TCIFLUSH
Definition: sftypes.h:993
int size_t
Definition: sftypes.h:40
#define d(i)
Definition: sha256.c:44
#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: visual.c:24
int y
Definition: visual.c:26
int x
Definition: visual.c:25
Definition: zipcmp.c:77
Definition: z80asm.h:102
RzAnalysisXRefType type
Definition: rz_analysis.h:909
int bits
Definition: rz_asm.h:100
_RzAsmPlugin * cur
Definition: rz_asm.h:106
Represent the output state of a command handler.
Definition: rz_cmd.h:91
RzConsPrintablePalette pal
Definition: rz_cons.h:491
struct rz_line_t * line
Definition: rz_cons.h:553
const char * teefile
Definition: rz_cons.h:519
int blankline
Definition: rz_cons.h:547
RzConsEvent event_resize
Definition: rz_cons.h:522
void * event_data
Definition: rz_cons.h:523
RzConsContext * context
Definition: rz_cons.h:502
int rows
Definition: rz_cons.h:508
int mouse
Definition: rz_cons.h:551
ut64 offset
Value of core->offset at the given time in history.
Definition: rz_core.h:145
bool vmode
Definition: rz_core.h:309
RzBuffer * yank_buf
Definition: rz_core.h:306
RzCons * cons
Definition: rz_core.h:312
bool scr_gadgets
Definition: rz_core.h:385
RzCoreVisualMode printidx
Definition: rz_core.h:357
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
int seltab
Definition: rz_core.h:368
RzDebug * dbg
Definition: rz_core.h:329
RzIO * io
Definition: rz_core.h:313
RzNum * num
Definition: rz_core.h:316
RzCoreTaskScheduler tasks
Definition: rz_core.h:362
RzCoreVisual visual
Definition: rz_core.h:351
int curtab
Definition: rz_core.h:367
char * stkcmd
Definition: rz_core.h:358
ut8 * block
Definition: rz_core.h:305
RzFlag * flags
Definition: rz_core.h:330
RzPanelsRoot * panels_root
Definition: rz_core.h:334
RzPrint * print
Definition: rz_core.h:327
RzCoreFile * file
Definition: rz_core.h:314
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
RzList * tabs
Definition: rz_core.h:241
int regcols
Definition: rz_debug.h:260
int bits
Definition: rz_debug.h:243
int va
Definition: rz_io.h:63
RzLinePromptType prompt_type
Definition: rz_cons.h:1116
ut64 value
Definition: rz_num.h:63
ut64 screen_bounds
Definition: rz_print.h:179
int cols
Definition: rz_print.h:136
int flags
Definition: rz_print.h:137
bool wide_offsets
Definition: rz_print.h:162
int ocur
Definition: rz_print.h:135
bool vflush
Definition: rz_print.h:176
bool cur_enabled
Definition: rz_print.h:130
Definition: dis.h:43
Definition: enough.c:118
const char * command
Definition: main.c:7
int pos
Definition: main.c:11
ut64 buflen
Definition: core.c:76
#define STDIN_FILENO
Definition: private.h:37
RZ_API void rz_core_task_enqueue_oneshot(RzCoreTaskScheduler *scheduler, RzCoreTaskOneShot func, void *user)
Definition: task.c:391
Definition: dis.c:32
RZ_API void rz_core_visual_asm(RzCore *core, ut64 off)
Definition: vasm.c:73
static int visual_help(RzCore *core)
Definition: visual.c:552
RZ_API void rz_core_visual_title(RzCore *core, int color)
Definition: visual.c:3287
static void cursor_nextrow(RzCore *core, bool use_ocur)
Definition: visual.c:1704
static void nextPrintCommand(void)
Definition: visual.c:215
RZ_API void rz_core_print_scrollbar_bottom(RzCore *core)
Definition: visual.c:3608
#define PIDX
Definition: visual.c:10
static const char * print3Formats[PRINT_3_FORMATS]
Definition: visual.c:71
static bool autoblocksize
Definition: visual.c:16
static void rotateAsmBits(RzCore *core)
Definition: visual.c:386
static int color
Definition: visual.c:20
static void cursor_left(RzCore *core, bool use_ocur)
Definition: visual.c:1875
RZ_API void rz_core_visual_toggle_decompiler_disasm(RzCore *core, bool for_graph, bool reset)
Definition: visual.c:127
static int printMode
Definition: visual.c:19
RZ_API int rz_core_visual_prevopsz(RzCore *core, ut64 addr)
Definition: visual.c:1272
static int visual_responsive(RzCore *core)
Definition: visual.c:3504
RZ_API void rz_core_visual_offset(RzCore *core)
Definition: visual.c:1247
RZ_API void rz_core_visual_seek_animation_undo(RzCore *core)
Definition: visual.c:1088
static const char * printfmtSingle[NPF]
Definition: visual.c:34
static void setcursor(RzCore *core, bool cur)
Definition: visual.c:159
#define NPF
Definition: visual.c:9
static bool __core_visual_gogo(RzCore *core, int ch)
Definition: visual.c:261
static bool __holdMouseState(RzCore *core)
Definition: visual.c:678
#define PRINT_5_FORMATS
Definition: visual.c:54
static void prevPrintCommand(void)
Definition: visual.c:221
static void nextPrintFormat(RzCore *core)
Definition: visual.c:463
static int numbuf_i
Definition: visual.c:2201
RZ_API void rz_core_visual_applyDisMode(RzCore *core, int disMode)
Definition: visual.c:174
static int isSpace(char ch)
Definition: visual.c:966
RZ_API void rz_core_visual_show_char(RzCore *core, char ch)
Definition: visual.c:1041
static void backup_current_addr(RzCore *core, ut64 *addr, ut64 *bsze, ut64 *newaddr, int *cur)
Definition: visual.c:684
static void findPair(RzCore *core)
Definition: visual.c:904
RZ_API void rz_core_visual_disasm_up(RzCore *core, int *cols)
Definition: visual.c:3802
static int obs
Definition: visual.c:14
RZ_API bool rz_core_visual_hud(RzCore *core)
Definition: visual.c:471
static void setdiff(RzCore *core)
Definition: visual.c:896
static void prompt_read(const char *p, char *buf, int buflen)
Definition: visual.c:662
#define PRINT_4_FORMATS
Definition: visual.c:53
RZ_API int rz_core_visual_cmd(RzCore *core, const char *arg)
Definition: visual.c:2232
static char numbuf[32]
Definition: visual.c:2200
static const char * rotateAsmemu(RzCore *core)
Definition: visual.c:405
RZ_API void rz_core_visual_append_help(RzStrBuf *p, const char *title, const char **help)
Definition: visual.c:532
static const char * __core_visual_print_command(RzCore *core)
Definition: visual.c:246
static void cursor_right(RzCore *core, bool use_ocur)
Definition: visual.c:1886
static bool fix_cursor(RzCore *core)
Definition: visual.c:1897
static void nextOpcode(RzCore *core)
Definition: visual.c:1682
static void visual_refresh(RzCore *core)
Definition: visual.c:3675
static void visual_refresh_oneshot(RzCore *core)
Definition: visual.c:3798
#define I
static bool is_mintty(RzCons *cons)
Definition: visual.c:3846
static void prevPrintFormat(RzCore *core)
Definition: visual.c:467
RZ_API bool rz_core_prevop_addr(RzCore *core, ut64 start_addr, int numinstrs, ut64 *prev_addr)
Definition: visual.c:1173
RZ_API void rz_core_visual_prompt_input(RzCore *core)
Definition: visual.c:733
static void restore_current_addr(RzCore *core, ut64 addr, ut64 bsze, ut64 newaddr, int cur)
Definition: visual.c:701
RZ_API int rz_core_visual_prompt(RzCore *core)
Definition: visual.c:756
static void cursor_ocur(RzCore *core, bool use_ocur)
Definition: visual.c:1673
RZ_API void rz_core_visual_browse(RzCore *core, const char *input)
Definition: visual.c:2067
static int blocksize
Definition: visual.c:15
#define PRINT_3_FORMATS
Definition: visual.c:52
RZ_API void rz_core_print_scrollbar(RzCore *core)
Definition: visual.c:3541
#define PRINT_HEX_FORMATS
Definition: visual.c:51
static void findPrevWord(RzCore *core)
Definition: visual.c:978
static void flush_stdin(void)
Definition: visual.c:3850
RZ_API RzListInfo * rz_listinfo_new(const char *name, RzInterval pitv, RzInterval vitv, int perm, const char *extra)
Definition: visual.c:4020
static void visual_search(RzCore *core)
Definition: visual.c:1002
static int currentFormat
Definition: visual.c:56
static void setprintmode(RzCore *core, int n)
Definition: visual.c:1094
static int __nib
Definition: visual.c:1955
static int visual_nkey(RzCore *core, int ch)
Definition: visual.c:793
RZ_API void rz_core_visual_applyHexMode(RzCore *core, int hexMode)
Definition: visual.c:84
static const char * printfmtColumns[NPF]
Definition: visual.c:42
static ut64 splitPtr
Definition: visual.c:381
static int numbuf_pull(void)
Definition: visual.c:2211
static void visual_comma(RzCore *core)
Definition: visual.c:1623
static void reset_print_cur(RzPrint *p)
Definition: visual.c:673
RZ_API int rz_core_visual(RzCore *core, const char *input)
Definition: visual.c:3856
#define CMD_REGISTERS_REFS
Definition: visual.c:32
#define KEY_ALTQ
Definition: visual.c:29
RZ_API void rz_core_visual_disasm_down(RzCore *core, RzAsmOp *op, int *cols)
Definition: visual.c:3806
static void visual_flagzone(RzCore *core)
Definition: visual.c:3258
RZ_API int rz_core_visual_xrefs(RzCore *core, bool xref_to, bool fcnInsteadOfAddr)
Definition: visual.c:1312
RZ_API void rz_listinfo_free(RzListInfo *info)
Definition: visual.c:4032
static bool canWrite(RzCore *core, ut64 addr)
Definition: visual.c:2224
RZ_API void rz_core_visual_toggle_hints(RzCore *core)
Definition: visual.c:109
static void visual_breakpoint(RzCore *core)
Definition: visual.c:789
static int current4format
Definition: visual.c:75
char * getcommapath(RzCore *core)
Definition: visual.c:1607
RZ_API void rz_core_visual_showcursor(RzCore *core, int x)
Definition: visual.c:420
static int zoom
Definition: visual.c:22
static void printFormat(RzCore *core, const int next)
Definition: visual.c:430
RZ_API ut64 rz_core_prevop_addr_force(RzCore *core, ut64 start_addr, int numinstrs)
Definition: visual.c:1195
static const char * help_msg_visual[]
Definition: visual.c:314
static void findNextWord(RzCore *core)
Definition: visual.c:946
static int debug
Definition: visual.c:21
RZ_API void rz_core_visual_jump(RzCore *core, ut8 ch)
Definition: visual.c:514
RZ_API void rz_core_visual_seek_animation(RzCore *core, ut64 addr)
Definition: visual.c:1077
RZ_API int rz_line_hist_offset_up(RzLine *line)
Definition: visual.c:1222
static const char * print4Formats[PRINT_4_FORMATS]
Definition: visual.c:76
static void numbuf_append(int ch)
Definition: visual.c:2203
static int follow_ref(RzCore *core, RzList *xrefs, int choice, bool xref_to)
Definition: visual.c:1299
static const char * help_visual[]
Definition: visual.c:300
static const char * printHexFormats[PRINT_HEX_FORMATS]
Definition: visual.c:58
static ut64 prevop_addr(RzCore *core, ut64 addr)
Definition: visual.c:1111
#define OPDELTA
Definition: visual.c:1110
static int current5format
Definition: visual.c:79
static int current0format
Definition: visual.c:57
static const char * help_msg_visual_fn[]
Definition: visual.c:371
static bool insert_mode_enabled(RzCore *core)
Definition: visual.c:1957
static void visual_seek_animation(RzCore *core, ut64 addr)
Definition: visual.c:1056
static const char * print5Formats[PRINT_5_FORMATS]
Definition: visual.c:80
static bool __ime
Definition: visual.c:1954
static bool isNumber(RzCore *core, int ch)
Definition: visual.c:2190
static const char * stackPrintCommand(RzCore *core)
Definition: visual.c:229
static void cursor_prevrow(RzCore *core, bool use_ocur)
Definition: visual.c:1784
RZ_API int rz_line_hist_offset_down(RzLine *line)
Definition: visual.c:1235
static bool splitView
Definition: visual.c:380
RZ_API void rz_core_visual_seek_animation_redo(RzCore *core)
Definition: visual.c:1082
static void prevOpcode(RzCore *core)
Definition: visual.c:1693
static int hexMode
Definition: visual.c:18
#define CMD_REGISTERS
Definition: visual.c:31
static int current3format
Definition: visual.c:70
static void add_comment(RzCore *core, ut64 addr, const char *prompt)
Definition: visual.c:1277
static int disMode
Definition: visual.c:17
static bool fill_hist_offset(RzCore *core, RzLine *line, RzCoreSeekItem *csi)
Definition: visual.c:1203
static bool isDisasmPrint(int mode)
Definition: visual.c:1669
RZ_API void rz_core_visual_mark(RzCore *core, ut8 ch)
Definition: vmarks.c:47
RZ_API bool rz_core_visual_mark_dump(RzCore *core)
Definition: vmarks.c:14
RZ_API void rz_core_visual_mark_seek(RzCore *core, ut8 ch)
Definition: vmarks.c:54
RZ_API void rz_core_visual_mark_del(RzCore *core, ut8 ch)
Definition: vmarks.c:40
RZ_API int rz_core_visual_comments(RzCore *core)
Definition: vmenus.c:1793
static char * prompt(const char *str, const char *txt)
Definition: vmenus.c:30
RZ_API void rz_core_visual_define(RzCore *core, const char *args, int distance)
Definition: vmenus.c:3149
RZ_API int rz_core_visual_view_rop(RzCore *core)
Definition: vmenus.c:1232
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
RZ_API bool rz_core_visual_esil(RzCore *core)
Definition: vmenus.c:89
RZ_API void rz_core_visual_config(RzCore *core)
Definition: vmenus.c:1984
#define lastPrintMode
Definition: vmenus.c:2430
RZ_API int rz_core_visual_trackflags(RzCore *core)
Definition: vmenus.c:1485
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 st64 delta
Definition: vmenus.c:2425
RZ_API void rz_core_visual_colors(RzCore *core)
Definition: vmenus.c:3615
RZ_API int rz_core_visual_analysis_classes(RzCore *core)
Definition: vmenus.c:1077
RZ_API int rz_core_visual_classes(RzCore *core)
Definition: vmenus.c:786
RZ_API int rz_core_visual_view_graph(RzCore *core)
Definition: vmenus_graph.c:255
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API RzList * rz_analysis_xrefs_get_from(RzAnalysis *analysis, ut64 addr)
Definition: xrefs.c:187
RZ_API RzList * rz_analysis_xrefs_get_to(RzAnalysis *analysis, ut64 addr)
Definition: xrefs.c:173
RZ_API const char * rz_analysis_xrefs_type_tostring(RzAnalysisXRefType type)
Definition: xrefs.c:216
RZ_API RzList * rz_analysis_function_get_xrefs_from(RzAnalysisFunction *fcn)
Definition: xrefs.c:297
RZ_API bool rz_core_yank(RzCore *core, ut64 addr, ut64 len)
Definition: yank.c:118
RZ_API bool rz_core_yank_paste(RzCore *core, ut64 addr, ut64 len)
Definition: yank.c:174
static int addr
Definition: z80asm.c:58
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
RZ_API bool rz_flag_zone_around(RzFlag *f, ut64 addr, const char **prev, const char **next)
Definition: zones.c:75
RZ_API RzList * rz_flag_zone_barlist(RzFlag *f, ut64 from, ut64 bsize, int rows)
Definition: zones.c:130