1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2
3 #include <r_util/r_print.h>
4 #include <r_anal.h>
5
6 #define DFLT_ROWS 16
7
8 static const char hex[16] = "0123456789ABCDEF";
9
nullprinter(const char * a,...)10 static int nullprinter(const char *a, ...) {
11 return 0;
12 }
13
libc_printf(const char * format,...)14 static int libc_printf(const char *format, ...) {
15 va_list ap;
16 va_start (ap, format);
17 vprintf (format, ap);
18 va_end (ap);
19 return 0;
20 }
21
libc_eprintf(const char * format,...)22 static int libc_eprintf(const char *format, ...) {
23 va_list ap;
24 va_start (ap, format);
25 vfprintf (stderr, format, ap);
26 va_end (ap);
27 return 0;
28 }
29
30 static RPrintIsInterruptedCallback is_interrupted_cb = NULL;
31
r_print_portionbar(RPrint * p,const ut64 * portions,int n_portions)32 R_API void r_print_portionbar(RPrint *p, const ut64 *portions, int n_portions) {
33 const int use_color = p->flags & R_PRINT_FLAGS_COLOR;
34 int i, j;
35 ut64 total = 0LL;
36 for (i = 0; i < n_portions; i++) {
37 ut64 sum = total + portions[i];
38 if (total > sum) {
39 eprintf ("portionbar overflow aborted\n");
40 return;
41 }
42 total = sum;
43 }
44 p->cb_printf ("[");
45 if (total == 0) {
46 total = 1;
47 }
48 for (i = 0; i < n_portions; i++) {
49 int pc = portions[i] * 100 / total;
50 // adjust pc to screen columns
51 pc = pc * p->width / 100;
52 if (use_color) {
53 p->cb_printf ("\x1b[%dm", 31 + (i % 8));
54 }
55 if (pc == 0) {
56 pc = 1;
57 }
58 for (j = 0; j < pc; j++) {
59 p->cb_printf ("%c", 'A'+ i);
60 }
61 if (use_color) {
62 p->cb_printf (Color_RESET);
63 }
64 }
65 p->cb_printf ("]\n");
66 }
67
r_print_columns(RPrint * p,const ut8 * buf,int len,int height)68 R_API void r_print_columns(RPrint *p, const ut8 *buf, int len, int height) {
69 #define cb_print(x) p->cb_printf("%s", x)
70 size_t i, j;
71 int cols = 78; // TODO: do not hardcode this value, columns should be defined by the user
72 int rows = height > 0 ? height : 10;
73 // int realrows = rows * 2;
74 bool colors = p->flags & R_PRINT_FLAGS_COLOR;
75 RConsPrintablePalette *pal = &p->cons->context->pal;
76 const char *vline = p->cons->use_utf8 ? RUNE_LINE_VERT : "|";
77 const char *block = p->cons->use_utf8 ? UTF_BLOCK : "#";
78 const char *kol[5];
79 kol[0] = pal->call;
80 kol[1] = pal->jmp;
81 kol[2] = pal->cjmp;
82 kol[3] = pal->mov;
83 kol[4] = pal->nop;
84 if (colors) {
85 for (i = 0; i < rows; i++) {
86 size_t threshold = i * (0xff / rows);
87 size_t koli = i * 5 / rows;
88 for (j = 0; j < cols; j++) {
89 int realJ = j * len / cols;
90 if (255 - buf[realJ] < threshold || (i + 1 == rows)) {
91 if (p->histblock) {
92 p->cb_printf ("%s%s%s", kol[koli], block, Color_RESET);
93 } else {
94 p->cb_printf ("%s%s%s", kol[koli], vline, Color_RESET);
95 }
96 } else {
97 cb_print (" ");
98 }
99 }
100 cb_print ("\n");
101 }
102 return;
103 }
104
105 for (i = 0; i < rows; i++) {
106 size_t threshold = i * (0xff / rows);
107 for (j = 0; j < cols; j++) {
108 size_t realJ = j * len / cols;
109 if (255 - buf[realJ] < threshold) {
110 if (p->histblock) {
111 p->cb_printf ("%s%s%s", Color_BGGRAY, block, Color_RESET);
112 } else {
113 cb_print (vline);
114 }
115 } else if (i + 1 == rows) {
116 cb_print ("_");
117 } else {
118 cb_print (" ");
119 }
120 }
121 cb_print ("\n");
122 }
123 }
124
r_util_lines_getline(ut64 * lines_cache,int lines_cache_sz,ut64 off)125 R_API int r_util_lines_getline(ut64 *lines_cache, int lines_cache_sz, ut64 off) {
126 int imax = lines_cache_sz;
127 int imin = 0;
128 int imid = 0;
129
130 while (imin <= imax) {
131 imid = imin + ((imax - imin) / 2);
132 if (lines_cache[imid] == off) {
133 return imid + 1;
134 }
135 if (lines_cache[imid] < off) {
136 imin = imid + 1;
137 } else {
138 imax = imid - 1;
139 }
140 }
141 return imin;
142 }
143
r_print_is_interrupted(void)144 R_API bool r_print_is_interrupted(void) {
145 if (is_interrupted_cb) {
146 return is_interrupted_cb ();
147 }
148 return false;
149 }
150
r_print_set_is_interrupted_cb(RPrintIsInterruptedCallback cb)151 R_API void r_print_set_is_interrupted_cb(RPrintIsInterruptedCallback cb) {
152 is_interrupted_cb = cb;
153 }
154
r_print_mute(RPrint * p,int x)155 R_API bool r_print_mute(RPrint *p, int x) {
156 if (x) {
157 if (p->cb_printf == &nullprinter) {
158 return false;
159 }
160 p->oprintf = p->cb_printf;
161 p->cb_printf = nullprinter;
162 return true;
163 }
164 if (p->cb_printf == nullprinter) {
165 p->cb_printf = p->oprintf;
166 return true;
167 }
168 return false;
169 }
170
r_print_stereogram_private(const char * bump,int w,int h,char * out,int size)171 static int r_print_stereogram_private(const char *bump, int w, int h, char *out, int size) {
172 static char data[32768]; // ???
173 const char *string = "Az+|.-=/^@_pT";
174 const int string_len = strlen (string);
175
176 int x, y, s, l = 0, l2 = 0, ch;
177 int skip = 7;
178 int bumpi = 0, outi = 0;
179 if (!bump || !out) {
180 return 0;
181 }
182 for (y = 0; bump[bumpi] && outi < size; y++) {
183 l = l2 = 0;
184 for (x = 0; bump[bumpi] && outi < size && x < w; x++) {
185 ch = string[x % string_len];
186 if (!l && x > skip) {
187 s = bump[bumpi++];
188 if (s >= '0' && s <= '9') {
189 s = '0' - s;
190 } else {
191 switch (s) {
192 case 0:
193 bumpi--;
194 /* passthru */
195 case '\n':
196 s = 0;
197 l = 1;
198 break;
199 case ' ':
200 s = 0;
201 break;
202 default:
203 s = -2;
204 break;
205 }
206 }
207 } else {
208 s = 0;
209 }
210 s += skip;
211 s = x - s;
212 if (s >= 0) {
213 ch = data[s];
214 }
215 if (!ch) {
216 ch = *string;
217 }
218 data[x] = ch;
219 if (outi >= size) {
220 break;
221 }
222 out[outi++] = ch;
223 }
224 out[outi++] = '\n';
225 s = 'a';
226 while (!l && s != '\n') {
227 s = bump[bumpi++];
228 if (!s) {
229 bumpi--;
230 break;
231 }
232 }
233 }
234 out[outi] = 0;
235 return 1;
236 }
237
r_print_stereogram(const char * bump,int w,int h)238 R_API char* r_print_stereogram(const char *bump, int w, int h) {
239 if (w < 1 || h < 1) {
240 return NULL;
241 }
242 ut64 size = w * (ut64) h * 2;
243 if (size > UT32_MAX) {
244 return NULL;
245 }
246 char *out = calloc (1, size * 2);
247 if (!out) {
248 return NULL;
249 }
250 //eprintf ("%s\n", bump);
251 (void) r_print_stereogram_private (bump, w, h, out, size);
252 return out;
253 }
254
255 #define STEREOGRAM_IN_COLOR 1
r_print_stereogram_bytes(const ut8 * buf,int len)256 R_API char* r_print_stereogram_bytes(const ut8 *buf, int len) {
257 int i, bumpi;
258 char *ret;
259 int scr_width = 80;
260 if (!buf || len < 1) {
261 return NULL;
262 }
263 //scr_width = r_cons_get_size (NULL) -10;
264 int cols = scr_width;
265 int rows = len / cols;
266
267 int size = (2 + cols) * rows;
268 char *bump = malloc (size + 1); //(cols+2) * rows);
269 if (!bump) {
270 return NULL;
271 }
272 for (i = bumpi = 0; bumpi < size && i < len; i++) {
273 int v = buf[i] / 26;
274 if (i && !(i % scr_width)) {
275 bump[bumpi++] = '\n';
276 }
277 bump[bumpi++] = '0' + v;
278 }
279 bump[bumpi] = 0;
280 ret = r_print_stereogram (bump, cols, rows);
281 free (bump);
282 return ret;
283 }
284
r_print_stereogram_print(RPrint * p,const char * ret)285 R_API void r_print_stereogram_print(RPrint *p, const char *ret) {
286 int i;
287 const int use_color = p->flags & R_PRINT_FLAGS_COLOR;
288 if (!ret) {
289 return;
290 }
291 if (use_color) {
292 for (i = 0; ret[i]; i++) {
293 p->cb_printf ("\x1b[%dm%c", 30 + (ret[i] % 8), ret[i]);
294 }
295 p->cb_printf ("\x1b[0m\n");
296 } else {
297 p->cb_printf ("%s\n", ret);
298 }
299 }
300
r_print_new(void)301 R_API RPrint* r_print_new(void) {
302 RPrint *p = R_NEW0 (RPrint);
303 if (!p) {
304 return NULL;
305 }
306 strcpy (p->datefmt, "%Y-%m-%d %H:%M:%S %z");
307 r_io_bind_init (p->iob);
308 p->pairs = true;
309 p->resetbg = true;
310 p->cb_printf = libc_printf;
311 p->cb_eprintf = libc_eprintf;
312 p->oprintf = nullprinter;
313 p->bits = 32;
314 p->stride = 0;
315 p->bytespace = 0;
316 p->big_endian = false;
317 p->datezone = 0;
318 p->col = 0;
319 p->width = 78;
320 p->cols = 16;
321 p->cur_enabled = false;
322 p->cur = p->ocur = -1;
323 p->formats = sdb_new0 ();
324 p->addrmod = 4;
325 p->flags =
326 R_PRINT_FLAGS_COLOR |
327 R_PRINT_FLAGS_OFFSET |
328 R_PRINT_FLAGS_HEADER |
329 R_PRINT_FLAGS_ADDRMOD;
330 p->seggrn = 4;
331 p->zoom = R_NEW0 (RPrintZoom);
332 p->reg = NULL;
333 p->get_register = NULL;
334 p->get_register_value = NULL;
335 p->lines_cache = NULL;
336 p->calc_row_offsets = true;
337 p->row_offsets_sz = 0;
338 p->row_offsets = NULL;
339 p->vflush = true;
340 p->screen_bounds = 0;
341 p->esc_bslash = false;
342 p->strconv_mode = NULL;
343 memset (&p->consbind, 0, sizeof (p->consbind));
344 p->io_unalloc_ch = '.';
345 p->enable_progressbar = true;
346 p->charset = r_charset_new ();
347 return p;
348 }
349
r_print_free(RPrint * p)350 R_API RPrint* r_print_free(RPrint *p) {
351 if (!p) {
352 return NULL;
353 }
354 sdb_free (p->formats);
355 p->formats = NULL;
356 R_FREE (p->strconv_mode);
357 if (p->zoom) {
358 free (p->zoom->buf);
359 free (p->zoom);
360 p->zoom = NULL;
361 }
362 R_FREE (p->lines_cache);
363 R_FREE (p->row_offsets);
364 r_charset_free (p->charset);
365 free (p);
366 return NULL;
367 }
368
369 // dummy setter can be removed
r_print_set_flags(RPrint * p,int _flags)370 R_API void r_print_set_flags(RPrint *p, int _flags) {
371 p->flags = _flags;
372 }
373
r_print_unset_flags(RPrint * p,int flags)374 R_API void r_print_unset_flags(RPrint *p, int flags) {
375 p->flags = p->flags & (p->flags ^ flags);
376 }
377
r_print_set_cursor(RPrint * p,int enable,int ocursor,int cursor)378 R_API void r_print_set_cursor(RPrint *p, int enable, int ocursor, int cursor) {
379 if (!p) {
380 return;
381 }
382 p->cur_enabled = enable;
383 p->ocur = ocursor;
384 if (cursor < 0) {
385 cursor = 0;
386 }
387 p->cur = cursor;
388 }
389
r_print_have_cursor(RPrint * p,int cur,int len)390 R_API bool r_print_have_cursor(RPrint *p, int cur, int len) {
391 if (!p || !p->cur_enabled) {
392 return false;
393 }
394 if (p->ocur != -1) {
395 int from = p->ocur;
396 int to = p->cur;
397 r_num_minmax_swap_i (&from, &to);
398 do {
399 if (cur + len - 1 >= from && cur + len - 1 <= to) {
400 return true;
401 }
402 } while (--len);
403 } else if (p->cur >= cur && p->cur <= cur + len - 1) {
404 return true;
405 }
406 return false;
407 }
408
r_print_cursor_pointer(RPrint * p,int cur,int len)409 R_API bool r_print_cursor_pointer(RPrint *p, int cur, int len) {
410 r_return_val_if_fail (p, false);
411 if (!p->cur_enabled) {
412 return false;
413 }
414 int to = p->cur;
415 do {
416 if (cur + len - 1 == to) {
417 return true;
418 }
419 } while (--len);
420 return false;
421 }
422
r_print_cursor(RPrint * p,int cur,int len,int set)423 R_API void r_print_cursor(RPrint *p, int cur, int len, int set) {
424 if (r_print_have_cursor (p, cur, len)) {
425 p->cb_printf ("%s", R_CONS_INVERT (set, 1));
426 }
427 }
428
r_print_addr(RPrint * p,ut64 addr)429 R_API void r_print_addr(RPrint *p, ut64 addr) {
430 char space[32] = {
431 0
432 };
433 const char *white = "";
434 #define PREOFF(x) (p && p->cons && p->cons->context && p->cons->context->pal.x)? p->cons->context->pal.x
435 PrintfCallback printfmt = (PrintfCallback) (p? p->cb_printf: libc_printf);
436 #define print(x) printfmt("%s", x)
437 bool use_segoff = p? (p->flags & R_PRINT_FLAGS_SEGOFF): false;
438 bool use_color = p? (p->flags & R_PRINT_FLAGS_COLOR): false;
439 bool dec = p? (p->flags & R_PRINT_FLAGS_ADDRDEC): false;
440 bool mod = p? (p->flags & R_PRINT_FLAGS_ADDRMOD): false;
441 char ch = p? ((p->addrmod && mod)? ((addr % p->addrmod)? ' ': ','): ' '): ' ';
442 if (p && p->flags & R_PRINT_FLAGS_COMPACT && p->col == 1) {
443 ch = '|';
444 }
445 if (p && p->pava) {
446 ut64 va = p->iob.p2v (p->iob.io, addr);
447 if (va != UT64_MAX) {
448 addr = va;
449 }
450 }
451 if (use_segoff) {
452 ut32 s, a;
453 a = addr & 0xffff;
454 s = (addr - a) >> (p? p->seggrn: 0);
455 if (dec) {
456 snprintf (space, sizeof (space), "%d:%d", s & 0xffff, a & 0xffff);
457 white = r_str_pad (' ', 9 - strlen (space));
458 }
459 if (use_color) {
460 const char *pre = PREOFF (offset): Color_GREEN;
461 const char *fin = Color_RESET;
462 if (dec) {
463 printfmt ("%s%s%s%s%c", pre, white, space, fin, ch);
464 } else {
465 printfmt ("%s%04x:%04x%s%c", pre, s & 0xffff, a & 0xffff, fin, ch);
466 }
467 } else {
468 if (dec) {
469 printfmt ("%s%s%c", white, space, ch);
470 } else {
471 printfmt ("%04x:%04x%c", s & 0xffff, a & 0xffff, ch);
472 }
473 }
474 } else {
475 if (dec) {
476 snprintf (space, sizeof (space), "%" PFMT64d, addr);
477 int w = R_MAX (10 - strlen (space), 0);
478 white = r_str_pad (' ', w);
479 }
480 if (use_color) {
481 const char *pre = PREOFF (offset): Color_GREEN;
482 const char *fin = Color_RESET;
483 if (p && p->flags & R_PRINT_FLAGS_RAINBOW) {
484 // pre = r_cons_rgb_str_off (rgbstr, addr);
485 if (p->cons && p->cons->rgbstr) {
486 static char rgbstr[32];
487 pre = p->cons->rgbstr (rgbstr, sizeof (rgbstr), addr);
488 }
489 }
490 if (dec) {
491 printfmt ("%s%s%" PFMT64d "%s%c", pre, white, addr, fin, ch);
492 } else {
493 if (p && p->wide_offsets) {
494 // TODO: make %016 depend on asm.bits
495 printfmt ("%s0x%016" PFMT64x "%s%c", pre, addr, fin, ch);
496 } else {
497 printfmt ("%s0x%08" PFMT64x "%s%c", pre, addr, fin, ch);
498 }
499 }
500 } else {
501 if (dec) {
502 printfmt ("%s%" PFMT64d "%c", white, addr, ch);
503 } else {
504 if (p && p->wide_offsets) {
505 // TODO: make %016 depend on asm.bits
506 printfmt ("0x%016" PFMT64x "%c", addr, ch);
507 } else {
508 printfmt ("0x%08" PFMT64x "%c", addr, ch);
509 }
510 }
511 }
512 }
513 }
514
r_print_hexpair(RPrint * p,const char * str,int n)515 R_API char* r_print_hexpair(RPrint *p, const char *str, int n) {
516 const char *s, *lastcol = Color_WHITE;
517 char *d, *dst = (char *) calloc ((strlen (str) + 2), 32);
518 int colors = p->flags & R_PRINT_FLAGS_COLOR;
519 const char *color_0x00 = "";
520 const char *color_0x7f = "";
521 const char *color_0xff = "";
522 const char *color_text = "";
523 const char *color_other = "";
524 int bs = p->bytespace;
525 /* XXX That's hacky as shit.. but partially works O:) */
526 /* TODO: Use r_print_set_cursor for win support */
527 int cur = R_MIN (p->cur, p->ocur);
528 int ocur = R_MAX (p->cur, p->ocur);
529 int ch, i;
530
531 if (colors) {
532 #define P(x) (p->cons && p->cons->context->pal.x)? p->cons->context->pal.x
533 color_0x00 = P (b0x00): Color_GREEN;
534 color_0x7f = P (b0x7f): Color_YELLOW;
535 color_0xff = P (b0xff): Color_RED;
536 color_text = P (btext): Color_MAGENTA;
537 color_other = P (other): "";
538 }
539 if (p->cur_enabled && cur == -1) {
540 cur = ocur;
541 }
542 ocur++;
543 d = dst;
544 // XXX: overflow here
545 // TODO: Use r_cons primitives here
546 #define memcat(x, y)\
547 { \
548 memcpy (x, y, strlen (y));\
549 (x) += strlen (y);\
550 }
551 for (s = str, i = 0; s[0]; i++) {
552 int d_inc = 2;
553 if (p->cur_enabled) {
554 if (i == ocur - n) {
555 memcat (d, Color_RESET);
556 }
557 if (colors) {
558 memcat (d, lastcol);
559 }
560 if (i >= cur - n && i < ocur - n) {
561 memcat (d, Color_INVERT);
562 }
563 }
564 if (colors) {
565 if (s[0] == '0' && s[1] == '0') {
566 lastcol = color_0x00;
567 } else if (s[0] == '7' && s[1] == 'f') {
568 lastcol = color_0x7f;
569 } else if (s[0] == 'f' && s[1] == 'f') {
570 lastcol = color_0xff;
571 } else {
572 ch = r_hex_pair2bin (s);
573 if (ch == -1) {
574 break;
575 }
576 if (IS_PRINTABLE (ch)) {
577 lastcol = color_text;
578 } else {
579 lastcol = color_other;
580 }
581 }
582 memcat (d, lastcol);
583 }
584 if (s[0] == '.') {
585 d_inc = 1;
586 }
587 memcpy (d, s, d_inc);
588 d += d_inc;
589 s += d_inc;
590 if (bs) {
591 memcat (d, " ");
592 }
593 }
594 if (colors || p->cur_enabled) {
595 if (p->resetbg) {
596 memcat (d, Color_RESET);
597 } else {
598 memcat (d, Color_RESET_NOBG);
599 }
600 }
601 *d = '\0';
602 return dst;
603 }
604
605 static char colorbuffer[64];
606 #define P(x) (p->cons && p->cons->context->pal.x)? p->cons->context->pal.x
r_print_byte_color(RPrint * p,int ch)607 R_API const char *r_print_byte_color(RPrint *p, int ch) {
608 if (p->flags & R_PRINT_FLAGS_RAINBOW) {
609 // EXPERIMENTAL
610 int bg = (p->flags & R_PRINT_FLAGS_NONHEX)? 48: 38;
611 snprintf (colorbuffer, sizeof (colorbuffer), "\033[%d;5;%dm", bg, ch);
612 return colorbuffer;
613 }
614 const bool use_color = p->flags & R_PRINT_FLAGS_COLOR;
615 if (!use_color) {
616 return NULL;
617 }
618 switch (ch) {
619 case 0x00: return P (b0x00): Color_GREEN;
620 case 0x7F: return P (b0x7f): Color_YELLOW;
621 case 0xFF: return P (b0xff): Color_RED;
622 default: return IS_PRINTABLE (ch)? P (btext): Color_MAGENTA: P (other): Color_WHITE;
623 }
624 return NULL;
625 }
626
r_print_byte(RPrint * p,const char * fmt,int idx,ut8 ch)627 R_API void r_print_byte(RPrint *p, const char *fmt, int idx, ut8 ch) {
628 PrintfCallback printfmt = (PrintfCallback) (p? p->cb_printf: libc_printf);
629 #define print(x) printfmt("%s", x)
630 ut8 rch = ch;
631 if (!IS_PRINTABLE (ch) && fmt[0] == '%' && fmt[1] == 'c') {
632 rch = '.';
633 }
634 r_print_cursor (p, idx, 1, 1);
635 if (p && p->flags & R_PRINT_FLAGS_COLOR) {
636 const char *bytecolor = r_print_byte_color (p, ch);
637 if (bytecolor) {
638 print ( bytecolor);
639 }
640 printfmt (fmt, rch);
641 if (bytecolor) {
642 print (Color_RESET);
643 }
644 } else {
645 printfmt (fmt, rch);
646 }
647 r_print_cursor (p, idx, 1, 0);
648 }
649
r_print_string(RPrint * p,ut64 seek,const ut8 * buf,int len,int options)650 R_API int r_print_string(RPrint *p, ut64 seek, const ut8 *buf, int len, int options) {
651 int i;
652 bool wide = (options & R_PRINT_STRING_WIDE);
653 bool wide32 = (options & R_PRINT_STRING_WIDE32);
654 bool zeroend = (options & R_PRINT_STRING_ZEROEND);
655 bool wrap = (options & R_PRINT_STRING_WRAP);
656 bool urlencode = (options & R_PRINT_STRING_URLENCODE);
657 bool esc_nl = (options & R_PRINT_STRING_ESC_NL);
658 int col = 0;
659 i = 0;
660 for (; !r_print_is_interrupted () && i < len; i++) {
661 if (wide32) {
662 int j = i;
663 while (buf[j] == '\0' && j < (i + 3)) {
664 j++;
665 }
666 i = j;
667 }
668 if (zeroend && buf[i] == '\0') {
669 break;
670 }
671 r_print_cursor (p, i, 1, 1);
672 ut8 b = buf[i];
673 if (b == '\n') {
674 col = 0;
675 }
676 col++;
677 if (urlencode) {
678 // TODO: some ascii can be bypassed here
679 p->cb_printf ("%%%02x", b);
680 } else {
681 if (b == '\\') {
682 p->cb_printf ("\\\\");
683 } else if ((b == '\n' && !esc_nl) || IS_PRINTABLE (b)) {
684 p->cb_printf ("%c", b);
685 } else {
686 p->cb_printf ("\\x%02x", b);
687 }
688 }
689 r_print_cursor (p, i, 1, 0);
690 if (wrap && col + 1 >= p->width) {
691 p->cb_printf ("\n");
692 col = 0;
693 }
694 if (wide) {
695 i++;
696 }
697 }
698 p->cb_printf ("\n");
699 return i;
700 }
701
r_print_hexpairs(RPrint * p,ut64 addr,const ut8 * buf,int len)702 R_API void r_print_hexpairs(RPrint *p, ut64 addr, const ut8 *buf, int len) {
703 int i;
704 for (i = 0; i < len; i++) {
705 p->cb_printf ("%02x ", buf[i]);
706 }
707 }
708
checkSparse(const ut8 * p,int len,int ch)709 static bool checkSparse(const ut8 *p, int len, int ch) {
710 int i;
711 ut8 q = *p;
712 if (ch && ch != q) {
713 return false;
714 }
715 for (i = 1; i < len; i++) {
716 if (p[i] != q) {
717 return false;
718 }
719 }
720 return true;
721 }
722
isAllZeros(const ut8 * buf,int len)723 static bool isAllZeros(const ut8 *buf, int len) {
724 int i;
725 for (i = 0; i < len; i++) {
726 if (buf[i] != 0) {
727 return false;
728 }
729 }
730 return true;
731 }
732
733 #define Pal(x,y) (x->cons && x->cons->context->pal.y)? x->cons->context->pal.y
r_print_hexii(RPrint * rp,ut64 addr,const ut8 * buf,int len,int step)734 R_API void r_print_hexii(RPrint *rp, ut64 addr, const ut8 *buf, int len, int step) {
735 PrintfCallback p = (PrintfCallback) rp->cb_printf;
736 bool c = rp->flags & R_PRINT_FLAGS_COLOR;
737 const char *color_0xff = c? (Pal (rp, b0xff): Color_RED): "";
738 const char *color_text = c? (Pal (rp, btext): Color_MAGENTA): "";
739 const char *color_other = c? (Pal (rp, other): Color_WHITE): "";
740 const char *color_reset = c? Color_RESET: "";
741 int i, j;
742 bool show_offset = rp->show_offset;
743
744 if (rp->flags & R_PRINT_FLAGS_HEADER) {
745 p (" ");
746 for (i = 0; i < step; i++) {
747 p ("%3X", i);
748 }
749 p ("\n");
750 }
751
752 for (i = 0; i < len; i += step) {
753 int inc = R_MIN (step, (len - i));
754 if (isAllZeros (buf + i, inc)) {
755 continue;
756 }
757 if (show_offset) {
758 p ("%8"PFMT64x":", addr + i);
759 }
760 for (j = 0; j < inc; j++) {
761 ut8 ch = buf[i + j];
762 if (ch == 0x00) {
763 p (" ");
764 } else if (ch == 0xff) {
765 p ("%s ##%s", color_0xff, color_reset);
766 } else if (IS_PRINTABLE (ch)) {
767 p ("%s .%c%s", color_text, ch, color_reset);
768 } else {
769 p ("%s %02x%s", color_other, ch, color_reset);
770 }
771 }
772 p ("\n");
773 }
774 p ("%8"PFMT64x" ]\n", addr + i);
775 }
776
777 /* set screen_bounds to addr if the cursor is not visible on the screen anymore.
778 * Note: screen_bounds is set only the first time this happens. */
r_print_set_screenbounds(RPrint * p,ut64 addr)779 R_API void r_print_set_screenbounds(RPrint *p, ut64 addr) {
780 int r, rc;
781
782 r_return_if_fail (p);
783
784 if (!p->screen_bounds) {
785 return;
786 }
787 if (!p->consbind.get_size) {
788 return;
789 }
790 if (!p->consbind.get_cursor) {
791 return;
792 }
793
794 if (p->screen_bounds == 1) {
795 (void)p->consbind.get_size (&r);
796 (void)p->consbind.get_cursor (&rc);
797
798 if (rc > r - 1) {
799 p->screen_bounds = addr;
800 }
801 }
802 }
803
r_print_section(RPrint * p,ut64 at)804 R_API void r_print_section(RPrint *p, ut64 at) {
805 bool use_section = p && p->flags & R_PRINT_FLAGS_SECTION;
806 if (use_section) {
807 const char *s = p->get_section_name (p->user, at);
808 if (!s) {
809 s = "";
810 }
811 char *tail = r_str_ndup (s, 19);
812 p->cb_printf ("%20s ", tail);
813 free (tail);
814 }
815 }
816
r_print_hexdump(RPrint * p,ut64 addr,const ut8 * buf,int len,int base,int step,size_t zoomsz)817 R_API void r_print_hexdump(RPrint *p, ut64 addr, const ut8 *buf, int len, int base, int step, size_t zoomsz) {
818 PrintfCallback printfmt = (PrintfCallback)printf;
819 #define print(x) printfmt("%s", x)
820 bool c = p? (p->flags & R_PRINT_FLAGS_COLOR): false;
821 const char *color_title = c? (Pal (p, offset): Color_MAGENTA): "";
822 int inc = p? p->cols : 16;
823 size_t i, j, k;
824 int sparse_char = 0;
825 int stride = 0;
826 int col = 0; // selected column (0=none, 1=hex, 2=ascii)
827 int use_sparse = 0;
828 bool use_header = true;
829 bool use_hdroff = true;
830 bool use_pair = true;
831 bool use_offset = true;
832 bool compact = false;
833 bool use_segoff = false;
834 bool pairs = false;
835 const char *bytefmt = "%02x";
836 const char *pre = "";
837 int last_sparse = 0;
838 bool use_hexa = true;
839 bool use_align = false;
840 bool use_unalloc = false;
841 const char *a, *b;
842 int K = 0;
843 bool hex_style = false;
844 if (step < len) {
845 len = len - (len % step);
846 }
847 if (p) {
848 pairs = p->pairs;
849 use_sparse = p->flags & R_PRINT_FLAGS_SPARSE;
850 use_header = p->flags & R_PRINT_FLAGS_HEADER;
851 use_hdroff = p->flags & R_PRINT_FLAGS_HDROFF;
852 use_segoff = p->flags & R_PRINT_FLAGS_SEGOFF;
853 use_align = p->flags & R_PRINT_FLAGS_ALIGN;
854 use_offset = p->flags & R_PRINT_FLAGS_OFFSET;
855 hex_style = p->flags & R_PRINT_FLAGS_STYLE;
856 use_hexa = !(p->flags & R_PRINT_FLAGS_NONHEX);
857 use_unalloc = p->flags & R_PRINT_FLAGS_UNALLOC;
858 compact = p->flags & R_PRINT_FLAGS_COMPACT;
859 inc = p->cols; // row width
860 col = p->col;
861 printfmt = (PrintfCallback) p->cb_printf;
862 stride = p->stride;
863 }
864 if (!use_hexa) {
865 inc *= 4;
866 }
867 if (step < 1) {
868 step = 1;
869 }
870 if (inc < 1) {
871 inc = 1;
872 }
873 if (zoomsz < 1) {
874 zoomsz = 1;
875 }
876 switch (base) {
877 case -10:
878 bytefmt = "0x%08x ";
879 pre = " ";
880 if (inc < 4) {
881 inc = 4;
882 }
883 break;
884 case -1:
885 bytefmt = "0x%08x ";
886 pre = " ";
887 if (inc < 4) {
888 inc = 4;
889 }
890 break;
891 case 8:
892 bytefmt = "%03o";
893 pre = " ";
894 break;
895 case 10:
896 bytefmt = "%3d";
897 pre = " ";
898 break;
899 case 16:
900 if (inc < 2) {
901 inc = 2;
902 use_header = false;
903 }
904 break;
905 case 32:
906 bytefmt = "0x%08x ";
907 pre = " ";
908 if (inc < 4) {
909 inc = 4;
910 }
911 break;
912 case 64:
913 bytefmt = "0x%016x ";
914 pre = " ";
915 if (inc < 8) {
916 inc = 8;
917 }
918 break;
919 }
920 const char *space = hex_style? ".": " ";
921 // TODO: Use base to change %03o and so on
922 if (step == 1 && base < 0) {
923 use_header = false;
924 }
925 if (use_header) {
926 if (c) {
927 print (color_title);
928 }
929 if (base < 32) {
930 { // XXX: use r_print_addr_header
931 int i, delta;
932 char soff[32];
933 if (hex_style) {
934 print ("..offset..");
935 } else {
936 print ("- offset -");
937 if (p->wide_offsets) {
938 print (" ");
939 }
940 }
941 if (use_segoff) {
942 ut32 s, a;
943 a = addr & 0xffff;
944 s = ((addr - a) >> p->seggrn) & 0xffff;
945 snprintf (soff, sizeof (soff), "%04x:%04x ", s, a);
946 delta = strlen (soff) - 10;
947 } else {
948 snprintf (soff, sizeof (soff), "0x%08" PFMT64x, addr);
949 delta = strlen (soff) - 9;
950 }
951 if (compact) {
952 delta--;
953 }
954 for (i = 0; i < delta; i++) {
955 print (space);
956 }
957 }
958 /* column after number, before hex data */
959 print ((col == 1)? "|": space);
960 if (use_hdroff) {
961 k = addr & 0xf;
962 K = (addr >> 4) & 0xf;
963 } else {
964 k = 0; // TODO: ??? SURE??? config.seek & 0xF;
965 }
966 if (use_hexa) {
967 /* extra padding for offsets > 8 digits */
968 for (i = 0; i < inc; i++) {
969 print (pre);
970 if (base < 0) {
971 if (i & 1) {
972 print (space);
973 }
974 }
975 if (use_hdroff) {
976 if (use_pair) {
977 printfmt ("%c%c",
978 hex[(((i+k) >> 4) + K) % 16],
979 hex[(i + k) % 16]);
980 } else {
981 printfmt (" %c", hex[(i + k) % 16]);
982 }
983 } else {
984 printfmt (" %c", hex[(i + k) % 16]);
985 }
986 if (i & 1 || !pairs) {
987 if (!compact) {
988 print (col != 1? space: ((i + 1) < inc)? space: "|");
989 }
990 }
991 }
992 }
993 /* ascii column */
994 if (compact) {
995 print (col > 0? "|": space);
996 } else {
997 print (col == 2? "|": space);
998 }
999 if (!p || !(p->flags & R_PRINT_FLAGS_NONASCII)) {
1000 for (i = 0; i < inc; i++) {
1001 printfmt ("%c", hex[(i + k) % 16]);
1002 }
1003 }
1004 if (col == 2) {
1005 printfmt ("|");
1006 }
1007 /* print comment header*/
1008 if (p && p->use_comments && !compact) {
1009 if (col != 2) {
1010 print (" ");
1011 }
1012 if (!hex_style) {
1013 print (" comment");
1014 }
1015 }
1016 print ("\n");
1017 }
1018
1019 if (c) {
1020 print (Color_RESET);
1021 }
1022 }
1023
1024 // is this necessary?
1025 r_print_set_screenbounds (p, addr);
1026 int rowbytes;
1027 int rows = 0;
1028 int bytes = 0;
1029 bool printValue = true;
1030 bool oPrintValue = true;
1031 bool isPxr = (p && p->flags & R_PRINT_FLAGS_REFS);
1032
1033 for (i = j = 0; i < len; i += (stride? stride: inc)) {
1034 if (p && p->cons && p->cons->context && p->cons->context->breaked) {
1035 break;
1036 }
1037 rowbytes = inc;
1038 if (use_align) {
1039 int sz = (p && p->offsize)? p->offsize (p->user, addr + j): -1;
1040 if (sz > 0) { // flags with size 0 dont work
1041 rowbytes = sz;
1042 }
1043 }
1044
1045 if (use_sparse) {
1046 if (checkSparse (buf + i, inc, sparse_char)) {
1047 if (i + inc >= len || checkSparse (buf + i + inc, inc, sparse_char)) {
1048 if (i + inc + inc >= len ||
1049 checkSparse (buf + i + inc + inc, inc, sparse_char)) {
1050 sparse_char = buf[j];
1051 last_sparse++;
1052 if (last_sparse == 2) {
1053 print (" ...\n");
1054 continue;
1055 }
1056 if (last_sparse > 2) {
1057 continue;
1058 }
1059 }
1060 }
1061 } else {
1062 last_sparse = 0;
1063 }
1064 }
1065 ut64 at = addr + (j * zoomsz);
1066 if (use_offset && (!isPxr || inc < 4)) {
1067 r_print_section (p, at);
1068 r_print_addr (p, at);
1069 }
1070 int row_have_cursor = -1;
1071 ut64 row_have_addr = UT64_MAX;
1072 if (use_hexa) {
1073 if (!compact && !isPxr) {
1074 print ((col == 1)? "|": " ");
1075 }
1076 for (j = i; j < i + inc; j++) {
1077 if (j!=i && use_align && rowbytes == inc) {
1078 int sz = (p && p->offsize)? p->offsize (p->user, addr + j): -1;
1079 if (sz >= 0) {
1080 rowbytes = bytes;
1081 }
1082 }
1083 if (row_have_cursor == -1) {
1084 if (r_print_cursor_pointer (p, j, 1)) {
1085 row_have_cursor = j - i;
1086 row_have_addr = addr + j;
1087 }
1088 }
1089 if (!compact && ((j >= len) || bytes >= rowbytes)) {
1090 if (col == 1) {
1091 if (j + 1 >= inc + i) {
1092 print (j % 2? " |": "| ");
1093 } else {
1094 print (j % 2? " ": " ");
1095 }
1096 } else {
1097 if (base == 32) {
1098 print ((j % 4)? " ": " ");
1099 } else if (base == 10) {
1100 print (j % 2? " ": " ");
1101 } else {
1102 print (j % 2? " ": " ");
1103 }
1104 }
1105 continue;
1106 }
1107 const char *hl = (hex_style && p && p->offname (p->user, addr + j))? Color_INVERT: NULL;
1108 if (hl) {
1109 print (hl);
1110 }
1111 if (p && (base == 32 || base == 64)) {
1112 int left = len - i;
1113 /* TODO: check step. it should be 2/4 for base(32) and 8 for
1114 * base(64) */
1115 ut64 n = 0;
1116 size_t sz_n = (base == 64)
1117 ? sizeof (ut64) : (step == 2)
1118 ? sizeof (ut16) : sizeof (ut32);
1119 sz_n = R_MIN (left, sz_n);
1120 if (j + sz_n > len) {
1121 // oob
1122 j += sz_n;
1123 continue;
1124 }
1125 r_mem_swaporcopy ((ut8 *) &n, buf + j, sz_n, p && p->big_endian);
1126 r_print_cursor (p, j, sz_n, 1);
1127 // stub for colors
1128 if (p && p->colorfor) {
1129 if (!p->iob.addr_is_mapped (p->iob.io, addr + j)) {
1130 a = p->cons->context->pal.ai_unmap;
1131 } else {
1132 a = p->colorfor (p->user, n, true);
1133 }
1134 if (a && *a) {
1135 b = Color_RESET;
1136 } else {
1137 a = b = "";
1138 }
1139 } else {
1140 a = b = "";
1141 }
1142 printValue = true;
1143 bool hasNull = false;
1144 if (isPxr) {
1145 if (n == 0) {
1146 if (oPrintValue) {
1147 hasNull = true;
1148 }
1149 printValue = false;
1150 }
1151 }
1152 if (printValue) {
1153 if (use_offset && !hasNull && isPxr) {
1154 r_print_section (p, at);
1155 r_print_addr (p, addr + j * zoomsz);
1156 }
1157 if (base == 64) {
1158 printfmt ("%s0x%016" PFMT64x "%s ", a, (ut64) n, b);
1159 } else if (step == 2) {
1160 printfmt ("%s0x%04x%s ", a, (ut16) n, b);
1161 } else {
1162 printfmt ("%s0x%08x%s ", a, (ut32) n, b);
1163 }
1164 } else {
1165 if (hasNull) {
1166 const char *n = p->offname (p->user, addr + j);
1167 r_print_section (p, at);
1168 r_print_addr (p, addr + j * zoomsz);
1169 printfmt ("..[ null bytes ].. 00000000 %s\n", r_str_get (n));
1170 }
1171 }
1172 r_print_cursor (p, j, sz_n, 0);
1173 oPrintValue = printValue;
1174 j += step - 1;
1175 } else if (base == -8) {
1176 long long w = r_read_ble64 (buf + j, p && p->big_endian);
1177 r_print_cursor (p, j, 8, 1);
1178 printfmt ("%23" PFMT64d " ", w);
1179 r_print_cursor (p, j, 8, 0);
1180 j += 7;
1181 } else if (base == -1) {
1182 st8 w = r_read_ble8 (buf + j);
1183 r_print_cursor (p, j, 1, 1);
1184 printfmt ("%4d ", w);
1185 r_print_cursor (p, j, 1, 0);
1186 } else if (base == -10) {
1187 if (j + 1 < len) {
1188 st16 w = r_read_ble16 (buf + j, p && p->big_endian);
1189 r_print_cursor (p, j, 2, 1);
1190 printfmt ("%7d ", w);
1191 r_print_cursor (p, j, 2, 0);
1192 }
1193 j += 1;
1194 } else if (base == 10) { // "pxd"
1195 if (j + 3 < len) {
1196 int w = r_read_ble32 (buf + j, p && p->big_endian);
1197 r_print_cursor (p, j, 4, 1);
1198 printfmt ("%13d ", w);
1199 r_print_cursor (p, j, 4, 0);
1200 }
1201 j += 3;
1202 } else {
1203 if (j >= len) {
1204 break;
1205 }
1206 if (use_unalloc && !p->iob.is_valid_offset (p->iob.io, addr + j, false)) {
1207 char ch = p->io_unalloc_ch;
1208 char dbl_ch_str[] = { ch, ch, 0 };
1209 p->cb_printf ("%s", dbl_ch_str);
1210 } else {
1211 r_print_byte (p, bytefmt, j, buf[j]);
1212 }
1213 if (pairs && !compact && (inc & 1)) {
1214 bool mustspace = (rows % 2) ? !(j&1) : (j&1);
1215 if (mustspace) {
1216 print (" ");
1217 }
1218 } else if (bytes % 2 || !pairs) {
1219 if (col == 1) {
1220 if (j + 1 < inc + i) {
1221 if (!compact) {
1222 print (" ");
1223 }
1224 } else {
1225 print ("|");
1226 }
1227 } else {
1228 if (!compact) {
1229 print (" ");
1230 }
1231 }
1232 }
1233 }
1234 if (hl) {
1235 print (Color_RESET);
1236 }
1237 bytes++;
1238 }
1239 }
1240 if (printValue) {
1241 if (compact) {
1242 if (col == 0) {
1243 print (" ");
1244 } else if (col == 1) {
1245 //print (" ");
1246 } else {
1247 print ((col == 2)? "|": "");
1248 }
1249 } else {
1250 print ((col == 2)? "|": " ");
1251 }
1252 if (!p || !(p->flags & R_PRINT_FLAGS_NONASCII)) {
1253 bytes = 0;
1254 size_t end = i + inc;
1255 for (j = i; j < end; j++) {
1256 if (j != i && use_align && bytes >= rowbytes) {
1257 int sz = (p && p->offsize)? p->offsize (p->user, addr + j): -1;
1258 if (sz >= 0) {
1259 print (" ");
1260 break;
1261 }
1262 }
1263 if (j >= len || (use_align && bytes >= rowbytes)) {
1264 break;
1265 }
1266 ut8 ch = (use_unalloc && p && !p->iob.is_valid_offset (p->iob.io, addr + j, false))
1267 ? ' ' : buf[j];
1268 r_print_byte (p, "%c", j, ch);
1269 bytes++;
1270 }
1271 }
1272 /* ascii column */
1273 if (col == 2) {
1274 print ("|");
1275 }
1276 bool eol = false;
1277 if (!eol && p && p->flags & R_PRINT_FLAGS_REFS) {
1278 ut64 off = UT64_MAX;
1279 if (inc == 8) {
1280 if (i + sizeof (ut64) - 1 < len) {
1281 off = r_read_le64 (buf + i);
1282 }
1283 } else if (inc == 4) {
1284 if (i + sizeof (ut32) - 1 < len) {
1285 off = r_read_le32 (buf + i);
1286 }
1287 } else if (inc == 2 && base == 16) {
1288 if (i + sizeof (ut16) - 1 < len) {
1289 off = r_read_le16 (buf + i);
1290 if (off == 0) {
1291 off = UT64_MAX;
1292 }
1293 }
1294 }
1295 if (p->hasrefs && off != UT64_MAX) {
1296 char *rstr = p->hasrefs (p->user, addr + i, false);
1297 if (rstr && *rstr) {
1298 printfmt (" @ %s", rstr);
1299 }
1300 free (rstr);
1301 rstr = p->hasrefs (p->user, off, true);
1302 if (rstr && *rstr) {
1303 printfmt (" %s", rstr);
1304 }
1305 free (rstr);
1306 }
1307 }
1308 if (!eol && p && p->use_comments) {
1309 for (; j < i + inc; j++) {
1310 print (" ");
1311 }
1312 for (j = i; j < i + inc; j++) {
1313 if (use_align && (j-i) >= rowbytes) {
1314 break;
1315 }
1316 if (p && p->offname) {
1317 a = p->offname (p->user, addr + j);
1318 if (p->colorfor && a && *a) {
1319 const char *color = p->colorfor (p->user, addr + j, true);
1320 printfmt ("%s ; %s%s", r_str_get (color), a,
1321 color ? Color_RESET : "");
1322 }
1323 }
1324 char *comment = p->get_comments (p->user, addr + j);
1325 if (comment) {
1326 if (p && p->colorfor) {
1327 a = p->colorfor (p->user, addr + j, true);
1328 if (R_STR_ISEMPTY (a)) {
1329 a = "";
1330 }
1331 } else {
1332 a = "";
1333 }
1334 printfmt ("%s ; %s", a, comment);
1335 free (comment);
1336 }
1337 }
1338 }
1339 if (use_align && rowbytes < inc && bytes >= rowbytes) {
1340 i -= (inc - bytes);
1341 }
1342 print ("\n");
1343 }
1344 rows++;
1345 bytes = 0;
1346 if (p && p->cfmt && *p->cfmt) {
1347 if (row_have_cursor != -1) {
1348 int i = 0;
1349 print (" _________");
1350 if (!compact) {
1351 print ("_");
1352 }
1353 for (i = 0; i < row_have_cursor; i++) {
1354 if (!pairs || (!compact && i % 2)) {
1355 print ("___");
1356 } else {
1357 print ("__");
1358 }
1359 }
1360 print ("__|\n");
1361 printfmt ("| cmd.hexcursor = %s\n", p->cfmt);
1362 p->coreb.cmdf (p->coreb.core,
1363 "%s @ 0x%08"PFMT64x, p->cfmt, row_have_addr);
1364 }
1365 }
1366 }
1367 }
1368
r_print_hexdump_simple(const ut8 * buf,int len)1369 R_API void r_print_hexdump_simple(const ut8 *buf, int len) {
1370 r_print_hexdump (NULL, 0, buf, len, 16, 16, 0);
1371 }
1372
getbytediff(RPrint * p,char * fmt,ut8 a,ut8 b)1373 static const char* getbytediff(RPrint *p, char *fmt, ut8 a, ut8 b) {
1374 if (*fmt) {
1375 if (a == b) {
1376 sprintf (fmt, "%s%02x" Color_RESET, p->cons->context->pal.graph_true, a);
1377 } else {
1378 sprintf (fmt, "%s%02x" Color_RESET, p->cons->context->pal.graph_false, a);
1379 }
1380 } else {
1381 sprintf (fmt, "%02x", a);
1382 }
1383 return fmt;
1384 }
1385
getchardiff(RPrint * p,char * fmt,ut8 a,ut8 b)1386 static const char* getchardiff(RPrint *p, char *fmt, ut8 a, ut8 b) {
1387 char ch = IS_PRINTABLE (a)? a: '.';
1388 if (*fmt) {
1389 if (a == b) {
1390 sprintf (fmt, "%s%c" Color_RESET, p->cons->context->pal.graph_true, ch);
1391 } else {
1392 sprintf (fmt, "%s%c" Color_RESET, p->cons->context->pal.graph_false, ch);
1393 }
1394 } else {
1395 sprintf (fmt, "%c", ch);
1396 }
1397 //else { fmt[0] = ch; fmt[1]=0; }
1398 return fmt;
1399 }
1400
1401 #define BD(a, b) getbytediff (p, fmt, (a)[i + j], (b)[i + j])
1402 #define CD(a, b) getchardiff (p, fmt, (a)[i + j], (b)[i + j])
1403
M(const ut8 * b,int len)1404 static ut8* M(const ut8 *b, int len) {
1405 ut8 *r = malloc (len + 16);
1406 if (r) {
1407 memset (r, 0xff, len + 16);
1408 memcpy (r, b, len);
1409 }
1410 return r;
1411 }
1412
1413 // TODO: add support for cursor
r_print_hexdiff(RPrint * p,ut64 aa,const ut8 * _a,ut64 ba,const ut8 * _b,int len,int scndcol)1414 R_API void r_print_hexdiff(RPrint *p, ut64 aa, const ut8 *_a, ut64 ba, const ut8 *_b, int len, int scndcol) {
1415 ut8 *a, *b;
1416 char linediff, fmt[64];
1417 int color = p->flags & R_PRINT_FLAGS_COLOR;
1418 int diffskip = p->flags & R_PRINT_FLAGS_DIFFOUT;
1419 int i, j, min;
1420 if (!((a = M (_a, len)))) {
1421 return;
1422 }
1423 if (!((b = M (_b, len)))) {
1424 free (a);
1425 return;
1426 }
1427 for (i = 0; i < len; i += 16) {
1428 min = R_MIN (16, len - i);
1429 linediff = (memcmp (a + i, b + i, min))? '!': '|';
1430 if (diffskip && linediff == '|') {
1431 continue;
1432 }
1433 p->cb_printf ("0x%08" PFMT64x " ", aa + i);
1434 for (j = 0; j < min; j++) {
1435 *fmt = color;
1436 r_print_cursor (p, i + j, 1, 1);
1437 p->cb_printf ("%s", BD (a, b));
1438 r_print_cursor (p, i + j, 1, 0);
1439 }
1440 p->cb_printf (" ");
1441 for (j = 0; j < min; j++) {
1442 *fmt = color;
1443 r_print_cursor (p, i + j, 1, 1);
1444 p->cb_printf ("%s", CD (a, b));
1445 r_print_cursor (p, i + j, 1, 0);
1446 }
1447 if (scndcol) {
1448 p->cb_printf (" %c 0x%08" PFMT64x " ", linediff, ba + i);
1449 for (j = 0; j < min; j++) {
1450 *fmt = color;
1451 r_print_cursor (p, i + j, 1, 1);
1452 p->cb_printf ("%s", BD (b, a));
1453 r_print_cursor (p, i + j, 1, 0);
1454 }
1455 p->cb_printf (" ");
1456 for (j = 0; j < min; j++) {
1457 *fmt = color;
1458 r_print_cursor (p, i + j, 1, 1);
1459 p->cb_printf ("%s", CD (b, a));
1460 r_print_cursor (p, i + j, 1, 0);
1461 }
1462 p->cb_printf ("\n");
1463 } else {
1464 p->cb_printf (" %c\n", linediff);
1465 }
1466 }
1467 free (a);
1468 free (b);
1469 }
1470
r_print_bytes(RPrint * p,const ut8 * buf,int len,const char * fmt)1471 R_API void r_print_bytes(RPrint *p, const ut8 *buf, int len, const char *fmt) {
1472 int i;
1473 if (p) {
1474 for (i = 0; i < len; i++) {
1475 p->cb_printf (fmt, buf[i]);
1476 }
1477 p->cb_printf ("\n");
1478 } else {
1479 for (i = 0; i < len; i++) {
1480 printf (fmt, buf[i]);
1481 }
1482 printf ("\n");
1483 }
1484 }
1485
r_print_raw(RPrint * p,ut64 addr,const ut8 * buf,int len,int offlines)1486 R_API void r_print_raw(RPrint *p, ut64 addr, const ut8 *buf, int len, int offlines) {
1487 if (offlines == 2) {
1488 int i, j, cols = p->cols * 4;
1489 char ch;
1490 for (i = 0; i < len; i += cols) {
1491 p->cb_printf ("0x%08"PFMT64x" ", addr + i);
1492 for (j = 0; j < cols; j++) {
1493 if ((i + j) >= len) {
1494 break;
1495 }
1496 ch = buf[i + j];
1497 if (p->cur_enabled) {
1498 r_print_cursor (p, i + j, 1, 1);
1499 p->cb_printf ("%c", IS_PRINTABLE (ch)? ch: ' ');
1500 r_print_cursor (p, i + j, 1, 0);
1501 } else {
1502 p->cb_printf ("%c", IS_PRINTABLE (ch)? ch: ' ');
1503 }
1504 }
1505 p->cb_printf ("\n");
1506 }
1507 } else if (offlines) {
1508 const ut8 *o, *q;
1509 ut64 off;
1510 int i, linenum_abs, mustbreak = 0, linenum = 1;
1511 o = q = buf;
1512 i = 0;
1513 do {
1514 off = addr + (int) (size_t) (q - buf);
1515 linenum_abs = r_util_lines_getline (p->lines_cache, p->lines_cache_sz, off);
1516 if (p->lines_cache_sz > 0 && p->lines_abs) {
1517 p->cb_printf ("%d 0x%08" PFMT64x " ", linenum_abs, off);
1518 } else {
1519 p->cb_printf ("+%d 0x%08" PFMT64x " ", linenum, off);
1520 }
1521 for (; i < len && *q && *q != '\n'; q++, i++) {
1522 // just loop
1523 }
1524 if ((i + 1) >= len || !*q) {
1525 mustbreak = 1;
1526 }
1527 if ((q - o) > 0) {
1528 p->write (o, (int) (size_t) (q - o));
1529 }
1530 p->cb_printf ("\n");
1531 linenum++;
1532 o = ++q;
1533 i++;
1534 } while (!mustbreak);
1535 } else {
1536 p->write (buf, len);
1537 }
1538 }
1539
r_print_c(RPrint * p,const ut8 * str,int len)1540 R_API void r_print_c(RPrint *p, const ut8 *str, int len) {
1541 int i, inc = p->width / 6;
1542 p->cb_printf ("#define _BUFFER_SIZE %d\n"
1543 "unsigned char buffer[_BUFFER_SIZE] = {\n",
1544 len);
1545 for (i = 0; !r_print_is_interrupted () && i < len;) {
1546 r_print_byte (p, "0x%02x", i, str[i]);
1547 if (++i < len) {
1548 p->cb_printf (", ");
1549 }
1550 if (!(i % inc)) {
1551 p->cb_printf ("\n");
1552 }
1553 }
1554 p->cb_printf (" };\n");
1555 }
1556
1557 // HACK :D
1558 static RPrint staticp = {
1559 .cb_printf = libc_printf
1560 };
1561
1562 /* TODO: handle screen width */
r_print_progressbar(RPrint * p,int pc,int _cols)1563 R_API void r_print_progressbar(RPrint *p, int pc, int _cols) {
1564 // TODO: add support for colors
1565 int i, cols = (_cols == -1)? 78: _cols;
1566 if (!p) {
1567 p = &staticp;
1568 }
1569 const char *h_line = p->cons->use_utf8 ? RUNE_LONG_LINE_HORIZ : "-";
1570 const char *block = p->cons->use_utf8 ? UTF_BLOCK : "#";
1571
1572 pc = R_MAX (0, R_MIN (100, pc));
1573 if (p->flags & R_PRINT_FLAGS_HEADER) {
1574 p->cb_printf ("%4d%% ", pc);
1575 }
1576 cols -= 15;
1577 p->cb_printf ("[");
1578 for (i = cols * pc / 100; i; i--) {
1579 p->cb_printf ("%s", block);
1580 }
1581 for (i = cols - (cols * pc / 100); i; i--) {
1582 p->cb_printf ("%s", h_line);
1583 }
1584 p->cb_printf ("]");
1585 }
1586
1587 /* TODO: handle screen width */
r_print_progressbar_with_count(RPrint * p,unsigned int pc,unsigned int total,int _cols,bool reset_line)1588 R_API void r_print_progressbar_with_count(RPrint *p, unsigned int pc, unsigned int total, int _cols, bool reset_line) {
1589 int i, cols = (_cols == -1)? 78: _cols;
1590 if (!p) {
1591 p = &staticp;
1592 }
1593 const bool enable_colors = p && (p->flags & R_PRINT_FLAGS_COLOR);
1594 const char *h_line = p->cons->use_utf8? RUNE_LONG_LINE_HORIZ: "-";
1595 const char *block = p->cons->use_utf8? UTF_BLOCK: "#";
1596
1597 total = R_MAX (1, total);
1598 pc = R_MAX (0, R_MIN (total, pc));
1599 if (reset_line) {
1600 p->cb_printf ("\r");
1601 }
1602 if (p->flags & R_PRINT_FLAGS_HEADER) {
1603 if (enable_colors) {
1604 p->cb_printf ("%s%4d%s%% %s%6d%s/%6d%s ", Color_GREEN, pc * 100 / total, Color_RESET, Color_GREEN, pc, Color_RESET, total, Color_YELLOW);
1605 } else {
1606 p->cb_printf ("%4d%% %6d/%6d ", pc * 100 / total, pc, total);
1607 }
1608 // TODO: determine string length of the numbers
1609 cols -= 20;
1610 }
1611 if (cols > 0) {
1612 if (enable_colors) {
1613 p->cb_printf ("[%s", Color_YELLOW);
1614 } else {
1615 p->cb_printf ("[");
1616 }
1617 for (i = cols * pc / total; i; i--) {
1618 p->cb_printf ("%s", block);
1619 }
1620 if (enable_colors) {
1621 p->cb_printf ("%s", Color_RESET);
1622 }
1623 for (i = cols - (cols * pc / total); i; i--) {
1624 p->cb_printf ("%s", h_line);
1625 }
1626 if (enable_colors) {
1627 p->cb_printf ("%s]", Color_RESET);
1628 }
1629 else {
1630 p->cb_printf ("]");
1631 }
1632 }
1633 }
1634
r_print_rangebar(RPrint * p,ut64 startA,ut64 endA,ut64 min,ut64 max,int cols)1635 R_API void r_print_rangebar(RPrint *p, ut64 startA, ut64 endA, ut64 min, ut64 max, int cols) {
1636 const char *h_line = p->cons->use_utf8? RUNE_LONG_LINE_HORIZ: "-";
1637 const char *block = p->cons->use_utf8? UTF_BLOCK: "#";
1638 const bool show_colors = p->flags & R_PRINT_FLAGS_COLOR;
1639 int j = 0;
1640 p->cb_printf ("|");
1641 if (cols < 1) {
1642 cols = 1;
1643 }
1644 int mul = (max - min) / cols;
1645 bool isFirst = true;
1646 for (j = 0; j < cols; j++) {
1647 ut64 startB = min + (j * mul);
1648 ut64 endB = min + ((j + 1) * mul);
1649 if (startA <= endB && endA >= startB) {
1650 if (show_colors & isFirst) {
1651 p->cb_printf (Color_GREEN);
1652 isFirst = false;
1653 }
1654 p->cb_printf ("%s", block);
1655 } else {
1656 if (!isFirst) {
1657 p->cb_printf (Color_RESET);
1658 }
1659 p->cb_printf ("%s", h_line);
1660 }
1661 }
1662 p->cb_printf ("|");
1663 }
1664
r_print_zoom_buf(RPrint * p,void * user,RPrintZoomCallback cb,ut64 from,ut64 to,int len,int maxlen)1665 R_API void r_print_zoom_buf(RPrint *p, void *user, RPrintZoomCallback cb, ut64 from, ut64 to, int len, int maxlen) {
1666 static int mode = -1;
1667 ut8 *bufz = NULL, *bufz2 = NULL;
1668 int i, j = 0;
1669 ut64 size = (to - from);
1670 size = len? size / len: 0;
1671
1672 if (maxlen < 2) {
1673 maxlen = 1024 * 1024;
1674 }
1675 if (size > maxlen) {
1676 size = maxlen;
1677 }
1678 if (size < 1) {
1679 size = 1;
1680 }
1681 if (len < 1) {
1682 len = 1;
1683 }
1684
1685 if (mode == p->zoom->mode && from == p->zoom->from && to == p->zoom->to && size == p->zoom->size) {
1686 // get from cache
1687 bufz = p->zoom->buf;
1688 size = p->zoom->size;
1689 } else {
1690 mode = p->zoom->mode;
1691 bufz = (ut8 *) calloc (1, len);
1692 if (!bufz) {
1693 return;
1694 }
1695 bufz2 = (ut8 *) calloc (1, size);
1696 if (!bufz2) {
1697 free (bufz);
1698 return;
1699 }
1700
1701 // TODO: memoize blocks or gtfo
1702 for (i = 0; i < len; i++) {
1703 if (p->cons->context->breaked) {
1704 break;
1705 }
1706 p->iob.read_at (p->iob.io, from + j, bufz2, size);
1707 bufz[i] = cb (user, p->zoom->mode, from + j, bufz2, size);
1708 j += size;
1709 }
1710 free (bufz2);
1711 // memoize
1712 free (p->zoom->buf);
1713 p->zoom->buf = bufz;
1714 p->zoom->from = from;
1715 p->zoom->to = to;
1716 p->zoom->size = len; // size;
1717 }
1718 }
1719
r_print_zoom(RPrint * p,void * user,RPrintZoomCallback cb,ut64 from,ut64 to,int len,int maxlen)1720 R_API void r_print_zoom(RPrint *p, void *user, RPrintZoomCallback cb, ut64 from, ut64 to, int len, int maxlen) {
1721 ut64 size = (to - from);
1722 r_print_zoom_buf (p, user, cb, from, to, len, maxlen);
1723 size = len? size / len: 0;
1724 p->flags &= ~R_PRINT_FLAGS_HEADER;
1725 r_print_hexdump (p, from, p->zoom->buf, p->zoom->size, 16, 1, size);
1726 p->flags |= R_PRINT_FLAGS_HEADER;
1727 }
1728
printHistBlock(RPrint * p,int k,int cols)1729 static inline void printHistBlock (RPrint *p, int k, int cols) {
1730 RConsPrintablePalette *pal = &p->cons->context->pal;
1731 const char *h_line = p->cons->use_utf8 ? RUNE_LONG_LINE_HORIZ : "-";
1732 const char *block = p->cons->use_utf8 ? UTF_BLOCK : "#";
1733 const char *kol[5];
1734 kol[0] = pal->nop;
1735 kol[1] = pal->mov;
1736 kol[2] = pal->cjmp;
1737 kol[3] = pal->jmp;
1738 kol[4] = pal->call;
1739 if (cols < 1) {
1740 cols = 1;
1741 }
1742 const bool show_colors = (p && (p->flags & R_PRINT_FLAGS_COLOR));
1743 if (show_colors) {
1744 int idx = (int) ((k * 4) / cols);
1745 const char *str = kol[idx];
1746 if (p->histblock) {
1747 p->cb_printf ("%s%s%s", str, block, Color_RESET);
1748 } else {
1749 p->cb_printf ("%s%s%s", str, h_line, Color_RESET);
1750 }
1751 } else {
1752 if (p->histblock) {
1753 p->cb_printf ("%s", block);
1754 } else {
1755 p->cb_printf ("%s", h_line);
1756 }
1757 }
1758 }
1759
r_print_fill(RPrint * p,const ut8 * arr,int size,ut64 addr,int step)1760 R_API void r_print_fill(RPrint *p, const ut8 *arr, int size, ut64 addr, int step) {
1761 r_return_if_fail (p && arr);
1762 const bool show_colors = (p && (p->flags & R_PRINT_FLAGS_COLOR));
1763 const bool show_offset = (p && (p->flags & R_PRINT_FLAGS_OFFSET));
1764 bool useUtf8 = p->cons->use_utf8;
1765 const char *v_line = useUtf8 ? RUNE_LINE_VERT : "|";
1766 int i = 0, j;
1767
1768 #define INC 5
1769 #if TOPLINE
1770 if (arr[0] > 1) {
1771 p->cb_printf (" ");
1772 if (addr != UT64_MAX && step > 0) {
1773 p->cb_printf (" ");
1774 }
1775 if (arr[0] > 1) {
1776 for (i = 0; i < arr[0]; i += INC) {
1777 p->cb_printf (h_line);
1778 }
1779 }
1780 p->cb_printf ("\n");
1781 }
1782 #endif
1783 // get the max of columns
1784 int cols = 0;
1785 for (i = 0; i < size; i++) {
1786 cols = arr[i] > cols ? arr[i] : cols;
1787 }
1788 cols /= 5;
1789 for (i = 0; i < size; i++) {
1790 ut8 next = (i + 1 < size)? arr[i + 1]: 0;
1791 int base = 0, k = 0;
1792 if (addr != UT64_MAX && step > 0) {
1793 ut64 at = addr + (i * step);
1794 if (show_offset) {
1795 if (p->cur_enabled) {
1796 if (i == p->cur) {
1797 p->cb_printf (Color_INVERT"> 0x%08" PFMT64x " "Color_RESET, at);
1798 if (p->num) {
1799 p->num->value = at;
1800 }
1801 } else {
1802 p->cb_printf (" 0x%08" PFMT64x " ", at);
1803 }
1804 } else {
1805 p->cb_printf ("0x%08" PFMT64x " ", at);
1806 }
1807 }
1808 p->cb_printf ("%03x %04x %s", i, arr[i], v_line);
1809 } else {
1810 p->cb_printf ("%s", v_line);
1811 }
1812 if (next < INC) {
1813 base = 1;
1814 }
1815 if (next < arr[i]) {
1816 if (arr[i] > INC) {
1817 for (j = 0; j < next + base; j += INC) {
1818 printHistBlock (p, k, cols);
1819 k++;
1820 }
1821 }
1822 for (j = next + INC; j + base < arr[i]; j += INC) {
1823 printHistBlock (p, k, cols);
1824 k++;
1825 }
1826 } else {
1827 printHistBlock (p, k, cols);
1828 k++;
1829 }
1830 if (i + 1 == size) {
1831 for (j = arr[i] + INC + base; j + base < next; j += INC) {
1832 printHistBlock (p, k, cols);
1833 k++;
1834 }
1835 } else if (arr[i + 1] > arr[i]) {
1836 for (j = arr[i] + INC + base; j + base < next; j += INC) {
1837 printHistBlock (p, k, cols);
1838 k++;
1839 }
1840 }
1841 if (show_colors) {
1842 p->cb_printf ("%s", Color_RESET);
1843 }
1844 p->cb_printf ("\n");
1845 }
1846 }
1847
r_print_2bpp_row(RPrint * p,ut8 * buf,const char ** colors)1848 R_API void r_print_2bpp_row(RPrint *p, ut8 *buf, const char **colors) {
1849 const bool useColor = p? (p->flags & R_PRINT_FLAGS_COLOR): false;
1850 int i, c = 0;
1851 for (i = 0; i < 8; i++) {
1852 if (buf[1] & ((1 << 7) >> i)) {
1853 c = 2;
1854 }
1855 if (buf[0] & ((1 << 7) >> i)) {
1856 c++;
1857 }
1858 const char *chstr = ".=*@";
1859 const char ch = chstr[c % 4];
1860 if (useColor) {
1861 const char *color = "";
1862 color = colors[c]; // c is by definition 0, 1, 2 or 3
1863 if (p) {
1864 p->cb_printf ("%s%c%c"Color_RESET, color, ch, ch);
1865 } else {
1866 printf ("%s%c%c"Color_RESET, color, ch, ch);
1867 }
1868 } else {
1869 if (p) {
1870 p->cb_printf ("%c%c", ch, ch);
1871 } else {
1872 printf ("%c%c", ch, ch);
1873 }
1874 }
1875 c = 0;
1876 }
1877 }
1878
r_print_2bpp_newline(RPrint * p,bool useColor)1879 static void r_print_2bpp_newline(RPrint *p, bool useColor) {
1880 if (p) {
1881 if (useColor) {
1882 p->cb_printf (Color_RESET "\n");
1883 } else {
1884 p->cb_printf ("\n");
1885 }
1886 } else {
1887 printf ("\n");
1888 }
1889 }
1890
r_print_2bpp_tiles(RPrint * p,ut8 * buf,size_t buflen,ut32 tiles,const char ** colors)1891 R_API void r_print_2bpp_tiles(RPrint *p, ut8 *buf, size_t buflen, ut32 tiles, const char **colors) {
1892 if (!colors) {
1893 colors = (const char *[]){
1894 Color_BGWHITE,
1895 Color_BGRED,
1896 Color_BGBLUE,
1897 Color_BGBLACK,
1898 };
1899 }
1900 int i, r;
1901 const bool useColor = p? (p->flags & R_PRINT_FLAGS_COLOR): false;
1902 int rows = buflen / tiles;
1903 int row, delta = 0;
1904 // hex.cols = 64 = 256 byte stride
1905 int stride = tiles * 16;
1906 bool eof = false;
1907 for (row = 1; row < rows; row++) {
1908 for (i = 0; i < 8 && !eof; i++) {
1909 for (r = 0; r < tiles; r++) {
1910 //int off = delta + 2 * i + r * 16;
1911 int off = delta + (2 * i) + (r * 16);
1912 if (off >= buflen) {
1913 eof = true;
1914 break;
1915 }
1916 r_print_2bpp_row (p, buf + off, colors);
1917 }
1918 r_print_2bpp_newline (p, useColor);
1919 }
1920 delta += stride;
1921 }
1922 }
1923
1924 // probably move somewhere else. RPrint doesnt needs to know about the R_ANAL_ enums
r_print_color_op_type(RPrint * p,ut32 anal_type)1925 R_API const char* r_print_color_op_type(RPrint *p, ut32 anal_type) {
1926 RConsPrintablePalette *pal = &p->cons->context->pal;
1927 switch (anal_type & R_ANAL_OP_TYPE_MASK) {
1928 case R_ANAL_OP_TYPE_NOP:
1929 return pal->nop;
1930 case R_ANAL_OP_TYPE_ADD:
1931 case R_ANAL_OP_TYPE_SUB:
1932 case R_ANAL_OP_TYPE_MUL:
1933 case R_ANAL_OP_TYPE_DIV:
1934 case R_ANAL_OP_TYPE_MOD:
1935 case R_ANAL_OP_TYPE_LENGTH:
1936 return pal->math;
1937 case R_ANAL_OP_TYPE_AND:
1938 case R_ANAL_OP_TYPE_OR:
1939 case R_ANAL_OP_TYPE_XOR:
1940 case R_ANAL_OP_TYPE_NOT:
1941 case R_ANAL_OP_TYPE_SHL:
1942 case R_ANAL_OP_TYPE_SAL:
1943 case R_ANAL_OP_TYPE_SAR:
1944 case R_ANAL_OP_TYPE_SHR:
1945 case R_ANAL_OP_TYPE_ROL:
1946 case R_ANAL_OP_TYPE_ROR:
1947 case R_ANAL_OP_TYPE_CPL:
1948 return pal->bin;
1949 case R_ANAL_OP_TYPE_IO:
1950 return pal->swi;
1951 case R_ANAL_OP_TYPE_JMP:
1952 case R_ANAL_OP_TYPE_UJMP:
1953 return pal->ujmp;
1954 case R_ANAL_OP_TYPE_IJMP:
1955 case R_ANAL_OP_TYPE_RJMP:
1956 case R_ANAL_OP_TYPE_IRJMP:
1957 case R_ANAL_OP_TYPE_MJMP:
1958 return pal->jmp;
1959 case R_ANAL_OP_TYPE_CJMP:
1960 case R_ANAL_OP_TYPE_UCJMP:
1961 case R_ANAL_OP_TYPE_SWITCH:
1962 return pal->cjmp;
1963 case R_ANAL_OP_TYPE_CMP:
1964 case R_ANAL_OP_TYPE_ACMP:
1965 return pal->cmp;
1966 case R_ANAL_OP_TYPE_UCALL:
1967 return pal->ucall;
1968 case R_ANAL_OP_TYPE_ICALL:
1969 case R_ANAL_OP_TYPE_RCALL:
1970 case R_ANAL_OP_TYPE_IRCALL:
1971 case R_ANAL_OP_TYPE_UCCALL:
1972 case R_ANAL_OP_TYPE_CALL:
1973 case R_ANAL_OP_TYPE_CCALL:
1974 return pal->call;
1975 case R_ANAL_OP_TYPE_NEW:
1976 case R_ANAL_OP_TYPE_SWI:
1977 return pal->swi;
1978 case R_ANAL_OP_TYPE_ILL:
1979 case R_ANAL_OP_TYPE_TRAP:
1980 return pal->trap;
1981 case R_ANAL_OP_TYPE_CRET:
1982 case R_ANAL_OP_TYPE_RET:
1983 return pal->ret;
1984 case R_ANAL_OP_TYPE_CAST:
1985 case R_ANAL_OP_TYPE_MOV:
1986 case R_ANAL_OP_TYPE_LEA:
1987 case R_ANAL_OP_TYPE_CMOV: // TODO: add cmov cathegory?
1988 return pal->mov;
1989 case R_ANAL_OP_TYPE_PUSH:
1990 case R_ANAL_OP_TYPE_UPUSH:
1991 case R_ANAL_OP_TYPE_RPUSH:
1992 case R_ANAL_OP_TYPE_LOAD:
1993 return pal->push;
1994 case R_ANAL_OP_TYPE_POP:
1995 case R_ANAL_OP_TYPE_STORE:
1996 return pal->pop;
1997 case R_ANAL_OP_TYPE_CRYPTO:
1998 return pal->crypto;
1999 case R_ANAL_OP_TYPE_NULL:
2000 return pal->other;
2001 case R_ANAL_OP_TYPE_UNK:
2002 default:
2003 return pal->invalid;
2004 }
2005 }
2006
2007 // Global buffer to speed up colorizing performance
2008 #define COLORIZE_BUFSIZE 1024
2009 static char o[COLORIZE_BUFSIZE];
2010
issymbol(char c)2011 static bool issymbol(char c) {
2012 switch (c) {
2013 case '$':
2014 case ':':
2015 case '+':
2016 case '-':
2017 /* case '/': not good for dalvik */
2018 case '>':
2019 case '<':
2020 case '(':
2021 case ')':
2022 case '*':
2023 case '%':
2024 case ']':
2025 case '[':
2026 case ',':
2027 case ' ':
2028 case '{':
2029 case '}':
2030 return true;
2031 default:
2032 return false;
2033 }
2034 }
2035
check_arg_name(RPrint * print,char * p,ut64 func_addr)2036 static bool check_arg_name(RPrint *print, char *p, ut64 func_addr) {
2037 if (func_addr && print->exists_var) {
2038 int z;
2039 for (z = 0; p[z] && (isalpha ((unsigned char)p[z]) || isdigit ((unsigned char)p[z]) || p[z] == '_'); z++) {
2040 ;
2041 }
2042 char tmp = p[z];
2043 p[z] = '\0';
2044 bool ret = print->exists_var (print, func_addr, p);
2045 p[z] = tmp;
2046 return ret;
2047 }
2048 return false;
2049 }
2050
ishexprefix(char * p)2051 static bool ishexprefix(char *p) {
2052 return (p[0] == '0' && p[1] == 'x');
2053 }
2054
r_print_colorize_opcode(RPrint * print,char * p,const char * reg,const char * num,bool partial_reset,ut64 func_addr)2055 R_API char* r_print_colorize_opcode(RPrint *print, char *p, const char *reg, const char *num, bool partial_reset, ut64 func_addr) {
2056 int i, j, k, is_mod, is_float = 0, is_arg = 0;
2057 char *reset = partial_reset ? Color_RESET_NOBG : Color_RESET;
2058 ut32 c_reset = strlen (reset);
2059 int is_jmp = p && (*p == 'j' || ((*p == 'c') && (p[1] == 'a')))? 1: 0;
2060 ut32 opcode_sz = p && *p? strlen (p) * 10 + 1: 0;
2061 char previous = '\0';
2062 const char *color_flag = print->cons->context->pal.flag;
2063
2064 if (!p || !*p) {
2065 return NULL;
2066 }
2067 if (is_jmp) {
2068 return strdup (p);
2069 }
2070 r_str_trim (p);
2071 if (opcode_sz > COLORIZE_BUFSIZE) {
2072 /* return same string in case of error */
2073 return strdup (p);
2074 }
2075
2076 memset (o, 0, COLORIZE_BUFSIZE);
2077 for (i = j = 0; p[i]; i++, j++) {
2078 /* colorize numbers */
2079 if ((ishexprefix (&p[i]) && previous != ':') \
2080 || (isdigit ((ut8)p[i]) && issymbol (previous))) {
2081 const char *num2 = num;
2082 ut64 n = r_num_get (NULL, p + i);
2083 const char *name = print->offname (print->user, n)? color_flag: NULL;
2084 if (name) {
2085 num2 = name;
2086 }
2087 int nlen = strlen (num2);
2088 if (nlen + j >= sizeof (o)) {
2089 eprintf ("Colorize buffer is too small\n");
2090 break;
2091 }
2092 memcpy (o + j, num2, nlen + 1);
2093 j += nlen;
2094 }
2095 previous = p[i];
2096 if (j + 100 >= COLORIZE_BUFSIZE) {
2097 eprintf ("r_print_colorize_opcode(): buffer overflow!\n");
2098 return strdup (p);
2099 }
2100 switch (p[i]) {
2101 // We dont need to skip ansi codes.
2102 // original colors must be preserved somehow
2103 case 0x1b:
2104 #define STRIP_ANSI 1
2105 #if STRIP_ANSI
2106 /* skip until 'm' */
2107 for (++i; p[i] && p[i] != 'm'; i++) {
2108 o[j] = p[i];
2109 }
2110 j--;
2111 continue;
2112 #else
2113 /* copy until 'm' */
2114 for (; p[i] && p[i] != 'm'; i++) {
2115 o[j++] = p[i];
2116 }
2117 o[j++] = p[i++];
2118 #endif
2119 case '+':
2120 case '-':
2121 case '/':
2122 case '>':
2123 case '<':
2124 case '(':
2125 case ')':
2126 case '*':
2127 case '%':
2128 case ']':
2129 case '[':
2130 case ',':
2131 /* ugly trick for dalvik */
2132 if (is_float) {
2133 /* do nothing, keep going until next */
2134 is_float = 0;
2135 } else if (is_arg) {
2136 if (c_reset + j + 10 >= COLORIZE_BUFSIZE) {
2137 eprintf ("r_print_colorize_opcode(): buffer overflow!\n");
2138 return strdup (p);
2139 }
2140
2141 bool found_var = check_arg_name (print, p + i + 1, func_addr);
2142 strcpy (o + j, reset);
2143 j += strlen (reset);
2144 o[j] = p[i];
2145 if (!(p[i+1] == '$' || ((p[i+1] > '0') && (p[i+1] < '9')))) {
2146 const char *color = found_var ? print->cons->context->pal.func_var_type : reg;
2147 ut32 color_len = strlen (color);
2148 if (color_len + j + 10 >= COLORIZE_BUFSIZE) {
2149 eprintf ("r_print_colorize_opcode(): buffer overflow!\n");
2150 return strdup (p);
2151 }
2152 strcpy (o + j + 1, color);
2153 j += strlen (color);
2154 }
2155 continue;
2156 }
2157 break;
2158 case ' ':
2159 is_arg = 1;
2160 // find if next ',' before ' ' is found
2161 is_mod = 0;
2162 is_float = 0;
2163 for (k = i + 1; p[k]; k++) {
2164 if (p[k] == 'e' && p[k + 1] == '+') {
2165 is_float = 1;
2166 break;
2167 }
2168 if (p[k] == ' ') {
2169 break;
2170 }
2171 if (p[k] == ',') {
2172 is_mod = 1;
2173 break;
2174 }
2175 }
2176 if (is_float) {
2177 strcpy (o + j, num);
2178 j += strlen (num);
2179 }
2180 if (!p[k]) {
2181 is_mod = 1;
2182 }
2183 if (is_mod) {
2184 // COLOR FOR REGISTER
2185 ut32 reg_len = strlen (reg);
2186 /* if (reg_len+j+10 >= opcode_sz) o = realloc_color_buffer (o, &opcode_sz, reg_len+100); */
2187 if (reg_len + j + 10 >= COLORIZE_BUFSIZE) {
2188 eprintf ("r_print_colorize_opcode(): buffer overflow!\n");
2189 return strdup (p);
2190 }
2191 strcpy (o + j, reg);
2192 j += strlen (reg);
2193 }
2194 break;
2195 case '0': /* address */
2196 if (p[i + 1] == 'x') {
2197 if (print->flags & R_PRINT_FLAGS_SECSUB) {
2198 RIOMap *map = print->iob.map_get (print->iob.io, r_num_get (NULL, p + i));
2199 if (map && map->name) {
2200 if (strlen (map->name) + j + 1 >= COLORIZE_BUFSIZE) {
2201 eprintf ("stop before overflow\n");
2202 break;
2203 }
2204 strcpy (o + j, map->name);
2205 j += strlen (o + j);
2206 strcpy (o + j, ".");
2207 j++;
2208 }
2209 }
2210 }
2211 break;
2212 }
2213 o[j] = p[i];
2214 }
2215 // decolorize at the end
2216 if (j + 20 >= opcode_sz) {
2217 char *t_o = o;
2218 /* o = malloc (opcode_sz+21); */
2219 memmove (o, t_o, opcode_sz);
2220 /* free (t_o); */
2221 }
2222 strcpy (o + j, reset);
2223 //strcpy (p, o); // may overflow .. but shouldnt because asm.buf_asm is big enought
2224 return strdup (o);
2225 }
2226
2227 // reset the status of row_offsets
r_print_init_rowoffsets(RPrint * p)2228 R_API void r_print_init_rowoffsets(RPrint *p) {
2229 if (p->calc_row_offsets) {
2230 R_FREE (p->row_offsets);
2231 p->row_offsets_sz = 0;
2232 }
2233 }
2234
2235 // set the offset, from the start of the printing, of the i-th row
r_print_set_rowoff(RPrint * p,int i,ut32 offset,bool overwrite)2236 R_API void r_print_set_rowoff(RPrint *p, int i, ut32 offset, bool overwrite) {
2237 if (!overwrite) {
2238 return;
2239 }
2240 if (i < 0) {
2241 return;
2242 }
2243 if (!p->row_offsets || !p->row_offsets_sz) {
2244 p->row_offsets_sz = R_MAX (i + 1, DFLT_ROWS);
2245 p->row_offsets = R_NEWS (ut32, p->row_offsets_sz);
2246 }
2247 if (i >= p->row_offsets_sz) {
2248 size_t new_size;
2249 p->row_offsets_sz *= 2;
2250 //XXX dangerous
2251 while (i >= p->row_offsets_sz) {
2252 p->row_offsets_sz *= 2;
2253 }
2254 new_size = sizeof (ut32) * p->row_offsets_sz;
2255 p->row_offsets = realloc (p->row_offsets, new_size);
2256 }
2257 p->row_offsets[i] = offset;
2258 }
2259
2260 // return the offset, from the start of the printing, of the i-th row.
2261 // if the line index is not valid, UT32_MAX is returned.
r_print_rowoff(RPrint * p,int i)2262 R_API ut32 r_print_rowoff(RPrint *p, int i) {
2263 if (i < 0 || i >= p->row_offsets_sz) {
2264 return UT32_MAX;
2265 }
2266 return p->row_offsets[i];
2267 }
2268
2269 // return the index of the row that contains the given offset or -1 if
2270 // that row doesn't exist.
r_print_row_at_off(RPrint * p,ut32 offset)2271 R_API int r_print_row_at_off(RPrint *p, ut32 offset) {
2272 int i = 0;
2273 ut32 tt;
2274 while ((tt = r_print_rowoff (p, i)) != UT32_MAX && tt <= offset) {
2275 i++;
2276 }
2277 return tt != UT32_MAX? i - 1: -1;
2278 }
2279
r_print_get_cursor(RPrint * p)2280 R_API int r_print_get_cursor(RPrint *p) {
2281 return p->cur_enabled? p->cur: 0;
2282 }
2283
r_print_jsondump(RPrint * p,const ut8 * buf,int len,int wordsize)2284 R_API int r_print_jsondump(RPrint *p, const ut8 *buf, int len, int wordsize) {
2285 ut16 *buf16 = (ut16*) buf;
2286 ut32 *buf32 = (ut32*) buf;
2287 ut64 *buf64 = (ut64*) buf;
2288 // TODDO: support p==NULL too
2289 if (!p || !buf || len < 1 || wordsize < 1) {
2290 return 0;
2291 }
2292 int bytesize = wordsize / 8;
2293 if (bytesize < 1) {
2294 bytesize = 8;
2295 }
2296 int i, words = (len / bytesize);
2297 p->cb_printf ("[");
2298 for (i = 0; i < words; i++) {
2299 switch (wordsize) {
2300 case 8: {
2301 p->cb_printf ("%s%d", i ? "," : "", buf[i]);
2302 break;
2303 }
2304 case 16: {
2305 ut16 w16 = r_read_ble16 (&buf16[i], p->big_endian);
2306 p->cb_printf ("%s%hd", i ? "," : "", w16);
2307 break;
2308 }
2309 case 32: {
2310 ut32 w32 = r_read_ble32 (&buf32[i], p->big_endian);
2311 p->cb_printf ("%s%d", i ? "," : "", w32);
2312 break;
2313 }
2314 case 64: {
2315 ut64 w64 = r_read_ble64 (&buf64[i], p->big_endian);
2316 p->cb_printf ("%s%"PFMT64d, i ? "," : "", w64);
2317 break;
2318 }
2319 }
2320 }
2321 p->cb_printf ("]\n");
2322 return words;
2323 }
2324
r_print_hex_from_bin(RPrint * p,char * bin_str)2325 R_API void r_print_hex_from_bin(RPrint *p, char *bin_str) {
2326 int i, j, index;
2327 RPrint myp = {.cb_printf = libc_printf};
2328 const int len = strlen (bin_str);
2329 if (!len) {
2330 return;
2331 }
2332 ut64 n, *buf = malloc (sizeof (ut64) * ((len + 63) / 64));
2333 if (!buf) {
2334 eprintf ("allocation failed\n");
2335 return;
2336 }
2337 if (!p) {
2338 p = &myp;
2339 }
2340 for (i = len - 1, index = 0; i >= 0; i -= 64, index++) {
2341 n = 0;
2342 for (j = 0; j < 64 && i - j >= 0; j++) {
2343 n += (ut64) (bin_str[i - j] - '0') << j;
2344 }
2345 buf[index] = n;
2346 }
2347 index--;
2348 p->cb_printf ("0x");
2349 while (buf[index] == 0 && index > 0) {
2350 index--;
2351 }
2352 p->cb_printf ("%" PFMT64x, buf[index]);
2353 index--;
2354 for (i = index; i >= 0; i--) {
2355 p->cb_printf ("%016" PFMT64x, buf[i]);
2356 }
2357 p->cb_printf ("\n");
2358 free (buf);
2359 }
2360
r_print_rowlog(RPrint * print,const char * str)2361 R_API const char* r_print_rowlog(RPrint *print, const char *str) {
2362 int use_color = print->flags & R_PRINT_FLAGS_COLOR;
2363 bool verbose = print->scr_prompt;
2364 r_return_val_if_fail (print->cb_eprintf, NULL);
2365 if (!verbose) {
2366 return NULL;
2367 }
2368 if (use_color) {
2369 print->cb_eprintf ("[ ] "Color_YELLOW"%s\r["Color_RESET, str);
2370 } else {
2371 print->cb_eprintf ("[ ] %s\r[", str);
2372 }
2373 return str;
2374 }
2375
r_print_rowlog_done(RPrint * print,const char * str)2376 R_API void r_print_rowlog_done(RPrint *print, const char *str) {
2377 int use_color = print->flags & R_PRINT_FLAGS_COLOR;
2378 bool verbose = print->scr_prompt;
2379 r_return_if_fail (print->cb_eprintf);
2380 if (verbose) {
2381 if (use_color) {
2382 print->cb_eprintf ("\r"Color_GREEN"[x]"Color_RESET" %s\n", str);
2383 } else {
2384 print->cb_eprintf ("\r[x] %s\n", str);
2385 }
2386 }
2387 }
2388