1 /* radare - LGPL - Copyright 2009-2021 - nibble, pancake, dso */
2 
3 #include "r_core.h"
4 
5 #define HASRETRY 1
6 #define HAVE_LOCALS 1
7 #define DEFAULT_NARGS 4
8 #define FLAG_PREFIX ";-- "
9 
10 #define COLOR(ds, field) ((ds)->show_color ? (ds)->field : "")
11 #define COLOR_ARG(ds, field) ((ds)->show_color && (ds)->show_color_args ? (ds)->field : "")
12 #define COLOR_CONST(ds, color) ((ds)->show_color ? Color_ ## color : "")
13 #define COLOR_RESET(ds) COLOR_CONST(ds, RESET)
14 
15 // ugly globals but meh
16 static ut64 emustack_min = 0LL;
17 static ut64 emustack_max = 0LL;
18 
19 static const char* r_vline_a[] = {
20 	"|",  // LINE_VERT
21 	"|-", // LINE_CROSS
22 	"-",  // LINE_HORIZ
23 	":",  // LINE_UP
24 	",",  // LUP_CORNER
25 	"\\", // RDWN_CORNER
26 	"/",  // RUP_CORNER
27 	"`",  // LDWN_CORNER
28 	"->", // ARROW_RIGHT
29 	"=<", // ARROW_LEFT
30 };
31 
32 static const char* r_vline_u[] = {
33 	"│", // LINE_VERT
34 	"├", // LINE_CROSS
35 	"─", // LINE_HORIZ
36 	"╎", // LINE_UP
37 	// "↑", // LINE_UP
38 	//"┌", // LUP_CORNER
39 	"┘", // LUP_CORNER
40 	"└", // RDWN_CORNER
41 	"┌", // RUP_CORNER
42 	"┐", // LDWN_CORNER
43 	">", // ARROW_RIGHT
44 	"<", // ARROW_LEFT
45 };
46 
47 static const char* r_vline_uc[] = {
48 	"│", // LINE_VERT
49 	"├", // LINE_CROSS
50 	"─", // LINE_HORIZ
51 	// "↑", // LINE_UP
52 	"╎", // LINE_UP
53 	// "≀", // LINE_UP
54 	//"┌", // LUP_CORNER
55 	"╯", // LUP_CORNER
56 	"╰", // RDWN_CORNER
57 	"╭", // RUP_CORNER
58 	"╮", // LDWN_CORNER
59 	">", // ARROW_RIGHT
60 	"<", // ARROW_LEFT
61 };
62 
63 #define DS_PRE_NONE         0
64 #define DS_PRE_EMPTY        1
65 #define DS_PRE_FCN_HEAD     2
66 #define DS_PRE_FCN_MIDDLE   3
67 #define DS_PRE_FCN_TAIL     4
68 
69 // TODO: what about using bit shifting and enum for keys? see libr/util/bitmap.c
70 // the problem of this is that the fields will be more opaque to bindings, but we will earn some bits
71 typedef struct {
72 	RCore *core;
73 	char str[1024], strsub[1024];
74 	bool immtrim;
75 	bool immstr;
76 	bool use_esil;
77 	bool show_color;
78 	bool show_color_bytes;
79 	bool show_color_args;
80 	int colorop;
81 	int acase;
82 	bool capitalize;
83 	bool show_flgoff;
84 	bool hasMidflag;
85 	bool hasMidbb;
86 	int atabs;
87 	int atabsonce;
88 	int atabsoff;
89 	int decode;
90 	bool pseudo;
91 	int subnames;
92 	int interactive;
93 	bool subjmp;
94 	bool subvar;
95 	bool show_lines;
96 	bool show_lines_bb;
97 	bool show_lines_ret;
98 	bool show_lines_call;
99 	bool show_lines_fcn;
100 	bool linesright;
101 	int tracespace;
102 	int cyclespace;
103 	int cmtfold;
104 	int show_indent;
105 	bool show_dwarf;
106 	bool show_size;
107 	bool show_trace;
108 	bool show_family;
109 	bool asm_describe;
110 	int linesout;
111 	int adistrick;
112 	bool asm_meta;
113 	bool asm_xrefs_code;
114 	int asm_demangle;
115 	bool asm_instr;
116 	bool show_offset;
117 	bool show_offdec; // dupe for r_print->flags
118 	bool show_bbline;
119 	bool show_emu;
120 	bool pre_emu;
121 	bool show_emu_str;
122 	bool show_emu_stroff;
123 	bool show_emu_strinv;
124 	bool show_emu_strflag;
125 	bool show_emu_stack;
126 	bool show_emu_write;
127 	bool show_optype;
128 	bool show_emu_strlea;
129 	bool show_emu_ssa;
130 	bool show_section;
131 	int show_section_col;
132 	bool flags_inline;
133 	bool show_section_perm;
134 	bool show_section_name;
135 	bool show_symbols;
136 	int show_symbols_col;
137 	bool show_offseg;
138 	bool show_flags;
139 	bool bblined;
140 	bool show_bytes;
141 	bool show_bytes_right;
142 	bool show_reloff;
143 	bool show_reloff_flags;
144 	bool show_comments;
145 	bool show_usercomments;
146 	bool asm_hints;
147 	bool asm_hint_jmp;
148 	bool asm_hint_cdiv;
149 	bool asm_hint_call;
150 	bool asm_hint_call_indirect;
151 	bool asm_hint_lea;
152 	bool asm_hint_emu;
153 	int  asm_hint_pos;
154 	ut64 emuptr;
155 	bool show_slow;
156 	Sdb *ssa;
157 	int cmtcol;
158 	bool show_calls;
159 	bool show_cmtflgrefs;
160 	bool show_cmtesil;
161 	bool show_cycles;
162 	bool show_refptr;
163 	bool show_stackptr;
164 	int stackFd;
165 	bool show_xrefs;
166 	bool show_cmtrefs;
167 	const char *show_cmtoff;
168 	bool show_functions;
169 	bool show_marks;
170 	bool show_asciidot;
171 	RStrEnc strenc;
172 	int cursor;
173 	int show_comment_right_default;
174 	RSpace *flagspace_ports;
175 	bool show_flag_in_bytes;
176 	int lbytes;
177 	int show_comment_right;
178 	int pre;
179 	char *ocomment;
180 	int linesopts;
181 	int lastfail;
182 	int ocols;
183 	int lcols;
184 	int nb, nbytes;
185 	int show_utf8;
186 	int lines;
187 	int oplen;
188 	bool show_varaccess;
189 	bool show_vars;
190 	bool show_fcnsig;
191 	bool hinted_line;
192 	int show_varsum;
193 	int midflags;
194 	bool midbb;
195 	bool midcursor;
196 	bool show_noisy_comments;
197 	ut64 asm_highlight;
198 	const char *pal_comment;
199 	const char *color_comment;
200 	const char *color_usrcmt;
201 	const char *color_fname;
202 	const char *color_floc;
203 	const char *color_fline;
204 	const char *color_flow;
205 	const char *color_flow2;
206 	const char *color_flag;
207 	const char *color_label;
208 	const char *color_other;
209 	const char *color_nop;
210 	const char *color_bin;
211 	const char *color_math;
212 	const char *color_btext;
213 	const char *color_jmp;
214 	const char *color_cjmp;
215 	const char *color_call;
216 	const char *color_cmp;
217 	const char *color_swi;
218 	const char *color_trap;
219 	const char *color_ret;
220 	const char *color_push;
221 	const char *color_pop;
222 	const char *color_reg;
223 	const char *color_num;
224 	const char *color_mov;
225 	const char *color_invalid;
226 	const char *color_gui_cflow;
227 	const char *color_gui_dataoffset;
228 	const char *color_gui_background;
229 	const char *color_gui_alt_background;
230 	const char *color_gui_border;
231 	const char *color_linehl;
232 	const char *color_func_var;
233 	const char *color_func_var_type;
234 	const char *color_func_var_addr;
235 
236 	RFlagItem *lastflag;
237 	RAnalHint *hint;
238 	RPrint *print;
239 
240 	ut64 esil_old_pc;
241 	ut8* esil_regstate;
242 	int esil_regstate_size;
243 	bool esil_likely;
244 
245 	int l;
246 	int middle;
247 	int indent_level;
248 	int indent_space;
249 	char *line;
250 	char *line_col, *prev_line_col;
251 	char *refline, *refline2;
252 	char *comment;
253 	char *opstr;
254 	char *osl, *sl;
255 	int stackptr, ostackptr;
256 	int index;
257 	ut64 at, vat, addr, dest;
258 	int tries, cbytes, idx;
259 	char chref;
260 	bool retry;
261 	RAsmOp asmop;
262 	RAnalOp analop;
263 	RAnalFunction *fcn;
264 	RAnalFunction *pdf;
265 	const ut8 *buf;
266 	int len;
267 	int maxrefs;
268 	int foldxrefs;
269 	char *prev_ins;
270 	bool prev_ins_eq;
271 	int prev_ins_count;
272 	bool show_nodup;
273 	bool has_description;
274 	// caches
275 	char *_tabsbuf;
276 	int _tabsoff;
277 	bool dwarfFile;
278 	bool dwarfAbspath;
279 	bool showpayloads;
280 	bool showrelocs;
281 	int cmtcount;
282 	bool asm_anal;
283 	ut64 printed_str_addr;
284 	ut64 printed_flag_addr;
285 	ut64 min_ref_addr;
286 
287 	PJ *pj; // not null if printing json
288 	int buf_line_begin;
289 	const char *strip;
290 	int maxflags;
291 	int asm_types;
292 } RDisasmState;
293 
294 static void ds_setup_print_pre(RDisasmState *ds, bool tail, bool middle);
295 static void ds_setup_pre(RDisasmState *ds, bool tail, bool middle);
296 static void ds_print_pre(RDisasmState *ds, bool fcnline);
297 static void ds_pre_line(RDisasmState *ds);
298 static void ds_begin_line(RDisasmState *ds);
299 static void ds_newline(RDisasmState *ds);
300 static void ds_begin_cont(RDisasmState *ds);
301 static void ds_print_esil_anal(RDisasmState *ds);
302 static void ds_reflines_init(RDisasmState *ds);
303 static void ds_align_comment(RDisasmState *ds);
304 static RDisasmState * ds_init(RCore * core);
305 static void ds_build_op_str(RDisasmState *ds, bool print_color);
306 static void ds_print_show_bytes(RDisasmState *ds);
307 static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines);
308 static void ds_show_xrefs(RDisasmState *ds);
309 static void ds_atabs_option(RDisasmState *ds);
310 static void ds_show_functions(RDisasmState *ds);
311 static void ds_control_flow_comments(RDisasmState *ds);
312 static void ds_adistrick_comments(RDisasmState *ds);
313 static void ds_print_comments_right(RDisasmState *ds);
314 static void ds_show_comments_right(RDisasmState *ds);
315 static void ds_show_flags(RDisasmState *ds);
316 static void ds_update_ref_lines(RDisasmState *ds);
317 static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len);
318 static void ds_print_lines_right(RDisasmState *ds);
319 static void ds_print_lines_left(RDisasmState *ds);
320 static void ds_print_cycles(RDisasmState *ds);
321 static void ds_print_family(RDisasmState *ds);
322 static void ds_print_stackptr(RDisasmState *ds);
323 static void ds_print_offset(RDisasmState *ds);
324 static void ds_print_op_size(RDisasmState *ds);
325 static void ds_print_trace(RDisasmState *ds);
326 static void ds_print_opstr(RDisasmState *ds);
327 static void ds_print_color_reset(RDisasmState *ds);
328 static int ds_print_middle(RDisasmState *ds, int ret);
329 static bool ds_print_labels(RDisasmState *ds, RAnalFunction *f);
330 static void ds_print_sysregs(RDisasmState *ds);
331 static void ds_print_fcn_name(RDisasmState *ds);
332 static void ds_print_as_string(RDisasmState *ds);
333 static bool ds_print_core_vmode(RDisasmState *ds, int pos);
334 static void ds_print_dwarf(RDisasmState *ds);
335 static void ds_print_asmop_payload(RDisasmState *ds, const ut8 *buf);
336 static char *ds_esc_str(RDisasmState *ds, const char *str, int len, const char **prefix_out, bool is_comment);
337 static void ds_print_ptr(RDisasmState *ds, int len, int idx);
338 static void ds_print_demangled(RDisasmState *ds);
339 static void ds_print_str(RDisasmState *ds, const char *str, int len, ut64 refaddr);
340 static char *ds_sub_jumps(RDisasmState *ds, char *str);
341 static void ds_start_line_highlight(RDisasmState *ds);
342 static void ds_end_line_highlight(RDisasmState *ds);
343 static bool line_highlighted(RDisasmState *ds);
344 static int ds_print_shortcut(RDisasmState *ds, ut64 addr, int pos);
345 
r_core_pava(RCore * core,ut64 addr)346 R_API ut64 r_core_pava (RCore *core, ut64 addr) {
347 	if (core->print->pava) {
348 		RIOMap *map = r_io_map_get_paddr (core->io, addr);
349 		if (map) {
350 			return addr - map->delta + r_io_map_begin (map);
351 		}
352 	}
353 	return addr;
354 }
355 
fcnIn(RDisasmState * ds,ut64 at,int type)356 static RAnalFunction *fcnIn(RDisasmState *ds, ut64 at, int type) {
357 	if (ds->fcn && r_anal_function_contains (ds->fcn, at)) {
358 		return ds->fcn;
359 	}
360 	return r_anal_get_fcn_in (ds->core->anal, at, type);
361 }
362 
get_utf8_char(const char line,RDisasmState * ds)363 static const char *get_utf8_char(const char line, RDisasmState *ds) {
364 	switch (line) {
365 	case '<': return ds->core->cons->vline[ARROW_LEFT];
366 	case '>': return ds->core->cons->vline[ARROW_RIGHT];
367 	case ':': return ds->core->cons->vline[LINE_UP];
368 	case '|': return ds->core->cons->vline[LINE_VERT];
369 	case '=':
370 	case '-': return ds->core->cons->vline[LINE_HORIZ];
371 	case ',': return ds->core->cons->vline[CORNER_TL];
372 	case '.': return ds->core->cons->vline[CORNER_TR];
373 	case '`': return ds->core->cons->vline[CORNER_BL];
374 	default: return " ";
375 	}
376 }
377 
ds_print_ref_lines(char * line,char * line_col,RDisasmState * ds)378 static void ds_print_ref_lines(char *line, char *line_col, RDisasmState *ds) {
379 	int i;
380 	int len = strlen (line);
381 	if (ds->core->cons->use_utf8 || ds->linesopts & R_ANAL_REFLINE_TYPE_UTF8) {
382 		if (ds->show_color) {
383 			for (i = 0; i < len; i++) {
384 				if (line[i] == ' ') {
385 					r_cons_printf (" ");
386 					continue;
387 				}
388 				if (line_col[i] == 'd') {
389 					r_cons_printf ("%s%s%s", COLOR (ds, color_flow), get_utf8_char (line[i], ds), COLOR_RESET (ds));
390 				} else	{
391 					r_cons_printf ("%s%s%s", COLOR (ds, color_flow2), get_utf8_char (line[i], ds), COLOR_RESET (ds));
392 				}
393 			}
394 		} else {
395 			len = strlen (line);
396 			for (i = 0; i < len; i++) {
397 				r_cons_printf ("%s", get_utf8_char (line[i], ds));
398 			}
399 		}
400 	} else {
401 		if (ds->show_color) {
402 			for (i = 0; i < len; i++) {
403 				if (line[i] == ' ') {
404 					r_cons_printf (" ");
405 					continue;
406 				}
407 				if (line_col[i] == 'd') {
408 					r_cons_printf ("%s%c%s", COLOR (ds, color_flow), line[i], COLOR_RESET (ds));
409 				} else	{
410 					r_cons_printf ("%s%c%s", COLOR (ds, color_flow2), line[i], COLOR_RESET (ds));
411 				}
412 			}
413 		} else {
414 			r_cons_printf ("%s", line);
415 		}
416 	}
417 }
418 
get_bits_comment(RCore * core,RAnalFunction * f,char * cmt,int cmt_size)419 static void get_bits_comment(RCore *core, RAnalFunction *f, char *cmt, int cmt_size) {
420 	if (core && f && cmt && cmt_size > 0 && f->bits && f->bits != core->rasm->bits) {
421 		const char *asm_arch = r_config_get (core->config, "asm.arch");
422 		if (asm_arch && *asm_arch && strstr (asm_arch, "arm")) {
423 			switch (f->bits) {
424 			case 16: strcpy (cmt, " (thumb)"); break;
425 			case 32: strcpy (cmt, " (arm)"); break;
426 			case 64: strcpy (cmt, " (aarch64)"); break;
427 			}
428 		} else {
429 			snprintf (cmt, cmt_size, " (%d bits)", f->bits);
430 		}
431 	} else {
432 		if (cmt) {
433 			cmt[0] = 0;
434 		}
435 	}
436 }
437 
r_core_get_section_name(RCore * core,ut64 addr)438 R_API const char *r_core_get_section_name(RCore *core, ut64 addr) {
439 	static char section[128] = "";
440 	static ut64 oaddr = UT64_MAX;
441 	if (oaddr == addr) {
442 		return section;
443 	}
444 	RBinObject *bo = r_bin_cur_object (core->bin);
445 	RBinSection *s = bo? r_bin_get_section_at (bo, addr, core->io->va): NULL;
446 	if (s && s->name && *s->name) {
447 		snprintf (section, sizeof (section) - 1, "%10s ", s->name);
448 	} else {
449 		RListIter *iter;
450 		RDebugMap *map;
451 		*section = 0;
452 		r_list_foreach (core->dbg->maps, iter, map) {
453 			if (addr >= map->addr && addr < map->addr_end) {
454 				const char *mn = r_str_lchr (map->name, '/');
455 				r_str_ncpy (section, mn? mn + 1: map->name, sizeof (section));
456 				break;
457 			}
458 		}
459 	}
460 	oaddr = addr;
461 	return section;
462 }
463 
464 // up means if this lines go up, it controls whether to insert `_
465 // nl if we have to insert new line, it controls whether to insert \n
_ds_comment_align_(RDisasmState * ds,bool up,bool nl)466 static void _ds_comment_align_(RDisasmState *ds, bool up, bool nl) {
467 	if (ds->show_comment_right) {
468 		if (ds->show_color) {
469 			r_cons_print (ds->pal_comment);
470 		}
471 		return;
472 	}
473 	const char *sn = ds->show_section ? r_core_get_section_name (ds->core, ds->at) : "";
474 	ds_align_comment (ds);
475 	ds_align_comment (ds);
476 	r_cons_print (COLOR_RESET (ds));
477 	ds_print_pre (ds, true);
478 	r_cons_printf ("%s%s", nl? "\n": "", sn);
479 	ds_print_ref_lines (ds->refline, ds->line_col, ds);
480 	r_cons_printf ("  %s %s",up? "": ".-", COLOR (ds, color_comment));
481 }
482 #define CMT_ALIGN _ds_comment_align_ (ds, true, false)
483 
ds_comment_lineup(RDisasmState * ds)484 static void ds_comment_lineup(RDisasmState *ds) {
485 	CMT_ALIGN;
486 }
487 
ds_comment_(RDisasmState * ds,bool align,bool nl,const char * format,va_list ap)488 static void ds_comment_(RDisasmState *ds, bool align, bool nl, const char *format, va_list ap) {
489 	if (ds->show_comments) {
490 		if (ds->show_comment_right && align) {
491 			ds_align_comment (ds);
492 		} else {
493 			r_cons_printf ("%s", COLOR (ds, color_comment));
494 		}
495 	}
496 
497 	r_cons_printf_list (format, ap);
498 	if (!ds->show_comment_right && nl) {
499 		ds_newline (ds);
500 	}
501 }
502 
ds_comment(RDisasmState * ds,bool align,const char * format,...)503 static void ds_comment(RDisasmState *ds, bool align, const char *format, ...) {
504 	va_list ap;
505 	va_start (ap, format);
506 	ds->cmtcount++;
507 	ds_comment_ (ds, align, align, format, ap);
508 	va_end (ap);
509 }
510 
511 #define DS_COMMENT_FUNC(name, align, nl) \
512 	static void ds_comment_##name(RDisasmState *ds, const char *format, ...) { \
513 		va_list ap; \
514 		va_start (ap, format); \
515 		ds_comment_ (ds, align, nl, format, ap); \
516 		va_end (ap); \
517 	}
518 
DS_COMMENT_FUNC(start,true,false)519 DS_COMMENT_FUNC (start, true, false)
520 DS_COMMENT_FUNC (middle, false, false)
521 DS_COMMENT_FUNC (end, false, true)
522 
523 static void ds_comment_esil(RDisasmState *ds, bool up, bool end, const char *format, ...) {
524 	va_list ap;
525 	va_start (ap, format);
526 
527 	if (ds->show_comments && up) {
528 		ds->show_comment_right ? ds_align_comment (ds) : ds_comment_lineup (ds);
529 	}
530 	r_cons_printf_list (format, ap);
531 	va_end (ap);
532 
533 	if (ds->show_comments && !ds->show_comment_right) {
534 		if (end) {
535 			ds_newline (ds);
536 		}
537 	}
538 }
539 
ds_print_esil_anal_fini(RDisasmState * ds)540 static void ds_print_esil_anal_fini(RDisasmState *ds) {
541 	RCore *core = ds->core;
542 	if (ds->show_emu && ds->esil_regstate) {
543 		RCore* core = ds->core;
544 		core->anal->last_disasm_reg = r_reg_arena_peek (core->anal->reg);
545 		const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
546 		RRegSet *regset = r_reg_regset_get (ds->core->anal->reg, R_REG_TYPE_GPR);
547 		if (ds->esil_regstate_size  == regset->arena->size) {
548 			r_reg_arena_poke (core->anal->reg, ds->esil_regstate);
549 		}
550 		r_reg_setv (core->anal->reg, pc, ds->esil_old_pc);
551 		R_FREE (ds->esil_regstate);
552 	}
553 	if (core && core->anal && core->anal->esil) {
554 		// make sure to remove reference to ds to avoid UAF
555 		core->anal->esil->user = NULL;
556 	}
557 }
558 
ds_init(RCore * core)559 static RDisasmState * ds_init(RCore *core) {
560 	RDisasmState *ds = R_NEW0 (RDisasmState);
561 	if (!ds) {
562 		return NULL;
563 	}
564 	ds->core = core;
565 	ds->strip = r_config_get (core->config, "asm.strip");
566 	ds->pal_comment = core->cons->context->pal.comment;
567 	#define P(x) (core->cons && core->cons->context->pal.x)? core->cons->context->pal.x
568 	ds->color_comment = P(comment): Color_CYAN;
569 	ds->color_usrcmt = P(usercomment): Color_CYAN;
570 	ds->color_fname = P(fname): Color_RED;
571 	ds->color_floc = P(floc): Color_MAGENTA;
572 	ds->color_fline = P(fline): Color_CYAN;
573 	ds->color_flow = P(flow): Color_CYAN;
574 	ds->color_flow2 = P(flow2): Color_BLUE;
575 	ds->color_flag = P(flag): Color_CYAN;
576 	ds->color_label = P(label): Color_CYAN;
577 	ds->color_other = P(other): Color_WHITE;
578 	ds->color_nop = P(nop): Color_BLUE;
579 	ds->color_bin = P(bin): Color_YELLOW;
580 	ds->color_math = P(math): Color_YELLOW;
581 	ds->color_btext = P(btext): Color_YELLOW;
582 	ds->color_jmp = P(jmp): Color_GREEN;
583 	ds->color_cjmp = P(cjmp): Color_GREEN;
584 	ds->color_call = P(call): Color_BGREEN;
585 	ds->color_cmp = P(cmp): Color_MAGENTA;
586 	ds->color_swi = P(swi): Color_MAGENTA;
587 	ds->color_trap = P(trap): Color_BRED;
588 	ds->color_ret = P(ret): Color_RED;
589 	ds->color_push = P(push): Color_YELLOW;
590 	ds->color_pop = P(pop): Color_BYELLOW;
591 	ds->color_reg = P(reg): Color_YELLOW;
592 	ds->color_num = P(num): Color_CYAN;
593 	ds->color_mov = P(mov): Color_WHITE;
594 	ds->color_invalid = P(invalid): Color_BRED;
595 	ds->color_gui_cflow = P(gui_cflow): Color_YELLOW;
596 	ds->color_gui_dataoffset = P(gui_dataoffset): Color_YELLOW;
597 	ds->color_gui_background = P(gui_background): Color_BLACK;
598 	ds->color_gui_alt_background = P(gui_alt_background): Color_GRAY;
599 	ds->color_gui_border = P(gui_border): Color_BGGRAY;
600 	ds->color_linehl = P(linehl): Color_BGBLUE;
601 	ds->color_func_var = P(func_var): Color_WHITE;
602 	ds->color_func_var_type = P(func_var_type): Color_BLUE;
603 	ds->color_func_var_addr = P(func_var_addr): Color_CYAN;
604 
605 	ds->immstr = r_config_get_i (core->config, "asm.imm.str");
606 	ds->immtrim = r_config_get_i (core->config, "asm.imm.trim");
607 	ds->use_esil = r_config_get_i (core->config, "asm.esil");
608 	ds->pre_emu = r_config_get_i (core->config, "emu.pre");
609 	ds->show_flgoff = r_config_get_i (core->config, "asm.flags.offset");
610 	ds->show_nodup = r_config_get_i (core->config, "asm.nodup");
611 	{
612 		const char *ah = r_config_get (core->config, "asm.highlight");
613 		ds->asm_highlight = (ah && *ah)? r_num_math (core->num, ah): UT64_MAX;
614 	}
615 	ds->asm_anal = r_config_get_i (core->config, "asm.anal");
616 	ds->show_color = r_config_get_i (core->config, "scr.color");
617 	ds->show_color_bytes = r_config_get_i (core->config, "scr.color.bytes"); // maybe rename to asm.color.bytes
618 	ds->show_color_args = r_config_get_i (core->config, "scr.color.args");
619 	ds->colorop = r_config_get_i (core->config, "scr.color.ops"); // XXX confusing name // asm.color.inst (mnemonic + operands) ?
620 	ds->show_utf8 = r_config_get_i (core->config, "scr.utf8");
621 	ds->acase = r_config_get_i (core->config, "asm.ucase");
622 	ds->capitalize = r_config_get_i (core->config, "asm.capitalize");
623 	ds->atabs = r_config_get_i (core->config, "asm.tabs");
624 	ds->atabsonce = r_config_get_i (core->config, "asm.tabs.once");
625 	ds->atabsoff = r_config_get_i (core->config, "asm.tabs.off");
626 	ds->midflags = r_config_get_i (core->config, "asm.flags.middle");
627 	ds->midbb = r_config_get_i (core->config, "asm.bb.middle");
628 	ds->midcursor = r_config_get_i (core->config, "asm.midcursor");
629 	ds->decode = r_config_get_i (core->config, "asm.decode");
630 	core->parser->pseudo = ds->pseudo = r_config_get_i (core->config, "asm.pseudo");
631 	if (ds->pseudo) {
632 		ds->atabs = 0;
633 	}
634 	ds->subnames = r_config_get_i (core->config, "asm.sub.names");
635 	ds->interactive = r_cons_is_interactive ();
636 	ds->subjmp = r_config_get_i (core->config, "asm.sub.jmp");
637 	ds->subvar = r_config_get_i (core->config, "asm.sub.var");
638 	core->parser->subrel = r_config_get_i (core->config, "asm.sub.rel");
639 	core->parser->subreg = r_config_get_i (core->config, "asm.sub.reg");
640 	core->parser->localvar_only = r_config_get_i (core->config, "asm.sub.varonly");
641 	core->parser->retleave_asm = NULL;
642 	ds->show_fcnsig = r_config_get_i (core->config, "asm.fcnsig");
643 	ds->show_vars = r_config_get_i (core->config, "asm.var");
644 	ds->show_varsum = r_config_get_i (core->config, "asm.var.summary");
645 	ds->show_varaccess = r_config_get_i (core->config, "asm.var.access");
646 	ds->maxrefs = r_config_get_i (core->config, "asm.xrefs.max");
647 	ds->maxflags = r_config_get_i (core->config, "asm.flags.limit");
648 	ds->flags_inline = r_config_get_i (core->config, "asm.flags.inline");
649 	ds->asm_types = r_config_get_i (core->config, "asm.types");
650 	ds->foldxrefs = r_config_get_i (core->config, "asm.xrefs.fold");
651 	ds->show_lines = r_config_get_i (core->config, "asm.lines");
652 	ds->show_lines_bb = ds->show_lines ? r_config_get_i (core->config, "asm.lines.bb") : false;
653 	ds->linesright = r_config_get_i (core->config, "asm.lines.right");
654 	ds->show_indent = r_config_get_i (core->config, "asm.indent");
655 	ds->indent_space = r_config_get_i (core->config, "asm.indentspace");
656 	ds->tracespace = r_config_get_i (core->config, "asm.tracespace");
657 	ds->cyclespace = r_config_get_i (core->config, "asm.cyclespace");
658 	ds->show_dwarf = r_config_get_i (core->config, "asm.dwarf");
659 	ds->dwarfFile = r_config_get_i (ds->core->config, "asm.dwarf.file");
660 	ds->dwarfAbspath = r_config_get_i (ds->core->config, "asm.dwarf.abspath");
661 	ds->show_lines_call = ds->show_lines ? r_config_get_i (core->config, "asm.lines.call") : false;
662 	ds->show_lines_ret = ds->show_lines ? r_config_get_i (core->config, "asm.lines.ret") : false;
663 	ds->show_size = r_config_get_i (core->config, "asm.size");
664 	ds->show_trace = r_config_get_i (core->config, "asm.trace");
665 	ds->linesout = r_config_get_i (core->config, "asm.lines.out");
666 	ds->adistrick = r_config_get_i (core->config, "asm.middle"); // TODO: find better name
667 	ds->asm_demangle = r_config_get_i (core->config, "asm.demangle");
668 	ds->asm_describe = r_config_get_i (core->config, "asm.describe");
669 	ds->show_offset = r_config_get_i (core->config, "asm.offset");
670 	ds->show_offdec = r_config_get_i (core->config, "asm.decoff");
671 	ds->show_bbline = r_config_get_i (core->config, "asm.bb.line");
672 	ds->show_section = r_config_get_i (core->config, "asm.section");
673 	ds->show_section_col = r_config_get_i (core->config, "asm.section.col");
674 	ds->show_section_perm = r_config_get_i (core->config, "asm.section.perm");
675 	ds->show_section_name = r_config_get_i (core->config, "asm.section.name");
676 	ds->show_symbols = r_config_get_i (core->config, "asm.symbol");
677 	ds->show_symbols_col = r_config_get_i (core->config, "asm.symbol.col");
678 	ds->asm_instr = r_config_get_i (core->config, "asm.instr");
679 	ds->show_emu = r_config_get_i (core->config, "asm.emu");
680 	ds->show_emu_str = r_config_get_i (core->config, "emu.str");
681 	ds->show_emu_stroff = r_config_get_i (core->config, "emu.str.off");
682 	ds->show_emu_strinv = r_config_get_i (core->config, "emu.str.inv");
683 	ds->show_emu_strflag = r_config_get_i (core->config, "emu.str.flag");
684 	ds->show_emu_strlea = r_config_get_i (core->config, "emu.str.lea");
685 	ds->show_emu_write = r_config_get_i (core->config, "emu.write");
686 	ds->show_emu_ssa = r_config_get_i (core->config, "emu.ssa");
687 	ds->show_emu_stack = r_config_get_i (core->config, "emu.stack");
688 	ds->stackFd = -1;
689 	if (ds->show_emu_stack) {
690 		// TODO: initialize fake stack in here
691 		const char *uri = "malloc://32K";
692 		ut64 size = r_num_get (core->num, "32K");
693 		ut64 addr = r_reg_getv (core->anal->reg, "SP") - (size / 2);
694 		emustack_min = addr;
695 		emustack_max = addr + size;
696 		ds->stackFd = r_io_fd_open (core->io, uri, R_PERM_RW, 0);
697 		RIOMap *map = r_io_map_add (core->io, ds->stackFd, R_PERM_RW, 0LL, addr, size);
698 		if (!map) {
699 			r_io_fd_close (core->io, ds->stackFd);
700 			eprintf ("Cannot create map for tha stack, fd %d got closed again\n", ds->stackFd);
701 			ds->stackFd = -1;
702 		} else {
703 			r_io_map_set_name (map, "fake.stack");
704 		}
705 	}
706 	ds->stackptr = core->anal->stackptr;
707 	ds->show_offseg = r_config_get_i (core->config, "asm.segoff");
708 	ds->show_flags = r_config_get_i (core->config, "asm.flags");
709 	ds->show_bytes = r_config_get_i (core->config, "asm.bytes");
710 	ds->show_bytes_right = r_config_get_i (core->config, "asm.bytes.right");
711 	ds->show_optype = r_config_get_i (core->config, "asm.optype");
712 	ds->asm_meta = r_config_get_i (core->config, "asm.meta");
713 	ds->asm_xrefs_code = r_config_get_i (core->config, "asm.xrefs.code");
714 	ds->show_reloff = r_config_get_i (core->config, "asm.reloff");
715 	ds->show_reloff_flags = r_config_get_i (core->config, "asm.reloff.flags");
716 	ds->show_lines_fcn = ds->show_lines ? r_config_get_i (core->config, "asm.lines.fcn") : false;
717 	ds->show_comments = r_config_get_i (core->config, "asm.comments");
718 	ds->show_usercomments = r_config_get_i (core->config, "asm.usercomments");
719 	ds->asm_hint_jmp = r_config_get_i (core->config, "asm.hint.jmp");
720 	ds->asm_hint_call = r_config_get_i (core->config, "asm.hint.call");
721 	ds->asm_hint_call_indirect = r_config_get_i (core->config, "asm.hint.call.indirect");
722 	ds->asm_hint_lea = r_config_get_i (core->config, "asm.hint.lea");
723 	ds->asm_hint_emu = r_config_get_i (core->config, "asm.hint.emu");
724 	ds->asm_hint_cdiv = r_config_get_i (core->config, "asm.hint.cdiv");
725 	ds->asm_hint_pos = r_config_get_i (core->config, "asm.hint.pos");
726 	ds->asm_hints = r_config_get_i (core->config, "asm.hints"); // only for cdiv wtf
727 	ds->show_slow = r_config_get_i (core->config, "asm.slow");
728 	ds->show_refptr = r_config_get_i (core->config, "asm.refptr");
729 	ds->show_calls = r_config_get_i (core->config, "asm.calls");
730 	ds->show_family = r_config_get_i (core->config, "asm.family");
731 	ds->cmtcol = r_config_get_i (core->config, "asm.cmt.col");
732 	ds->show_cmtesil = r_config_get_i (core->config, "asm.cmt.esil");
733 	ds->show_cmtflgrefs = r_config_get_i (core->config, "asm.cmt.flgrefs");
734 	ds->show_cycles = r_config_get_i (core->config, "asm.cycles");
735 	ds->show_stackptr = r_config_get_i (core->config, "asm.stackptr");
736 	ds->show_xrefs = r_config_get_i (core->config, "asm.xrefs");
737 	ds->show_cmtrefs = r_config_get_i (core->config, "asm.cmt.refs");
738 	ds->cmtfold = r_config_get_i (core->config, "asm.cmt.fold");
739 	ds->show_cmtoff = r_config_get (core->config, "asm.cmt.off");
740 	if (!ds->show_cmtoff) {
741 		ds->show_cmtoff = "nodup";
742 	}
743 	ds->show_functions = r_config_get_i (core->config, "asm.functions");
744 	ds->nbytes = r_config_get_i (core->config, "asm.nbytes");
745 	ds->show_asciidot = !strcmp (core->print->strconv_mode, "asciidot");
746 	const char *strenc_str = r_config_get (core->config, "bin.str.enc");
747 	if (!strenc_str) {
748 		ds->strenc = R_STRING_ENC_GUESS;
749 	} else if (!strcmp (strenc_str, "latin1")) {
750 		ds->strenc = R_STRING_ENC_LATIN1;
751 	} else if (!strcmp (strenc_str, "utf8")) {
752 		ds->strenc = R_STRING_ENC_UTF8;
753 	} else if (!strcmp (strenc_str, "utf16le")) {
754 		ds->strenc = R_STRING_ENC_UTF16LE;
755 	} else if (!strcmp (strenc_str, "utf32le")) {
756 		ds->strenc = R_STRING_ENC_UTF32LE;
757 	} else if (!strcmp (strenc_str, "utf16be")) {
758 		ds->strenc = R_STRING_ENC_UTF16BE;
759 	} else if (!strcmp (strenc_str, "utf32be")) {
760 		ds->strenc = R_STRING_ENC_UTF32BE;
761 	} else {
762 		ds->strenc = R_STRING_ENC_GUESS;
763 	}
764 	core->print->bytespace = r_config_get_i (core->config, "asm.bytes.space");
765 	ds->cursor = 0;
766 	ds->nb = 0;
767 	ds->flagspace_ports = r_flag_space_get (core->flags, "ports");
768 	ds->lbytes = r_config_get_i (core->config, "asm.lbytes");
769 	ds->show_comment_right_default = r_config_get_b (core->config, "asm.cmt.right");
770 	ds->show_comment_right = ds->show_comment_right_default;
771 	ds->show_flag_in_bytes = r_config_get_i (core->config, "asm.flags.inbytes");
772 	ds->show_marks = r_config_get_i (core->config, "asm.marks");
773 	ds->show_noisy_comments = r_config_get_i (core->config, "asm.noisy");
774 	ds->pre = DS_PRE_NONE;
775 	ds->ocomment = NULL;
776 	ds->linesopts = 0;
777 	ds->lastfail = 0;
778 	ds->ocols = 0;
779 	ds->lcols = 0;
780 	ds->printed_str_addr = UT64_MAX;
781 	ds->printed_flag_addr = UT64_MAX;
782 
783 	ds->esil_old_pc = UT64_MAX;
784 	ds->esil_regstate = NULL;
785 	ds->esil_likely = false;
786 
787 	ds->showpayloads = r_config_get_i (ds->core->config, "asm.payloads");
788 	ds->showrelocs = r_config_get_i (core->config, "bin.relocs");
789 	ds->min_ref_addr = r_config_get_i (core->config, "asm.sub.varmin");
790 
791 	if (ds->show_flag_in_bytes) {
792 		ds->show_flags = false;
793 	}
794 	if (r_config_get_i (core->config, "asm.lines.wide")) {
795 		ds->linesopts |= R_ANAL_REFLINE_TYPE_WIDE;
796 	}
797 	if (core->cons->vline) {
798 		if (ds->show_utf8) {
799 			ds->linesopts |= R_ANAL_REFLINE_TYPE_UTF8;
800 		}
801 	}
802 	if (ds->show_lines_bb) {
803 		ds->ocols += 10; // XXX
804 	}
805 	if (ds->show_offset) {
806 		ds->ocols += 14;
807 	}
808 	ds->lcols = ds->ocols + 2;
809 	if (ds->show_bytes) {
810 		ds->ocols += 20;
811 	}
812 	if (ds->show_trace) {
813 		ds->ocols += 8;
814 	}
815 	if (ds->show_stackptr) {
816 		ds->ocols += 4;
817 	}
818 	/* disasm */ ds->ocols += 20;
819 	ds->nb = ds->nbytes? (1 + ds->nbytes * 2): 0;
820 	ds->tries = 3;
821 	if (core->print->cur_enabled) {
822 		if (core->print->cur < 0) {
823 			core->print->cur = 0;
824 		}
825 		ds->cursor = core->print->cur;
826 	} else {
827 		ds->cursor = -1;
828 	}
829 	if (r_config_get_i (core->config, "asm.lines.wide")) {
830 		ds->linesopts |= R_ANAL_REFLINE_TYPE_WIDE;
831 	}
832 	if (core->cons->vline) {
833 		if (ds->show_utf8) {
834 			ds->linesopts |= R_ANAL_REFLINE_TYPE_UTF8;
835 		}
836 	}
837 	return ds;
838 }
839 
840 static ut64 lastaddr = UT64_MAX;
841 
ds_reflines_fini(RDisasmState * ds)842 static void ds_reflines_fini(RDisasmState *ds) {
843 	RAnal *anal = ds->core->anal;
844 	r_list_free (anal->reflines);
845 	anal->reflines = NULL;
846 	R_FREE (ds->refline);
847 	R_FREE (ds->refline2);
848 	R_FREE (ds->prev_line_col);
849 }
850 
ds_reflines_init(RDisasmState * ds)851 static void ds_reflines_init(RDisasmState *ds) {
852 	RAnal *anal = ds->core->anal;
853 
854 	lastaddr = UT64_MAX;
855 
856 	if (ds->show_lines_bb || ds->pj) {
857 		ds_reflines_fini (ds);
858 		anal->reflines = r_anal_reflines_get (anal,
859 			ds->addr, ds->buf, ds->len, ds->l,
860 			ds->linesout, ds->show_lines_call);
861 	} else {
862 		r_list_free (anal->reflines);
863 		anal->reflines = NULL;
864 	}
865 }
866 
ds_free(RDisasmState * ds)867 static void ds_free(RDisasmState *ds) {
868 	if (!ds) {
869 		return;
870 	}
871 	if (ds->show_emu_stack) {
872 		// TODO: destroy fake stack in here
873 		eprintf ("Free fake stack\n");
874 		if (ds->stackFd != -1) {
875 			r_io_fd_close (ds->core->io, ds->stackFd);
876 		}
877 	}
878 	r_asm_op_fini (&ds->asmop);
879 	r_anal_op_fini (&ds->analop);
880 	r_anal_hint_free (ds->hint);
881 	ds_print_esil_anal_fini (ds);
882 	ds_reflines_fini (ds);
883 	ds_print_esil_anal_fini (ds);
884 	sdb_free (ds->ssa);
885 	free (ds->comment);
886 	free (ds->line);
887 	free (ds->line_col);
888 	free (ds->refline);
889 	free (ds->refline2);
890 	free (ds->prev_line_col);
891 	free (ds->opstr);
892 	free (ds->osl);
893 	free (ds->sl);
894 	free (ds->_tabsbuf);
895 	R_FREE (ds);
896 }
897 
898 /* XXX move to r_print */
colorize_asm_string(RCore * core,RDisasmState * ds,bool print_color)899 static char *colorize_asm_string(RCore *core, RDisasmState *ds, bool print_color) {
900 	char *source = ds->opstr? ds->opstr: r_asm_op_get_asm (&ds->asmop);
901 	const char *hlstr = r_meta_get_string (ds->core->anal, R_META_TYPE_HIGHLIGHT, ds->at);
902 	bool partial_reset = line_highlighted (ds) ? true : ((hlstr && *hlstr) ? true : false);
903 	RAnalFunction *f = ds->show_color_args ? fcnIn (ds, ds->vat, R_ANAL_FCN_TYPE_NULL) : NULL;
904 
905 	if (!ds->show_color || !ds->colorop) {
906 		return strdup (source);
907 	}
908 
909 	if (print_color) {
910 		r_cons_strcat (r_print_color_op_type (core->print, ds->analop.type));
911 	}
912 	// workaround dummy colorizer in case of paired commands (tms320 & friends)
913 	char *spacer = strstr (source, "||");
914 	if (spacer) {
915 		char *scol1, *s1 = r_str_ndup (source, spacer - source);
916 		char *scol2, *s2 = strdup (spacer + 2);
917 
918 		scol1 = r_print_colorize_opcode (ds->core->print, s1, ds->color_reg, ds->color_num, partial_reset, f ? f->addr : 0);
919 		free (s1);
920 		scol2 = r_print_colorize_opcode (ds->core->print, s2, ds->color_reg, ds->color_num, partial_reset, f ? f->addr : 0);
921 		free (s2);
922 		if (!scol1) {
923 			scol1 = strdup ("");
924 		}
925 		if (!scol2) {
926 			scol2 = strdup ("");
927 		}
928 		source = r_str_newf ("%s||%s", scol1, scol2);
929 		free (scol1);
930 		free (scol2);
931 		return source;
932 	}
933 	return r_print_colorize_opcode (ds->core->print, source, ds->color_reg, ds->color_num, partial_reset, f ? f->addr : 0);
934 }
935 
ds_must_strip(RDisasmState * ds)936 static bool ds_must_strip(RDisasmState *ds) {
937 	if (ds && ds->strip && *ds->strip) {
938 		const char * optype = r_anal_optype_to_string (ds->analop.type);
939 		if (optype && *optype) {
940 			return strstr (ds->strip, optype);
941 		}
942 	}
943 	return false;
944 }
945 
ds_highlight_word(RDisasmState * ds,char * word,char * color)946 static void ds_highlight_word(RDisasmState * ds, char *word, char *color) {
947 	char *source = ds->opstr? ds->opstr: r_asm_op_get_asm (&ds->asmop);
948 	const char *color_reset = line_highlighted (ds) ? ds->color_linehl : Color_RESET_BG;
949 	char *asm_str = r_str_highlight (source, word, color, color_reset);
950 	ds->opstr = asm_str? asm_str: source;
951 }
952 
__replaceImports(RDisasmState * ds)953 static void __replaceImports(RDisasmState *ds) {
954 	if (ds->core->anal->imports) {
955 		char *imp;
956 		RListIter *iter;
957 		r_list_foreach (ds->core->anal->imports, iter, imp) {
958 			ds->opstr = r_str_replace (ds->opstr, imp,  ".", 1);
959 		}
960 	}
961 	if (ds->fcn && ds->fcn->imports) {
962 		char *imp;
963 		RListIter *iter;
964 		r_list_foreach (ds->fcn->imports, iter, imp) {
965 			ds->opstr = r_str_replace (ds->opstr, imp,  ".", 1);
966 		}
967 	}
968 }
969 
get_op_ireg(void * user,ut64 addr)970 static char *get_op_ireg (void *user, ut64 addr) {
971 	RCore *core = (RCore *)user;
972 	char *res = NULL;
973 	RAnalOp *op = r_core_anal_op (core, addr, 0);
974 	if (op && op->ireg) {
975 		res = strdup (op->ireg);
976 	}
977 	r_anal_op_free (op);
978 	return res;
979 }
980 
get_ptr_at(RAnalFunction * fcn,st64 delta,ut64 addr)981 static st64 get_ptr_at(RAnalFunction *fcn, st64 delta, ut64 addr) {
982 	return r_anal_function_get_var_stackptr_at (fcn, delta, addr);
983 }
984 
get_reg_at(RAnalFunction * fcn,st64 delta,ut64 addr)985 static const char *get_reg_at(RAnalFunction *fcn, st64 delta, ut64 addr) {
986 	return r_anal_function_get_var_reg_at (fcn, delta, addr);
987 }
988 
ds_build_op_str(RDisasmState * ds,bool print_color)989 static void ds_build_op_str(RDisasmState *ds, bool print_color) {
990 	RCore *core = ds->core;
991 	if (ds->use_esil) {
992 		free (ds->opstr);
993 		if (*R_STRBUF_SAFEGET (&ds->analop.esil)) {
994 			ds->opstr = strdup (R_STRBUF_SAFEGET (&ds->analop.esil));
995 		} else {
996 			ds->opstr = strdup (",");
997 		}
998 		return;
999 	}
1000 	if (ds->decode) {
1001 		free (ds->opstr);
1002 		ds->opstr = r_anal_op_to_string (core->anal, &ds->analop);
1003 		return;
1004 	}
1005 	if (!ds->opstr) {
1006 		ds->opstr = strdup (r_asm_op_get_asm (&ds->asmop));
1007 	}
1008 	/* initialize */
1009 	core->parser->subrel = r_config_get_i (core->config, "asm.sub.rel");
1010 	core->parser->subreg = r_config_get_i (core->config, "asm.sub.reg");
1011 	core->parser->subrel_addr = 0;
1012 	if (core->parser->subrel
1013 	    && (ds->analop.type == R_ANAL_OP_TYPE_LEA || ds->analop.type == R_ANAL_OP_TYPE_MOV
1014 	        || ds->analop.type == R_ANAL_OP_TYPE_CMP)
1015 	    && ds->analop.ptr != UT64_MAX) {
1016 		core->parser->subrel_addr = ds->analop.ptr;
1017 	}
1018 	if (ds->subvar && ds->opstr) {
1019 		ut64 at = ds->vat;
1020 		RAnalFunction *f = fcnIn (ds, at, R_ANAL_FCN_TYPE_NULL);
1021 		core->parser->get_op_ireg = get_op_ireg;
1022 		core->parser->get_ptr_at = get_ptr_at;
1023 		core->parser->get_reg_at = get_reg_at;
1024 		r_parse_subvar (core->parser, f, at, ds->analop.size,
1025 			ds->opstr, ds->strsub, sizeof (ds->strsub));
1026 		if (*ds->strsub) {
1027 			free (ds->opstr);
1028 			ds->opstr = strdup (ds->strsub);
1029 		}
1030 		if (core->parser->subrel) {
1031 			RList *list = r_anal_refs_get (core->anal, at);
1032 			RListIter *iter;
1033 			RAnalRef *ref;
1034 			r_list_foreach (list, iter, ref) {
1035 				if ((ref->type == R_ANAL_REF_TYPE_DATA
1036 					|| ref->type == R_ANAL_REF_TYPE_STRING)
1037 					&& ds->analop.type == R_ANAL_OP_TYPE_LEA) {
1038 					core->parser->subrel_addr = ref->addr;
1039 					break;
1040 				}
1041 			}
1042 			r_list_free (list);
1043 		}
1044 	}
1045 
1046 	if (ds->pseudo) {
1047 		const char *opstr = ds->opstr ? ds->opstr : r_asm_op_get_asm (&ds->asmop);
1048 		r_parse_parse (core->parser, opstr, ds->str);
1049 		free (ds->opstr);
1050 		ds->opstr = strdup (ds->str);
1051 	}
1052 	ds->opstr = ds_sub_jumps (ds, ds->opstr);
1053 	if (ds->immtrim) {
1054 		char *res = r_parse_immtrim (ds->opstr);
1055 		if (res) {
1056 			ds->opstr = res;
1057 		}
1058 		return;
1059 	}
1060 	if (ds->hint && ds->hint->opcode) {
1061 		free (ds->opstr);
1062 		ds->opstr = strdup (ds->hint->opcode);
1063 	}
1064 	if (ds->subnames) {
1065 		RSpace *ofs = core->parser->flagspace;
1066 		RSpace *fs = ds->flagspace_ports;
1067 		if (ds->analop.type == R_ANAL_OP_TYPE_IO) {
1068 			core->parser->notin_flagspace = NULL;
1069 			core->parser->flagspace = fs;
1070 		} else {
1071 			if (fs) {
1072 				core->parser->notin_flagspace = fs;
1073 				core->parser->flagspace = fs;
1074 			} else {
1075 				core->parser->notin_flagspace = NULL;
1076 				core->parser->flagspace = NULL;
1077 			}
1078 		}
1079 		if (core->parser->subrel && ds->analop.refptr) {
1080 			if (core->parser->subrel_addr == 0) {
1081 				ut64 killme = UT64_MAX;
1082 				const int be = core->rasm->big_endian;
1083 				r_io_read_i (core->io, ds->analop.ptr, &killme, ds->analop.refptr, be);
1084 				core->parser->subrel_addr = killme;
1085 			}
1086 		}
1087 		char *asm_str = colorize_asm_string (core, ds, print_color);
1088 		r_parse_filter (core->parser, ds->vat, core->flags, ds->hint, asm_str,
1089 				ds->str, sizeof (ds->str), core->print->big_endian);
1090 		free (asm_str);
1091 		// subvar depends on filter
1092 		if (ds->subvar) {
1093 			// HACK to do subvar outside rparse becacuse the whole rparse api must be rewritten
1094 			char *ox = strstr (ds->str, "0x");
1095 			if (ox) {
1096 				char *e = strchr (ox, ']');
1097 				if (e) {
1098 					e = strdup (e);
1099 					ut64 addr = r_num_get (NULL, ox);
1100 					if (addr > ds->min_ref_addr) {
1101 						RFlagItem *fi = r_flag_get_i (ds->core->flags, addr);
1102 						if (fi) {
1103 							r_str_cpy (ox, fi->name);
1104 							r_str_cat (ox, e);
1105 						}
1106 					}
1107 					free (e);
1108 				}
1109 			}
1110 		}
1111 		core->parser->flagspace = ofs;
1112 		free (ds->opstr);
1113 		ds->opstr = strdup (ds->str);
1114 	} else {
1115 		r_str_trim (ds->opstr); // trim before coloring git
1116 		char *asm_str = colorize_asm_string (core, ds, print_color);
1117 		free (ds->opstr);
1118 		ds->opstr = asm_str;
1119 	}
1120 	r_str_trim (ds->opstr);
1121 	// updates ds->opstr
1122 	__replaceImports (ds);
1123 	if (ds->show_color) {
1124 		int i = 0;
1125 		char *word = NULL;
1126 		char *bgcolor = NULL;
1127 		const char *wcdata = r_meta_get_string (ds->core->anal, R_META_TYPE_HIGHLIGHT, ds->at);
1128 		int argc = 0;
1129 		char **wc_array = r_str_argv (wcdata, &argc);
1130 		for (i = 0; i < argc; i++) {
1131 			bgcolor = strchr (wc_array[i], '\x1b');
1132 			word = r_str_newlen (wc_array[i], bgcolor - wc_array[i]);
1133 			ds_highlight_word (ds, word, bgcolor);
1134 		}
1135 	}
1136 }
1137 
r_core_hint_begin(RCore * core,RAnalHint * hint,ut64 at)1138 R_API RAnalHint *r_core_hint_begin(RCore *core, RAnalHint* hint, ut64 at) {
1139 	static char *hint_syntax = NULL;
1140 	r_anal_hint_free (hint);
1141 	hint = r_anal_hint_get (core->anal, at);
1142 	if (hint_syntax) {
1143 		r_config_set (core->config, "asm.syntax", hint_syntax);
1144 		hint_syntax = NULL;
1145 	}
1146 	if (hint) {
1147 		/* syntax */
1148 		if (hint->syntax) {
1149 			if (!hint_syntax) {
1150 				hint_syntax = strdup (r_config_get (core->config, "asm.syntax"));
1151 			}
1152 			r_config_set (core->config, "asm.syntax", hint->syntax);
1153 		}
1154 		if (hint->high) {
1155 			/* TODO: do something here */
1156 		}
1157 	}
1158 	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, at, 0);
1159 	if (fcn) {
1160 		if (fcn->bits == 16 || fcn->bits == 32) {
1161 			if (!hint) {
1162 				hint = R_NEW0 (RAnalHint);
1163 			}
1164 			hint->bits = fcn->bits;
1165 			hint->new_bits = fcn->bits;
1166 		}
1167 	}
1168 	return hint;
1169 }
1170 
ds_pre_line(RDisasmState * ds)1171 static void ds_pre_line(RDisasmState *ds) {
1172 	ds_setup_pre (ds, false, false);
1173 	ds_print_pre (ds, true);
1174 	char *tmp = ds->line;
1175 	char *tmp_col = ds->line_col;
1176 	ds->line = ds->refline2;
1177 	ds->line_col = ds->prev_line_col;
1178 	ds_print_lines_left (ds);
1179 	ds->line = tmp;
1180 	ds->line_col = tmp_col;
1181 }
1182 
ds_begin_line(RDisasmState * ds)1183 static void ds_begin_line(RDisasmState *ds) {
1184 	if (ds->pj) {
1185 		pj_o (ds->pj);
1186 		pj_kn (ds->pj, "offset", ds->vat);
1187 		if (ds->core->anal->reflines) {
1188 			RAnalRefline *ref;
1189 			RListIter *iter;
1190 			// XXX Probably expensive
1191 			r_list_foreach (ds->core->anal->reflines, iter, ref) {
1192 				if (ref->from == ds->vat) {
1193 					pj_kn (ds->pj, "arrow", ref->to);
1194 					break;
1195 				}
1196 			}
1197 		}
1198 		pj_k (ds->pj, "text");
1199 	}
1200 	ds->buf_line_begin = r_cons_get_buffer_len ();
1201 	if (!ds->pj && ds->asm_hint_pos == -1) {
1202 		if (!ds_print_core_vmode (ds, ds->asm_hint_pos)) {
1203 			r_cons_printf ("    ");
1204 		}
1205 	}
1206 }
1207 
ds_newline(RDisasmState * ds)1208 static void ds_newline(RDisasmState *ds) {
1209 	if (ds->pj) {
1210 		const bool is_html = r_config_get_i (ds->core->config, "scr.html");
1211 		if (is_html) {
1212 			char *s = r_cons_html_filter (r_cons_get_buffer (), NULL);
1213 			pj_s (ds->pj, s);
1214 			free (s);
1215 		} else {
1216 			pj_s (ds->pj, r_cons_get_buffer ());
1217 		}
1218 		r_cons_reset ();
1219 		pj_end (ds->pj);
1220 	} else {
1221 		r_cons_newline ();
1222 	}
1223 }
1224 
ds_begin_cont(RDisasmState * ds)1225 static void ds_begin_cont(RDisasmState *ds) {
1226 	ds_begin_line (ds);
1227 	ds_setup_print_pre (ds, false, false);
1228 	if (!ds->linesright && ds->show_lines_bb && ds->line) {
1229 		RAnalRefStr *refstr = r_anal_reflines_str (ds->core, ds->at,
1230 		                    ds->linesopts | R_ANAL_REFLINE_TYPE_MIDDLE_AFTER);
1231 		ds_print_ref_lines (refstr->str, refstr->cols, ds);
1232 		r_anal_reflines_str_free (refstr);
1233 	}
1234 }
1235 
ds_begin_comment(RDisasmState * ds)1236 static void ds_begin_comment(RDisasmState *ds) {
1237 	if (ds->show_comment_right) {
1238 		CMT_ALIGN;
1239 	} else {
1240 		ds_begin_line (ds);
1241 		ds_pre_xrefs (ds, false);
1242 	}
1243 }
1244 
ds_show_refs(RDisasmState * ds)1245 static void ds_show_refs(RDisasmState *ds) {
1246 	RAnalRef *ref;
1247 	RListIter *iter;
1248 
1249 	if (!ds->show_cmtrefs) {
1250 		return;
1251 	}
1252 	RList *list = r_anal_xrefs_get_from (ds->core->anal, ds->at);
1253 
1254 	r_list_foreach (list, iter, ref) {
1255 		const char *cmt = r_meta_get_string (ds->core->anal, R_META_TYPE_COMMENT, ref->addr);
1256 		const RList *fls = r_flag_get_list (ds->core->flags, ref->addr);
1257 		RListIter *iter2;
1258 		RFlagItem *fis;
1259 		r_list_foreach (fls, iter2, fis) {
1260 			ds_begin_comment (ds);
1261 			ds_comment (ds, true, "; (%s)", fis->name);
1262 		}
1263 
1264 		// ds_align_comment (ds);
1265 		if (ds->show_color) {
1266 			r_cons_strcat (ds->color_comment);
1267 		}
1268 		if (cmt) {
1269 			ds_begin_comment (ds);
1270 			ds_comment (ds, true, "; (%s)", cmt);
1271 		}
1272 		if (ref->type & R_ANAL_REF_TYPE_CALL) {
1273 			RAnalOp aop;
1274 			ut8 buf[12];
1275 			r_io_read_at (ds->core->io, ref->at, buf, sizeof (buf));
1276 			r_anal_op (ds->core->anal, &aop, ref->at, buf, sizeof (buf), R_ANAL_OP_MASK_ALL);
1277 			if ((aop.type & R_ANAL_OP_TYPE_MASK) == R_ANAL_OP_TYPE_UCALL) {
1278 				RAnalFunction * fcn = r_anal_get_function_at (ds->core->anal, ref->addr);
1279 				ds_begin_comment (ds);
1280 				if (fcn) {
1281 					ds_comment (ds, true, "; %s", fcn->name);
1282 				} else {
1283 					ds_comment (ds, true, "; 0x%" PFMT64x"", ref->addr);
1284 				}
1285 			}
1286 		}
1287 		ds_print_color_reset (ds);
1288 	}
1289 	r_list_free (list);
1290 }
1291 
ds_show_xrefs(RDisasmState * ds)1292 static void ds_show_xrefs(RDisasmState *ds) {
1293 	RAnalRef *refi;
1294 	RListIter *iter, *it;
1295 	RCore *core = ds->core;
1296 	char *name, *realname;
1297 	int count = 0;
1298 	if (!ds->show_xrefs || !ds->show_comments) {
1299 		return;
1300 	}
1301 	/* show xrefs */
1302 	RList *xrefs = r_anal_xrefs_get (core->anal, ds->at);
1303 	if (!xrefs) {
1304 		return;
1305 	}
1306 	// only show fcnline in xrefs when addr is not the beginning of a function
1307 	bool fcnlines = (ds->fcn && ds->fcn->addr == ds->at);
1308 	if (r_list_length (xrefs) > ds->maxrefs) {
1309 		ds_begin_line (ds);
1310 		ds_pre_xrefs (ds, fcnlines);
1311 		ds_comment (ds, false, "%s; XREFS(%d)",
1312 			ds->show_color? ds->pal_comment: "",
1313 			r_list_length (xrefs));
1314 		if (ds->show_color) {
1315 			ds_print_color_reset (ds);
1316 		}
1317 		ds_newline (ds);
1318 		r_list_free (xrefs);
1319 		return;
1320 	}
1321 	if (r_list_length (xrefs) > ds->foldxrefs) {
1322 		int cols = r_cons_get_size (NULL);
1323 		cols -= 15;
1324 		cols /= 23;
1325 		cols = cols > 5 ? 5 : cols;
1326 		ds_begin_line (ds);
1327 		ds_pre_xrefs (ds, fcnlines);
1328 		ds_comment (ds, false, "%s; XREFS: ", ds->show_color? ds->pal_comment: "");
1329 		r_list_foreach (xrefs, iter, refi) {
1330 			ds_comment (ds, false, "%s 0x%08"PFMT64x"  ",
1331 				r_anal_xrefs_type_tostring (refi->type), refi->addr);
1332 			if (count == cols) {
1333 				if (iter->n) {
1334 					ds_print_color_reset (ds);
1335 					ds_newline (ds);
1336 					ds_begin_line (ds);
1337 					ds_pre_xrefs (ds, fcnlines);
1338 					ds_comment (ds, false, "%s; XREFS: ", ds->show_color? ds->pal_comment: "");
1339 				}
1340 				count = 0;
1341 			} else {
1342 				count++;
1343 			}
1344 		}
1345 		ds_print_color_reset (ds);
1346 		ds_newline (ds);
1347 		r_list_free (xrefs);
1348 		return;
1349 	}
1350 
1351 	RList *addrs = r_list_newf (free);
1352 	RAnalFunction *fun, *next_fun;
1353 	RFlagItem *f, *next_f;
1354 	r_list_foreach (xrefs, iter, refi) {
1355 		if (!ds->asm_xrefs_code && refi->type == R_ANAL_REF_TYPE_CODE) {
1356 			continue;
1357 		}
1358 		if (refi->at == ds->at) {
1359 			realname = NULL;
1360 			fun = fcnIn (ds, refi->addr, -1);
1361 			if (fun) {
1362 				if (iter != xrefs->tail) {
1363 					ut64 next_addr = ((RAnalRef *)(iter->n->data))->addr;
1364 					next_fun = r_anal_get_fcn_in (core->anal, next_addr, -1);
1365 					if (next_fun && next_fun->addr == fun->addr) {
1366 						r_list_append (addrs, r_num_dup (refi->addr));
1367 						continue;
1368 					}
1369 				}
1370 				if (ds->asm_demangle) {
1371 					f = r_flag_get_by_spaces (core->flags, fun->addr, R_FLAGS_FS_SYMBOLS, NULL);
1372 					if (f && f->demangled && f->realname) {
1373 						realname = strdup (f->realname);
1374 					}
1375 				}
1376 				name = strdup (fun->name);
1377 				r_list_append (addrs, r_num_dup (refi->addr));
1378 			} else {
1379 				f = r_flag_get_at (core->flags, refi->addr, true);
1380 				if (f) {
1381 					if (iter != xrefs->tail) {
1382 						ut64 next_addr = ((RAnalRef *)(iter->n->data))->addr;
1383 						next_f = r_flag_get_at (core->flags, next_addr, true);
1384 						if (next_f && f->offset == next_f->offset) {
1385 							r_list_append (addrs, r_num_dup (refi->addr - f->offset));
1386 							continue;
1387 						}
1388 					}
1389 					if (ds->asm_demangle) {
1390 						RFlagItem *f_sym = f;
1391 						if (!r_str_startswith (f_sym->name, "sym.")) {
1392 							f_sym = r_flag_get_by_spaces (core->flags, f->offset,
1393 							                              R_FLAGS_FS_SYMBOLS, NULL);
1394 						}
1395 						if (f_sym && f_sym->demangled && f_sym->realname) {
1396 							f = f_sym;
1397 							realname = strdup (f->realname);
1398 						}
1399 					}
1400 					name = strdup (f->name);
1401 					r_list_append (addrs, r_num_dup (refi->addr - f->offset));
1402 				} else {
1403 					name = strdup ("unk");
1404 				}
1405 			}
1406 			ds_begin_line (ds);
1407 			ds_pre_xrefs (ds, fcnlines);
1408 			const char* plural = r_list_length (addrs) > 1 ? "S" : "";
1409 			const char* plus = fun ? "" : "+";
1410 			ds_comment (ds, false, "%s; %s XREF%s from %s @ ",
1411 				COLOR (ds, pal_comment), r_anal_xrefs_type_tostring (refi->type), plural,
1412 				realname ? realname : name);
1413 			ut64 *addrptr;
1414 			r_list_foreach (addrs, it, addrptr) {
1415 				if (addrptr && *addrptr) {
1416 					ds_comment (ds, false, "%s%s0x%"PFMT64x, it == addrs->head ? "" : ", ", plus, *addrptr);
1417 				}
1418 			}
1419 			if (realname && (!fun || r_anal_get_function_at (core->anal, ds->at))) {
1420 				const char *pad = ds->show_comment_right ? "" : " ";
1421 				if (!ds->show_comment_right) {
1422 					ds_newline (ds);
1423 					ds_begin_line (ds);
1424 					ds_pre_xrefs (ds, fcnlines);
1425 				}
1426 				ds_comment (ds, false, " %s; %s", pad, name);
1427 			}
1428 			ds_comment (ds, false, "%s", COLOR_RESET (ds));
1429 			ds_newline (ds);
1430 			r_list_purge (addrs);
1431 			R_FREE (name);
1432 			free (realname);
1433 		} else {
1434 			eprintf ("Corrupted database?\n");
1435 		}
1436 	}
1437 	r_list_free (addrs);
1438 	r_list_free (xrefs);
1439 }
1440 
ds_atabs_option(RDisasmState * ds)1441 static void ds_atabs_option(RDisasmState *ds) {
1442 	int n, i = 0, comma = 0, word = 0;
1443 	int brackets = 0;
1444 	char *t, *b;
1445 	if (!ds || !ds->atabs) {
1446 		return;
1447 	}
1448 	int bufasm_len = r_strbuf_length (&ds->asmop.buf_asm);
1449 	int size = bufasm_len * (ds->atabs + 1) * 4;
1450 	if (size < 1 || size < bufasm_len) {
1451 		return;
1452 	}
1453 	b = malloc (size + 1);
1454 	if (ds->opstr) {
1455 		strcpy (b, ds->opstr);
1456 	} else {
1457 		strcpy (b, r_asm_op_get_asm (&ds->asmop));
1458 	}
1459 	if (!b) {
1460 		return;
1461 	}
1462 	free (ds->opstr);
1463 	ds->opstr = b;
1464 	for (; *b; b++, i++) {
1465 		if (*b == '(' || *b == '[') {
1466 			brackets++;
1467 		}
1468 		if (*b == ')' || *b == ']') {
1469 			brackets--;
1470 		}
1471 		if (*b == ',') {
1472 			comma = 1;
1473 		}
1474 		if (*b != ' ') {
1475 			continue;
1476 		}
1477 		if (word > 0 && !comma) {
1478 			continue; //&& b[1]=='[') continue;
1479 		}
1480 		if (brackets > 0) {
1481 			continue;
1482 		}
1483 		comma = 0;
1484 		brackets = 0;
1485 		n = (ds->atabs - i);
1486 		t = strdup (b + 1); //XXX slow!
1487 		if (n < 1) {
1488 			n = 1;
1489 		}
1490 		memset (b, ' ', n);
1491 		b += n;
1492 		strcpy (b, t);
1493 		free (t);
1494 		i = 0;
1495 		word++;
1496 		if (ds->atabsonce) {
1497 			break;
1498 		}
1499 	}
1500 }
1501 
handleMidFlags(RCore * core,RDisasmState * ds,bool print)1502 static int handleMidFlags(RCore *core, RDisasmState *ds, bool print) {
1503 	int i;
1504 
1505 	ds->hasMidflag = false;
1506 	if (ds->midcursor && core->print->cur != -1) {
1507 		ut64 cur = core->offset + core->print->cur;
1508 		ut64 from = ds->at;
1509 		ut64 to = ds->at + ds->oplen;
1510 		if (cur > from && cur < to) {
1511 			return cur - from;
1512 		}
1513 	}
1514 	for (i = 1; i < ds->oplen; i++) {
1515 		RFlagItem *fi = r_flag_get_i (core->flags, ds->at + i);
1516 		if (fi && fi->name) {
1517 			if (ds->midflags == 2 && ((fi->name[0] == '$') || (fi->realname && fi->realname[0] == '$'))) {
1518 				i = 0;
1519 			} else if (!strncmp (fi->name, "hit.", 4)) { // use search.prefix ?
1520 				i = 0;
1521 			} else if (!strncmp (fi->name, "str.", 4)) {
1522 				ds->midflags = R_MIDFLAGS_REALIGN;
1523 			} else if (!strncmp (fi->name, "reloc.", 6)) {
1524 				continue;
1525 			} else if (ds->midflags == R_MIDFLAGS_SYMALIGN) {
1526 				if (strncmp (fi->name, "sym.", 4)) {
1527 					continue;
1528 				}
1529 			}
1530 			ds->hasMidflag = true;
1531 			return i;
1532 		}
1533 	}
1534 	return 0;
1535 }
1536 
handleMidBB(RCore * core,RDisasmState * ds)1537 static int handleMidBB(RCore *core, RDisasmState *ds) {
1538 	int i;
1539 	ds->hasMidbb = false;
1540 	r_return_val_if_fail (core->anal, 0);
1541 	// Unfortunately, can't just check the addr of the last insn byte since
1542 	// a bb (and fcn) can be as small as 1 byte, and advancing i based on
1543 	// bb->size is unsound if basic blocks can nest or overlap
1544 	for (i = 1; i < ds->oplen; i++) {
1545 		RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, ds->at + i, 0);
1546 		if (fcn) {
1547 			RAnalBlock *bb = r_anal_fcn_bbget_in (core->anal, fcn, ds->at + i);
1548 			if (bb && bb->addr > ds->at) {
1549 				ds->hasMidbb = true;
1550 				return bb->addr - ds->at;
1551 			}
1552 		}
1553 	}
1554 	return 0;
1555 }
1556 
r_core_flag_in_middle(RCore * core,ut64 at,int oplen,int * midflags)1557 R_API int r_core_flag_in_middle(RCore *core, ut64 at, int oplen, int *midflags) {
1558 	r_return_val_if_fail (midflags, 0);
1559 	RDisasmState ds = {
1560 		.at = at,
1561 		.oplen = oplen,
1562 		.midflags = *midflags
1563 	};
1564 	int ret = handleMidFlags (core, &ds, true);
1565 	*midflags = ds.midflags;
1566 	return ret;
1567 }
1568 
r_core_bb_starts_in_middle(RCore * core,ut64 at,int oplen)1569 R_API int r_core_bb_starts_in_middle(RCore *core, ut64 at, int oplen) {
1570 	RDisasmState ds = {
1571 		.at = at,
1572 		.oplen = oplen
1573 	};
1574 	return handleMidBB (core, &ds);
1575 }
1576 
ds_print_show_cursor(RDisasmState * ds)1577 static void ds_print_show_cursor(RDisasmState *ds) {
1578 	RCore *core = ds->core;
1579 	char res[] = "     ";
1580 	if (!ds->show_marks) {
1581 		return;
1582 	}
1583 	int q = core->print->cur_enabled &&
1584 		ds->cursor >= ds->index &&
1585 		ds->cursor < (ds->index + ds->asmop.size);
1586 	RBreakpointItem *p = r_bp_get_at (core->dbg->bp, ds->at);
1587 	if (ds->midflags) {
1588 		(void)handleMidFlags (core, ds, false);
1589 	}
1590 	if (ds->midbb) {
1591 		(void)handleMidBB (core, ds);
1592 	}
1593 	if (p) {
1594 		res[0] = 'b';
1595 	}
1596 	if (ds->hasMidflag || ds->hasMidbb) {
1597 		res[1] = '~';
1598 	}
1599 	if (q) {
1600 		if (ds->cursor == ds->index) {
1601 			res[2] = '*';
1602 		} else {
1603 			int i = 2, diff = ds->cursor - ds->index;
1604 			if (diff > 9) {
1605 				res[i++] = '0' + (diff / 10);
1606 			}
1607 			res[i] = '0' + (diff % 10);
1608 		}
1609 	}
1610 	r_cons_strcat (res);
1611 }
1612 
ds_pre_xrefs(RDisasmState * ds,bool no_fcnlines)1613 static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines) {
1614 	ds_setup_pre (ds, false, false);
1615 	if (ds->pre != DS_PRE_NONE && ds->pre != DS_PRE_EMPTY) {
1616 		ds->pre = no_fcnlines ? DS_PRE_EMPTY : DS_PRE_FCN_MIDDLE;
1617 	}
1618 	ds_print_pre (ds, !no_fcnlines);
1619 	char *tmp = ds->line;
1620 	char *tmp_col = ds->line_col;
1621 	ds->line = ds->refline2;
1622 	ds->line_col = ds->prev_line_col;
1623 	ds_print_lines_left (ds);
1624 	if (!ds->show_offset && ds->show_marks) {
1625 		ds_print_show_cursor (ds);
1626 	}
1627 	ds->line = tmp;
1628 	ds->line_col = tmp_col;
1629 }
1630 
1631 //TODO: this function is a temporary fix. All analysis should be based on realsize. However, now for same architectures realisze is not used
tmp_get_realsize(RAnalFunction * f)1632 static ut32 tmp_get_realsize (RAnalFunction *f) {
1633 	ut32 size = r_anal_function_realsize (f);
1634 	return (size > 0) ? size : r_anal_function_linear_size (f);
1635 }
1636 
ds_show_functions_argvar(RDisasmState * ds,RAnalFunction * fcn,RAnalVar * var,const char * base,bool is_var,char sign)1637 static void ds_show_functions_argvar(RDisasmState *ds, RAnalFunction *fcn, RAnalVar *var, const char *base, bool is_var, char sign) {
1638 	int delta = var->kind == 'b' ? R_ABS (var->delta + fcn->bp_off) : R_ABS (var->delta);
1639 	const char *pfx = is_var ? "var" : "arg";
1640 	char *constr = r_anal_var_get_constraints_readable (var);
1641 	r_cons_printf ("%s%s %s%s%s%s %s%s%s%s@ %s%c0x%x", COLOR_ARG (ds, color_func_var), pfx,
1642 			COLOR_ARG (ds, color_func_var_type), var->type,
1643 			r_str_endswith (var->type, "*") ? "" : " ",
1644 			var->name, COLOR_ARG (ds, color_func_var_addr),
1645 			constr? " { ":"",
1646 			r_str_get (constr),
1647 			constr? "} ":"",
1648 			base, sign, delta);
1649 	if (ds->show_varsum == -1) {
1650 		char *val = r_core_cmd_strf (ds->core, ".afvd %s", var->name);
1651 		if (val) {
1652 			r_str_replace_char (val, '\n', '\0');
1653 			r_cons_printf (" = %s", val);
1654 			free (val);
1655 		}
1656 	}
1657 	free (constr);
1658 }
1659 
printVarSummary(RDisasmState * ds,RList * list)1660 static void printVarSummary(RDisasmState *ds, RList *list) {
1661 	const char *numColor = ds->core->cons->context->pal.num;
1662 	RAnalVar *var;
1663 	RListIter *iter;
1664 	int bp_vars = 0;
1665 	int sp_vars = 0;
1666 	int rg_vars = 0;
1667 	int bp_args = 0;
1668 	int sp_args = 0;
1669 	int rg_args = 0;
1670 	const char *bp_vars_color = COLOR_RESET (ds);
1671 	const char *sp_vars_color = COLOR_RESET (ds);
1672 	const char *rg_vars_color = COLOR_RESET (ds);
1673 	const char *bp_args_color = COLOR_RESET (ds);
1674 	const char *sp_args_color = COLOR_RESET (ds);
1675 	const char *rg_args_color = COLOR_RESET (ds);
1676 	r_list_foreach (list, iter, var) {
1677 		if (var->isarg) {
1678 			switch (var->kind) {
1679 			case 'b':
1680 				bp_args++;
1681 				break;
1682 			case 's':
1683 				sp_args++;
1684 				break;
1685 			case 'r':
1686 				rg_args++;
1687 				break;
1688 			}
1689 		} else {
1690 			switch (var->kind) {
1691 			case 'b':
1692 				bp_vars++;
1693 				break;
1694 			case 's':
1695 				sp_vars++;
1696 				break;
1697 			case 'r':
1698 				rg_vars++;
1699 				break;
1700 			}
1701 		}
1702 	}
1703 	if (bp_vars) { bp_vars_color = numColor; }
1704 	if (sp_vars) { sp_vars_color = numColor; }
1705 	if (rg_vars) { rg_vars_color = numColor; }
1706 	if (bp_args) { bp_args_color = numColor; }
1707 	if (sp_args) { sp_args_color = numColor; }
1708 	if (rg_args) { rg_args_color = numColor; }
1709 	if (ds->show_varsum == 2) {
1710 		ds_begin_line (ds);
1711 		ds_print_pre (ds, true);
1712 		r_cons_printf ("vars: %s%d%s %s%d%s %s%d%s",
1713 				bp_vars_color, bp_vars, COLOR_RESET (ds),
1714 				sp_vars_color, sp_vars, COLOR_RESET (ds),
1715 				rg_vars_color, rg_vars, COLOR_RESET (ds));
1716 		ds_newline (ds);
1717 		ds_begin_line (ds);
1718 		ds_print_pre (ds, true);
1719 		r_cons_printf ("args: %s%d%s %s%d%s %s%d%s",
1720 				bp_args_color, bp_args, COLOR_RESET (ds),
1721 				sp_args_color, sp_args, COLOR_RESET (ds),
1722 				rg_args_color, rg_args, COLOR_RESET (ds));
1723 		ds_newline (ds);
1724 		return;
1725 	}
1726 	ds_begin_line (ds);
1727 	ds_print_pre (ds, true);
1728 	r_cons_printf ("bp: %s%d%s (vars %s%d%s, args %s%d%s)",
1729 			bp_args || bp_vars ? numColor : COLOR_RESET (ds), bp_args + bp_vars, COLOR_RESET (ds),
1730 			bp_vars_color, bp_vars, COLOR_RESET (ds),
1731 			bp_args_color, bp_args, COLOR_RESET (ds));
1732 	ds_newline (ds);
1733 	ds_begin_line (ds);
1734 	ds_print_pre (ds, true);
1735 	r_cons_printf ("sp: %s%d%s (vars %s%d%s, args %s%d%s)",
1736 			sp_args || sp_vars ? numColor : COLOR_RESET (ds), sp_args+sp_vars, COLOR_RESET (ds),
1737 			sp_vars_color, sp_vars, COLOR_RESET (ds),
1738 			sp_args_color, sp_args, COLOR_RESET (ds));
1739 	ds_newline (ds);
1740 	ds_begin_line (ds);
1741 	ds_print_pre (ds, true);
1742 	r_cons_printf ("rg: %s%d%s (vars %s%d%s, args %s%d%s)",
1743 			rg_args || rg_vars ? numColor : COLOR_RESET (ds), rg_args+rg_vars, COLOR_RESET (ds),
1744 			rg_vars_color, rg_vars, COLOR_RESET (ds),
1745 			rg_args_color, rg_args, COLOR_RESET (ds));
1746 	ds_newline (ds);
1747 }
1748 
empty_signature(const char * s)1749 static bool empty_signature(const char *s) {
1750 	return (s && !strncmp (s, "void ", 5) && strstr (s, "()"));
1751 }
1752 
ds_show_functions(RDisasmState * ds)1753 static void ds_show_functions(RDisasmState *ds) {
1754 	RAnalFunction *f;
1755 	RCore *core = ds->core;
1756 	char *fcn_name;
1757 	bool fcn_name_alloc = false; // whether fcn_name needs to be freed by this function
1758 
1759 	if (!ds->show_functions) {
1760 		return;
1761 	}
1762 	bool demangle = r_config_get_i (core->config, "bin.demangle");
1763 	bool keep_lib = r_config_get_i (core->config, "bin.demangle.libs");
1764 	bool showSig = ds->show_fcnsig && ds->show_calls;
1765 	bool call = r_config_get_i (core->config, "asm.calls");
1766 	const char *lang = demangle ? r_config_get (core->config, "bin.lang") : NULL;
1767 	f = r_anal_get_function_at (core->anal, ds->at);
1768 	if (!f) {
1769 		return;
1770 	}
1771 	if (demangle) {
1772 		fcn_name = r_bin_demangle (core->bin->cur, lang, f->name, f->addr, keep_lib);
1773 		if (fcn_name) {
1774 			fcn_name_alloc = true;
1775 		} else {
1776 			fcn_name = f->name;
1777 		}
1778 	} else {
1779 		fcn_name = f->name;
1780 	}
1781 
1782 	ds_begin_line (ds);
1783 	char *sign = r_anal_function_get_signature (f);
1784 	if (empty_signature (sign)) {
1785 		R_FREE (sign);
1786 	}
1787 	if (f->type == R_ANAL_FCN_TYPE_LOC) {
1788 		r_cons_printf ("%s%s ", COLOR (ds, color_fline),
1789 			core->cons->vline[LINE_CROSS]); // |-
1790 		if (!showSig) {
1791 			r_cons_printf ("%s%s%s %"PFMT64u, COLOR (ds, color_floc),
1792 					fcn_name, COLOR_RESET (ds), r_anal_function_linear_size (f));
1793 			ds_newline (ds);
1794 		}
1795 	} else {
1796 		const char *fcntype;
1797 		char cmt[32];
1798 		get_bits_comment (core, f, cmt, sizeof (cmt));
1799 
1800 		switch (f->type) {
1801 		case R_ANAL_FCN_TYPE_FCN:
1802 		case R_ANAL_FCN_TYPE_SYM:
1803 			fcntype = "fcn";
1804 			break;
1805 		case R_ANAL_FCN_TYPE_IMP:
1806 			fcntype = "imp";
1807 			break;
1808 		default:
1809 			fcntype = "loc";
1810 			break;
1811 		}
1812 		//ds_set_pre (ds, core->cons->vline[CORNER_TL]);
1813 		if (ds->show_lines_fcn) {
1814 			ds->pre = DS_PRE_FCN_HEAD;
1815 		}
1816 		ds_print_pre (ds, true);
1817 		if (ds->show_flgoff) {
1818 			ds_print_lines_left (ds);
1819 			ds_print_offset (ds);
1820 		}
1821 		if (!showSig) {
1822 			r_cons_printf ("%s(%s) %s%s%s %d", COLOR (ds, color_fname),
1823 					fcntype, fcn_name, cmt, COLOR_RESET (ds), tmp_get_realsize (f));
1824 			ds_newline (ds);
1825 		}
1826 	}
1827 	if (!showSig) {
1828 		if (sign) {
1829 			ds_begin_line (ds);
1830 			r_cons_printf ("// %s", sign);
1831 			ds_newline (ds);
1832 		}
1833 	}
1834 	R_FREE (sign);
1835 	if (ds->show_lines_fcn) {
1836 		ds->pre = DS_PRE_FCN_MIDDLE;
1837 	}
1838 	ds->stackptr = core->anal->stackptr;
1839 	RAnalFcnVarsCache vars_cache;
1840 	r_anal_fcn_vars_cache_init (core->anal, &vars_cache, f);
1841 
1842 	int o_varsum = ds->show_varsum;
1843 	if (ds->interactive && !o_varsum) {
1844 		int padding = 10;
1845 		int numvars = vars_cache.bvars->length + vars_cache.rvars->length + vars_cache.svars->length + padding;
1846 		if (numvars > ds->l) {
1847 			ds->show_varsum = 1;
1848 		} else {
1849 			ds->show_varsum = 0;
1850 		}
1851 	}
1852 
1853 	if (call) {
1854 		if (!showSig) {
1855 			ds_begin_line (ds);
1856 			r_cons_print (COLOR (ds, color_fline));
1857 			ds_print_pre (ds, true);
1858 			r_cons_printf ("%s  ", COLOR_RESET (ds));
1859 		}
1860 		r_cons_printf ("%" PFMT64d ": ", r_anal_function_realsize (f));
1861 
1862 		// show function's realname in the signature if realnames are enabled
1863 		if (core->flags->realnames) {
1864 			RFlagItem *flag = r_flag_get (core->flags, fcn_name);
1865 			if (flag && flag->realname) {
1866 				fcn_name = flag->realname;
1867 			}
1868 		}
1869 
1870 		char *sig = r_anal_fcn_format_sig (core->anal, f, fcn_name, &vars_cache, COLOR (ds, color_fname), COLOR_RESET (ds));
1871 		if (sig) {
1872 			r_cons_print (sig);
1873 			free (sig);
1874 		}
1875 		ds_newline (ds);
1876 	}
1877 
1878 	if (ds->show_vars) {
1879 		if (ds->show_varsum && ds->show_varsum != -1) {
1880 			RList *all_vars = vars_cache.bvars;
1881 			r_list_join (all_vars, vars_cache.svars);
1882 			r_list_join (all_vars, vars_cache.rvars);
1883 			printVarSummary (ds, all_vars);
1884 		} else {
1885 			char spaces[32];
1886 			RAnalVar *var;
1887 			RListIter *iter;
1888 			RList *all_vars = vars_cache.bvars;
1889 			r_list_join (all_vars, vars_cache.svars);
1890 			r_list_join (all_vars, vars_cache.rvars);
1891 			r_list_foreach (all_vars, iter, var) {
1892 				ds_begin_line (ds);
1893 				int idx;
1894 				RAnal *anal = ds->core->anal;
1895 				memset (spaces, ' ', sizeof(spaces));
1896 				idx = 12 - strlen (var->name);
1897 				if (idx < 0) {
1898 					idx = 0;
1899 				}
1900 				spaces[idx] = 0;
1901 				ds_pre_xrefs (ds, false);
1902 
1903 				if (ds->show_flgoff) {
1904 					ds_print_offset (ds);
1905 				}
1906 				r_cons_printf ("%s; ", COLOR_ARG (ds, color_func_var));
1907 				switch (var->kind) {
1908 				case R_ANAL_VAR_KIND_BPV: {
1909 					char sign = var->isarg || (-var->delta <= f->bp_off) ? '+' : '-';
1910 					bool is_var = !var->isarg;
1911 					ds_show_functions_argvar (ds, f, var,
1912 						anal->reg->name[R_REG_NAME_BP], is_var, sign);
1913 					}
1914 					break;
1915 				case R_ANAL_VAR_KIND_REG: {
1916 					RRegItem *i = r_reg_index_get (anal->reg, var->delta);
1917 					if (!i) {
1918 						eprintf ("Register not found");
1919 						break;
1920 					}
1921 					r_cons_printf ("%sarg %s%s%s%s %s@ %s", COLOR_ARG (ds, color_func_var),
1922 						COLOR_ARG (ds, color_func_var_type),
1923 						var->type, r_str_endswith (var->type, "*") ? "" : " ",
1924 						var->name, COLOR_ARG (ds, color_func_var_addr), i->name);
1925 					if (ds->show_varsum == -1) {
1926 						char *val = r_core_cmd_strf (ds->core, ".afvd %s", var->name);
1927 						if (val) {
1928 							r_str_replace_char (val, '\n', '\0');
1929 							r_cons_printf ("%s", val);
1930 							free (val);
1931 						}
1932 					}
1933 					}
1934 					break;
1935 				case R_ANAL_VAR_KIND_SPV: {
1936 					bool is_var = !var->isarg;
1937 					int saved_delta = var->delta;
1938 					var->delta = f->maxstack + var->delta;
1939 					char sign = var->isarg || (-var->delta <= f->maxstack) ? '+' : '-';
1940 					ds_show_functions_argvar (ds, f, var,
1941 						anal->reg->name[R_REG_NAME_SP],
1942 						is_var, sign);
1943 					var->delta = saved_delta;
1944 					}
1945 					break;
1946 				}
1947 				if (var->comment) {
1948 					r_cons_printf ("    %s; %s", COLOR (ds, color_comment), var->comment);
1949 				}
1950 				r_cons_print (COLOR_RESET (ds));
1951 				ds_newline (ds);
1952 			}
1953 		}
1954 	}
1955 	ds->show_varsum = o_varsum;
1956 	r_anal_fcn_vars_cache_fini (&vars_cache);
1957 	if (fcn_name_alloc) {
1958 		free (fcn_name);
1959 	}
1960 	{
1961 		RListIter *iter;
1962 		char *imp;
1963 		if (ds->fcn && ds->fcn->imports) {
1964 			r_list_foreach (ds->fcn->imports, iter, imp) {
1965 				ds_print_pre (ds, true);
1966 				ds_print_lines_left(ds);
1967 				r_cons_printf (".import %s", imp);
1968 				ds_newline (ds);
1969 			}
1970 		}
1971 		r_list_foreach (ds->core->anal->imports, iter, imp) {
1972 			ds_print_pre (ds, true);
1973 			ds_print_lines_left(ds);
1974 			r_cons_printf (".globalimport %s", imp);
1975 			ds_newline (ds);
1976 		}
1977 	}
1978 }
1979 
ds_setup_print_pre(RDisasmState * ds,bool tail,bool middle)1980 static void ds_setup_print_pre(RDisasmState *ds, bool tail, bool middle) {
1981 	ds_setup_pre (ds, tail, middle);
1982 	ds_print_pre (ds, true);
1983 }
1984 
ds_setup_pre(RDisasmState * ds,bool tail,bool middle)1985 static void ds_setup_pre(RDisasmState *ds, bool tail, bool middle) {
1986 	ds->cmtcount = 0;
1987 	if (!ds->show_functions || !ds->show_lines_fcn) {
1988 		ds->pre = DS_PRE_NONE;
1989 		return;
1990 	}
1991 	ds->pre = DS_PRE_EMPTY;
1992 	RAnalFunction *f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
1993 	if (f) {
1994 		if (f->addr == ds->at) {
1995 			if (ds->analop.size == r_anal_function_linear_size (f) && !middle) {
1996 				ds->pre = DS_PRE_FCN_TAIL;
1997 			} else {
1998 				ds->pre = DS_PRE_FCN_MIDDLE;
1999 			}
2000 		} else if (r_anal_function_max_addr (f) - ds->analop.size == ds->at && f->addr == r_anal_function_min_addr (f)) {
2001 			ds->pre = DS_PRE_FCN_TAIL;
2002 		} else if (r_anal_function_contains (f, ds->at)) {
2003 			ds->pre = DS_PRE_FCN_MIDDLE;
2004 		}
2005 		if (tail) {
2006 			if (ds->pre == DS_PRE_FCN_TAIL) {
2007 				ds->pre = DS_PRE_EMPTY;
2008 			}
2009 			if (ds->pre == DS_PRE_FCN_MIDDLE) {
2010 				ds->pre = DS_PRE_FCN_TAIL;
2011 			}
2012 		}
2013 	}
2014 }
2015 
ds_print_pre(RDisasmState * ds,bool fcnline)2016 static void ds_print_pre(RDisasmState *ds, bool fcnline) {
2017 	RCore *core = ds->core;
2018 	int pre = ds->pre;
2019 	const char *c = NULL;
2020 	if (!fcnline) {
2021 		pre = DS_PRE_EMPTY;
2022 	}
2023 	switch (pre) {
2024 	case DS_PRE_FCN_HEAD:
2025 		c = core->cons->vline[CORNER_TL];
2026 		break;
2027 	case DS_PRE_FCN_MIDDLE:
2028 		c = core->cons->vline[LINE_VERT];
2029 		break;
2030 	case DS_PRE_FCN_TAIL:
2031 		c = core->cons->vline[CORNER_BL];
2032 		break;
2033 	case DS_PRE_EMPTY:
2034 		r_cons_print ("  ");
2035 		return;
2036 	case DS_PRE_NONE:
2037 	default:
2038 		return;
2039 	}
2040 	char *kolor = strdup (ds->color_fline);
2041 	RAnalBlock *bb;
2042 	RList *list = r_anal_get_blocks_in (core->anal, ds->at);
2043 	RListIter *iter;
2044 	r_list_foreach (list, iter, bb) {
2045 		if (bb->color.r || bb->color.g || bb->color.b) {
2046 			kolor = r_cons_rgb_str (NULL, -1, &bb->color);
2047 			break;
2048 		}
2049 	}
2050 	r_cons_printf ("%s%s%s ", kolor, c, COLOR_RESET (ds));
2051 	r_list_free (list);
2052 	free (kolor);
2053 }
2054 
ds_show_comments_describe(RDisasmState * ds)2055 static void ds_show_comments_describe(RDisasmState *ds) {
2056 	/* respect asm.describe */
2057 	char *desc = NULL;
2058 	if (ds->asm_describe && !ds->has_description) {
2059 		char *op, *locase = strdup (r_asm_op_get_asm (&ds->asmop));
2060 		if (!locase) {
2061 			return;
2062 		}
2063 		op = strchr (locase, ' ');
2064 		if (op) {
2065 			*op = 0;
2066 		}
2067 		r_str_case (locase, 0);
2068 		desc = r_asm_describe (ds->core->rasm, locase);
2069 		free (locase);
2070 	}
2071 	if (desc && *desc) {
2072 		ds_begin_comment (ds);
2073 		ds_align_comment (ds);
2074 		if (ds->show_color) {
2075 			r_cons_strcat (ds->color_comment);
2076 		}
2077 		r_cons_strcat ("; ");
2078 		r_cons_strcat (desc);
2079 		ds_print_color_reset (ds);
2080 		ds_newline (ds);
2081 		free (desc);
2082 	}
2083 }
2084 
2085 //XXX review this with asm.cmt.right
ds_show_comments_right(RDisasmState * ds)2086 static void ds_show_comments_right(RDisasmState *ds) {
2087 	int linelen;
2088 	RCore *core = ds->core;
2089 	/* show comment at right? */
2090 	int scr = ds->show_comment_right;
2091 	if (!ds->show_comments && !ds->show_usercomments) {
2092 		return;
2093 	}
2094 	RFlagItem *item = r_flag_get_i (core->flags, ds->at);
2095 	const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ds->at);
2096 	const char *vartype = r_meta_get_string (core->anal, R_META_TYPE_VARTYPE, ds->at);
2097 	if (!comment) {
2098 		if (vartype) {
2099 			ds->comment = r_str_newf ("%s; %s", COLOR_ARG (ds, color_func_var_type), vartype);
2100 		} else if (item && item->comment && *item->comment) {
2101 			ds->ocomment = item->comment;
2102 			ds->comment = strdup (item->comment);
2103 		}
2104 	} else if (vartype) {
2105 		ds->comment = r_str_newf ("%s; %s %s%s; %s", COLOR_ARG (ds, color_func_var_type), vartype, Color_RESET, COLOR (ds, color_usrcmt), comment);
2106 	} else {
2107 		ds->comment = r_str_newf ("%s; %s", COLOR_ARG (ds, color_usrcmt), comment);
2108 	}
2109 	if (!ds->comment || !*ds->comment) {
2110 		return;
2111 	}
2112 	linelen = strlen (ds->comment) + 5;
2113 	if (ds->show_comment_right_default) {
2114 		if (ds->ocols + linelen < core->cons->columns) {
2115 			if (!strchr (ds->comment, '\n')) { // more than one line?
2116 				ds->show_comment_right = true;
2117 			}
2118 		}
2119 	}
2120 	if (!ds->show_comment_right) {
2121 		ds_begin_line (ds);
2122 		int mycols = ds->lcols;
2123 		if ((mycols + linelen + 10) > core->cons->columns) {
2124 			mycols = 0;
2125 		}
2126 		mycols /= 2;
2127 		if (ds->show_color) {
2128 			r_cons_strcat (ds->pal_comment);
2129 		}
2130 		/* print multiline comment */
2131 		if (ds->cmtfold) {
2132 			char *p = strdup (ds->comment);
2133 			char *q = strchr (p, '\n');
2134 			if (q) {
2135 				*q = 0;
2136 				r_cons_strcat (p);
2137 				r_cons_strcat (" ; [z] unfold");
2138 			}
2139 			free (p);
2140 		} else {
2141 			ds_pre_xrefs (ds, false);
2142 			if (ds->show_color) {
2143 				r_cons_strcat (ds->color_usrcmt);
2144 			}
2145 			ds_comment (ds, false, "%s", ds->comment);
2146 		}
2147 		if (ds->show_color) {
2148 			ds_print_color_reset (ds);
2149 		}
2150 		R_FREE (ds->comment);
2151 		ds_newline (ds);
2152 		/* flag one */
2153 		if (item && item->comment && ds->ocomment != item->comment) {
2154 			ds_begin_line (ds);
2155 			if (ds->show_color) {
2156 				r_cons_strcat (ds->pal_comment);
2157 			}
2158 			ds_newline (ds);
2159 			ds_begin_line (ds);
2160 			r_cons_strcat ("  ;  ");
2161 			r_cons_strcat_justify (item->comment, mycols, ';');
2162 			ds_newline (ds);
2163 			if (ds->show_color) {
2164 				ds_print_color_reset (ds);
2165 			}
2166 		}
2167 	}
2168 	ds->show_comment_right = scr;
2169 }
2170 
flagCmp(const void * a,const void * b)2171 static int flagCmp(const void *a, const void *b) {
2172 	const RFlagItem *fa = a;
2173 	const RFlagItem *fb = b;
2174 	if (fa->realname && fb->realname) {
2175 		return strcmp (fa->realname, fb->realname);
2176 	}
2177 	return strcmp (fa->name, fb->name);
2178 }
2179 
__preline_flag(RDisasmState * ds,RFlagItem * flag)2180 static void __preline_flag(RDisasmState *ds, RFlagItem *flag) {
2181 	ds_newline (ds);
2182 	ds_begin_line (ds);
2183 	ds_pre_line (ds);
2184 	if (ds->show_color) {
2185 		bool hasColor = false;
2186 		if (flag->color) {
2187 			char *color = r_cons_pal_parse (flag->color, NULL);
2188 			if (color) {
2189 				r_cons_strcat (color);
2190 				free (color);
2191 				ds->lastflag = flag;
2192 				hasColor = true;
2193 			}
2194 		}
2195 		if (!hasColor) {
2196 			r_cons_strcat (ds->color_flag);
2197 		}
2198 	}
2199 	if (!ds->show_offset) {
2200 		r_cons_printf ("     ");
2201 	}
2202 }
2203 
2204 #define printPre (outline || !*comma)
ds_show_flags(RDisasmState * ds)2205 static void ds_show_flags(RDisasmState *ds) {
2206 	//const char *beginch;
2207 	RFlagItem *flag;
2208 	RListIter *iter;
2209 	RAnalFunction *f = NULL;
2210 	if (!ds->show_flags) {
2211 		return;
2212 	}
2213 	RCore *core = ds->core;
2214 	char addr[64];
2215 	ut64 switch_addr = UT64_MAX;
2216 	int case_start = -1, case_prev = 0, case_current = 0;
2217 	f = r_anal_get_function_at (ds->core->anal, ds->at);
2218 	const RList *flaglist = r_flag_get_list (core->flags, ds->at);
2219 	RList *uniqlist = flaglist? r_list_uniq (flaglist, flagCmp): NULL;
2220 	int count = 0;
2221 	bool outline = !ds->flags_inline;
2222 	const char *comma = "";
2223 	bool keep_lib = r_config_get_i (core->config, "bin.demangle.libs");
2224 	bool docolon = true;
2225 	int nth = 0;
2226 	r_list_foreach (uniqlist, iter, flag) {
2227 		if (f && f->addr == flag->offset && !strcmp (flag->name, f->name)) {
2228 			// do not show flags that have the same name as the function
2229 			continue;
2230 		}
2231 		bool no_fcn_lines = (f && f->addr == flag->offset);
2232 		if (ds->maxflags && count >= ds->maxflags) {
2233 			if (printPre) {
2234 				ds_pre_xrefs (ds, no_fcn_lines);
2235 			}
2236 			r_cons_printf ("...");
2237 			break;
2238 		}
2239 		count++;
2240 		if (!strncmp (flag->name, "case.", 5)) {
2241 			sscanf (flag->name + 5, "%63[^.].%d", addr, &case_current);
2242 			ut64 saddr = r_num_math (core->num, addr);
2243 			if (case_start == -1) {
2244 				switch_addr = saddr;
2245 				case_prev = case_current;
2246 				case_start = case_current;
2247 				if (iter != uniqlist->tail) {
2248 					continue;
2249 				}
2250 			}
2251 			if (case_current == case_prev + 1 && switch_addr == saddr) {
2252 				case_prev = case_current;
2253 				if (iter != uniqlist->tail) {
2254 					continue;
2255 				}
2256 			}
2257 		}
2258 		if (printPre) {
2259 			ds_begin_line (ds);
2260 		}
2261 
2262 		bool fake_flag_marks = (!ds->show_offset && ds->show_marks);
2263 		if (printPre) {
2264 			if (ds->show_flgoff) {
2265 				ds_pre_line (ds);
2266 				ds_print_offset (ds);
2267 				if (!fake_flag_marks) {
2268 					r_cons_printf (" ");
2269 				}
2270 			} else {
2271 				ds_pre_xrefs (ds, no_fcn_lines);
2272 			}
2273 		}
2274 
2275 		if (ds->show_color) {
2276 			bool hasColor = false;
2277 			if (flag->color) {
2278 				char *color = r_cons_pal_parse (flag->color, NULL);
2279 				if (color) {
2280 					r_cons_strcat (color);
2281 					free (color);
2282 					ds->lastflag = flag;
2283 					hasColor = true;
2284 				}
2285 			}
2286 			if (!hasColor) {
2287 				r_cons_strcat (ds->color_flag);
2288 			}
2289 		}
2290 
2291 		if (ds->asm_demangle && flag->realname) {
2292 			if (!strncmp (flag->name, "switch.", 7)) {
2293 				r_cons_printf (FLAG_PREFIX"switch");
2294 			} else if (!strncmp (flag->name, "case.", 5)) {
2295 				if (nth > 0) {
2296 					__preline_flag (ds, flag);
2297 				}
2298 				if (!strncmp (flag->name + 5, "default", 7)) {
2299 					r_cons_printf (FLAG_PREFIX "default:"); // %s:", flag->name);
2300 					r_str_ncpy (addr, flag->name + 5 + strlen ("default."), sizeof (addr));
2301 					nth = 0;
2302 				} else if (case_prev != case_start) {
2303 					r_cons_printf (FLAG_PREFIX "case %d...%d:", case_start, case_prev);
2304 					if (iter != uniqlist->head && iter != uniqlist->tail) {
2305 						iter = iter->p;
2306 					}
2307 					case_start = case_current;
2308 				} else {
2309 					r_cons_printf (FLAG_PREFIX "case %d:", case_prev);
2310 					case_start = -1;
2311 				}
2312 				case_prev = case_current;
2313 				ds_align_comment (ds);
2314 				r_cons_printf ("%s; from %s", ds->show_color ? ds->pal_comment : "", addr);
2315 				outline = false;
2316 				docolon = false;
2317 			} else {
2318 				const char *lang = r_config_get (core->config, "bin.lang");
2319 				char *name = r_bin_demangle (core->bin->cur, lang, flag->realname, flag->offset, keep_lib);
2320 				if (!name) {
2321 					const char *n = flag->realname? flag->realname: flag->name;
2322 					if (n) {
2323 						name = strdup (n);
2324 					}
2325 				}
2326 				if (name) {
2327 					r_str_ansi_filter (name, NULL, NULL, -1);
2328 					if (!ds->flags_inline || nth == 0) {
2329 						r_cons_printf (FLAG_PREFIX);
2330 					}
2331 					if (outline) {
2332 						r_cons_printf ("%s:", name);
2333 					} else {
2334 						r_cons_printf ("%s%s", comma, flag->name);
2335 					}
2336 					R_FREE (name);
2337 				}
2338 			}
2339 		} else {
2340 			if (outline) {
2341 				r_cons_printf ("%s", flag->name);
2342 			} else {
2343 				r_cons_printf ("%s%s", comma, flag->name);
2344 			}
2345 		}
2346 		if (ds->show_color) {
2347 			r_cons_strcat (Color_RESET);
2348 		}
2349 		if (outline) {
2350 			ds_newline (ds);
2351 		} else {
2352 			comma = ", ";
2353 		}
2354 		nth++;
2355 	}
2356 	if (!outline && *comma) {
2357 		if (nth > 0 && docolon) {
2358 			r_cons_printf (":");
2359 		}
2360 		ds_newline (ds);
2361 	}
2362 	r_list_free (uniqlist);
2363 }
2364 
ds_update_ref_lines(RDisasmState * ds)2365 static void ds_update_ref_lines(RDisasmState *ds) {
2366 	if (ds->show_lines_bb) {
2367 		free (ds->line);
2368 		free (ds->line_col);
2369 		RAnalRefStr *line = r_anal_reflines_str (ds->core, ds->at, ds->linesopts);
2370 		ds->line = line->str;
2371 		ds->line_col = line->cols;
2372 		free (ds->refline);
2373 		ds->refline = ds->line? strdup (ds->line): NULL;
2374 		free (ds->refline2);
2375 		free (ds->prev_line_col);
2376 		free (line);
2377 		line = r_anal_reflines_str (ds->core, ds->at,
2378 			ds->linesopts | R_ANAL_REFLINE_TYPE_MIDDLE_BEFORE);
2379 		ds->refline2 = line->str;
2380 		ds->prev_line_col = line->cols;
2381 		if (ds->line) {
2382 			if (strchr (ds->line, '<')) {
2383 				ds->indent_level++;
2384 			}
2385 			if (strchr (ds->line, '>')) {
2386 				ds->indent_level--;
2387 			}
2388 		} else {
2389 			ds->indent_level = 0;
2390 		}
2391 		free (line);
2392 	} else {
2393 		R_FREE (ds->line);
2394 		R_FREE (ds->line_col);
2395 		R_FREE (ds->prev_line_col);
2396 		free (ds->refline);
2397 		free (ds->refline2);
2398 		free (ds->prev_line_col);
2399 		ds->refline = strdup ("");
2400 		ds->refline2 = strdup ("");
2401 		ds->line = NULL;
2402 		ds->line_col = NULL;
2403 		ds->prev_line_col = NULL;
2404 	}
2405 }
2406 
ds_disassemble(RDisasmState * ds,ut8 * buf,int len)2407 static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len) {
2408 	RCore *core = ds->core;
2409 	int ret;
2410 
2411 	// find the meta item at this offset if any
2412 	RPVector *metas = r_meta_get_all_at (ds->core->anal, ds->at); // TODO: do in range
2413 	RAnalMetaItem *meta = NULL;
2414 	ut64 meta_size = UT64_MAX;
2415 	if (metas) {
2416 		void **it;
2417 		r_pvector_foreach (metas, it) {
2418 			RIntervalNode *node = *it;
2419 			RAnalMetaItem *mi = node->data;
2420 			switch (mi->type) {
2421 			case R_META_TYPE_DATA:
2422 			case R_META_TYPE_STRING:
2423 			case R_META_TYPE_FORMAT:
2424 			case R_META_TYPE_MAGIC:
2425 			case R_META_TYPE_HIDE:
2426 			case R_META_TYPE_RUN:
2427 				meta = mi;
2428 				meta_size = r_meta_item_size (node->start, node->end);
2429 				break;
2430 			default:
2431 				break;
2432 			}
2433 		}
2434 		r_pvector_free (metas);
2435 	}
2436 	if (ds->hint && ds->hint->bits) {
2437 		if (!ds->core->anal->opt.ignbithints) {
2438 			r_config_set_i (core->config, "asm.bits", ds->hint->bits);
2439 		}
2440 	}
2441 	if (ds->hint && ds->hint->size) {
2442 		ds->oplen = ds->hint->size;
2443 	}
2444 	if (ds->hint && ds->hint->opcode) {
2445 		free (ds->opstr);
2446 		ds->opstr = strdup (ds->hint->opcode);
2447 	}
2448 	r_asm_op_fini (&ds->asmop);
2449 	ret = r_asm_disassemble (core->rasm, &ds->asmop, buf, len);
2450 	if (ds->asmop.size < 1) {
2451 		ds->asmop.size = 1;
2452 	}
2453 	// handle meta here //
2454 	if (!ds->asm_meta) {
2455 		int i = 0;
2456 		if (meta && meta_size > 0 && meta->type != R_META_TYPE_HIDE) {
2457 			// XXX this is just noise. should be rewritten
2458 			switch (meta->type) {
2459 			case R_META_TYPE_DATA:
2460 				if (meta->str) {
2461 					r_cons_printf (".data: %s\n", meta->str);
2462 				}
2463 				i += meta_size;
2464 				break;
2465 			case R_META_TYPE_STRING:
2466 				i += meta_size;
2467 				break;
2468 			case R_META_TYPE_FORMAT:
2469 				r_cons_printf (".format : %s\n", meta->str);
2470 				i += meta_size;
2471 				break;
2472 			case R_META_TYPE_MAGIC:
2473 				r_cons_printf (".magic : %s\n", meta->str);
2474 				i += meta_size;
2475 				break;
2476 			case R_META_TYPE_RUN:
2477 				r_core_cmd0 (core, meta->str);
2478 				break;
2479 			default:
2480 				break;
2481 			}
2482 			int sz = R_MIN (16, meta_size);
2483 			ds->asmop.size = sz;
2484 			r_asm_op_set_hexbuf (&ds->asmop, buf, sz);
2485 			const char *tail = (meta_size > 16)? "...": "";
2486 			switch (meta->type) {
2487 			case R_META_TYPE_STRING:
2488 				r_asm_op_set_asm (&ds->asmop, sdb_fmt (".string \"%s%s\"", meta->str, tail));
2489 				break;
2490 			default: {
2491 				char *op_hex = r_asm_op_get_hex (&ds->asmop);
2492 				r_asm_op_set_asm (&ds->asmop, sdb_fmt (".hex %s%s", op_hex, tail));
2493 				free (op_hex);
2494 				break;
2495 			}
2496 			}
2497 			ds->oplen = meta_size;
2498 			return i;
2499 		}
2500 	}
2501 
2502 	if (ds->show_nodup) {
2503 		const char *opname = (ret < 1)? "invalid": r_asm_op_get_asm (&ds->asmop);
2504 		if (ds->prev_ins && !strcmp (ds->prev_ins, opname)) {
2505 			if (!ds->prev_ins_eq) {
2506 				ds->prev_ins_eq = true;
2507 				r_cons_printf ("...");
2508 			}
2509 			ds->prev_ins_count++;
2510 			return -31337;
2511 		}
2512 		if (ds->prev_ins_eq) {
2513 			r_cons_printf ("dup (%d)\n", ds->prev_ins_count);
2514 		}
2515 		ds->prev_ins_count = 0;
2516 		ds->prev_ins_eq = false;
2517 		if (ds->prev_ins) {
2518 			R_FREE (ds->prev_ins);
2519 		}
2520 		ds->prev_ins = strdup (r_asm_op_get_asm (&ds->asmop));
2521 	}
2522 	ds->oplen = ds->asmop.size;
2523 
2524 	if (ret < 1) {
2525 		ret = -1;
2526 #if HASRETRY
2527 		if (!ds->cbytes && ds->tries > 0) {
2528 			ds->addr = core->rasm->pc;
2529 			ds->tries--;
2530 			ds->idx = 0;
2531 			ds->retry = true;
2532 			return ret;
2533 		}
2534 #endif
2535 		ds->lastfail = 1;
2536 		ds->asmop.size = (ds->hint && ds->hint->size) ? ds->hint->size : 1;
2537 		ds->oplen = ds->asmop.size;
2538 	} else {
2539 		ds->lastfail = 0;
2540 		ds->asmop.size = (ds->hint && ds->hint->size)
2541 				? ds->hint->size
2542 				: r_asm_op_get_size (&ds->asmop);
2543 		ds->oplen = ds->asmop.size;
2544 	}
2545 	if (ds->pseudo) {
2546 		r_parse_parse (core->parser, ds->opstr
2547 				? ds->opstr
2548 				: r_asm_op_get_asm (&ds->asmop),
2549 				ds->str);
2550 		free (ds->opstr);
2551 		ds->opstr = strdup (ds->str);
2552 	}
2553 	if (ds->acase) {
2554 		r_str_case (r_asm_op_get_asm (&ds->asmop), 1);
2555 	} else if (ds->capitalize) {
2556 		char *ba = r_asm_op_get_asm (&ds->asmop);
2557 		*ba = toupper ((ut8)*ba);
2558 	}
2559 	if (meta && meta_size != UT64_MAX) {
2560 		ds->oplen = meta_size;
2561 	}
2562 	return ret;
2563 }
2564 
ds_control_flow_comments(RDisasmState * ds)2565 static void ds_control_flow_comments(RDisasmState *ds) {
2566 	if (ds->show_comments && ds->show_cmtflgrefs) {
2567 		RFlagItem *item;
2568 		if (ds->asm_anal) {
2569 			switch (ds->analop.type) {
2570 			case R_ANAL_OP_TYPE_CALL:
2571 				r_core_cmdf (ds->core, "af @ 0x%"PFMT64x, ds->analop.jump);
2572 				break;
2573 			}
2574 		}
2575 		switch (ds->analop.type) {
2576 		case R_ANAL_OP_TYPE_JMP:
2577 		case R_ANAL_OP_TYPE_CJMP:
2578 		case R_ANAL_OP_TYPE_CALL:
2579 			item = r_flag_get_i (ds->core->flags, ds->analop.jump);
2580 			if (item && item->comment) {
2581 				if (ds->show_color) {
2582 					r_cons_strcat (ds->pal_comment);
2583 				}
2584 				ds_align_comment (ds);
2585 				r_cons_printf ("  ; ref to %s: %s\n", item->name, item->comment);
2586 				ds_print_color_reset (ds);
2587 			}
2588 			break;
2589 		}
2590 	}
2591 }
2592 
ds_print_lines_right(RDisasmState * ds)2593 static void ds_print_lines_right(RDisasmState *ds){
2594 	if (ds->linesright && ds->show_lines_bb && ds->line) {
2595 		ds_print_ref_lines (ds->line, ds->line_col, ds);
2596 	}
2597 }
2598 
printCol(RDisasmState * ds,char * sect,int cols,const char * color)2599 static void printCol(RDisasmState *ds, char *sect, int cols, const char *color) {
2600 	int pre;
2601 	if (cols < 8) {
2602 		cols = 8;
2603 	}
2604 	int outsz = cols + 32;
2605 	char *out = malloc (outsz);
2606 	if (!out) {
2607 		return;
2608 	}
2609 	memset (out, ' ', outsz);
2610 	out[outsz - 1] = 0;
2611 	int sect_len = strlen (sect);
2612 
2613 	if (sect_len > cols) {
2614 		sect[cols - 2] = '.';
2615 		sect[cols - 1] = '.';
2616 		sect[cols] = 0;
2617 	}
2618 	if (ds->show_color) {
2619 		pre = strlen (color) + 1;
2620 		snprintf (out, outsz-pre, "%s %s", color, sect);
2621 		strcat (out, Color_RESET);
2622 		out[outsz - 1] = 0;
2623 	} else {
2624 		r_str_ncpy (out + 1, sect, outsz - 2);
2625 	}
2626 	strcat (out, " ");
2627 	r_cons_strcat (out);
2628 	free (out);
2629 }
2630 
ds_print_lines_left(RDisasmState * ds)2631 static void ds_print_lines_left(RDisasmState *ds) {
2632 	if (ds->linesright) {
2633 		return;
2634 	}
2635 	RCore *core = ds->core;
2636 	if (ds->show_section) {
2637 		char *str = NULL;
2638 		if (ds->show_section_perm) {
2639 			// iosections must die, this should be rbin_section_get
2640 			RIOMap *map = r_io_map_get (core->io, ds->at);
2641 			str = strdup (map? r_str_rwx_i (map->perm): "---");
2642 		}
2643 		if (ds->show_section_name) {
2644 			str = r_str_appendf (str, " %s", r_core_get_section_name (core, ds->at));
2645 		}
2646 		char *sect = str? str: strdup ("");
2647 		printCol (ds, sect, ds->show_section_col, ds->color_reg);
2648 		free (sect);
2649 	}
2650 	if (ds->show_symbols) {
2651 		static RFlagItem sfi = R_EMPTY;
2652 		const char *name = "";
2653 		int delta = 0;
2654 		if (ds->fcn) {
2655 			sfi.offset = ds->fcn->addr;
2656 			sfi.name = ds->fcn->name;
2657 			ds->lastflag = &sfi;
2658 		} else {
2659 			RFlagItem *fi = r_flag_get_at (core->flags, ds->at, !ds->lastflag);
2660 			if (fi) { // && (!ds->lastflag || fi->offset != ds->at))
2661 				sfi.offset = fi->offset;
2662 				sfi.name = fi->name;
2663 				ds->lastflag = &sfi;
2664 			}
2665 		}
2666 		if (ds->lastflag && ds->lastflag->name) {
2667 			name = ds->lastflag->name;
2668 			delta = ds->at - ds->lastflag->offset;
2669 		}
2670 		{
2671 			char *str = r_str_newf ("%s + %-4d", name, delta);
2672 			printCol (ds, str, ds->show_symbols_col, ds->color_num);
2673 			free (str);
2674 		}
2675 	}
2676 	if (ds->line) {
2677 		ds_print_ref_lines (ds->line, ds->line_col, ds);
2678 	}
2679 }
2680 
ds_print_family(RDisasmState * ds)2681 static void ds_print_family(RDisasmState *ds) {
2682 	if (ds->show_family) {
2683 		const char *familystr = r_anal_op_family_to_string (ds->analop.family);
2684 		r_cons_printf ("%5s ", r_str_get (familystr));
2685 	}
2686 }
2687 
ds_print_cycles(RDisasmState * ds)2688 static void ds_print_cycles(RDisasmState *ds) {
2689 	if (ds->show_cycles) {
2690 		if (!ds->analop.failcycles) {
2691 			r_cons_printf ("%3d     ", ds->analop.cycles);
2692 		} else {
2693 			r_cons_printf ("%3d %3d ", ds->analop.cycles, ds->analop.failcycles);
2694 		}
2695 	}
2696 	if (ds->cyclespace) {
2697 		char spaces [32];
2698 		int times = R_MIN (ds->analop.cycles/4, 30); // limit to 30
2699 		memset (spaces, ' ', sizeof (spaces));
2700 		spaces[times] = 0;
2701 		r_cons_strcat (spaces);
2702 	}
2703 }
2704 
2705 #include "disasm_stackptr.inc"
2706 
ds_print_offset(RDisasmState * ds)2707 static void ds_print_offset(RDisasmState *ds) {
2708 	RCore *core = ds->core;
2709 	ut64 at = ds->vat;
2710 
2711 	bool hasCustomColor = false;
2712 	// probably tooslow
2713 	RFlagItem *f = r_flag_get_at (core->flags, at, 1);
2714 	if (ds->show_color && f) { // ds->lastflag) {
2715 		const char *color = f->color;
2716 		if (ds->at >= f->offset && ds->at < f->offset + f->size) {
2717 		//	if (r_itv_inrange (f->itv, ds->at))
2718 			if (color && *color) {
2719 				char *k = r_cons_pal_parse (f->color, NULL);
2720 				if (k) {
2721 					r_cons_printf ("%s", k);
2722 					hasCustomColor = true;
2723 					free (k);
2724 				}
2725 			}
2726 		}
2727 	}
2728 	r_print_set_screenbounds (core->print, at);
2729 	if (ds->show_offset) {
2730 		static RFlagItem sfi = R_EMPTY;
2731 		const char *label = NULL;
2732 		RFlagItem *fi;
2733 		int delta = -1;
2734 		bool show_trace = false;
2735 		unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
2736 
2737 		if (ds->show_reloff) {
2738 			RAnalFunction *f = r_anal_get_function_at (core->anal, at);
2739 			if (!f) {
2740 				f = fcnIn (ds, at, R_ANAL_FCN_TYPE_NULL); // r_anal_get_fcn_in (core->anal, at, R_ANAL_FCN_TYPE_NULL);
2741 			}
2742 			if (f) {
2743 				delta = at - f->addr;
2744 				sfi.name = f->name;
2745 				sfi.offset = f->addr;
2746 				ds->lastflag = &sfi;
2747 				label = f->name;
2748 			} else {
2749 				if (ds->show_reloff_flags) {
2750 					/* XXX: this is wrong if starting to disasm after a flag */
2751 					fi = r_flag_get_i (core->flags, at);
2752 					if (fi) {
2753 						ds->lastflag = fi;
2754 					}
2755 					if (ds->lastflag) {
2756 						if (ds->lastflag->offset == at) {
2757 							delta = 0;
2758 						} else {
2759 							delta = at - ds->lastflag->offset;
2760 						}
2761 					} else {
2762 						delta = at - core->offset;
2763 					}
2764 					if (ds->lastflag) {
2765 						label = ds->lastflag->name;
2766 					}
2767 				}
2768 			}
2769 			if (!ds->lastflag) {
2770 				delta = 0;
2771 			}
2772 		}
2773 		if (ds->show_trace) {
2774 			RDebugTracepoint *tp = r_debug_trace_get (ds->core->dbg, ds->at);
2775 			show_trace = (tp? !!tp->count: false);
2776 		}
2777 		if (ds->hint && ds->hint->high) {
2778 			show_trace = true;
2779 		}
2780 		if (hasCustomColor) {
2781 			int of = core->print->flags;
2782 			core->print->flags = 0;
2783 			r_print_offset_sg (core->print, at, (at == ds->dest) || show_trace,
2784 					ds->show_offseg, seggrn, ds->show_offdec, delta, label);
2785 			core->print->flags = of;
2786 			r_cons_strcat (Color_RESET);
2787 		} else {
2788 			r_print_offset_sg (core->print, at, (at == ds->dest) || show_trace,
2789 					ds->show_offseg, seggrn, ds->show_offdec, delta, label);
2790 		}
2791 	}
2792 	if (ds->atabsoff > 0 && ds->show_offset) {
2793 		if (ds->_tabsoff != ds->atabsoff) {
2794 			// TODO optimize to avoid down resizing
2795 			char *b = malloc (ds->atabsoff + 1);
2796 			if (b) {
2797 				memset (b, ' ', ds->atabsoff);
2798 				b[ds->atabsoff] = 0;
2799 				free (ds->_tabsbuf);
2800 				ds->_tabsbuf = b;
2801 				ds->_tabsoff = ds->atabsoff;
2802 			}
2803 		}
2804 		r_cons_strcat (ds->_tabsbuf);
2805 	}
2806 }
2807 
ds_print_op_size(RDisasmState * ds)2808 static void ds_print_op_size(RDisasmState *ds) {
2809 	if (ds->show_size) {
2810 		int size = ds->oplen;
2811 		r_cons_printf ("%d ", size); //ds->analop.size);
2812 	}
2813 }
2814 
ds_print_trace(RDisasmState * ds)2815 static void ds_print_trace(RDisasmState *ds) {
2816 	RDebugTracepoint *tp = NULL;
2817 	if (ds->show_trace) {
2818 		tp = r_debug_trace_get (ds->core->dbg, ds->at);
2819 		r_cons_printf ("%02x:%04x ", tp?tp->times:0, tp?tp->count:0);
2820 	}
2821 	if (ds->tracespace) {
2822 		char spaces [32];
2823 		int times;
2824 		if (!tp) {
2825 			tp = r_debug_trace_get (ds->core->dbg, ds->at);
2826 		}
2827 		if (tp) {
2828 			times = R_MIN (tp->times, 30); // limit to 30
2829 			memset (spaces, ' ', sizeof (spaces));
2830 			spaces[times] = 0;
2831 			r_cons_strcat (spaces);
2832 		}
2833 	}
2834 }
2835 
ds_adistrick_comments(RDisasmState * ds)2836 static void ds_adistrick_comments(RDisasmState *ds) {
2837 	if (ds->adistrick) {
2838 		ds->middle = r_anal_reflines_middle (ds->core->anal,
2839 			ds->core->anal->reflines, ds->at, ds->analop.size);
2840 	}
2841 }
2842 
2843 // TODO move into RAnal.meta
ds_print_data_type(RDisasmState * ds,const ut8 * buf,int ib,int size)2844 static bool ds_print_data_type(RDisasmState *ds, const ut8 *buf, int ib, int size) {
2845 	RCore *core = ds->core;
2846 	const char *type = NULL;
2847 	char msg[64];
2848 	const int isSigned = (ib == 1 || ib == 8 || ib == 10)? 1: 0;
2849 	switch (size) {
2850 	case 1: type = isSigned? ".char": ".byte"; break;
2851 	case 2: type = isSigned? ".int16": ".word"; break;
2852 	case 3: type = "htons"; break;
2853 	case 4: type = isSigned? ".int32": ".dword"; break;
2854 	case 8: type = isSigned? ".int64": ".qword"; break;
2855 	default: return false;
2856 	}
2857 	// adjust alignment
2858 	ut64 n = r_read_ble (buf, core->print->big_endian, size * 8);
2859 	if (r_config_get_i (core->config, "asm.marks")) {
2860 		r_cons_printf ("  ");
2861 		int q = core->print->cur_enabled &&
2862 			ds->cursor >= ds->index &&
2863 			ds->cursor < (ds->index + size);
2864 		if (q) {
2865 			if (ds->cursor > ds->index) {
2866 				int diff = ds->cursor - ds->index;
2867 				r_cons_printf ("%d  ", diff);
2868 			} else if (ds->cursor == ds->index) {
2869 				r_cons_printf ("*  ");
2870 			} else {
2871 				r_cons_printf ("   ");
2872 			}
2873 		} else {
2874 			r_cons_printf ("   ");
2875 		}
2876 	}
2877 
2878 	r_cons_strcat (ds->color_mov);
2879 	switch (ib) {
2880 	case 1:
2881 		r_str_bits (msg, buf, size * 8, NULL);
2882 		r_cons_printf ("%s %sb", type, msg);
2883 		break;
2884 	case 3:
2885 		r_cons_printf ("%s %d", type, ntohs (n & 0xFFFF));
2886 		break;
2887 	case 8:
2888 		r_cons_printf ("%s %" PFMT64o "o", type, n);
2889 		break;
2890 	case 10:
2891 		r_cons_printf ("%s %" PFMT64d, type, n);
2892 		break;
2893 	default:
2894 		switch (size) {
2895 		case 1:
2896 			r_cons_printf ("%s 0x%02" PFMT64x, type, n);
2897 			break;
2898 		case 2:
2899 			r_cons_printf ("%s 0x%04" PFMT64x, type, n);
2900 			break;
2901 		case 4:
2902 			r_cons_printf ("%s 0x%08" PFMT64x, type, n);
2903 			break;
2904 		case 8:
2905 			r_cons_printf ("%s 0x%016" PFMT64x, type, n);
2906 			break;
2907 		default:
2908 			return false;
2909 		}
2910 	}
2911 
2912 	if (size == 4 || size == 8) {
2913 		if (r_str_startswith (r_config_get (core->config, "asm.arch"), "arm")) {
2914 			ut64 bits = r_config_get_i (core->config, "asm.bits");
2915 			//adjust address for arm/thumb address
2916 			if (bits < 64) {
2917 				if (n & 1) {
2918 					n--;
2919 				}
2920 			}
2921 		}
2922 		if (n >= ds->min_ref_addr) {
2923 			const RList *flags = r_flag_get_list (core->flags, n);
2924 			RListIter *iter;
2925 			RFlagItem *fi;
2926 			r_list_foreach (flags, iter, fi) {
2927 				r_cons_printf (" ; %s", fi->name);
2928 			}
2929 		}
2930 	}
2931 	return true;
2932 }
2933 
ds_print_meta_infos(RDisasmState * ds,ut8 * buf,int len,int idx,int * mi_type)2934 static bool ds_print_meta_infos(RDisasmState *ds, ut8* buf, int len, int idx, int *mi_type) {
2935 	bool ret = false;
2936 	RAnalMetaItem *fmi;
2937 	RCore *core = ds->core;
2938 	if (!ds->asm_meta) {
2939 		return false;
2940 	}
2941 	RPVector *metas = r_meta_get_all_in (core->anal, ds->at, R_META_TYPE_ANY);
2942 	if (!metas) {
2943 		return false;
2944 	}
2945 	bool once = true;
2946 	fmi = NULL;
2947 	void **it;
2948 	r_pvector_foreach (metas, it) {
2949 		RIntervalNode *node = *it;
2950 		RAnalMetaItem *mi = node->data;
2951 		switch (mi->type) {
2952 		case R_META_TYPE_DATA:
2953 			if (once) {
2954 				if (ds->asm_hint_pos == 0) {
2955 					if (ds->asm_hint_lea) {
2956 						ds_print_shortcut (ds, node->start, 0);
2957 					} else {
2958 						r_cons_strcat ("   ");
2959 					}
2960 				}
2961 				once = false;
2962 			}
2963 			break;
2964 		case R_META_TYPE_STRING:
2965 			fmi = mi;
2966 			break;
2967 		default:
2968 			break;
2969 		}
2970 	}
2971 	r_pvector_foreach (metas, it) {
2972 		RIntervalNode *node = *it;
2973 		RAnalMetaItem *mi = node->data;
2974 		ut64 mi_size = r_meta_node_size (node);
2975 		char *out = NULL;
2976 		int hexlen;
2977 		int delta;
2978 		if (fmi && mi != fmi) {
2979 			continue;
2980 		}
2981 		if (mi_type) {
2982 			*mi_type = mi->type;
2983 		}
2984 		switch (mi->type) {
2985 		case R_META_TYPE_STRING:
2986 		if (mi->str) {
2987 			bool esc_bslash = core->print->esc_bslash;
2988 
2989 			switch (mi->subtype) {
2990 			case R_STRING_ENC_UTF8:
2991 				out = r_str_escape_utf8 (mi->str, false, esc_bslash);
2992 				break;
2993 			case 0:  /* temporary legacy workaround */
2994 				esc_bslash = false;
2995 				/* fallthrough */
2996 			default:
2997 				out = r_str_escape_latin1 (mi->str, false, esc_bslash, false);
2998 			}
2999 			if (!out) {
3000 				break;
3001 			}
3002 			r_cons_printf ("    .string %s\"%s\"%s ; len=%"PFMT64d,
3003 					COLOR (ds, color_btext), out, COLOR_RESET (ds),
3004 					mi_size);
3005 			free (out);
3006 			delta = ds->at - node->start;
3007 			ds->oplen = mi_size - delta;
3008 			ds->asmop.size = (int)mi_size;
3009 			//i += mi->size-1; // wtf?
3010 			R_FREE (ds->line);
3011 			R_FREE (ds->line_col);
3012 			R_FREE (ds->refline);
3013 			R_FREE (ds->refline2);
3014 			R_FREE (ds->prev_line_col);
3015 			ret = true;
3016 			break;
3017 		}
3018 		case R_META_TYPE_HIDE:
3019 			r_cons_printf ("(%"PFMT64d" bytes hidden)", mi_size);
3020 			ds->asmop.size = mi_size;
3021 			ds->oplen = mi_size;
3022 			ret = true;
3023 			break;
3024 		case R_META_TYPE_RUN:
3025 			r_core_cmdf (core, "%s @ 0x%"PFMT64x, mi->str, ds->at);
3026 			ds->asmop.size = mi_size;
3027 			ds->oplen = mi_size;
3028 			ret = true;
3029 			break;
3030 		case R_META_TYPE_DATA:
3031 			hexlen = len - idx;
3032 			delta = ds->at - node->start;
3033 			if (mi_size < hexlen) {
3034 				hexlen = mi_size;
3035 			}
3036 			ds->oplen = mi_size - delta;
3037 			core->print->flags &= ~R_PRINT_FLAGS_HEADER;
3038 			int size = mi_size;
3039 			if (!ds_print_data_type (ds, buf + idx, ds->hint? ds->hint->immbase: 0, size)) {
3040 				if (size > delta) {
3041 					r_cons_printf ("hex size=%d delta=%d\n", size , delta);
3042 					int remaining = size - delta;
3043 					remaining = R_MAX (remaining, 0);
3044 					if (remaining > (len - delta)) {
3045 						ut8 *b = calloc (1, size - delta);
3046 						memcpy (b, buf, len);
3047 						r_print_hexdump (core->print, ds->at,
3048 								b + idx, remaining, 16, 1, 1);
3049 						free (b);
3050 					} else {
3051 						r_print_hexdump (core->print, ds->at,
3052 							buf + idx, remaining, 16, 1, 1);
3053 					}
3054 				} else {
3055 					r_cons_printf ("hex size=%d hexlen=%d delta=%d",
3056 						size, hexlen, delta);
3057 				}
3058 			}
3059 			core->print->flags |= R_PRINT_FLAGS_HEADER;
3060 			ds->asmop.size = (int)size - (node->start - ds->at);
3061 			R_FREE (ds->line);
3062 			R_FREE (ds->line_col);
3063 			R_FREE (ds->refline);
3064 			R_FREE (ds->refline2);
3065 			R_FREE (ds->prev_line_col);
3066 			ret = true;
3067 			break;
3068 		case R_META_TYPE_FORMAT:
3069 			{
3070 				r_cons_printf ("pf %s # size=%" PFMT64d "\n", mi->str, mi_size);
3071 				int len_before = r_cons_get_buffer_len ();
3072 				r_print_format (core->print, ds->at, buf + idx,
3073 						len - idx, mi->str, R_PRINT_MUSTSEE, NULL, NULL);
3074 				int len_after = r_cons_get_buffer_len ();
3075 				const char *cons_buf = r_cons_get_buffer ();
3076 				if (len_after > len_before && buf && cons_buf[len_after - 1] == '\n') {
3077 					r_cons_drop (1);
3078 				}
3079 				ds->oplen = ds->asmop.size = (int)mi_size;
3080 				R_FREE (ds->line);
3081 				R_FREE (ds->refline);
3082 				R_FREE (ds->refline2);
3083 				R_FREE (ds->prev_line_col);
3084 				ret = true;
3085 			}
3086 			break;
3087 		default:
3088 			break;
3089 		}
3090 	}
3091 	r_pvector_free (metas);
3092 	return ret;
3093 }
3094 
revert_cdiv_magic(st64 magic)3095 static st64 revert_cdiv_magic(st64 magic) {
3096 	ut64 amagic = llabs (magic);
3097 	const st64 N = ST64_MAX;
3098 	st64 E, candidate;
3099 	short s;
3100 
3101 	if (amagic < 0xFFFFFF || amagic > UT32_MAX) {
3102 		return 0;
3103 	}
3104 	if (magic < 0) {
3105 		magic += 1LL << 32;
3106 	}
3107 	for (s = 0; s < 16; s++) {
3108 		E = 1LL << (32 + s);
3109 		candidate = (E + magic - 1) / magic;
3110 		if (candidate > 0) {
3111 			if ( ((N * magic) >> (32 + s)) == (N / candidate) ) {
3112 				return candidate;
3113 			}
3114 		}
3115 	}
3116 	return 0;
3117 }
3118 
ds_cdiv_optimization(RDisasmState * ds)3119 static void ds_cdiv_optimization(RDisasmState *ds) {
3120 	char *esil;
3121 	char *end, *comma;
3122 	st64 imm;
3123 	st64 divisor;
3124 	if (!ds->asm_hints || !ds->asm_hint_cdiv) {
3125 		return;
3126 	}
3127 	switch (ds->analop.type) {
3128 	case R_ANAL_OP_TYPE_MOV:
3129 	case R_ANAL_OP_TYPE_MUL:
3130 		esil = R_STRBUF_SAFEGET (&ds->analop.esil);
3131 		while (esil) {
3132 			comma = strchr (esil, ',');
3133 			if (!comma) {
3134 				break;
3135 			}
3136 			imm = strtol (esil, &end, 10);
3137 			if (comma && comma == end) {
3138 				divisor = revert_cdiv_magic (imm);
3139 				if (divisor) {
3140 					r_cons_printf (" ; CDIV: %lld * 2^n", divisor);
3141 					break;
3142 				}
3143 			}
3144 			esil = comma + 1;
3145 		}
3146 	}
3147 	// /TODO: check following SHR instructions
3148 }
3149 
ds_print_show_bytes(RDisasmState * ds)3150 static void ds_print_show_bytes(RDisasmState *ds) {
3151 	RCore* core = ds->core;
3152 	char *nstr, *str = NULL, pad[64];
3153 	char *flagstr = NULL;
3154 	int oldFlags = core->print->flags;
3155 	char extra[128];
3156 	int j, k;
3157 
3158 	if (!ds->show_bytes || ds->nb < 1) {
3159 		return;
3160 	}
3161 	if (!ds->show_color_bytes) {
3162 		core->print->flags &= ~R_PRINT_FLAGS_COLOR;
3163 	}
3164 	strcpy (extra, " ");
3165 	if (ds->show_flag_in_bytes) {
3166 		flagstr = r_flag_get_liststr (core->flags, ds->at);
3167 	}
3168 	if (flagstr) {
3169 		str = r_str_newf ("%s:", flagstr);
3170 		if (ds->nb > 0) {
3171 			k = ds->nb - strlen (str) - 1;
3172 			if (k < 0) {
3173 				str[ds->nb - 1] = '\0';
3174 			}
3175 			if (k > sizeof (pad)) {
3176 				k = 0;
3177 			}
3178 			for (j = 0; j < k; j++) {
3179 				pad[j] = ' ';
3180 			}
3181 			pad[j] = '\0';
3182 		} else {
3183 			pad[0] = 0;
3184 		}
3185 		R_FREE (flagstr);
3186 	} else {
3187 		if (ds->show_flag_in_bytes) {
3188 			k = ds->nb - 1;
3189 			if (k < 0 || k > sizeof (pad)) {
3190 				k = 0;
3191 			}
3192 			for (j = 0; j < k; j++) {
3193 				pad[j] = ' ';
3194 			}
3195 			pad[j] = '\0';
3196 			str = strdup ("");
3197 		} else {
3198 			str = r_asm_op_get_hex (&ds->asmop);
3199 			if (r_str_ansi_len (str) > ds->nb) {
3200 				char *p = (char *)r_str_ansi_chrn (str, ds->nb);
3201 				if (p)  {
3202 					p[0] = '.';
3203 					p[1] = '\0';
3204 				}
3205 			}
3206 			ds->print->cur_enabled = (ds->cursor != -1);
3207 			nstr = r_print_hexpair (ds->print, str, ds->index);
3208 			if (ds->print->bytespace) {
3209 				k = (ds->nb + (ds->nb / 2)) - r_str_ansi_len (nstr) + 2;
3210 			} else {
3211 				k = ds->nb - r_str_ansi_len (nstr) + 1;
3212 			}
3213   			if (k > 0) {
3214 				// setting to sizeof screw up the disasm
3215 				if (k > sizeof (pad)) {
3216 					k = 18;
3217 				}
3218 				for (j = 0; j < k; j++) {
3219 					pad[j] = ' ';
3220 				}
3221 				pad[j] = 0;
3222 				if (ds->lbytes) {
3223 					// hack to align bytes left
3224 					strcpy (extra, pad);
3225 					*pad = 0;
3226 				}
3227 			} else {
3228 				pad[0] = 0;
3229 			}
3230 			free (str);
3231 			str = nstr;
3232 		}
3233 	}
3234 	r_cons_printf ("%s%s %s", pad, str, extra);
3235 	free (str);
3236 	core->print->flags = oldFlags;
3237 }
3238 
ds_print_indent(RDisasmState * ds)3239 static void ds_print_indent(RDisasmState *ds) {
3240 	if (ds->show_indent) {
3241 		char indent[128];
3242 		int num = ds->indent_level * ds->indent_space;
3243 		if (num < 0) {
3244 			num = 0;
3245 		}
3246 		if (num >= sizeof (indent)) {
3247 			num = sizeof (indent) - 1;
3248 		}
3249 		memset (indent, ' ', num);
3250 		indent[num] = 0;
3251 		r_cons_strcat (indent);
3252 	}
3253 }
3254 
ds_print_optype(RDisasmState * ds)3255 static void ds_print_optype(RDisasmState *ds) {
3256 	if (ds->show_optype) {
3257 		const char *optype = r_anal_optype_to_string (ds->analop.type);
3258 		ds_print_color_reset (ds);
3259 		const char *pad = r_str_pad (' ', 8 - strlen (optype));
3260 		r_cons_printf ("[%s]%s", optype, pad);
3261 	}
3262 }
3263 
ds_print_opstr(RDisasmState * ds)3264 static void ds_print_opstr(RDisasmState *ds) {
3265 	ds_print_indent (ds);
3266 	if (ds->asm_instr) {
3267 		r_cons_strcat (ds->opstr);
3268 		ds_print_color_reset (ds);
3269 	}
3270 }
3271 
ds_print_color_reset(RDisasmState * ds)3272 static void ds_print_color_reset(RDisasmState *ds) {
3273 	if (ds->show_color) {
3274 		r_cons_strcat (Color_RESET);
3275 	}
3276 }
3277 
ds_print_middle(RDisasmState * ds,int ret)3278 static int ds_print_middle(RDisasmState *ds, int ret) {
3279 	if (ds->middle != 0) {
3280 		ret -= ds->middle;
3281 		ds_align_comment (ds);
3282 		if (ds->show_color) {
3283 			r_cons_strcat (ds->pal_comment);
3284 		}
3285 		r_cons_printf (" ; *middle* %d", ret);
3286 		if (ds->show_color) {
3287 			r_cons_strcat (Color_RESET);
3288 		}
3289 	}
3290 	return ret;
3291 }
3292 
ds_print_labels(RDisasmState * ds,RAnalFunction * f)3293 static bool ds_print_labels(RDisasmState *ds, RAnalFunction *f) {
3294 	const char *label;
3295 	if (!f) {
3296 		// f = r_anal_get_fcn_in (core->anal, ds->at, 0);
3297 		f = fcnIn (ds, ds->at, 0);
3298 	}
3299 	if (!f) {
3300 		return false;
3301 	}
3302 	label = r_anal_function_get_label_at (f, ds->at);
3303 	if (!label) {
3304 		return false;
3305 	}
3306 	ds_pre_line (ds);
3307 	if (ds->show_color) {
3308 		r_cons_strcat (ds->color_label);
3309 		r_cons_printf (" .%s:\n", label);
3310 		ds_print_color_reset (ds);
3311 	} else {
3312 		r_cons_printf (" .%s:\n", label);
3313 	}
3314 	return true;
3315 }
3316 
ds_print_sysregs(RDisasmState * ds)3317 static void ds_print_sysregs(RDisasmState *ds) {
3318 	RCore *core = ds->core;
3319 	if (!ds->show_comments) {
3320 		return;
3321 	}
3322 	switch (ds->analop.type) {
3323 	// Syscalls first
3324 	case R_ANAL_OP_TYPE_IO:
3325 		{
3326 			const int imm = (int)ds->analop.val;
3327 			RSyscall *sc = core->anal->syscall;
3328 			const char *ioname = r_syscall_get_io (sc, imm);
3329 			if (ioname && *ioname) {
3330 				CMT_ALIGN;
3331 				ds_comment (ds, true, "; IO %s", ioname);
3332 				ds->has_description = true;
3333 			}
3334 		}
3335 		break;
3336 	// Then sysregs
3337 	case R_ANAL_OP_TYPE_MOV:
3338 	case R_ANAL_OP_TYPE_LEA:
3339 	case R_ANAL_OP_TYPE_LOAD:
3340 	case R_ANAL_OP_TYPE_STORE:
3341 		{
3342 			const int imm = (int)ds->analop.ptr;
3343 			const char *sr = r_syscall_sysreg (core->anal->syscall, "reg", imm);
3344 			if (sr) {
3345 				CMT_ALIGN;
3346 				ds_comment (ds, true, "; REG %s - %s", sr, "");
3347 				// TODO: add register description description
3348 				ds->has_description = true;
3349 			}
3350 		}
3351 		break;
3352 	}
3353 }
3354 
ds_print_fcn_name(RDisasmState * ds)3355 static void ds_print_fcn_name(RDisasmState *ds) {
3356 	if (!ds->show_comments) {
3357 		return;
3358 	}
3359 	if (ds->analop.type != R_ANAL_OP_TYPE_JMP
3360 		&& ds->analop.type != R_ANAL_OP_TYPE_CJMP
3361 		&& ds->analop.type != R_ANAL_OP_TYPE_CALL) {
3362 		return;
3363 	}
3364 	RAnalFunction *f = fcnIn (ds, ds->analop.jump, R_ANAL_FCN_TYPE_NULL);
3365 	if (!f && ds->core->flags && (!ds->core->vmode || (!ds->subjmp && !ds->subnames))) {
3366 		const char *arch;
3367 		RFlagItem *flag = r_flag_get_by_spaces (ds->core->flags, ds->analop.jump,
3368 		                                        R_FLAGS_FS_CLASSES, R_FLAGS_FS_SYMBOLS, NULL);
3369 		if (flag && flag->name && ds->opstr && !strstr (ds->opstr, flag->name)
3370 		    && (r_str_startswith (flag->name, "sym.") || r_str_startswith (flag->name, "method."))
3371 		    && (arch = r_config_get (ds->core->config, "asm.arch")) && strcmp (arch, "dalvik")) {
3372 			RFlagItem *flag_sym = flag;
3373 			if (ds->core->vmode && ds->asm_demangle
3374 			    && (r_str_startswith (flag->name, "sym.")
3375 			        || (flag_sym = r_flag_get_by_spaces (ds->core->flags, ds->analop.jump,
3376 			                                             R_FLAGS_FS_SYMBOLS, NULL)))
3377 			    && flag_sym->demangled) {
3378 				return;
3379 			}
3380 			ds_begin_comment (ds);
3381 			ds_comment (ds, true, "; %s", flag->name);
3382 			return;
3383 		}
3384 	}
3385 	if (!f || !f->name) {
3386 		return;
3387 	}
3388 	st64 delta = ds->analop.jump - f->addr;
3389 	const char *label = r_anal_function_get_label_at (f, ds->analop.jump);
3390 	if (label) {
3391 		ds_begin_comment (ds);
3392 		ds_comment (ds, true, "; %s.%s", f->name, label);
3393 	} else {
3394 		RAnalFunction *f2 = fcnIn (ds, ds->at, 0);
3395 		if (f == f2) {
3396 			return;
3397 		}
3398 		if (delta > 0) {
3399 			ds_begin_comment (ds);
3400 			ds_comment (ds, true, "; %s+0x%x", f->name, delta);
3401 		} else if (delta < 0) {
3402 			ds_begin_comment (ds);
3403 			ds_comment (ds, true, "; %s-0x%x", f->name, -delta);
3404 		} else if ((!ds->core->vmode || (!ds->subjmp && !ds->subnames))
3405 			   && (!ds->opstr || !strstr (ds->opstr, f->name))) {
3406 			RFlagItem *flag_sym;
3407 			if (ds->core->vmode && ds->asm_demangle
3408 			    && (flag_sym = r_flag_get_by_spaces (ds->core->flags, ds->analop.jump,
3409 			                                         R_FLAGS_FS_SYMBOLS, NULL))
3410 			    && flag_sym->demangled) {
3411 				return;
3412 			}
3413 			ds_begin_comment (ds);
3414 			ds_comment (ds, true, "; %s", f->name);
3415 		}
3416 	}
3417 }
3418 
ds_print_shortcut(RDisasmState * ds,ut64 addr,int pos)3419 static int ds_print_shortcut(RDisasmState *ds, ut64 addr, int pos) {
3420 	char *shortcut = r_core_add_asmqjmp (ds->core, addr);
3421 	int slen = shortcut? strlen (shortcut): 0;
3422 	if (ds->asm_hint_pos > 0) {
3423 		if (pos) {
3424 			ds_align_comment (ds);
3425 		}
3426 	}
3427 	const char *ch = (pos)? ";": "";
3428 	if (ds->asm_hint_pos == -1) {
3429 		ch = " ";
3430 	}
3431 	if (ds->show_color) {
3432 		r_cons_strcat (ds->pal_comment);
3433 	}
3434 	if (*ch) {
3435 		slen++;
3436 	}
3437 	if (shortcut) {
3438 		if (ds->core->is_asmqjmps_letter) {
3439 			r_cons_printf ("%s[o%s]", ch, shortcut);
3440 			slen++;
3441 		} else {
3442 			r_cons_printf ("%s[%s]", ch, shortcut);
3443 		}
3444 		free (shortcut);
3445 	} else {
3446 		r_cons_printf ("%s[?]", ch);
3447 	}
3448 	if (ds->show_color) {
3449 		if (ds->core->print->resetbg) {
3450 			r_cons_strcat (Color_RESET);
3451 		} else {
3452 			r_cons_strcat (Color_RESET_NOBG);
3453 		}
3454 	}
3455 	slen++;
3456 	return slen;
3457 }
3458 
ds_print_core_vmode_jump_hit(RDisasmState * ds,int pos)3459 static bool ds_print_core_vmode_jump_hit(RDisasmState *ds, int pos) {
3460 	RCore *core = ds->core;
3461 	RAnal *a = core->anal;
3462 	RAnalHint *hint = r_anal_hint_get (a, ds->at);
3463 	bool res = false;
3464 	if (hint) {
3465 		if (hint->jump != UT64_MAX) {
3466 			ds_print_shortcut (ds, hint->jump, pos);
3467 			res = true;
3468 		}
3469 		r_anal_hint_free (hint);
3470 	}
3471 	return res;
3472 }
3473 
get_ptr(RDisasmState * ds,ut64 addr)3474 static ut64 get_ptr(RDisasmState *ds, ut64 addr) {
3475 	ut8 buf[sizeof (ut64)] = {0};
3476 	r_io_read_at (ds->core->io, addr, buf, sizeof (buf));
3477 	ut64 n64_32;
3478 	if (ds->core->rasm->bits == 64) {
3479 		n64_32 = r_read_ble64 (buf, 0);
3480 	} else {
3481 		n64_32 = r_read_ble32 (buf, 0);
3482 	}
3483 	return n64_32;
3484 }
3485 
get_ptr_ble(RDisasmState * ds,ut64 addr)3486 static ut64 get_ptr_ble(RDisasmState *ds, ut64 addr) {
3487 	ut8 buf[sizeof (ut64)] = {0};
3488 	int endian = ds->core->rasm->big_endian;
3489 	ut64 n64_32;
3490 	r_io_read_at (ds->core->io, addr, buf, sizeof (buf));
3491 	if (ds->core->rasm->bits == 64) {
3492 		n64_32 = r_read_ble64 (buf, endian);
3493 	} else {
3494 		n64_32 = r_read_ble32 (buf, endian);
3495 	}
3496 	return n64_32;
3497 }
3498 
ds_print_core_vmode(RDisasmState * ds,int pos)3499 static bool ds_print_core_vmode(RDisasmState *ds, int pos) {
3500 	RCore *core = ds->core;
3501 	bool gotShortcut = false;
3502 	int i, slen = 0;
3503 
3504 	if (!core->vmode) {
3505 		return false;
3506 	}
3507 	if (!ds->asm_hints) {
3508 		return false;
3509 	}
3510 	if (ds->asm_hint_emu) {
3511 		if (ds->emuptr) {
3512 			if (r_io_is_valid_offset (core->io, ds->emuptr, 0)) {
3513 				ds_print_shortcut (ds, ds->emuptr, pos);
3514 				//getPtr (ds, ds->emuptr, pos);
3515 				ds->emuptr = 0;
3516 				ds->hinted_line = true;
3517 				gotShortcut = true;
3518 				goto beach;
3519 			}
3520 		}
3521 	}
3522 	if (ds->asm_hint_lea) {
3523 		ut64 size;
3524 		RAnalMetaItem *mi = r_meta_get_at (ds->core->anal, ds->at, R_META_TYPE_ANY, &size);
3525 		if (mi) {
3526 			int obits = ds->core->rasm->bits;
3527 			ds->core->rasm->bits = size * 8;
3528 			slen = ds_print_shortcut(ds, get_ptr (ds, ds->at), pos);
3529 			ds->core->rasm->bits = obits;
3530 			gotShortcut = true;
3531 		}
3532 	}
3533 	switch (ds->analop.type) {
3534 	case R_ANAL_OP_TYPE_UJMP:
3535 	case R_ANAL_OP_TYPE_UJMP | R_ANAL_OP_TYPE_IND:
3536 	case R_ANAL_OP_TYPE_UJMP | R_ANAL_OP_TYPE_IND | R_ANAL_OP_TYPE_COND:
3537 	case R_ANAL_OP_TYPE_UJMP | R_ANAL_OP_TYPE_IND | R_ANAL_OP_TYPE_REG:
3538 		if (ds->asm_hint_lea) {
3539 			if (ds->analop.ptr != UT64_MAX && ds->analop.ptr != UT32_MAX) {
3540 				slen = ds_print_shortcut (ds, get_ptr (ds, ds->analop.ptr), pos);
3541 				gotShortcut = true;
3542 			}
3543 		}
3544 		break;
3545 	case R_ANAL_OP_TYPE_MOV:
3546 	case R_ANAL_OP_TYPE_LEA:
3547 	case R_ANAL_OP_TYPE_LOAD:
3548 		if (ds->asm_hint_lea) {
3549 			if (ds->analop.ptr != UT64_MAX && ds->analop.ptr != UT32_MAX && ds->analop.ptr > 256) {
3550 				slen = ds_print_shortcut (ds, ds->analop.ptr, pos);
3551 				gotShortcut = true;
3552 			}
3553 		}
3554 		break;
3555 	case R_ANAL_OP_TYPE_UCALL:
3556 	case R_ANAL_OP_TYPE_UCALL | R_ANAL_OP_TYPE_REG | R_ANAL_OP_TYPE_IND:
3557 	case R_ANAL_OP_TYPE_UCALL | R_ANAL_OP_TYPE_IND:
3558 		if (ds->asm_hint_call) {
3559 			if (ds->analop.jump != UT64_MAX) {
3560 				slen = ds_print_shortcut (ds, ds->analop.jump, pos);
3561 			} else {
3562 				ut64 addr;
3563 				if (ds->asm_hint_call_indirect) {
3564 					addr = get_ptr_ble (ds, ds->analop.ptr);
3565 				} else {
3566 					addr = ds->analop.ptr;
3567 				}
3568 				slen = ds_print_shortcut (ds, addr, pos);
3569 			}
3570 			gotShortcut = true;
3571 		}
3572 		break;
3573 	case R_ANAL_OP_TYPE_RJMP:
3574 	case R_ANAL_OP_TYPE_RCALL:
3575 		if (ds->analop.jump != UT64_MAX && ds->analop.jump != UT32_MAX) {
3576 			ds->analop.jump = get_ptr_ble (ds, ds->analop.jump);
3577 			slen = ds_print_shortcut (ds, ds->analop.jump, pos);
3578 			gotShortcut = true;
3579 		}
3580 		break;
3581 	case R_ANAL_OP_TYPE_JMP:
3582 	case R_ANAL_OP_TYPE_CJMP:
3583 		if (ds->asm_hint_jmp) {
3584 			slen = ds_print_shortcut (ds, ds->analop.jump, pos);
3585 			gotShortcut = true;
3586 		}
3587 		break;
3588 	case R_ANAL_OP_TYPE_CALL:
3589 	case R_ANAL_OP_TYPE_COND | R_ANAL_OP_TYPE_CALL:
3590 		if (ds->asm_hint_call) {
3591 			slen = ds_print_shortcut (ds, ds->analop.jump, pos);
3592 			gotShortcut = true;
3593 		}
3594 		break;
3595 	default:
3596 		if (ds_print_core_vmode_jump_hit (ds, pos)) {
3597 			gotShortcut = true;
3598 		}
3599 		break;
3600 	}
3601 beach:
3602 	if (ds->asm_hint_pos > 0) {
3603 		const int begin = gotShortcut ? 2: 3;
3604 		for (i = begin - slen; i > 0; i--) {
3605 			r_cons_strcat (" ");
3606 		}
3607 	} else if (ds->asm_hint_pos == 0 && !gotShortcut) {
3608 		r_cons_strcat ("   ");
3609 	}
3610 	ds->hinted_line = gotShortcut;
3611 	return gotShortcut;
3612 }
3613 
ds_begin_nl_comment(RDisasmState * ds)3614 static void ds_begin_nl_comment(RDisasmState *ds) {
3615 	if (ds->cmtcount > 0 && ds->show_comment_right) {
3616 		ds_newline (ds);
3617 		ds_begin_cont (ds);
3618 	} else if (ds->cmtcount > 0 || !ds->show_comment_right) {
3619 		ds_begin_line (ds);
3620 		ds_pre_xrefs (ds, false);
3621 	}
3622 	if (ds->show_color && (ds->cmtcount > 0 || ds->show_comment_right)) {
3623 		r_cons_print (ds->pal_comment);
3624 	}
3625 }
3626 
3627 // align for comment
ds_align_comment(RDisasmState * ds)3628 static void ds_align_comment(RDisasmState *ds) {
3629 	if (!ds->show_comment_right_default) {
3630 		return;
3631 	}
3632 	const int cmtcol = ds->cmtcol - 1;
3633 	const char *ll = r_cons_get_buffer ();
3634 	if (!ll) {
3635 		return;
3636 	}
3637 	ll += ds->buf_line_begin;
3638 	int cells = r_str_len_utf8_ansi (ll);
3639 	int cols = ds->interactive ? ds->core->cons->columns : 1024;
3640 	if (cells < cmtcol) {
3641 		int len = cmtcol - cells;
3642 		if (len < cols && len > 0) {
3643 			r_cons_memset (' ', len);
3644 		}
3645 	}
3646 	r_cons_print (" ");
3647 }
3648 
ds_print_dwarf(RDisasmState * ds)3649 static void ds_print_dwarf(RDisasmState *ds) {
3650 	if (ds->show_dwarf) {
3651 		// TODO: cache value in ds
3652 		int dwarfFile = (int)ds->dwarfFile + (int)ds->dwarfAbspath;
3653 		free (ds->sl);
3654 		ds->sl = r_bin_addr2text (ds->core->bin, ds->at, dwarfFile);
3655 		if (ds->sl) {
3656 			if ((!ds->osl || (ds->osl && strcmp (ds->sl, ds->osl)))) {
3657 				char *line = strdup (ds->sl);
3658 				if (!line) {
3659 					return;
3660 				}
3661 				r_str_replace_char (line, '\t', ' ');
3662 				r_str_replace_char (line, '\x1b', ' ');
3663 				r_str_replace_char (line, '\r', ' ');
3664 				r_str_replace_char (line, '\n', '\x00');
3665 				r_str_trim (line);
3666 				if (!*line) {
3667 					free (line);
3668 					return;
3669 				}
3670 				// handle_set_pre (ds, "  ");
3671 				ds_align_comment (ds);
3672 				if (ds->show_color) {
3673 					r_cons_printf ("%s; %s"Color_RESET, ds->pal_comment, line);
3674 				} else {
3675 					r_cons_printf ("; %s", line);
3676 				}
3677 				free (ds->osl);
3678 				ds->osl = ds->sl;
3679 				ds->sl = NULL;
3680 				free (line);
3681 			}
3682 		}
3683 	}
3684 }
3685 
ds_print_asmop_payload(RDisasmState * ds,const ut8 * buf)3686 static void ds_print_asmop_payload(RDisasmState *ds, const ut8 *buf) {
3687 	if (ds->show_varaccess) {
3688 		// XXX assume analop is filled
3689 		//r_anal_op (core->anal, &ds->analop, ds->at, core->block+i, core->blocksize-i);
3690 		int v = ds->analop.ptr;
3691 		switch (ds->analop.stackop) {
3692 		case R_ANAL_STACK_GET:
3693 			if (v < 0) {
3694 				r_cons_printf (" ; local.get %d", -v);
3695 			} else {
3696 				r_cons_printf (" ; arg.get %d", v);
3697 			}
3698 			break;
3699 		case R_ANAL_STACK_SET:
3700 			if (v < 0) {
3701 				r_cons_printf (" ; local.set %d", -v);
3702 			} else {
3703 				r_cons_printf (" ; arg.set %d", v);
3704 			}
3705 			break;
3706 		default:
3707 			break;
3708 		}
3709 	}
3710 	if (ds->asmop.payload != 0) {
3711 		r_cons_printf ("\n; .. payload of %d byte(s)", ds->asmop.payload);
3712 		if (ds->showpayloads) {
3713 			int mod = ds->asmop.payload % ds->core->rasm->dataalign;
3714 			int x;
3715 			for (x = 0; x < ds->asmop.payload; x++) {
3716 				r_cons_printf ("\n        0x%02x", buf[ds->oplen + x]);
3717 			}
3718 			for (x = 0; x < mod; x++) {
3719 				r_cons_printf ("\n        0x%02x ; alignment", buf[ds->oplen + ds->asmop.payload + x]);
3720 			}
3721 		}
3722 	}
3723 }
3724 
3725 /* Do not use this function for escaping JSON! */
ds_esc_str(RDisasmState * ds,const char * str,int len,const char ** prefix_out,bool is_comment)3726 static char *ds_esc_str(RDisasmState *ds, const char *str, int len, const char **prefix_out, bool is_comment) {
3727 	int str_len;
3728 	char *escstr = NULL;
3729 	const char *prefix = "";
3730 	bool esc_bslash = ds->core->print->esc_bslash;
3731 	RStrEnc strenc = ds->strenc;
3732 	if (strenc == R_STRING_ENC_GUESS) {
3733 		strenc = r_utf_bom_encoding ((ut8 *)str, len);
3734 	}
3735 	switch (strenc) {
3736 	case R_STRING_ENC_LATIN1:
3737 		escstr = r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash, is_comment);
3738 		break;
3739 	case R_STRING_ENC_UTF8:
3740 		escstr = r_str_escape_utf8 (str, ds->show_asciidot, esc_bslash);
3741 		break;
3742 	case R_STRING_ENC_UTF16LE:
3743 		escstr = r_str_escape_utf16le (str, len, ds->show_asciidot, esc_bslash);
3744 		prefix = "u";
3745 		break;
3746 	case R_STRING_ENC_UTF32LE:
3747 		escstr = r_str_escape_utf32le (str, len, ds->show_asciidot, esc_bslash);
3748 		prefix = "U";
3749 		break;
3750 	case R_STRING_ENC_UTF16BE:
3751 		escstr = r_str_escape_utf16be (str, len, ds->show_asciidot, esc_bslash);
3752 		prefix = "ub";
3753 		break;
3754 	case R_STRING_ENC_UTF32BE:
3755 		escstr = r_str_escape_utf32be (str, len, ds->show_asciidot, esc_bslash);
3756 		prefix = "Ub";
3757 		break;
3758 	default:
3759 		str_len = strlen (str);
3760 		if ((str_len == 1 && len > 3 && str[2] && !str[3])
3761 		    || (str_len == 3 && len > 5 && !memcmp (str, "\xff\xfe", 2) && str[4] && !str[5])) {
3762 			escstr = r_str_escape_utf16le (str, len, ds->show_asciidot, esc_bslash);
3763 			prefix = "u";
3764 		} else if (str_len == 1 && len > 7 && !str[2] && !str[3] && str[4] && !str[5]) {
3765 			RStrEnc enc = R_STRING_ENC_UTF32LE;
3766 			RRune ch;
3767 			const char *ptr, *end;
3768 			end = (const char *)r_mem_mem_aligned ((ut8 *)str, len, (ut8 *)"\0\0\0\0", 4, 4);
3769 			if (!end) {
3770 				end = str + len - 1;
3771 			}
3772 			for (ptr = str; ptr < end; ptr += 4) {
3773 				if (r_utf32le_decode ((ut8 *)ptr, end - ptr, &ch) > 0 && ch > 0x10ffff) {
3774 					enc = R_STRING_ENC_LATIN1;
3775 					break;
3776 				}
3777 			}
3778 			if (enc == R_STRING_ENC_UTF32LE) {
3779 				escstr = r_str_escape_utf32le (str, len, ds->show_asciidot, esc_bslash);
3780 				prefix = "U";
3781 			} else {
3782 				escstr = r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash, is_comment);
3783 			}
3784 		} else {
3785 			RStrEnc enc = R_STRING_ENC_LATIN1;
3786 			const char *ptr = str, *end = str + str_len;
3787 			for (; ptr < end; ptr++) {
3788 				if (r_utf8_decode ((ut8 *)ptr, end - ptr, NULL) > 1) {
3789 					enc = R_STRING_ENC_UTF8;
3790 					break;
3791 				}
3792 			}
3793 			escstr = (enc == R_STRING_ENC_UTF8 ?
3794 				r_str_escape_utf8 (str, ds->show_asciidot, esc_bslash) :
3795 				r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash, is_comment));
3796 		}
3797 	}
3798 	if (prefix_out) {
3799 		*prefix_out = prefix;
3800 	}
3801 	return escstr;
3802 }
3803 
ds_print_str(RDisasmState * ds,const char * str,int len,ut64 refaddr)3804 static void ds_print_str(RDisasmState *ds, const char *str, int len, ut64 refaddr) {
3805 	if (ds->core->flags->realnames || !r_bin_string_filter (ds->core->bin, str, refaddr)) {
3806 		return;
3807 	}
3808 	// do not resolve strings on arm64 pointed with ADRP
3809 	if (ds->analop.type == R_ANAL_OP_TYPE_LEA) {
3810 		if (ds->core->rasm->bits == 64 && r_str_startswith (r_config_get (ds->core->config, "asm.arch"), "arm")) {
3811 			return;
3812 		}
3813 	}
3814 	const char *prefix;
3815 	char *escstr = ds_esc_str (ds, str, len, &prefix, false);
3816 	if (escstr) {
3817 		bool inv = ds->show_color && !ds->show_emu_strinv;
3818 		ds_begin_comment (ds);
3819 		ds_comment (ds, true, "; %s%s\"%s\"%s", inv ? Color_INVERT : "", prefix, escstr,
3820 		            inv ? Color_INVERT_RESET : "");
3821 		ds->printed_str_addr = refaddr;
3822 		free (escstr);
3823 	}
3824 }
3825 
is_filtered_flag(RDisasmState * ds,const char * name)3826 static inline bool is_filtered_flag(RDisasmState *ds, const char *name) {
3827 	if (ds->show_noisy_comments || strncmp (name, "str.", 4)) {
3828 		return false;
3829 	}
3830 	ut64 refaddr = ds->analop.ptr;
3831 	const char *anal_flag = r_meta_get_string (ds->core->anal, R_META_TYPE_STRING, refaddr);
3832 	if (anal_flag) {
3833 		char *dupped = strdup (anal_flag);
3834 		if (dupped) {
3835 			r_name_filter (dupped, -1);
3836 			if (!strcmp (&name[4], dupped)) {
3837 				return true;
3838 			}
3839 		}
3840 	}
3841 	return false;
3842 }
3843 
3844 /* convert numeric value in opcode to ascii char or number */
ds_print_ptr(RDisasmState * ds,int len,int idx)3845 static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
3846 	RCore *core = ds->core;
3847 	ut64 p = ds->analop.ptr;
3848 	ut64 v = ds->analop.val;
3849 	ut64 refaddr = p;
3850 	bool aligned = false;
3851 	int refptr = ds->analop.refptr;
3852 	RFlagItem *f = NULL, *f2 = NULL;
3853 	bool f2_in_opstr = false;  /* Also if true, f exists */
3854 	if (!ds->show_comments || !ds->show_slow) {
3855 		return;
3856 	}
3857 	const int opType = ds->analop.type & R_ANAL_OP_TYPE_MASK;
3858 	bool canHaveChar = opType == R_ANAL_OP_TYPE_MOV;
3859 	if (!canHaveChar) {
3860 		canHaveChar = opType == R_ANAL_OP_TYPE_PUSH;
3861 	}
3862 
3863 	ds->chref = 0;
3864 	if ((char)v > 0 && v >= '!') {
3865 		ds->chref = (char)v;
3866 		if (ds->immstr) {
3867 			char *str = r_str_from_ut64 (r_read_ble64 (&v, core->print->big_endian));
3868 			if (str && *str) {
3869 				const char *ptr = str;
3870 				bool printable = true;
3871 				for (; *ptr; ptr++) {
3872 					if (!IS_PRINTABLE (*ptr)) {
3873 						printable = false;
3874 						break;
3875 					}
3876 				}
3877 				if (r_flag_get_i (core->flags, v)) {
3878 					printable = false;
3879 				}
3880 				if (canHaveChar && printable) {
3881 					ds_begin_comment (ds);
3882 					ds_comment (ds, true, "; '%s'", str);
3883 				}
3884 			}
3885 			free (str);
3886 		} else {
3887 			if (canHaveChar && (char)v > 0 && v >= '!' && v <= '~') {
3888 				ds_begin_comment (ds);
3889 				aligned = true;
3890 				ds_comment (ds, true, "; '%c'", (char)v);
3891 			}
3892 		}
3893 	}
3894 	RList *list = NULL;
3895 	RListIter *iter;
3896 	RAnalRef *ref;
3897 	list = r_anal_refs_get (core->anal, ds->at);
3898 	r_list_foreach (list, iter, ref) {
3899 		if (ref->type == R_ANAL_REF_TYPE_STRING || ref->type == R_ANAL_REF_TYPE_DATA) {
3900 			if ((f = r_flag_get_i (core->flags, ref->addr))) {
3901 				refaddr = ref->addr;
3902 				break;
3903 			}
3904 		}
3905 	}
3906 	r_list_free (list);
3907 	if (ds->analop.type == (R_ANAL_OP_TYPE_MOV | R_ANAL_OP_TYPE_REG)
3908 	    && ds->analop.stackop == R_ANAL_STACK_SET
3909 	    && ds->analop.val != UT64_MAX && ds->analop.val > 10) {
3910 		const char *arch = r_config_get (core->config, "asm.arch");
3911 		if (arch && !strcmp (arch, "x86")) {
3912 			p = refaddr = ds->analop.val;
3913 			refptr = 0;
3914 		}
3915 	}
3916 	bool flag_printed = false;
3917 	bool refaddr_printed = false;
3918 	bool string_printed = false;
3919 	if (refaddr == UT64_MAX) {
3920 		/* do nothing */
3921 	} else if (((st64)p) > 0 || ((st64)refaddr) > 0) {
3922 		const char *kind;
3923 		char *msg = calloc (sizeof (char), len);
3924 		if (((st64)p) > 0) {
3925 			f = r_flag_get_i (core->flags, p);
3926 			if (f) {
3927 				ut64 subrel_addr = core->parser->subrel_addr;
3928 				if (subrel_addr && subrel_addr != p) {
3929 					f2 = r_core_flag_get_by_spaces (core->flags, subrel_addr);
3930 					f2_in_opstr = f2 && ds->opstr && (strstr (ds->opstr, f2->name) || strstr (ds->opstr, f2->realname)) ;
3931 				}
3932 				refaddr = p;
3933 				if (!flag_printed && !is_filtered_flag (ds, f->name)
3934 				    && (!ds->opstr || (!strstr (ds->opstr, f->name) && !strstr (ds->opstr, f->realname)))
3935 				    && !f2_in_opstr) {
3936 					ds_begin_comment (ds);
3937 					ds_comment (ds, true, "; %s", f->name);
3938 					ds->printed_flag_addr = p;
3939 					flag_printed = true;
3940 				}
3941 			}
3942 		}
3943 		r_io_read_at (core->io, refaddr, (ut8*)msg, len - 1);
3944 		if (refptr && ds->show_refptr) {
3945 			ut64 num = r_read_ble (msg, core->print->big_endian, refptr * 8);
3946 			st64 n = (st64)num;
3947 			st32 n32 = (st32)(n & UT32_MAX);
3948 			if (ds->analop.type == R_ANAL_OP_TYPE_LEA) {
3949 				char str[128] = {0};
3950 				f = r_flag_get_i (core->flags, refaddr);
3951 				if (!f && ds->show_slow) {
3952 					r_io_read_at (ds->core->io, ds->analop.ptr,
3953 						      (ut8 *)str, sizeof (str) - 1);
3954 					str[sizeof (str) - 1] = 0;
3955 					if (!string_printed && str[0] && r_str_is_printable_incl_newlines (str)) {
3956 						ds_print_str (ds, str, sizeof (str), ds->analop.ptr);
3957 						string_printed = true;
3958 					}
3959 				}
3960 			} else {
3961 				if (n == UT32_MAX || n == UT64_MAX) {
3962 					ds_begin_nl_comment (ds);
3963 					ds_comment (ds, true, "; [0x%" PFMT64x":%d]=-1",
3964 							refaddr, refptr);
3965 				} else if (n == n32 && (n32 > -512 && n32 < 512)) {
3966 					ds_begin_nl_comment (ds);
3967 					ds_comment (ds, true, "; [0x%" PFMT64x
3968 							  ":%d]=%"PFMT64d, refaddr, refptr, n);
3969 				} else {
3970 					const char *kind, *flag = "";
3971 					char *msg2 = NULL;
3972 					RFlagItem *f2_ = r_flag_get_i (core->flags, n);
3973 					if (f2_) {
3974 						flag = f2_->name;
3975 					} else {
3976 						msg2 = calloc (sizeof (char), len);
3977 						r_io_read_at (core->io, n, (ut8*)msg2, len - 1);
3978 						msg2[len - 1] = 0;
3979 						kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg2, len - 1);
3980 						if (kind && !strcmp (kind, "text")) {
3981 							r_str_filter (msg2, 0);
3982 							if (*msg2) {
3983 								char *lala = r_str_newf ("\"%s\"", msg2);
3984 								free (msg2);
3985 								flag = msg2 = lala;
3986 							}
3987 						}
3988 					}
3989 					//ds_align_comment (ds);
3990 					{
3991 						const char *refptrstr = "";
3992 						if (core->print->flags & R_PRINT_FLAGS_SECSUB) {
3993 							RBinObject *bo = r_bin_cur_object (core->bin);
3994 							RBinSection *s = bo? r_bin_get_section_at (bo, n, core->io->va): NULL;
3995 							if (s) {
3996 								refptrstr = s->name;
3997 							}
3998 						}
3999 						ds_begin_nl_comment (ds);
4000 						ds_comment_start (ds, "; [");
4001 						if (f && f2_in_opstr) {
4002 							ds_comment_middle (ds, "%s", f->name);
4003 							flag_printed = true;
4004 						} else {
4005 							ds_comment_middle (ds, "0x%" PFMT64x, refaddr);
4006 						}
4007 						ds_comment_end (ds, ":%d]=%s%s0x%" PFMT64x "%s%s",
4008 								refptr, refptrstr, *refptrstr ? "." : "",
4009 								n, (flag && *flag) ? " " : "", flag);
4010 					}
4011 					free (msg2);
4012 				}
4013 				refaddr_printed = true;
4014 			}
4015 		}
4016 		if (!strcmp (ds->show_cmtoff, "true")) {
4017 			ds_begin_comment (ds);
4018 			ds_comment (ds, true, "; 0x%" PFMT64x, refaddr);
4019 			refaddr_printed = true;
4020 		} else if (!refaddr_printed && strcmp (ds->show_cmtoff, "false")) {
4021 			char addrstr[32] = {0};
4022 			snprintf (addrstr, sizeof (addrstr), "0x%" PFMT64x, refaddr);
4023 			if (!ds->opstr || !strstr (ds->opstr, addrstr)) {
4024 				snprintf (addrstr, sizeof (addrstr), "0x%08" PFMT64x, refaddr);
4025 				if (!ds->opstr || !strstr (ds->opstr, addrstr)) {
4026 					bool print_refaddr = true;
4027 					if (refaddr < 10) {
4028 						snprintf (addrstr, sizeof (addrstr), "%" PFMT64u, refaddr);
4029 						if (ds->opstr && strstr (ds->opstr, addrstr)) {
4030 							print_refaddr = false;
4031 						}
4032 					}
4033 					if (print_refaddr) {
4034 						if (!aligned) {
4035 							ds_begin_nl_comment (ds);
4036 						}
4037 						ds_comment (ds, true, "; 0x%" PFMT64x, refaddr);
4038 						refaddr_printed = true;
4039 					}
4040 				}
4041 			}
4042 		}
4043 		bool print_msg = true;
4044 #if 1
4045 		if (ds->strenc == R_STRING_ENC_GUESS
4046 		    && r_utf_bom_encoding ((ut8 *)msg, len) == R_STRING_ENC_GUESS
4047 		    && !(IS_PRINTABLE (*msg) || IS_WHITECHAR (*msg))) {
4048 			print_msg = false;
4049 		} else {
4050 			msg[len - 1] = 0;
4051 		}
4052 #endif
4053 		f = r_flag_get_i (core->flags, refaddr);
4054 		if (f) {
4055 			if (strlen (msg) != 1) {
4056 				char *msg2 = r_str_new (msg);
4057 				if (msg2) {
4058 					r_str_filter (msg2, 0);
4059 					if (!strncmp (msg2, "UH..", 4)) {
4060 						print_msg = false;
4061 					}
4062 					free (msg2);
4063 				}
4064 			}
4065 			if (print_msg) {
4066 				if (!string_printed) {
4067 					ds_print_str (ds, msg, len, refaddr);
4068 					string_printed = true;
4069 				}
4070 			} else if (!flag_printed && (!ds->opstr ||
4071 						(!strstr (ds->opstr, f->name) && !strstr (ds->opstr, f->realname)))) {
4072 				ds_begin_nl_comment (ds);
4073 				ds_comment (ds, true, "; %s", f->name);
4074 				ds->printed_flag_addr = refaddr;
4075 				flag_printed = true;
4076 			}
4077 		} else {
4078 			if (refaddr == UT64_MAX || refaddr == UT32_MAX) {
4079 				ds_begin_comment (ds);
4080 				ds_comment (ds, true, "; -1");
4081 			} else if (((char)refaddr > 0) && refaddr >= '!' && refaddr <= '~') {
4082 				char ch = refaddr;
4083 				if (canHaveChar && ch != ds->chref) {
4084 					ds_begin_comment (ds);
4085 					ds_comment (ds, true, "; '%c'", ch);
4086 				}
4087 			} else if (refaddr > 10) {
4088 				if ((st64)refaddr < 0) {
4089 					// resolve local var if possible
4090 					RAnalFunction *fcn = r_anal_get_function_at (core->anal, ds->at);
4091 					RAnalVar *v = fcn ? r_anal_function_get_var (fcn, 'v', (int)refaddr) : NULL;
4092 					ds_begin_comment (ds);
4093 					if (v) {
4094 						ds_comment (ds, true, "; var %s", v->name);
4095 					} else {
4096 						ds_comment (ds, true, "; var %d", -(int)refaddr);
4097 					}
4098 				} else {
4099 					if (r_core_anal_address (core, refaddr) & R_ANAL_ADDR_TYPE_ASCII) {
4100 						if (!string_printed && print_msg) {
4101 							ds_print_str (ds, msg, len, refaddr);
4102 							string_printed = true;
4103 						}
4104 					}
4105 				}
4106 			}
4107 			//XXX this should be refactored with along the above
4108 			kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg, len - 1);
4109 			if (kind) {
4110 				if (!strcmp (kind, "text")) {
4111 					if (!string_printed && print_msg) {
4112 						ds_print_str (ds, msg, len, refaddr);
4113 						string_printed = true;
4114 					}
4115 				} else if (!strcmp (kind, "invalid")) {
4116 					int *n = (int*)&refaddr;
4117 					ut64 p = ds->analop.val;
4118 					if (p == UT64_MAX || p == UT32_MAX) {
4119 						p = ds->analop.ptr;
4120 					}
4121 					/* avoid double ; -1 */
4122 					if (p != UT64_MAX && p != UT32_MAX) {
4123 						if (*n > -0xfff && *n < 0xfff) {
4124 							if (!aligned) {
4125 								ds_begin_comment (ds);
4126 							}
4127 							ds_comment (ds, true, "; %"PFMT64d, p);
4128 						}
4129 					}
4130 				} else {
4131 					// r_cons_printf (" ; %s", kind);
4132 				}
4133 				// TODO: check for more data kinds
4134 			}
4135 		}
4136 		free (msg);
4137 	} else {
4138 		ds_print_as_string (ds);
4139 	}
4140 	if (!ds->show_comment_right && ds->cmtcount > 0) {
4141 		const char *p = r_cons_get_buffer ();
4142 		if (p) {
4143 			int l = strlen (p);
4144 			if (p[l - 1] != '\n') {
4145 				ds_newline (ds);
4146 			}
4147 		}
4148 	}
4149 #if DEADCODE
4150 	if (aligned && ds->show_color) {
4151 		r_cons_strcat (Color_RESET);
4152 	}
4153 #endif
4154 }
4155 
ds_print_demangled(RDisasmState * ds)4156 static void ds_print_demangled(RDisasmState *ds) {
4157 	if (!ds->show_comments || !ds->asm_demangle) {
4158 		return;
4159 	}
4160 	RCore *core = ds->core;
4161 	RFlagItem *f;
4162 	int optype = ds->analop.type & 0xFFFF;
4163 	switch (optype) {
4164 	case R_ANAL_OP_TYPE_JMP:
4165 	case R_ANAL_OP_TYPE_UJMP:
4166 	case R_ANAL_OP_TYPE_CALL:
4167 		f = r_flag_get_by_spaces (core->flags, ds->analop.jump, R_FLAGS_FS_SYMBOLS, NULL);
4168 		if (f && f->demangled && f->realname && ds->opstr && !strstr (ds->opstr, f->realname)) {
4169 			ds_begin_nl_comment (ds);
4170 			ds_comment (ds, true, "; %s", f->realname);
4171 		}
4172 	}
4173 }
4174 
ds_print_relocs(RDisasmState * ds)4175 static void ds_print_relocs(RDisasmState *ds) {
4176 	char *demname = NULL;
4177 	if (!ds->showrelocs || !ds->show_slow) {
4178 		return;
4179 	}
4180 	RCore *core = ds->core;
4181 	const char *lang = r_config_get (core->config, "bin.lang");
4182 	bool demangle = r_config_get_i (core->config, "asm.demangle");
4183 	bool keep_lib = r_config_get_i (core->config, "bin.demangle.libs");
4184 	RBinReloc *rel = r_core_getreloc (core, ds->at, ds->analop.size);
4185 	if (rel) {
4186 		int cstrlen = 0;
4187 		char *ll = r_cons_lastline (&cstrlen);
4188 		if (!ll) {
4189 			return;
4190 		}
4191 		int ansilen = r_str_ansi_len (ll);
4192 		int utf8len = r_utf8_strlen ((const ut8*)ll);
4193 		int cells = utf8len - (cstrlen - ansilen);
4194 		int len = ds->cmtcol - cells;
4195 		r_cons_memset (' ', len);
4196 		if (rel->import) {
4197 			if (demangle) {
4198 				demname = r_bin_demangle (core->bin->cur, lang, rel->import->name, rel->vaddr, keep_lib);
4199 			}
4200 			r_cons_printf ("; RELOC %d %s", rel->type, demname ? demname : rel->import->name);
4201 		} else if (rel->symbol) {
4202 			if (demangle) {
4203 				demname = r_bin_demangle (core->bin->cur, lang, rel->symbol->name, rel->symbol->vaddr, keep_lib);
4204 			}
4205 			r_cons_printf ("; RELOC %d %s @ 0x%08" PFMT64x,
4206 					rel->type, demname ? demname : rel->symbol->name,
4207 					rel->symbol->vaddr);
4208 			if (rel->addend) {
4209 				if (rel->addend > 0) {
4210 					r_cons_printf (" + 0x%" PFMT64x, rel->addend);
4211 				} else {
4212 					r_cons_printf (" - 0x%" PFMT64x, -rel->addend);
4213 				}
4214 			}
4215 		} else {
4216 			r_cons_printf ("; RELOC %d ", rel->type);
4217 		}
4218 		free (demname);
4219 	}
4220 }
4221 
mymemwrite0(RAnalEsil * esil,ut64 addr,const ut8 * buf,int len)4222 static int mymemwrite0(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
4223 	return 0;
4224 }
4225 
mymemwrite1(RAnalEsil * esil,ut64 addr,const ut8 * buf,int len)4226 static int mymemwrite1(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
4227 	return 1;
4228 }
4229 
mymemwrite2(RAnalEsil * esil,ut64 addr,const ut8 * buf,int len)4230 static int mymemwrite2(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
4231 	return (addr >= emustack_min && addr < emustack_max);
4232 }
4233 
ssa_get(RAnalEsil * esil,const char * reg)4234 static char *ssa_get(RAnalEsil *esil, const char *reg) {
4235 	RDisasmState *ds = esil->user;
4236 	if (isdigit ((unsigned char)*reg)) {
4237 		return strdup (reg);
4238 	}
4239 	if (!ds->ssa) {
4240 		ds->ssa = sdb_new0 ();
4241 	}
4242 	int n = sdb_num_get (ds->ssa, reg, NULL);
4243 	return r_str_newf ("%s_%d", reg, n);
4244 }
4245 
ssa_set(RAnalEsil * esil,const char * reg)4246 static void ssa_set(RAnalEsil *esil, const char *reg) {
4247 	RDisasmState *ds = esil->user;
4248 	(void)sdb_num_inc (ds->ssa, reg, 1, 0);
4249 }
4250 
4251 #define R_DISASM_MAX_STR 512
myregread(RAnalEsil * esil,const char * name,ut64 * res,int * size)4252 static int myregread(RAnalEsil *esil, const char *name, ut64 *res, int *size) {
4253 	RDisasmState *ds = esil->user;
4254 	if (ds && ds->show_emu_ssa) {
4255 		if (!isdigit ((unsigned char)*name)) {
4256 			char *r = ssa_get (esil, name);
4257 			ds_comment_esil (ds, true, false, "<%s", r);
4258 			free (r);
4259 		}
4260 	}
4261 	return 0;
4262 }
4263 
myregwrite(RAnalEsil * esil,const char * name,ut64 * val)4264 static int myregwrite(RAnalEsil *esil, const char *name, ut64 *val) {
4265 	char str[64], *msg = NULL;
4266 	ut32 *n32 = (ut32*)str;
4267 	RDisasmState *ds = esil->user;
4268 	if (!ds) {
4269 		return 0;
4270 	}
4271 	if (!ds->show_emu_strlea && ds->analop.type == R_ANAL_OP_TYPE_LEA) {
4272 		// useful for ARM64
4273 		// reduce false positives in emu.str=true when loading strings via adrp+add
4274 		return 0;
4275 	}
4276 	ds->esil_likely = true;
4277 	if (ds->show_emu_ssa) {
4278 		ssa_set (esil, name);
4279 		char *r = ssa_get (esil, name);
4280 		ds_comment_esil (ds, true, false, ">%s", r);
4281 		free (r);
4282 		return 0;
4283 	}
4284 	if (!ds->show_slow) {
4285 		return 0;
4286 	}
4287 	memset (str, 0, sizeof (str));
4288 	if (*val) {
4289 		bool emu_str_printed = false;
4290 		char *type = NULL;
4291 		(void)r_io_read_at (esil->anal->iob.io, *val, (ut8*)str, sizeof (str)-1);
4292 		str[sizeof (str) - 1] = 0;
4293 		ds->emuptr = *val;
4294 		// support cstring here
4295 		{
4296 			ut64 *cstr = (ut64*) str;
4297 			ut64 addr = cstr[0];
4298 			if (!(*val >> 32)) {
4299 				addr = addr & UT32_MAX;
4300 			}
4301 			if (cstr[0] == 0 && cstr[1] < 0x1000) {
4302 				ut64 addr = cstr[2];
4303 				if (!(*val >> 32)) {
4304 					addr = addr & UT32_MAX;
4305 				}
4306 				(void)r_io_read_at (esil->anal->iob.io, addr,
4307 					(ut8*)str, sizeof (str)-1);
4308 			//	eprintf ("IS CSTRING 0x%llx %s\n", addr, str);
4309 				type = r_str_newf ("(cstr 0x%08"PFMT64x") ", addr);
4310 				ds->printed_str_addr = cstr[2];
4311 			} else if (r_io_is_valid_offset (esil->anal->iob.io, addr, 0)) {
4312 				ds->printed_str_addr = cstr[0];
4313 				type = r_str_newf ("(pstr 0x%08"PFMT64x") ", addr);
4314 				(void)r_io_read_at (esil->anal->iob.io, addr,
4315 					(ut8*)str, sizeof (str) - 1);
4316 			//	eprintf ("IS PSTRING 0x%llx %s\n", addr, str);
4317 			}
4318 		}
4319 
4320 		if (*str && !r_bin_strpurge (ds->core->bin, str, *val) && r_str_is_printable_incl_newlines (str)
4321 		    && (ds->printed_str_addr == UT64_MAX || *val != ds->printed_str_addr)) {
4322 			bool jump_op = false;
4323 			bool ignored = false;
4324 			switch (ds->analop.type) {
4325 			case R_ANAL_OP_TYPE_JMP:
4326 			case R_ANAL_OP_TYPE_UJMP:
4327 			case R_ANAL_OP_TYPE_RJMP:
4328 			case R_ANAL_OP_TYPE_IJMP:
4329 			case R_ANAL_OP_TYPE_IRJMP:
4330 			case R_ANAL_OP_TYPE_CJMP:
4331 			case R_ANAL_OP_TYPE_MJMP:
4332 			case R_ANAL_OP_TYPE_UCJMP:
4333 				jump_op = true;
4334 				break;
4335 			case R_ANAL_OP_TYPE_TRAP:
4336 			case R_ANAL_OP_TYPE_RET:
4337 				ignored = true;
4338 				break;
4339 			case R_ANAL_OP_TYPE_LEA:
4340 				if (ds->core->rasm->bits == 64 && r_str_startswith (r_config_get (ds->core->config, "asm.arch"), "arm")) {
4341 					ignored = true;
4342 				}
4343 				break;
4344 			}
4345 			if (!jump_op && !ignored) {
4346 				const char *prefix;
4347 				ut32 len = sizeof (str) -1;
4348 #if 0
4349 				RCore *core = ds->core;
4350 				ut32 len = core->blocksize + 256;
4351 				if (len < core->blocksize || len > R_DISASM_MAX_STR) {
4352 					len = R_DISASM_MAX_STR;
4353 				}
4354 #endif
4355 				ds->emuptr = *val;
4356 				char *escstr = ds_esc_str (ds, str, (int)len, &prefix, false);
4357 				if (escstr) {
4358 					char *m;
4359 					if (ds->show_color) {
4360 						bool inv = ds->show_emu_strinv;
4361 						m = r_str_newf ("%s%s%s\"%s\"%s",
4362 						                  prefix, r_str_get (type), inv ? Color_INVERT : "",
4363 						                  escstr, inv ? Color_INVERT_RESET : "");
4364 					} else {
4365 						m = r_str_newf ("%s%s\"%s\"", prefix, r_str_get (type), escstr);
4366 					}
4367 					msg = r_str_append_owned (msg, m);
4368 					emu_str_printed = true;
4369 					free (escstr);
4370 				}
4371 			}
4372 		} else {
4373 			if (!*n32) {
4374 				// msg = strdup ("NULL");
4375 			} else if (*n32 == UT32_MAX) {
4376 				/* nothing */
4377 			} else {
4378 				if (!ds->show_emu_str) {
4379 					msg = r_str_appendf (msg, "-> 0x%x", *n32);
4380 				}
4381 			}
4382 		}
4383 		R_FREE (type);
4384 		if ((ds->printed_flag_addr == UT64_MAX || *val != ds->printed_flag_addr)
4385 		    && (ds->show_emu_strflag || !emu_str_printed)) {
4386 			RFlagItem *fi = r_flag_get_i (esil->anal->flb.f, *val);
4387 			if (fi && (!ds->opstr || !strstr (ds->opstr, fi->name))) {
4388 				msg = r_str_appendf (msg, "%s%s", msg && *msg ? " " : "", fi->name);
4389 			}
4390 		}
4391 	}
4392 	if (ds->show_emu_str) {
4393 		if (msg && *msg) {
4394 			ds->emuptr = *val;
4395 			if (ds->show_emu_stroff && *msg == '"') {
4396 				ds_comment_esil (ds, true, false, "; 0x%"PFMT64x" %s", *val, msg);
4397 			} else {
4398 				ds_comment_esil (ds, true, false, "; %s", msg);
4399 			}
4400 			if (ds->show_comments && !ds->show_comment_right) {
4401 				ds_newline (ds);
4402 			}
4403 		}
4404 	} else {
4405 		if (msg && *msg) {
4406 			ds_comment_esil (ds, true, false, "; %s=0x%"PFMT64x" %s", name, *val, msg);
4407 		} else {
4408 			ds_comment_esil (ds, true, false, "; %s=0x%"PFMT64x, name, *val);
4409 		}
4410 		if (ds->show_comments && !ds->show_comment_right) {
4411 			ds_newline (ds);
4412 		}
4413 	}
4414 	free (msg);
4415 	return 0;
4416 }
4417 
ds_pre_emulation(RDisasmState * ds)4418 static void ds_pre_emulation(RDisasmState *ds) {
4419 	bool do_esil = ds->show_emu;
4420 	if (!ds->pre_emu) {
4421 		return;
4422 	}
4423 	RFlagItem *f = r_flag_get_at (ds->core->flags, ds->core->offset, true);
4424 	if (!f) {
4425 		return;
4426 	}
4427 	ut64 base = f->offset;
4428 	RAnalEsil *esil = ds->core->anal->esil;
4429 	int i, end = ds->core->offset - base;
4430 	int maxemu = 1024 * 1024;
4431 	RAnalEsilHookRegWriteCB orig_cb = esil->cb.hook_reg_write;
4432 	if (end < 0 || end > maxemu) {
4433 		return;
4434 	}
4435 	ds->stackptr = ds->core->anal->stackptr;
4436 	esil->cb.hook_reg_write = NULL;
4437 	for (i = 0; i < end; i++) {
4438 		ut64 addr = base + i;
4439 		RAnalOp* op = r_core_anal_op (ds->core, addr, R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
4440 		if (op) {
4441 			if (do_esil) {
4442 				r_anal_esil_set_pc (esil, addr);
4443 				r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&op->esil));
4444 				if (op->size > 0) {
4445 					i += op->size - 1;
4446 				}
4447 			}
4448 			ds_update_stackptr (ds, op);
4449 			r_anal_op_free (op);
4450 		}
4451 	}
4452 	esil->cb.hook_reg_write = orig_cb;
4453 }
4454 
ds_print_esil_anal_init(RDisasmState * ds)4455 static void ds_print_esil_anal_init(RDisasmState *ds) {
4456 	RCore *core = ds->core;
4457 	const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
4458 	if (!pc) {
4459 		return;
4460 	}
4461 	ds->esil_old_pc = r_reg_getv (core->anal->reg, pc);
4462 	if (!ds->esil_old_pc || ds->esil_old_pc == UT64_MAX) {
4463 		ds->esil_old_pc = core->offset;
4464 	}
4465 	if (!ds->show_emu) {
4466 		// XXX. stackptr not computed without asm.emu, when its not required
4467 		return;
4468 	}
4469 	if (!core->anal->esil) {
4470 		int iotrap = r_config_get_i (core->config, "esil.iotrap");
4471 		int esd = r_config_get_i (core->config, "esil.stack.depth");
4472 		unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
4473 
4474 		if (!(core->anal->esil = r_anal_esil_new (esd, iotrap, addrsize))) {
4475 			R_FREE (ds->esil_regstate);
4476 			return;
4477 		}
4478 		r_anal_esil_setup (core->anal->esil, core->anal, 0, 0, 1);
4479 	}
4480 	core->anal->esil->user = ds;
4481 	free (ds->esil_regstate);
4482 	R_FREE (core->anal->last_disasm_reg);
4483 	if (core->anal->gp) {
4484 		r_reg_setv (core->anal->reg, "gp", core->anal->gp);
4485 	}
4486 	ds->esil_regstate = r_reg_arena_peek (core->anal->reg);
4487 	RRegSet *regset = r_reg_regset_get (core->anal->reg, R_REG_TYPE_GPR);
4488 	if (ds->esil_regstate && regset) {
4489 		ds->esil_regstate_size = regset->arena->size;
4490 	}
4491 
4492 	// TODO: emulate N instructions BEFORE the current offset to get proper full function emulation
4493 	ds_pre_emulation (ds);
4494 }
4495 
ds_print_bbline(RDisasmState * ds)4496 static void ds_print_bbline(RDisasmState *ds) {
4497 	if (ds->show_bbline && ds->at) {
4498 		RAnalBlock *bb = NULL;
4499 		RAnalFunction *f_before = NULL;
4500 		if (ds->fcn) {
4501 			bb = r_anal_fcn_bbget_at (ds->core->anal, ds->fcn, ds->at);
4502 		} else {
4503 			f_before = fcnIn (ds, ds->at - 1, R_ANAL_FCN_TYPE_NULL);
4504 		}
4505 		if ((ds->fcn && bb && ds->fcn->addr != ds->at) || (!ds->fcn && f_before)) {
4506 			ds_begin_line (ds);
4507 			// adapted from ds_setup_pre ()
4508 			ds->cmtcount = 0;
4509 			if (!ds->show_functions || !ds->show_lines_fcn) {
4510 				ds->pre = DS_PRE_NONE;
4511 			} else {
4512 				ds->pre = DS_PRE_EMPTY;
4513 				if (!f_before) {
4514 					f_before = fcnIn (ds, ds->at - 1, R_ANAL_FCN_TYPE_NULL);
4515 				}
4516 				if (f_before == ds->fcn) {
4517 					ds->pre = DS_PRE_FCN_MIDDLE;
4518 				}
4519 			}
4520 			ds_print_pre (ds, true);
4521 			if (!ds->linesright && ds->show_lines_bb && ds->line) {
4522 				char *refline, *reflinecol = NULL;
4523 				ds_update_ref_lines (ds);
4524 				refline = ds->refline2;
4525 				reflinecol = ds->prev_line_col;
4526 				ds_print_ref_lines (refline, reflinecol, ds);
4527 			}
4528 			r_cons_printf ("|");
4529 			ds_newline (ds);
4530 		}
4531 	}
4532 }
4533 
print_fcn_arg(RCore * core,const char * type,const char * name,const char * fmt,const ut64 addr,const int on_stack,int asm_types)4534 static void print_fcn_arg(RCore *core, const char *type, const char *name,
4535 			   const char *fmt, const ut64 addr,
4536 			   const int on_stack, int asm_types) {
4537 	if (on_stack == 1 && asm_types > 1) {
4538 		r_cons_printf ("%s", type);
4539 	}
4540 	if (addr != UT32_MAX && addr != UT64_MAX  && addr != 0) {
4541 		char *res = r_core_cmd_strf (core, "pf%s %s%s %s @ 0x%08" PFMT64x,
4542 				(asm_types==2)? "": "q", (on_stack == 1) ? "*" : "", fmt, name, addr);
4543 		r_str_trim (res);
4544 		r_cons_printf ("%s", res);
4545 		free (res);
4546 	} else {
4547 		r_cons_printf ("-1");
4548 	}
4549 	r_cons_chop ();
4550 }
4551 
delete_last_comment(RDisasmState * ds)4552 static void delete_last_comment(RDisasmState *ds) {
4553 	if (!ds->show_comment_right_default) {
4554 		return;
4555 	}
4556 	const char *ll = r_cons_get_buffer ();
4557 	if (!ll) {
4558 		return;
4559 	}
4560 	ll += ds->buf_line_begin;
4561 	const char *begin = ll;
4562 	if (begin) {
4563 		ds_newline (ds);
4564 		ds_begin_cont (ds);
4565 	}
4566 }
4567 
can_emulate_metadata(RCore * core,ut64 at)4568 static bool can_emulate_metadata(RCore *core, ut64 at) {
4569 	// check if there is a meta at the addr that is unemulateable
4570 	const char *emuskipmeta = r_config_get (core->config, "emu.skip");
4571 	bool ret = true;
4572 	RPVector *metas = r_meta_get_all_at (core->anal, at);
4573 	void **it;
4574 	r_pvector_foreach (metas, it) {
4575 		RAnalMetaItem *item = ((RIntervalNode *)*it)->data;
4576 		if (strchr (emuskipmeta, (char)item->type)) {
4577 			ret = false;
4578 			break;
4579 		}
4580 	}
4581 	r_pvector_free (metas);
4582 	return ret;
4583 }
4584 
mipsTweak(RDisasmState * ds)4585 static void mipsTweak(RDisasmState *ds) {
4586 	RCore *core = ds->core;
4587 	const char *asm_arch = r_config_get (core->config, "asm.arch");
4588 	if (asm_arch && *asm_arch && strstr (asm_arch, "mips")) {
4589 		if (r_config_get_i (core->config, "anal.gpfixed")) {
4590 			ut64 gp = r_config_get_i (core->config, "anal.gp");
4591 			r_reg_setv (core->anal->reg, "gp", gp);
4592 		}
4593 	}
4594 }
4595 
4596 // modifies anal register state
ds_print_esil_anal(RDisasmState * ds)4597 static void ds_print_esil_anal(RDisasmState *ds) {
4598 	RCore *core = ds->core;
4599 	RAnalEsil *esil = core->anal->esil;
4600 	const char *pc;
4601 	int (*hook_mem_write)(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) = NULL;
4602 	int i, nargs;
4603 	ut64 at = r_core_pava (core, ds->at);
4604 	RConfigHold *hc = r_config_hold_new (core->config);
4605 	if (!hc) {
4606 		return;
4607 	}
4608 	if (!esil) {
4609 		ds_print_esil_anal_init (ds);
4610 		esil = core->anal->esil;
4611 	}
4612 	if (!ds->show_emu) {
4613 		goto beach;
4614 	}
4615 	if (!can_emulate_metadata (core, at)) {
4616 		goto beach;
4617 	}
4618 	if (ds->show_color) {
4619 		r_cons_strcat (ds->pal_comment);
4620 	}
4621 	esil = core->anal->esil;
4622 	pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
4623 	if (pc) {
4624 		r_reg_setv (core->anal->reg, pc, at + ds->analop.size);
4625 		esil->cb.user = ds;
4626 		esil->cb.hook_reg_write = myregwrite;
4627 		esil->cb.hook_reg_read = myregread;
4628 		hook_mem_write = esil->cb.hook_mem_write;
4629 	}
4630 	if (ds->show_emu_stack) {
4631 		esil->cb.hook_mem_write = mymemwrite2;
4632 	} else {
4633 		if (ds->show_emu_write) {
4634 			esil->cb.hook_mem_write = mymemwrite0;
4635 		} else {
4636 			esil->cb.hook_mem_write = mymemwrite1;
4637 		}
4638 	}
4639 	ds->esil_likely = 0;
4640 	const char *esilstr = R_STRBUF_SAFEGET (&ds->analop.esil);
4641 	if (R_STR_ISNOTEMPTY (esilstr)) {
4642 		mipsTweak (ds);
4643 		r_anal_esil_set_pc (esil, at);
4644 		r_anal_esil_parse (esil, esilstr);
4645 	}
4646 	r_anal_esil_stack_free (esil);
4647 	r_config_hold (hc, "io.cache", NULL);
4648 	r_config_set (core->config, "io.cache", "true");
4649 	if (!ds->show_comments) {
4650 		goto beach;
4651 	}
4652 	switch (ds->analop.type) {
4653 	case R_ANAL_OP_TYPE_SWI: {
4654 		char *s = cmd_syscall_dostr (core, ds->analop.val, at);
4655 		if (s) {
4656 			ds_comment_esil (ds, true, true, "; %s", s);
4657 			free (s);
4658 		}
4659 		} break;
4660 	case R_ANAL_OP_TYPE_CJMP:
4661 		ds_comment_esil (ds, true, true, ds->esil_likely? "; likely" : "; unlikely");
4662 		break;
4663 	case R_ANAL_OP_TYPE_JMP:
4664 		{
4665 			ut64 addr = ds->analop.jump;
4666 			if (!r_anal_get_function_at (ds->core->anal, addr)
4667 					&& !r_flag_get_at (core->flags, addr, false)) {
4668 				break;
4669 			}
4670 		}
4671 	case R_ANAL_OP_TYPE_UCALL:
4672 	case R_ANAL_OP_TYPE_ICALL:
4673 	case R_ANAL_OP_TYPE_RCALL:
4674 	case R_ANAL_OP_TYPE_IRCALL:
4675 	case R_ANAL_OP_TYPE_CALL:
4676 		{
4677 			RAnalFunction *fcn;
4678 			RAnalFuncArg *arg;
4679 			RListIter *iter;
4680 			RListIter *nextele;
4681 			const char *fcn_name = NULL;
4682 			char *key = NULL;
4683 			ut64 pcv = ds->analop.jump;
4684 			if (ds->analop.type == R_ANAL_OP_TYPE_RCALL) {
4685 				pcv = UT64_MAX;
4686 			}
4687 			if (pcv == UT64_MAX) {
4688 				pcv = ds->analop.ptr; // call [reloc-addr] // windows style
4689 				if (pcv == UT64_MAX || !pcv) {
4690 					r_anal_esil_reg_read (esil, "$jt", &pcv, NULL);
4691 					if (pcv == UT64_MAX || !pcv) {
4692 						pcv = r_reg_getv (core->anal->reg, pc);
4693 					}
4694 				}
4695 			}
4696 			fcn = r_anal_get_function_at (core->anal, pcv);
4697 			if (fcn) {
4698 				fcn_name = fcn->name;
4699 			} else {
4700 				RFlagItem *item = r_flag_get_i (core->flags, pcv);
4701 				if (item) {
4702 					fcn_name = item->name;
4703 				}
4704 			}
4705 			if (fcn_name) {
4706 				key = resolve_fcn_name (core->anal, fcn_name);
4707 			}
4708 			if (key) {
4709 				if (ds->asm_types < 1) {
4710 					free (key);
4711 					break;
4712 				}
4713 				const char *fcn_type = r_type_func_ret (core->anal->sdb_types, key);
4714 				int nargs = r_type_func_args_count (core->anal->sdb_types, key);
4715 				// remove other comments
4716 				delete_last_comment (ds);
4717 				// ds_comment_start (ds, "");
4718 				ds_comment_esil (ds, true, false, "%s", ds->show_color ? ds->pal_comment : "");
4719 				if (fcn_type) {
4720 					ds_comment_middle (ds, "; %s%s%s(", r_str_getf (fcn_type),
4721 							(*fcn_type && fcn_type[strlen (fcn_type) - 1] == '*') ? "" : " ",
4722 							r_str_getf (key));
4723 					if (!nargs) {
4724 						ds_comment_end (ds, "void)");
4725 						free (key);
4726 						break;
4727 					}
4728 				}
4729 			}
4730 			ut64 s_width = (core->anal->bits == 64)? 8: 4;
4731 			const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
4732 			ut64 spv = r_reg_getv (core->anal->reg, sp);
4733 			r_reg_setv (core->anal->reg, sp, spv + s_width); // temporarily set stack ptr to sync with carg.c
4734 			RList *list = r_core_get_func_args (core, fcn_name);
4735 			if (!r_list_empty (list)) {
4736 				bool warning = false;
4737 				bool on_stack = false;
4738 				r_list_foreach (list, iter, arg) {
4739 					if (arg->cc_source && r_str_startswith (arg->cc_source, "stack")) {
4740 						on_stack = true;
4741 					}
4742 					if (!arg->size) {
4743 						if (ds->asm_types == 2) {
4744 							ds_comment_middle (ds, "%s: unk_size", arg->c_type);
4745 						}
4746 						warning = true;
4747 					}
4748 					nextele = r_list_iter_get_next (iter);
4749 					if (!arg->fmt) {
4750 						if (ds->asm_types > 1) {
4751 							if (warning) {
4752 								ds_comment_middle (ds, "_format");
4753 							} else {
4754 								ds_comment_middle (ds, "%s : unk_format", arg->c_type);
4755 							}
4756 						} else {
4757 							ds_comment_middle (ds, "?");
4758 						}
4759 						ds_comment_middle (ds, nextele?", ":")");
4760 					} else {
4761 						// TODO: may need ds_comment_esil
4762 						print_fcn_arg (core, arg->orig_c_type, arg->name, arg->fmt, arg->src, on_stack, ds->asm_types);
4763 						ds_comment_middle (ds, nextele?", ":")");
4764 					}
4765 				}
4766 				ds_comment_end (ds, "");
4767 				r_list_free (list);
4768 				free (key);
4769 				break;
4770 			} else {
4771 				r_list_free (list);
4772 				// function name not resolved
4773 				r_warn_if_fail (!key);
4774 				free (key);
4775 				nargs = DEFAULT_NARGS;
4776 				if (fcn) {
4777 					// @TODO: fcn->nargs should be updated somewhere and used here instead
4778 					nargs = r_anal_var_count (core->anal, fcn, 's', 1) +
4779 							r_anal_var_count (core->anal, fcn, 'b', 1) +
4780 							r_anal_var_count (core->anal, fcn, 'r', 1);
4781 				}
4782 				if (nargs > 0) {
4783 					ds_comment_esil (ds, true, false, "%s", ds->show_color ? ds->pal_comment : "");
4784 					if (fcn_name) {
4785 						ds_comment_middle (ds, "; %s(", fcn_name);
4786 					} else {
4787 						ds_comment_middle (ds, "; 0x%"PFMT64x"(", pcv);
4788 					}
4789 					const char *cc = r_anal_syscc_default (core->anal);
4790 					for (i = 0; i < nargs; i++) {
4791 						ut64 v = r_debug_arg_get (core->dbg, cc, i);
4792 						ds_comment_middle (ds, "%s0x%"PFMT64x, i?", ":"", v);
4793 					}
4794 					ds_comment_end (ds, ")");
4795 				}
4796 			}
4797 			r_reg_setv (core->anal->reg, sp, spv); // reset stack ptr
4798 		}
4799 		break;
4800 	}
4801 	ds_print_color_reset (ds);
4802 beach:
4803 	if (esil) {
4804 		esil->cb.hook_mem_write = hook_mem_write;
4805 	}
4806 	r_config_hold_restore (hc);
4807 	r_config_hold_free (hc);
4808 }
4809 
ds_print_calls_hints(RDisasmState * ds)4810 static void ds_print_calls_hints(RDisasmState *ds) {
4811 	int emu = r_config_get_i (ds->core->config, "asm.emu");
4812 	int emuwrite = r_config_get_i (ds->core->config, "emu.write");
4813 	if (emu && emuwrite) {
4814 		// this is done by ESIL
4815 		return;
4816 	}
4817 	RAnal *anal = ds->core->anal;
4818 	Sdb *TDB = anal->sdb_types;
4819 	char *name;
4820 	char *full_name = NULL;
4821 	if (ds->analop.type == R_ANAL_OP_TYPE_CALL) {
4822 		// RAnalFunction *fcn = r_anal_get_fcn_in (anal, ds->analop.jump, -1);
4823 		RAnalFunction *fcn = fcnIn (ds, ds->analop.jump, -1);
4824 		if (fcn) {
4825 			full_name = fcn->name;
4826 		}
4827 	} else if (ds->analop.ptr != UT64_MAX) {
4828 		RFlagItem *flag = r_flag_get_i (ds->core->flags, ds->analop.ptr);
4829 		if (flag && flag->space && !strcmp (flag->space->name, R_FLAGS_FS_IMPORTS)) {
4830 			full_name = flag->realname;
4831 		}
4832 	}
4833 	if (!full_name) {
4834 		return;
4835 	}
4836 	if (r_type_func_exist (TDB, full_name)) {
4837 		name = strdup (full_name);
4838 	} else if (!(name = r_type_func_guess (TDB, full_name))) {
4839 		return;
4840 	}
4841 	ds_begin_comment (ds);
4842 	const char *fcn_type = r_type_func_ret (TDB, name);
4843 	if (!fcn_type || !*fcn_type) {
4844 		free (name);
4845 		return;
4846 	}
4847 	char *cmt = r_str_newf ("; %s%s%s(", fcn_type,
4848 		fcn_type[strlen (fcn_type) - 1] == '*' ? "" : " ",
4849 		name);
4850 	int i, arg_max = r_type_func_args_count (TDB, name);
4851 	if (!arg_max) {
4852 		cmt = r_str_append (cmt, "void)");
4853 	} else {
4854 		for (i = 0; i < arg_max; i++) {
4855 			char *type = r_type_func_args_type (TDB, name, i);
4856 			const char *tname = r_type_func_args_name (TDB, name, i);
4857 			if (type && *type) {
4858 				cmt = r_str_appendf (cmt, "%s%s%s%s%s", i == 0 ? "": " ", type,
4859 						type[strlen (type) - 1] == '*' ? "": " ",
4860 						tname, i == arg_max - 1 ? ")": ",");
4861 			} else if (tname && !strcmp (tname, "...")) {
4862 				cmt = r_str_appendf (cmt, "%s%s%s", i == 0 ? "": " ",
4863 						tname, i == arg_max - 1 ? ")": ",");
4864 			}
4865 			free (type);
4866 		}
4867 	}
4868 	ds_comment (ds, true, "%s", cmt);
4869 	ds_print_color_reset (ds);
4870 	free (cmt);
4871 	free (name);
4872 }
4873 
ds_print_comments_right(RDisasmState * ds)4874 static void ds_print_comments_right(RDisasmState *ds) {
4875 	char *desc = NULL;
4876 	RCore *core = ds->core;
4877 	ds_print_relocs (ds);
4878 	bool is_code = (!ds->hint) || (ds->hint && ds->hint->type != 'd');
4879 	RAnalMetaItem *mi = r_meta_get_at (ds->core->anal, ds->at, R_META_TYPE_ANY, NULL);
4880 	if (mi) {
4881 		is_code = mi->type != 'd';
4882 		mi = NULL;
4883 	}
4884 	if (is_code && ds->asm_describe && !ds->has_description) {
4885 		char *op, *locase = strdup (r_asm_op_get_asm (&ds->asmop));
4886 		if (!locase) {
4887 			return;
4888 		}
4889 		op = strchr (locase, ' ');
4890 		if (op) {
4891 			*op = 0;
4892 		}
4893 		r_str_case (locase, 0);
4894 		desc = r_asm_describe (core->rasm, locase);
4895 		free (locase);
4896 	}
4897 	if (ds->show_usercomments || ds->show_comments) {
4898 		if (desc && *desc) {
4899 			ds_align_comment (ds);
4900 			if (ds->show_color) {
4901 				r_cons_strcat (ds->color_comment);
4902 			}
4903 			r_cons_strcat ("; ");
4904 			r_cons_strcat (desc);
4905 			ds_print_color_reset (ds);
4906 		}
4907 		if (ds->show_comment_right && ds->comment) {
4908 			char *comment = ds->comment;
4909 			r_str_trim (comment);
4910 			if (*comment) {
4911 				if (!desc) {
4912 					ds_align_comment (ds);
4913 				}
4914 				if (strchr (comment, '\n')) {
4915 					comment = strdup (comment);
4916 					if (comment) {
4917 						ds_newline (ds);
4918 						ds_begin_line (ds);
4919 						size_t lines_count;
4920 						size_t *line_indexes = r_str_split_lines (comment, &lines_count);
4921 						if (line_indexes) {
4922 							int i;
4923 							for (i = 0; i < lines_count; i++) {
4924 								char *c = comment + line_indexes[i];
4925 								ds_print_pre (ds, true);
4926 								if (ds->show_color) {
4927 									r_cons_strcat (ds->color_usrcmt);
4928 								}
4929 								r_cons_printf (i == 0 ? "%s" : "; %s", c);
4930 								if (i < lines_count - 1) {
4931 									ds_newline (ds);
4932 									ds_begin_line (ds);
4933 								}
4934 							}
4935 						}
4936 						free (line_indexes);
4937 					}
4938 					free (comment);
4939 				} else {
4940 					if (comment) {
4941 						r_cons_strcat (comment);
4942 					}
4943 				}
4944 			}
4945 			//r_cons_strcat_justify (comment, strlen (ds->refline) + 5, ';');
4946 			ds_print_color_reset (ds);
4947 			R_FREE (ds->comment);
4948 		}
4949 	}
4950 	free (desc);
4951 	if ((ds->analop.type == R_ANAL_OP_TYPE_CALL || ds->analop.type & R_ANAL_OP_TYPE_UCALL) && ds->show_calls) {
4952 		ds_print_calls_hints (ds);
4953 	}
4954 }
4955 
ds_print_as_string(RDisasmState * ds)4956 static void ds_print_as_string(RDisasmState *ds) {
4957 	char *str = r_num_as_string (NULL, ds->analop.ptr, true);
4958 	if (str) {
4959 		ds_comment (ds, false, "%s; \"%s\"%s", COLOR (ds, pal_comment),
4960 			str, COLOR_RESET (ds));
4961 	}
4962 	free (str);
4963 }
4964 
_find_next_number(char * op)4965 static char *_find_next_number(char *op) {
4966 	char *p = op;
4967 	if (p) {
4968 		while (*p) {
4969 			// look for start of next separator or ANSI sequence
4970 			while (*p && !IS_SEPARATOR (*p) && *p != 0x1b) {
4971 				p++;
4972 			}
4973 			if (*p == 0x1b) {
4974 				// skip to end of ANSI sequence (lower or uppercase char)
4975 				while (*p && !(*p >= 'A' && *p <= 'Z') && !(*p >= 'a' && *p <= 'z')) {
4976 					p++;
4977 				}
4978 				if (*p) {
4979 					p++;
4980 				}
4981 			}
4982 			if (IS_SEPARATOR (*p)) {
4983 				// skip to end of separator
4984 				while (*p && IS_SEPARATOR (*p)) {
4985 					p++;
4986 				}
4987 			}
4988 			if (IS_DIGIT (*p)) {
4989 				// we found the start of the next number
4990 				return p;
4991 			}
4992 		}
4993 	}
4994 	return NULL;
4995 }
4996 
set_jump_realname(RDisasmState * ds,ut64 addr,const char ** kw,const char ** name)4997 static bool set_jump_realname(RDisasmState *ds, ut64 addr, const char **kw, const char **name) {
4998 	RFlag *f = ds->core->flags;
4999 	if (!f) {
5000 		return false;
5001 	}
5002 	if (!ds->asm_demangle && !f->realnames) {
5003 		// nothing to do, neither demangled nor regular realnames should be shown
5004 		return false;
5005 	}
5006 	RFlagItem *flag_sym = r_flag_get_by_spaces (f, addr, R_FLAGS_FS_SYMBOLS, NULL);
5007 	if (!flag_sym || !flag_sym->realname) {
5008 		// nothing to replace
5009 		return false;
5010 	}
5011 	if (!flag_sym->demangled && !f->realnames) {
5012 		// realname is not demangled and we don't want to show non-demangled realnames
5013 		return false;
5014 	}
5015 	*name = flag_sym->realname;
5016 	RFlagItem *flag_mthd = r_flag_get_by_spaces (f, addr, R_FLAGS_FS_CLASSES, NULL);
5017 	if (!f->realnames) {
5018 		// for asm.flags.real, we don't want these prefixes
5019 		if (flag_mthd && flag_mthd->name && r_str_startswith (flag_mthd->name, "method.")) {
5020 			*kw = "method ";
5021 		} else {
5022 			*kw = "sym ";
5023 		}
5024 	}
5025 	return true;
5026 }
5027 
5028 // TODO: this should be moved into r_parse
ds_sub_jumps(RDisasmState * ds,char * str)5029 static char *ds_sub_jumps(RDisasmState *ds, char *str) {
5030 	RAnal *anal = ds->core->anal;
5031 	RFlag *f = ds->core->flags;
5032 	const char *name = NULL;
5033 	const char *kw = "";
5034 	if (!ds->subjmp || !anal) {
5035 		return str;
5036 	}
5037 	int optype = ds->analop.type & 0xFFFF;
5038 	switch (optype) {
5039 	case R_ANAL_OP_TYPE_JMP:
5040 	case R_ANAL_OP_TYPE_UJMP:
5041 	case R_ANAL_OP_TYPE_CALL:
5042 		break;
5043 	default:
5044 		return str;
5045 	}
5046 	ut64 addr = ds->analop.jump;
5047 
5048 	RAnalFunction *fcn = r_anal_get_function_at (anal, addr);
5049 	if (fcn) {
5050 		if (!set_jump_realname (ds, addr, &kw, &name)) {
5051 			name = fcn->name;
5052 		}
5053 	} else if (f) {
5054 		RBinReloc *rel = NULL;
5055 		if (!ds->core->bin->is_reloc_patched) {
5056 			rel = r_core_getreloc (ds->core, ds->analop.addr, ds->analop.size);
5057 		}
5058 		if (!rel) {
5059 			rel = r_core_getreloc (ds->core, addr, ds->analop.size);
5060 		}
5061 		if (rel) {
5062 			if (rel && rel->import && rel->import->name) {
5063 				name = rel->import->name;
5064 			} else if (rel && rel->symbol && rel->symbol->name) {
5065 				name = rel->symbol->name;
5066 			}
5067 		} else {
5068 			if (!set_jump_realname (ds, addr, &kw, &name)) {
5069 				RFlagItem *flag = r_core_flag_get_by_spaces (f, addr);
5070 				if (flag) {
5071 					if (strchr (flag->name, '.')) {
5072 						name = flag->name;
5073 						if (f->realnames && flag->realname) {
5074 							name = flag->realname;
5075 						}
5076 					}
5077 				}
5078 			}
5079 		}
5080 	}
5081 	if (name) {
5082 		char *nptr, *ptr;
5083 		ut64 numval;
5084 		ptr = str;
5085 		while ((nptr = _find_next_number (ptr))) {
5086 			ptr = nptr;
5087 			numval = r_num_get (NULL, ptr);
5088 			if (numval == addr) {
5089 				while (*nptr && !IS_SEPARATOR (*nptr) && *nptr != 0x1b) {
5090 					nptr++;
5091 				}
5092 				char *kwname = r_str_newf ("%s%s", kw, name);
5093 				if (kwname) {
5094 					char* numstr = r_str_ndup (ptr, nptr-ptr);
5095 					if (numstr) {
5096 						str = r_str_replace (str, numstr, kwname, 0);
5097 						free (numstr);
5098 					}
5099 					free (kwname);
5100 				}
5101 				break;
5102 			}
5103 		}
5104 	}
5105 	return str;
5106 }
5107 
line_highlighted(RDisasmState * ds)5108 static bool line_highlighted(RDisasmState *ds) {
5109 	return ds->asm_highlight != UT64_MAX && ds->vat == ds->asm_highlight;
5110 }
5111 
ds_start_line_highlight(RDisasmState * ds)5112 static void ds_start_line_highlight(RDisasmState *ds) {
5113 	if (ds->show_color && line_highlighted (ds)) {
5114 		r_cons_strcat (ds->color_linehl);
5115 	}
5116 }
5117 
ds_end_line_highlight(RDisasmState * ds)5118 static void ds_end_line_highlight(RDisasmState *ds) {
5119 	if (ds->show_color && line_highlighted (ds)) {
5120 		r_cons_strcat (Color_RESET);
5121 	}
5122 }
5123 
5124 // int l is for lines
r_core_print_disasm(RPrint * p,RCore * core,ut64 addr,ut8 * buf,int len,int l,int invbreak,int cbytes,bool json,PJ * pj,RAnalFunction * pdf)5125 R_API int r_core_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len, int l, int invbreak, int cbytes, bool json, PJ *pj, RAnalFunction *pdf) {
5126 	int continueoninvbreak = (len == l) && invbreak;
5127 	RAnalFunction *of = NULL;
5128 	RAnalFunction *f = NULL;
5129 	bool calc_row_offsets = p->calc_row_offsets;
5130 	int ret, i, inc = 0, skip_bytes_flag = 0, skip_bytes_bb = 0, idx = 0;
5131 	ut8 *nbuf = NULL;
5132 	const int addrbytes = core->io->addrbytes;
5133 
5134 	// TODO: All those ds must be print flags
5135 	RDisasmState *ds = ds_init (core);
5136 	ds->cbytes = cbytes;
5137 	ds->print = p;
5138 	ds->l = l;
5139 	ds->buf = buf;
5140 	ds->len = len;
5141 	ds->addr = addr;
5142 	ds->hint = NULL;
5143 	ds->buf_line_begin = 0;
5144 	ds->pdf = pdf;
5145 
5146 	if (json) {
5147 		ds->pj = pj ? pj : r_core_pj_new (core);
5148 		if (!ds->pj) {
5149 			ds_free (ds);
5150 			return 0;
5151 		}
5152 		r_cons_push ();
5153 	} else {
5154 		ds->pj = NULL;
5155 	}
5156 
5157 	// disable row_offsets to prevent other commands to overwrite computed info
5158 	p->calc_row_offsets = false;
5159 
5160 	//r_cons_printf ("len =%d l=%d ib=%d limit=%d\n", len, l, invbreak, p->limit);
5161 	// TODO: import values from debugger is possible
5162 	// TODO: allow to get those register snapshots from traces
5163 	// TODO: per-function register state trace
5164 	// XXX - is there a better way to reset a the analysis counter so that
5165 	// when code is disassembled, it can actually find the correct offsets
5166 	{ /* used by asm.emu */
5167 		r_reg_arena_push (core->anal->reg);
5168 	}
5169 
5170 	ds_reflines_init (ds);
5171 	/* reset jmp table if not asked to keep it */
5172 	if (!core->keep_asmqjmps) { // hack
5173 		core->asmqjmps_count = 0;
5174 		ut64 *p = realloc (core->asmqjmps, R_CORE_ASMQJMPS_NUM * sizeof (ut64));
5175 		if (p) {
5176 			core->asmqjmps_size = R_CORE_ASMQJMPS_NUM;
5177 			core->asmqjmps = p;
5178 			for (i = 0; i < R_CORE_ASMQJMPS_NUM; i++) {
5179 				core->asmqjmps[i] = UT64_MAX;
5180 			}
5181 		}
5182 	}
5183 	if (ds->pj && !pj) {
5184 		pj_a (ds->pj);
5185 	}
5186 toro:
5187 	// uhm... is this necessary? imho can be removed
5188 	r_asm_set_pc (core->rasm, r_core_pava (core, ds->addr + idx));
5189 	core->cons->vline = r_config_get_i (core->config, "scr.utf8") ? (r_config_get_i (core->config, "scr.utf8.curvy") ? r_vline_uc : r_vline_u) : r_vline_a;
5190 
5191 	if (core->print->cur_enabled) {
5192 		// TODO: support in-the-middle-of-instruction too
5193 		r_anal_op_fini (&ds->analop);
5194 		if (r_anal_op (core->anal, &ds->analop, core->offset + core->print->cur,
5195 			buf + core->print->cur, (int)(len - core->print->cur), R_ANAL_OP_MASK_ALL)) {
5196 			// TODO: check for ds->analop.type and ret
5197 			ds->dest = ds->analop.jump;
5198 		}
5199 	} else {
5200 		/* highlight eip */
5201 		const char *pc = core->anal->reg->name[R_REG_NAME_PC];
5202 		if (pc) {
5203 			RFlagItem *item = r_flag_get (core->flags, pc);
5204 			if (item) {
5205 				ds->dest = item->offset;
5206 			}
5207 		}
5208 	}
5209 
5210 	ds_print_esil_anal_init (ds);
5211 	inc = 0;
5212 	if (!ds->l) {
5213 		ds->l = core->blocksize;
5214 	}
5215 	r_cons_break_push (NULL, NULL);
5216 	for (i = idx = ret = 0; addrbytes * idx < len && ds->lines < ds->l; idx += inc, i++, ds->index += inc, ds->lines++) {
5217 		ds->at = ds->addr + idx;
5218 		ds->vat = r_core_pava (core, ds->at);
5219 		if (r_cons_is_breaked ()) {
5220 			R_FREE (nbuf);
5221 			if (ds->pj) {
5222 				r_cons_pop ();
5223 			}
5224 			r_cons_break_pop ();
5225 			ds_free (ds);
5226 			return 0; //break;
5227 		}
5228 		if (core->print->flags & R_PRINT_FLAGS_UNALLOC) {
5229 			if (!core->anal->iob.is_valid_offset (core->anal->iob.io, ds->at, 0)) {
5230 				ds_begin_line (ds);
5231 				ds_print_labels (ds, f);
5232 				ds_setup_print_pre (ds, false, false);
5233 				ds_print_lines_left (ds);
5234 				core->print->resetbg = (ds->asm_highlight == UT64_MAX);
5235 				ds_start_line_highlight (ds);
5236 				ds_print_offset (ds);
5237 				r_cons_printf ("  unmapped\n");
5238 				inc = 1;
5239 				continue;
5240 			}
5241 		}
5242 		if (!ds->show_comment_right) {
5243 			if (ds->show_cmtesil) {
5244 				const char *esil = R_STRBUF_SAFEGET (&ds->analop.esil);
5245 				// ds_begin_line (ds);
5246 				ds_pre_line (ds);
5247 				ds_setup_print_pre (ds, false, false);
5248 				r_cons_strcat ("      ");
5249                                 ds_print_lines_left (ds);
5250 				ds_begin_comment (ds);
5251 				if (ds->show_color) {
5252 					ds_comment (ds, true, "; %s%s%s",
5253 						ds->pal_comment, esil, Color_RESET);
5254 				} else {
5255 					ds_comment (ds, true, "; %s", esil);
5256 				}
5257 			}
5258 		}
5259 		r_core_seek_arch_bits (core, ds->at); // slow but safe
5260 		ds->has_description = false;
5261 		ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
5262 		ds->printed_str_addr = UT64_MAX;
5263 		ds->printed_flag_addr = UT64_MAX;
5264 		// XXX. this must be done in ds_update_pc()
5265 		// ds_update_pc (ds, ds->at);
5266 		r_asm_set_pc (core->rasm, ds->at);
5267 		ds_update_ref_lines (ds);
5268 		r_anal_op_fini (&ds->analop);
5269 		r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * idx, (int)(len - addrbytes * idx), R_ANAL_OP_MASK_ALL);
5270 		if (ds_must_strip (ds)) {
5271 			inc = ds->analop.size;
5272 			// inc = ds->asmop.payload + (ds->asmop.payload % ds->core->rasm->dataalign);
5273 			r_anal_op_fini (&ds->analop);
5274 			continue;
5275 		}
5276 		// f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
5277 		f = ds->fcn = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
5278 		if (f && f->folded && r_anal_function_contains (f, ds->at)) {
5279 			int delta = (ds->at <= f->addr) ? (ds->at - r_anal_function_max_addr (f)) : 0;
5280 			if (of != f) {
5281 				char cmt[32];
5282 				get_bits_comment (core, f, cmt, sizeof (cmt));
5283 				const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ds->at);
5284 				if (comment) {
5285 					ds_pre_xrefs (ds, true);
5286 					r_cons_printf ("; %s\n", comment);
5287 				}
5288 				r_cons_printf ("%s%s%s (fcn) %s%s%s\n",
5289 					COLOR (ds, color_fline), core->cons->vline[CORNER_TL],
5290 					COLOR (ds, color_fname), f->name, cmt, COLOR_RESET (ds));
5291 				ds_setup_print_pre (ds, true, false);
5292 				ds_print_lines_left (ds);
5293 				ds_print_offset (ds);
5294 				r_cons_printf ("(%" PFMT64d " byte folded function)\n", r_anal_function_linear_size (f));
5295 				//r_cons_printf ("%s%s%s\n", COLOR (ds, color_fline), core->cons->vline[RDWN_CORNER], COLOR_RESET (ds));
5296 				if (delta < 0) {
5297 					delta = -delta;
5298 				}
5299 				ds->addr += delta + idx;
5300 				r_io_read_at (core->io, ds->addr, buf, len);
5301 				inc = 0; //delta;
5302 				idx = 0;
5303 				of = f;
5304 				r_anal_op_fini (&ds->analop);
5305 				if (len == l) {
5306 					break;
5307 				}
5308 			} else {
5309 				ds->lines--;
5310 				ds->addr += 1;
5311 				r_io_read_at (core->io, ds->addr, buf, len);
5312 				inc = 0; //delta;
5313 				idx = 0;
5314 				r_anal_op_fini (&ds->analop);
5315 			}
5316 			continue;
5317 		}
5318 		ds_show_comments_right (ds);
5319 		// TRY adding here
5320 		char *link_key = sdb_fmt ("link.%08"PFMT64x, ds->addr + idx);
5321 		const char *link_type = sdb_const_get (core->anal->sdb_types, link_key, 0);
5322 		if (link_type) {
5323 			char *fmt = r_type_format (core->anal->sdb_types, link_type);
5324 			if (fmt) {
5325 				r_cons_printf ("(%s)\n", link_type);
5326 				r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, ds->addr + idx);
5327 				const ut32 type_bitsize = r_type_get_bitsize (core->anal->sdb_types, link_type);
5328 				// always round up when calculating byte_size from bit_size of types
5329 				// could be struct with a bitfield entry
5330 				inc = (type_bitsize >> 3) + (!!(type_bitsize & 0x7));
5331 				free (fmt);
5332 				r_anal_op_fini (&ds->analop);
5333 				continue;
5334 			}
5335 		} else {
5336 			if (idx >= 0) {
5337 				ret = ds_disassemble (ds, buf + addrbytes * idx, len - addrbytes * idx);
5338 				if (ret == -31337) {
5339 					inc = ds->oplen;
5340 					r_anal_op_fini (&ds->analop);
5341 					continue;
5342 				}
5343 			}
5344 		}
5345 		if (ds->retry) {
5346 			ds->retry = false;
5347 			r_cons_break_pop ();
5348 			r_anal_op_fini (&ds->analop);
5349 			goto retry;
5350 		}
5351 		ds_atabs_option (ds);
5352 		if (ds->analop.addr != ds->at) {
5353 			r_anal_op_fini (&ds->analop);
5354 			r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * idx, (int)(len - addrbytes * idx), R_ANAL_OP_MASK_ALL);
5355 		}
5356 		if (ret < 1) {
5357 			r_strbuf_fini (&ds->analop.esil);
5358 			r_strbuf_init (&ds->analop.esil);
5359 			ds->analop.type = R_ANAL_OP_TYPE_ILL;
5360 		}
5361 		if (ds->hint) {
5362 			if (ds->hint->size) {
5363 				ds->analop.size = ds->hint->size;
5364 			}
5365 			if (ds->hint->ptr) {
5366 				ds->analop.ptr = ds->hint->ptr;
5367 			}
5368 		}
5369 		ds_print_bbline (ds);
5370 		if (ds->at >= addr) {
5371 			r_print_set_rowoff (core->print, ds->lines, ds->at - addr, calc_row_offsets);
5372 		}
5373 		if (ds->midflags) {
5374 			skip_bytes_flag = handleMidFlags (core, ds, true);
5375 			if (skip_bytes_flag && ds->midflags == R_MIDFLAGS_SHOW) {
5376 				ds->at += skip_bytes_flag;
5377 			}
5378 		}
5379 		ds_show_xrefs (ds);
5380 		ds_show_flags (ds);
5381 		if (skip_bytes_flag && ds->midflags == R_MIDFLAGS_SHOW) {
5382 			ds->at -= skip_bytes_flag;
5383 		}
5384 		if (ds->midbb) {
5385 			skip_bytes_bb = handleMidBB (core, ds);
5386 		}
5387 		if (ds->pdf) {
5388 			static bool sparse = false;
5389 			RAnalBlock *bb = r_anal_fcn_bbget_in (core->anal, ds->pdf, ds->at);
5390 			if (!bb) {
5391 				for (inc = 1; inc < ds->oplen; inc++) {
5392 					RAnalBlock *bb = r_anal_fcn_bbget_in (core->anal, ds->pdf, ds->at + inc);
5393 					if (bb) {
5394 						break;
5395 					}
5396 				}
5397 				r_anal_op_fini (&ds->analop);
5398 				if (!sparse) {
5399 					r_cons_printf ("..\n");
5400 					sparse = true;
5401 				}
5402 				continue;
5403 			}
5404 			sparse = false;
5405 		}
5406 		ds_control_flow_comments (ds);
5407 		ds_adistrick_comments (ds);
5408 		/* XXX: This is really cpu consuming.. need to be fixed */
5409 		ds_show_functions (ds);
5410 
5411 		if (ds->show_comments && !ds->show_comment_right) {
5412 			ds_show_refs (ds);
5413 			ds_build_op_str (ds, false);
5414 			ds_print_ptr (ds, len + 256, idx);
5415 			ds_print_sysregs (ds);
5416 			ds_print_fcn_name (ds);
5417 			ds_print_demangled (ds);
5418 			ds_print_color_reset (ds);
5419 			if (!ds->pseudo) {
5420 				R_FREE (ds->opstr);
5421 			}
5422 			if (ds->show_emu) {
5423 				ds_print_esil_anal (ds);
5424 			}
5425 			if ((ds->analop.type == R_ANAL_OP_TYPE_CALL || ds->analop.type & R_ANAL_OP_TYPE_UCALL) && ds->show_calls) {
5426 				ds_print_calls_hints (ds);
5427 			}
5428 			ds_show_comments_describe (ds);
5429 		}
5430 
5431 		f = fcnIn (ds, ds->addr, 0);
5432 		ds_begin_line (ds);
5433 		ds_print_labels (ds, f);
5434 		ds_setup_print_pre (ds, false, false);
5435 		ds_print_lines_left (ds);
5436 		core->print->resetbg = (ds->asm_highlight == UT64_MAX);
5437 		ds_start_line_highlight (ds);
5438 		ds_print_offset (ds);
5439 		////
5440 		RAnalFunction *fcn = f;
5441 		if (fcn) {
5442 			RAnalBlock *bb = r_anal_fcn_bbget_in (core->anal, fcn, ds->at);
5443 			if (!bb) {
5444 				fcn = r_anal_get_function_at (core->anal, ds->at);
5445 				if (fcn) {
5446 					bb = r_anal_fcn_bbget_in (core->anal, fcn, ds->at);
5447 				}
5448 			}
5449 			if (bb) {
5450 				if (bb->folded) {
5451 					r_cons_printf ("[+] Folded BB [..0x%08"PFMT64x"]\n", ds->at + bb->size);
5452 					inc = bb->size;
5453 					continue;
5454 				}
5455 			}
5456 		}
5457 		////
5458 		int mi_type;
5459 		bool mi_found = ds_print_meta_infos (ds, buf, len, idx, &mi_type);
5460 		if (ds->asm_hint_pos == 0) {
5461 			if (mi_found) {
5462 				r_cons_printf ("      ");
5463 			} else {
5464 				ds_print_core_vmode (ds, ds->asm_hint_pos);
5465 			}
5466 		}
5467 		ds_print_op_size (ds);
5468 		ds_print_trace (ds);
5469 		ds_print_cycles (ds);
5470 		ds_print_family (ds);
5471 		ds_print_stackptr (ds);
5472 		if (mi_found) {
5473 			ds_print_dwarf (ds);
5474 			ret = ds_print_middle (ds, ret);
5475 
5476 			ds_print_asmop_payload (ds, buf + addrbytes * idx);
5477 			if (core->rasm->syntax != R_ASM_SYNTAX_INTEL) {
5478 				RAsmOp ao; /* disassemble for the vm .. */
5479 				int os = core->rasm->syntax;
5480 				r_asm_set_syntax (core->rasm, R_ASM_SYNTAX_INTEL);
5481 				r_asm_disassemble (core->rasm, &ao, buf + addrbytes * idx,
5482 					len - addrbytes * idx + 5);
5483 				r_asm_set_syntax (core->rasm, os);
5484 			}
5485 			if (mi_type == R_META_TYPE_FORMAT) {
5486 				if ((ds->show_comments || ds->show_usercomments) && ds->show_comment_right) {
5487 			//		haveMeta = false;
5488 				}
5489 			}
5490 			if (mi_type != R_META_TYPE_FORMAT) {
5491 				if (ds->asm_hint_pos > 0) {
5492 					ds_print_core_vmode (ds, ds->asm_hint_pos);
5493 				}
5494 			}
5495 			{
5496 				ds_end_line_highlight (ds);
5497 				if ((ds->show_comments || ds->show_usercomments) && ds->show_comment_right) {
5498 					ds_print_color_reset (ds);
5499 					ds_print_comments_right (ds);
5500 				}
5501 			}
5502 		} else {
5503 			/* show cursor */
5504 			ds_print_show_cursor (ds);
5505 			if (!ds->show_bytes_right) {
5506 				ds_print_show_bytes (ds);
5507 			}
5508 			ds_print_lines_right (ds);
5509 			ds_print_optype (ds);
5510 			ds_build_op_str (ds, true);
5511 			ds_print_opstr (ds);
5512 			ds_end_line_highlight (ds);
5513 			ds_print_dwarf (ds);
5514 			ret = ds_print_middle (ds, ret);
5515 
5516 			ds_print_asmop_payload (ds, buf + addrbytes * idx);
5517 			if (core->rasm->syntax != R_ASM_SYNTAX_INTEL) {
5518 				RAsmOp ao; /* disassemble for the vm .. */
5519 				int os = core->rasm->syntax;
5520 				r_asm_set_syntax (core->rasm, R_ASM_SYNTAX_INTEL);
5521 				r_asm_disassemble (core->rasm, &ao, buf + addrbytes * idx,
5522 					len - addrbytes * idx + 5);
5523 				r_asm_set_syntax (core->rasm, os);
5524 			}
5525 			if (ds->show_bytes_right && ds->show_bytes) {
5526 				ds_comment (ds, true, "");
5527 				ds_print_show_bytes (ds);
5528 			}
5529 			if (ds->asm_hint_pos > 0) {
5530 				ds_print_core_vmode (ds, ds->asm_hint_pos);
5531 			}
5532 			// ds_print_cc_update (ds);
5533 
5534 			ds_cdiv_optimization (ds);
5535 			if ((ds->show_comments || ds->show_usercomments) && ds->show_comment_right) {
5536 				if (ds->show_cmtesil) {
5537 					const char *esil = R_STRBUF_SAFEGET (&ds->analop.esil);
5538 					if (ds->show_color) {
5539 						ds_comment (ds, true, "; %s%s%s",
5540 							ds->pal_comment, esil, Color_RESET);
5541 					} else {
5542 						ds_comment (ds, true, "; %s", esil);
5543 					}
5544 				}
5545 				ds_print_ptr (ds, len + 256, idx);
5546 				ds_print_sysregs (ds);
5547 				ds_print_fcn_name (ds);
5548 				ds_print_demangled (ds);
5549 				ds_print_color_reset (ds);
5550 				ds_print_comments_right (ds);
5551 				ds_print_esil_anal (ds);
5552 				ds_show_refs (ds);
5553 			}
5554 		}
5555 		core->print->resetbg = true;
5556 		ds_newline (ds);
5557 		if (ds->line) {
5558 			if (ds->show_lines_ret && ds->analop.type == R_ANAL_OP_TYPE_RET) {
5559 				if (strchr (ds->line, '>')) {
5560 					memset (ds->line, ' ', r_str_len_utf8 (ds->line));
5561 				}
5562 				ds_begin_line (ds);
5563 				ds_print_pre (ds, true);
5564 				ds_print_ref_lines (ds->line, ds->line_col, ds);
5565 				r_cons_printf ("; --------------------------------------");
5566 				ds_newline (ds);
5567 			}
5568 			R_FREE (ds->line);
5569 			R_FREE (ds->line_col);
5570 			R_FREE (ds->refline);
5571 			R_FREE (ds->refline2);
5572 			R_FREE (ds->prev_line_col);
5573 		}
5574 		R_FREE (ds->opstr);
5575 		inc = ds->oplen;
5576 
5577 		if (ds->midflags == R_MIDFLAGS_REALIGN && skip_bytes_flag) {
5578 			inc = skip_bytes_flag;
5579 		}
5580 		if (skip_bytes_bb && skip_bytes_bb < inc) {
5581 			inc = skip_bytes_bb;
5582 		}
5583 		if (inc < 1) {
5584 			inc = 1;
5585 		}
5586 		inc += ds->asmop.payload + (ds->asmop.payload % ds->core->rasm->dataalign);
5587 	}
5588 	r_anal_op_fini (&ds->analop);
5589 
5590 	R_FREE (nbuf);
5591 	r_cons_break_pop ();
5592 
5593 #if HASRETRY
5594 	if (!ds->cbytes && ds->lines < ds->l) {
5595 		ds->addr = ds->at + inc;
5596 	retry:
5597 		if (len < 4) {
5598 			len = 4;
5599 		}
5600 		free (nbuf);
5601 		buf = nbuf = malloc (len);
5602 		if (ds->tries > 0) {
5603 			if (r_io_read_at (core->io, ds->addr, buf, len)) {
5604 				goto toro;
5605 			}
5606 		}
5607 		if (ds->lines < ds->l) {
5608 			//ds->addr += idx;
5609 			if (!r_io_read_at (core->io, ds->addr, buf, len)) {
5610 				//ds->tries = -1;
5611 			}
5612 			goto toro;
5613 		}
5614 		if (continueoninvbreak) {
5615 			goto toro;
5616 		}
5617 		R_FREE (nbuf);
5618 	}
5619 #endif
5620 	if (ds->pj) {
5621 		r_cons_pop ();
5622 		if (!pj) {
5623 			pj_end (ds->pj);
5624 			r_cons_printf ("%s", pj_string (ds->pj));
5625 			pj_free (ds->pj);
5626 		}
5627 	}
5628 	r_print_set_rowoff (core->print, ds->lines, ds->at - addr, calc_row_offsets);
5629 	r_print_set_rowoff (core->print, ds->lines + 1, UT32_MAX, calc_row_offsets);
5630 	// TODO: this too (must review)
5631 	ds_print_esil_anal_fini (ds);
5632 	ds_reflines_fini (ds);
5633 	ds_free (ds);
5634 	R_FREE (nbuf);
5635 	p->calc_row_offsets = calc_row_offsets;
5636 	/* used by asm.emu */
5637 	r_reg_arena_pop (core->anal->reg);
5638 	return addrbytes * idx; //-ds->lastfail;
5639 }
5640 
check_end(int nb_opcodes,int nb_bytes,int i,int j)5641 static inline bool check_end(int nb_opcodes, int nb_bytes, int i, int j) {
5642 	if (nb_opcodes > 0) {
5643 		if (nb_bytes > 0) {
5644 			return j < nb_opcodes && i < nb_bytes;
5645 		}
5646 		return j < nb_opcodes;
5647 	}
5648 	return i < nb_bytes;
5649 }
5650 
r_core_print_disasm_instructions_with_buf(RCore * core,ut64 address,ut8 * buf,int nb_bytes,int nb_opcodes)5651 R_API int r_core_print_disasm_instructions_with_buf(RCore *core, ut64 address, ut8 *buf, int nb_bytes, int nb_opcodes) {
5652 	RDisasmState *ds = NULL;
5653 	int i, j, ret, len = 0;
5654 	char *tmpopstr;
5655 	const ut64 old_offset = core->offset;
5656 	bool hasanal = false;
5657 	const size_t addrbytes = buf ? 1 : core->io->addrbytes;
5658 	int skip_bytes_flag = 0, skip_bytes_bb = 0;
5659 
5660 	if (nb_bytes < 1 && nb_opcodes < 1) {
5661 		return 0;
5662 	}
5663 
5664 	r_reg_arena_push (core->anal->reg);
5665 
5666 	ds = ds_init (core);
5667 	ds->l = nb_opcodes;
5668 	ds->len = nb_opcodes * 8;
5669 
5670 	if (!buf) {
5671 		r_core_seek (core, address, true);
5672 		buf = core->block;
5673 	}
5674 
5675 	core->offset = address;
5676 
5677 	r_cons_break_push (NULL, NULL);
5678 	//build ranges to map addr with bits
5679 	j = 0;
5680 toro:
5681 	for (i = 0; check_end (nb_opcodes, nb_bytes, addrbytes * i, j); i += ret, j++) {
5682 		ds->at = address + i;
5683 		ds->vat = r_core_pava (core, ds->at);
5684 		hasanal = false;
5685 		r_core_seek_arch_bits (core, ds->at);
5686 		if (r_cons_is_breaked ()) {
5687 			break;
5688 		}
5689 		ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
5690 		ds->has_description = false;
5691 		r_asm_set_pc (core->rasm, ds->at);
5692 		// XXX copypasta from main disassembler function
5693 		// r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
5694 		ret = r_asm_disassemble (core->rasm, &ds->asmop,
5695 			buf + addrbytes * i, nb_bytes - addrbytes * i);
5696 		ds->oplen = ret;
5697 		if (ds->midflags) {
5698 			skip_bytes_flag = handleMidFlags (core, ds, true);
5699 		}
5700 		if (ds->midbb) {
5701 			skip_bytes_bb = handleMidBB (core, ds);
5702 		}
5703 		if (skip_bytes_flag && ds->midflags > R_MIDFLAGS_SHOW) {
5704 			ret = skip_bytes_flag;
5705 		}
5706 		if (skip_bytes_bb && skip_bytes_bb < ret) {
5707 			ret = skip_bytes_bb;
5708 		}
5709 		r_anal_op_fini (&ds->analop);
5710 		if (!hasanal) {
5711 			// XXX we probably don't need MASK_ALL
5712 			r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * i, nb_bytes - addrbytes * i, R_ANAL_OP_MASK_ALL);
5713 			hasanal = true;
5714 		}
5715 		if (ds_must_strip (ds)) {
5716 			continue;
5717 		}
5718 
5719 		if (ds->hint && ds->hint->size > 0) {
5720 			ret = ds->hint->size;
5721 			ds->oplen = ret;
5722 			ds->analop.size = ret;
5723 			ds->asmop.size = ret;
5724 		}
5725 		/* fix infinite loop */
5726 		if (ret < 1) {
5727 			ret = 1;
5728 		}
5729 		len += R_MAX (0, ret);
5730 		if (ds->hint && ds->hint->opcode) {
5731 			free (ds->opstr);
5732 			ds->opstr = strdup (ds->hint->opcode);
5733 		} else {
5734 			if (ds->decode && !ds->immtrim) {
5735 				R_FREE (ds->opstr);
5736 				if (!hasanal) {
5737 					r_anal_op (core->anal, &ds->analop, ds->at, buf + i, nb_bytes - i, R_ANAL_OP_MASK_ALL);
5738 					hasanal = true;
5739 				}
5740 				tmpopstr = r_anal_op_to_string (core->anal, &ds->analop);
5741 				ds->opstr = (tmpopstr)? tmpopstr: strdup (r_asm_op_get_asm (&ds->asmop));
5742 			} else if (ds->immtrim) {
5743 				free (ds->opstr);
5744 				ds->opstr = strdup (r_asm_op_get_asm (&ds->asmop));
5745 				char *res = r_parse_immtrim (ds->opstr);
5746 				if (res) {
5747 					ds->opstr = res;
5748 				}
5749 			} else if (ds->use_esil) {
5750 				if (!hasanal) {
5751 					r_anal_op (core->anal, &ds->analop,
5752 						ds->at, buf + i,
5753 						nb_bytes - i, R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
5754 					hasanal = true;
5755 				}
5756 				if (*R_STRBUF_SAFEGET (&ds->analop.esil)) {
5757 					free (ds->opstr);
5758 					ds->opstr = strdup (R_STRBUF_SAFEGET (&ds->analop.esil));
5759 				}
5760 			} else if (ds->subnames) {
5761 				char *asm_str;
5762 				RSpace *ofs = core->parser->flagspace;
5763 				RSpace *fs = ds->flagspace_ports;
5764 				if (ds->analop.type == R_ANAL_OP_TYPE_IO) {
5765 					core->parser->notin_flagspace = NULL;
5766 					core->parser->flagspace = fs;
5767 				} else {
5768 					if (fs) {
5769 						core->parser->notin_flagspace = fs;
5770 						core->parser->flagspace = fs;
5771 					} else {
5772 						core->parser->notin_flagspace = NULL;
5773 						core->parser->flagspace = NULL;
5774 					}
5775 				}
5776 				ds_build_op_str (ds, true);
5777 				free (ds->opstr);
5778 				ds->opstr = strdup (ds->str);
5779 				asm_str = colorize_asm_string (core, ds, true);
5780 				core->parser->flagspace = ofs;
5781 				free (ds->opstr);
5782 				ds->opstr = asm_str;
5783 			} else {
5784 				ds->opstr = strdup (r_asm_op_get_asm (&ds->asmop));
5785 			}
5786 			if (ds->immtrim) {
5787 				free (ds->opstr);
5788 				ds->opstr = strdup (r_asm_op_get_asm (&ds->asmop));
5789 				ds->opstr = r_parse_immtrim (ds->opstr);
5790 			}
5791 		}
5792 		if (ds->asm_instr) {
5793 			const char *opcolor = NULL;
5794 			if (ds->show_color) {
5795 				opcolor = r_print_color_op_type (core->print, ds->analop.type);
5796 				r_cons_printf ("%s%s" Color_RESET "\n", opcolor, ds->opstr);
5797 			} else {
5798 				r_cons_println (ds->opstr);
5799 			}
5800 			R_FREE (ds->opstr);
5801 		}
5802 		if (ds->hint) {
5803 			r_anal_hint_free (ds->hint);
5804 			ds->hint = NULL;
5805 		}
5806 	}
5807 	if (buf == core->block && nb_opcodes > 0 && j < nb_opcodes) {
5808 		r_core_seek (core, core->offset + i, true);
5809 		i = 0;
5810 		goto toro;
5811 	}
5812 	r_cons_break_pop ();
5813 	ds_free (ds);
5814 	core->offset = old_offset;
5815 	r_reg_arena_pop (core->anal->reg);
5816 
5817 	return len;
5818 }
5819 
handle_backwards_disasm(RCore * core,int * nb_opcodes,int * nb_bytes)5820 static bool handle_backwards_disasm(RCore *core, int *nb_opcodes, int *nb_bytes) {
5821 	if (!*nb_opcodes && !*nb_bytes) {
5822 		return false;
5823 	}
5824 	if (!*nb_bytes) {
5825 		*nb_bytes = core->blocksize;
5826 		if (*nb_opcodes < 0) {
5827 			/* Backward disassembly of nb_opcodes opcodes
5828 			 * - We compute the new starting offset
5829 			 * - Read at the new offset */
5830 			*nb_opcodes = -*nb_opcodes;
5831 
5832 			const ut64 old_offset = core->offset;
5833 			int nbytes = 0;
5834 
5835 			// We have some anal_info.
5836 			if (r_core_prevop_addr (core, core->offset, *nb_opcodes, &core->offset)) {
5837 				nbytes = old_offset - core->offset;
5838 			} else {
5839 				// core->offset is modified by r_core_prevop_addr
5840 				core->offset = old_offset;
5841 				r_core_asm_bwdis_len (core, &nbytes, &core->offset, *nb_opcodes);
5842 			}
5843 			if (nbytes > core->blocksize) {
5844 				r_core_block_size (core, nbytes);
5845 			}
5846 			r_io_read_at (core->io, core->offset, core->block, nbytes);
5847 		}
5848 	} else {
5849 		if (*nb_bytes < 0) { // Disassemble backward `nb_bytes` bytes
5850 			*nb_bytes = -*nb_bytes;
5851 			core->offset -= *nb_bytes;
5852 			if (*nb_bytes > core->blocksize) {
5853 				ut64 obsz = core->blocksize;
5854 				r_core_block_size (core, *nb_bytes);
5855 				if (core->blocksize == *nb_bytes) {
5856 					r_io_read_at (core->io, core->offset, core->block, *nb_bytes);
5857 				} else {
5858 					eprintf ("Cannot read that much!\n");
5859 					r_core_block_size (core, obsz);
5860 					return false;
5861 				}
5862 				r_core_block_size (core, obsz);
5863 			} else {
5864 				r_io_read_at (core->io, core->offset, core->block, *nb_bytes);
5865 			}
5866 		} else {
5867 			if (*nb_bytes > core->blocksize) {
5868 				r_core_block_size (core, *nb_bytes);
5869 				r_io_read_at (core->io, core->offset, core->block, *nb_bytes);
5870 			}
5871 		}
5872 	}
5873 	return true;
5874 }
5875 
5876 /* Disassemble either `nb_opcodes` instructions, or
5877  * `nb_bytes` bytes; both can be negative.
5878  * Set to 0 the parameter you don't use */
r_core_print_disasm_instructions(RCore * core,int nb_bytes,int nb_opcodes)5879 R_API int r_core_print_disasm_instructions(RCore *core, int nb_bytes, int nb_opcodes) {
5880 	const ut64 ocore_offset = core->offset;
5881 	int ret = -1;
5882 	if (handle_backwards_disasm (core, &nb_opcodes, &nb_bytes)) {
5883 		ret = r_core_print_disasm_instructions_with_buf (core, core->offset, NULL, nb_bytes, nb_opcodes);
5884 	}
5885 	r_core_seek (core, ocore_offset, true);
5886 	return ret;
5887 }
5888 
r_core_print_disasm_json(RCore * core,ut64 addr,ut8 * buf,int nb_bytes,int nb_opcodes,PJ * pj)5889 R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int nb_bytes, int nb_opcodes, PJ *pj) {
5890 	RAsmOp asmop;
5891 	RDisasmState *ds;
5892 	RAnalFunction *f;
5893 	int i, j, k, ret, line;
5894 	ut64 old_offset = core->offset;
5895 	ut64 at;
5896 	int dis_opcodes = 0;
5897 	int limit_by = 'b';
5898 	char str[512];
5899 
5900 	if (nb_opcodes != 0) {
5901 		limit_by = 'o';
5902 	}
5903 	if (nb_opcodes) { // Disassemble `nb_opcodes` opcodes.
5904 		if (nb_opcodes < 0) {
5905 			int count, nbytes = 0;
5906 
5907 			/* Backward disassembly of `nb_opcodes` opcodes:
5908 			 * - We compute the new starting offset
5909 			 * - Read at the new offset */
5910 			nb_opcodes = -nb_opcodes;
5911 
5912 			if (nb_opcodes > 0xffff) {
5913 				eprintf ("Too many backward instructions\n");
5914 				return false;
5915 			}
5916 
5917 			if (r_core_prevop_addr (core, core->offset, nb_opcodes, &addr)) {
5918 				nbytes = old_offset - addr;
5919 			} else if (!r_core_asm_bwdis_len (core, &nbytes, &addr, nb_opcodes)) {
5920 				/* workaround to avoid empty arrays */
5921 #define BWRETRY 0
5922 #if BWRETRY
5923 				nb_opcodes ++;
5924 				if (!r_core_asm_bwdis_len (core, &nbytes, &addr, nb_opcodes)) {
5925 #endif
5926 					pj_end (pj);
5927 					return false;
5928 #if BWRETRY
5929 				}
5930 #endif
5931 				nb_opcodes --;
5932 			}
5933 			count = R_MIN (nb_bytes, nbytes);
5934 			if (count > 0) {
5935 				r_io_read_at (core->io, addr, buf, count);
5936 				r_io_read_at (core->io, addr+count, buf+count, nb_bytes-count);
5937 			} else {
5938 				if (nb_bytes > 0) {
5939 					memset (buf, 0xff, nb_bytes);
5940 				}
5941 			}
5942 		} else {
5943 			// If we are disassembling a positive number of lines, enable dis_opcodes
5944 			// to be used to finish the loop
5945 			// If we are disasembling a negative number of lines, we just calculate
5946 			// the equivalent addr and nb_size and scan a positive number of BYTES
5947 			// so keep dis_opcodes = 0;
5948 			dis_opcodes = 1;
5949 			r_io_read_at (core->io, addr, buf, nb_bytes);
5950 		}
5951 	} else { // Disassemble `nb_bytes` bytes
5952 		if (nb_bytes < 0) {
5953 			//Backward disassembly of `nb_bytes` bytes
5954 			nb_bytes = -nb_bytes;
5955 			addr -= nb_bytes;
5956 			r_io_read_at (core->io, addr, buf, nb_bytes);
5957 		}
5958 	}
5959 	core->offset = addr;
5960 
5961 	// TODO: add support for anal hints
5962 	// If using #bytes i = j
5963 	// If using #opcodes, j is the offset from start address. i is the
5964 	// offset in current disassembly buffer (256 by default)
5965 	i = k = j = line = 0;
5966 	// i = number of bytes
5967 	// j = number of instructions
5968 	// k = delta from addr
5969 	ds = ds_init (core);
5970 	bool result = false;
5971 
5972 	for (;;) {
5973 		bool end_nbopcodes, end_nbbytes;
5974 		int skip_bytes_flag = 0, skip_bytes_bb = 0;
5975 
5976 		at = addr + k;
5977 		ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
5978 		r_asm_set_pc (core->rasm, at);
5979 		// 32 is the biggest opcode length in intel
5980 		// Make sure we have room for it
5981 		if (dis_opcodes == 1 && i >= nb_bytes - 32) {
5982 			// Read another nb_bytes bytes into buf from current offset
5983 			r_io_read_at (core->io, at, buf, nb_bytes);
5984 			i = 0;
5985 		}
5986 
5987 		if (limit_by == 'o') {
5988 			if (j >= nb_opcodes) {
5989 				break;
5990 			}
5991 		} else if (i >= nb_bytes) {
5992 			break;
5993 		}
5994 		memset (&asmop, 0, sizeof (RAsmOp));
5995 		ret = r_asm_disassemble (core->rasm, &asmop, buf + i, nb_bytes - i);
5996 		if (ret < 1) {
5997 			char *hex = r_asm_op_get_hex (&asmop);
5998 			pj_o (pj);
5999 			pj_kn (pj, "offset", at);
6000 			pj_ki (pj, "size", 1);
6001 			pj_ks (pj, "bytes", hex);
6002 			pj_ks (pj, "type", "invalid");
6003 			pj_end (pj);
6004 			i++;
6005 			k++;
6006 			j++;
6007 			result = true;
6008 			free (hex);
6009 			continue;
6010 		}
6011 
6012 		char opstr[256];
6013 		r_str_ncpy (opstr, r_asm_op_get_asm (&asmop), sizeof (opstr) - 1);
6014 
6015 		ds->has_description = false;
6016 		r_anal_op_fini (&ds->analop);
6017 		r_anal_op (core->anal, &ds->analop, at, buf + i, nb_bytes - i, R_ANAL_OP_MASK_ALL);
6018 
6019 		if (ds->pseudo) {
6020 			r_parse_parse (core->parser, opstr, opstr);
6021 		}
6022 
6023 		// f = r_anal_get_fcn_in (core->anal, at,
6024 		f = fcnIn (ds, at, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM | R_ANAL_FCN_TYPE_LOC);
6025 		if (ds->subvar && f) {
6026 			int ba_len = r_strbuf_length (&asmop.buf_asm) + 128;
6027 			char *ba = malloc (ba_len);
6028 			if (ba) {
6029 				strcpy (ba, r_asm_op_get_asm (&asmop));
6030 				r_parse_subvar (core->parser, f, at, ds->analop.size,
6031 						ba, ba, ba_len);
6032 				r_asm_op_set_asm (&asmop, ba);
6033 				free (ba);
6034 			}
6035 		}
6036 		ds->oplen = r_asm_op_get_size (&asmop);
6037 		ds->at = at;
6038 		if (ds->midflags) {
6039 			skip_bytes_flag = handleMidFlags (core, ds, false);
6040 		}
6041 		if (ds->midbb) {
6042 			skip_bytes_bb = handleMidBB (core, ds);
6043 		}
6044 		if (skip_bytes_flag && ds->midflags > R_MIDFLAGS_SHOW) {
6045 			ds->oplen = ret = skip_bytes_flag;
6046 		}
6047 		if (skip_bytes_bb && skip_bytes_bb < ret) {
6048 			ds->oplen = ret = skip_bytes_bb;
6049 		}
6050 		{
6051 			ut64 killme = UT64_MAX;
6052 			bool be = core->print->big_endian;
6053 			if (r_io_read_i (core->io, ds->analop.ptr, &killme, ds->analop.refptr, be)) {
6054 				core->parser->subrel_addr = killme;
6055 			}
6056 		}
6057 		{
6058 			char *aop = r_asm_op_get_asm (&asmop);
6059 			char *buf = malloc (strlen (aop) + 128);
6060 			if (buf) {
6061 				strcpy (buf, aop);
6062 				buf = ds_sub_jumps (ds, buf);
6063 				r_parse_filter (core->parser, ds->vat, core->flags, ds->hint, buf,
6064 					str, sizeof (str) - 1, core->print->big_endian);
6065 				str[sizeof (str) - 1] = '\0';
6066 				r_asm_op_set_asm (&asmop, buf);
6067 				free (buf);
6068 			}
6069 		}
6070 
6071 		pj_o (pj);
6072 		pj_kn (pj, "offset", at);
6073 		if (ds->analop.ptr != UT64_MAX) {
6074 			pj_kn (pj, "ptr", ds->analop.ptr);
6075 		}
6076 		if (ds->analop.val != UT64_MAX) {
6077 			pj_kn (pj, "val", ds->analop.val);
6078 		}
6079 		pj_k (pj, "esil"); // split key and value to allow empty strings
6080 		pj_s (pj, R_STRBUF_SAFEGET (&ds->analop.esil));
6081 		pj_kb (pj, "refptr", ds->analop.refptr);
6082 		pj_kn (pj, "fcn_addr", f ? f->addr : 0);
6083 		pj_kn (pj, "fcn_last", f ? r_anal_function_max_addr (f) - ds->oplen : 0);
6084 		pj_ki (pj, "size", ds->analop.size);
6085 		pj_ks (pj, "opcode", opstr);
6086 		pj_ks (pj, "disasm", str);
6087 		{
6088 			char *hex = r_asm_op_get_hex (&asmop);
6089 			pj_ks (pj, "bytes", hex);
6090 			free (hex);
6091 		}
6092 		pj_ks (pj, "family", r_anal_op_family_to_string (ds->analop.family));
6093 		pj_ks (pj, "type", r_anal_optype_to_string (ds->analop.type));
6094 		// indicate a relocated address
6095 		RBinReloc *rel = r_core_getreloc (core, ds->at, ds->analop.size);
6096 		// reloc is true if address in reloc table
6097 		pj_kb (pj, "reloc", rel);
6098 		// wanted the numerical values of the type information
6099 		pj_kn (pj, "type_num", (ut64)(ds->analop.type & UT64_MAX));
6100 		pj_kn (pj, "type2_num", (ut64)(ds->analop.type2 & UT64_MAX));
6101 		// handle switch statements
6102 		if (ds->analop.switch_op && r_list_length (ds->analop.switch_op->cases) > 0) {
6103 			// XXX - the java caseop will still be reported in the assembly,
6104 			// this is an artifact to make ensure the disassembly is properly
6105 			// represented during the analysis
6106 			RListIter *iter;
6107 			RAnalCaseOp *caseop;
6108 			pj_k (pj, "switch");
6109 			pj_a (pj);
6110 			r_list_foreach (ds->analop.switch_op->cases, iter, caseop ) {
6111 				pj_o (pj);
6112 				pj_kn (pj, "addr", caseop->addr);
6113 				pj_kN (pj, "value", (st64) caseop->value);
6114 				pj_kn (pj, "jump", caseop->jump);
6115 				pj_end (pj);
6116 			}
6117 			pj_end (pj);
6118 		}
6119 		if (ds->analop.jump != UT64_MAX ) {
6120 			pj_kN (pj, "jump", ds->analop.jump);
6121 			if (ds->analop.fail != UT64_MAX) {
6122 				pj_kn (pj, "fail", ds->analop.fail);
6123 			}
6124 		}
6125 		/* add flags */
6126 		{
6127 			const RList *flags = r_flag_get_list (core->flags, at);
6128 			RFlagItem *flag;
6129 			RListIter *iter;
6130 			if (flags && !r_list_empty (flags)) {
6131 				pj_k (pj, "flags");
6132 				pj_a (pj);
6133 				r_list_foreach (flags, iter, flag) {
6134 					pj_s (pj, flag->name);
6135 				}
6136 				pj_end (pj);
6137 			}
6138 		}
6139 		/* add comments */
6140 		{
6141 			// TODO: slow because we are encoding b64
6142 			const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, at);
6143 			if (comment) {
6144 				char *b64comment = sdb_encode ((const ut8*)comment, -1);
6145 				pj_ks (pj, "comment", b64comment);
6146 				free (b64comment);
6147 			}
6148 		}
6149 		/* add refs */
6150 		{
6151 			RAnalRef *ref;
6152 			RListIter *iter;
6153 			RList *refs = r_anal_refs_get (core->anal, at);
6154 			if (refs && !r_list_empty (refs)) {
6155 				pj_k (pj, "refs");
6156 				pj_a (pj);
6157 				r_list_foreach (refs, iter, ref) {
6158 					pj_o (pj);
6159 					pj_kn (pj, "addr", ref->addr);
6160 					pj_ks (pj, "type", r_anal_xrefs_type_tostring (ref->type));
6161 					pj_end (pj);
6162 				}
6163 				pj_end (pj);
6164 			}
6165 			r_list_free (refs);
6166 		}
6167 		/* add xrefs */
6168 		{
6169 			RAnalRef *ref;
6170 			RListIter *iter;
6171 			RList *xrefs = r_anal_xrefs_get (core->anal, at);
6172 			if (xrefs && !r_list_empty (xrefs)) {
6173 				pj_k (pj, "xrefs");
6174 				pj_a (pj);
6175 				r_list_foreach (xrefs, iter, ref) {
6176 					pj_o (pj);
6177 					pj_kn (pj, "addr", ref->addr);
6178 					pj_ks (pj, "type", r_anal_xrefs_type_tostring (ref->type));
6179 					pj_end (pj);
6180 				}
6181 				pj_end (pj);
6182 			}
6183 			r_list_free (xrefs);
6184 		}
6185 
6186 		pj_end (pj);
6187 		i += ds->oplen + asmop.payload + (ds->asmop.payload % ds->core->rasm->dataalign); // bytes
6188 		k += ds->oplen + asmop.payload + (ds->asmop.payload % ds->core->rasm->dataalign); // delta from addr
6189 		j++; // instructions
6190 		line++;
6191 
6192 		end_nbopcodes = dis_opcodes == 1 && nb_opcodes > 0 && line>=nb_opcodes;
6193 		end_nbbytes = dis_opcodes == 0 && nb_bytes > 0 && i>=nb_bytes;
6194 		result = true;
6195 		if (end_nbopcodes || end_nbbytes) {
6196 			break;
6197 		}
6198 	}
6199 	core->offset = old_offset;
6200 	r_anal_op_fini (&ds->analop);
6201 	ds_free (ds);
6202 	if (!result) {
6203 		pj_o (pj);
6204 		pj_end (pj);
6205 		result = true;
6206 	}
6207 	return result;
6208 }
6209 
r_core_print_disasm_all(RCore * core,ut64 addr,int l,int len,int mode)6210 R_API int r_core_print_disasm_all(RCore *core, ut64 addr, int l, int len, int mode) {
6211 	const bool scr_color = r_config_get_i (core->config, "scr.color");
6212 	int i, ret, count = 0;
6213 	ut8 *buf = core->block;
6214 	char str[128];
6215 	RAsmOp asmop;
6216 	if (l < 1) {
6217 		l = len;
6218 	}
6219 	RDisasmState *ds = ds_init (core);
6220 	if (l > core->blocksize || addr != core->offset) {
6221 		buf = malloc (l + 1);
6222 		r_io_read_at (core->io, addr, buf, l);
6223 	}
6224 	PJ *pj = NULL;
6225 	if (mode == 'j') {
6226 		pj = r_core_pj_new (core);
6227 		if (!pj) {
6228 			ds_free (ds);
6229 			return 0;
6230 		}
6231 		pj_a (pj);
6232 	}
6233 	r_cons_break_push (NULL, NULL);
6234 	for (i = 0; i < l; i++) {
6235 		ds->at = addr + i;
6236 		ds->vat = r_core_pava (core, ds->at);
6237 		r_asm_set_pc (core->rasm, ds->vat);
6238 		if (r_cons_is_breaked ()) {
6239 			break;
6240 		}
6241 		ret = r_asm_disassemble (core->rasm, &asmop, buf + i, l - i);
6242 		if (ret < 1) {
6243 			switch (mode) {
6244 			case 'j':
6245 			case '=':
6246 				break;
6247 			case 'i':
6248 				r_cons_printf ("???\n");
6249 				break;
6250 			default:
6251 				r_cons_printf ("0x%08"PFMT64x" ???\n", ds->vat);
6252 				break;
6253 			}
6254 		} else {
6255 			count ++;
6256 			switch (mode) {
6257 			case 'i':
6258 				r_parse_filter (core->parser, ds->vat, core->flags, ds->hint, r_asm_op_get_asm (&asmop),
6259 						str, sizeof (str), core->print->big_endian);
6260 				if (scr_color) {
6261 					RAnalOp aop;
6262 					RAnalFunction *f = fcnIn (ds, ds->vat, R_ANAL_FCN_TYPE_NULL);
6263 					r_anal_op (core->anal, &aop, addr, buf+i, l-i, R_ANAL_OP_MASK_ALL);
6264 					char *buf_asm = r_print_colorize_opcode (core->print, str,
6265 							core->cons->context->pal.reg, core->cons->context->pal.num, false, f ? f->addr : 0);
6266 					if (buf_asm) {
6267 						r_cons_printf ("%s%s\n", r_print_color_op_type (core->print, aop.type), buf_asm);
6268 						free (buf_asm);
6269 					}
6270 				} else {
6271 					r_cons_println (r_asm_op_get_asm (&asmop));
6272 				}
6273 				break;
6274 			case '=':
6275 				if (i < 28) {
6276 					char *str = r_str_newf ("0x%08"PFMT64x" %60s  %s\n", ds->vat, "", r_asm_op_get_asm (&asmop));
6277 					char *sp = strchr (str, ' ');
6278 					if (sp) {
6279 						char *end = sp + 60 + 1;
6280 						char *src = r_asm_op_get_hex (&asmop);
6281 						char *dst = sp + 1 + (i * 2);
6282 						int len = strlen (src);
6283 						if (dst < end) {
6284 							if (dst + len >= end) {
6285 								len = end - dst;
6286 								dst[len] = '.';
6287 							}
6288 							memcpy (dst, src, len);
6289 						}
6290 						free (src);
6291 					}
6292 					r_cons_strcat (str);
6293 					free (str);
6294 				}
6295 				break;
6296 			case 'j': {
6297 				char *op_hex = r_asm_op_get_hex (&asmop);
6298 				pj_o (pj);
6299 				pj_kn (pj, "addr", addr + i);
6300 				pj_ks (pj, "bytes", op_hex);
6301 				pj_ks (pj, "inst", r_asm_op_get_asm (&asmop));
6302 				pj_end (pj);
6303 				free (op_hex);
6304 				break;
6305 			}
6306 			default: {
6307 				char *op_hex = r_asm_op_get_hex (&asmop);
6308 				r_cons_printf ("0x%08"PFMT64x" %20s  %s\n",
6309 						addr + i, op_hex,
6310 						r_asm_op_get_asm (&asmop));
6311 				free (op_hex);
6312 			}
6313 			}
6314 		}
6315 	}
6316 	r_cons_break_pop ();
6317 	if (buf != core->block) {
6318 		free (buf);
6319 	}
6320 	if (mode == 'j') {
6321 		pj_end (pj);
6322 		r_cons_println (pj_string (pj));
6323 		pj_free (pj);
6324 	}
6325 	ds_free (ds);
6326 	return count;
6327 }
6328 
r_core_disasm_pdi_with_buf(RCore * core,ut64 address,ut8 * buf,ut32 nb_opcodes,ut32 nb_bytes,int fmt)6329 R_API int r_core_disasm_pdi_with_buf(RCore *core, ut64 address, ut8 *buf, ut32 nb_opcodes, ut32 nb_bytes, int fmt) {
6330 	bool show_offset = r_config_get_i (core->config, "asm.offset");
6331 	bool show_bytes = r_config_get_i (core->config, "asm.bytes");
6332 	int decode = r_config_get_i (core->config, "asm.decode");
6333 	int subnames = r_config_get_i (core->config, "asm.sub.names");
6334 	int show_color = r_config_get_i (core->config, "scr.color");
6335 	bool asm_ucase = r_config_get_i (core->config, "asm.ucase");
6336 	bool asm_instr = r_config_get_i (core->config, "asm.instr");
6337 	int esil = r_config_get_i (core->config, "asm.esil");
6338 	int flags = r_config_get_i (core->config, "asm.flags");
6339 	bool asm_immtrim = r_config_get_i (core->config, "asm.imm.trim");
6340 	int i = 0, j, ret, err = 0;
6341 	ut64 old_offset = core->offset;
6342 	RAsmOp asmop;
6343 	const char *color_reg = R_CONS_COLOR_DEF (reg, Color_YELLOW);
6344 	const char *color_num = R_CONS_COLOR_DEF (num, Color_CYAN);
6345 	const size_t addrbytes = buf ? 1 : core->io->addrbytes;
6346 
6347 	if (fmt == 'e') {
6348 		show_bytes = false;
6349 		decode = 1;
6350 	}
6351 
6352 	if (nb_opcodes < 1 && nb_bytes < 1) {
6353 		return 0;
6354 	}
6355 
6356 	if (!buf) {
6357 		r_core_seek (core, address, true);
6358 		buf = core->block;
6359 	}
6360 
6361 	r_cons_break_push (NULL, NULL);
6362 	r_core_seek (core, address, false);
6363 	int midflags = r_config_get_i (core->config, "asm.flags.middle");
6364 	int midbb = r_config_get_i (core->config, "asm.bb.middle");
6365 	bool asmmarks = r_config_get_i (core->config, "asm.marks");
6366 	r_config_set_b (core->config, "asm.marks", false);
6367 	i = 0;
6368 	j = 0;
6369 	RAnalMetaItem *meta = NULL;
6370 toro:
6371 	for (; check_end (nb_opcodes, nb_bytes, addrbytes * i, j); j++) {
6372 		if (r_cons_is_breaked ()) {
6373 			err = 1;
6374 			break;
6375 		}
6376 		ut64 at = core->offset + i;
6377 		if (flags) {
6378 			if (fmt != 'e') { // pie
6379 				RFlagItem *item = r_flag_get_i (core->flags, at);
6380 				if (item) {
6381 					if (show_offset) {
6382 						const int show_offseg = (core->print->flags & R_PRINT_FLAGS_SEGOFF) != 0;
6383 						const int show_offdec = (core->print->flags & R_PRINT_FLAGS_ADDRDEC) != 0;
6384 						unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
6385 						r_print_offset_sg (core->print, at, 0, show_offseg, seggrn, show_offdec, 0, NULL);
6386 					}
6387 					r_cons_printf ("  %s:\n", item->name);
6388 				}
6389 			} // do not show flags in pie
6390 		}
6391 		if (show_offset) {
6392 			const int show_offseg = (core->print->flags & R_PRINT_FLAGS_SEGOFF) != 0;
6393 			const int show_offdec = (core->print->flags & R_PRINT_FLAGS_ADDRDEC) != 0;
6394 			unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
6395 			r_print_offset_sg (core->print, at, 0, show_offseg, seggrn, show_offdec, 0, NULL);
6396 		}
6397 		ut64 meta_start = at;
6398 		ut64 meta_size;
6399 		meta = r_meta_get_at (core->anal, meta_start, R_META_TYPE_ANY, &meta_size);
6400 		if (meta) {
6401 			switch (meta->type) {
6402 			case R_META_TYPE_DATA:
6403 				//r_cons_printf (".data: %s\n", meta->str);
6404 				i += meta_size;
6405 				{
6406 					int idx = i;
6407 					ut64 at = core->offset + i;
6408 					int hexlen = nb_bytes - idx;
6409 					int delta = at - meta_start;
6410 					if (meta_size < hexlen) {
6411 						hexlen = meta_size;
6412 					}
6413 					// int oplen = meta->size - delta;
6414 					core->print->flags &= ~R_PRINT_FLAGS_HEADER;
6415 					// TODO do not pass a copy in parameter buf that is possibly to small for this
6416 					// print operation
6417 					int size = R_MIN (meta_size, nb_bytes - idx);
6418 					RDisasmState ds = {0};
6419 					ds.core = core;
6420 					if (!ds_print_data_type (&ds, buf + i, 0, size)) {
6421 						r_cons_printf ("hex length=%d delta=%d\n", size, delta);
6422 						r_print_hexdump (core->print, at, buf + idx, hexlen - delta, 16, 1, 1);
6423 					} else {
6424 						r_cons_newline ();
6425 					}
6426 					ret = true;
6427 				}
6428 				continue;
6429 			case R_META_TYPE_STRING:
6430 			case R_META_TYPE_FORMAT:
6431 			case R_META_TYPE_MAGIC:
6432 				//r_cons_printf (".magic : %s\n", meta->str);
6433 				i += meta_size;
6434 				continue;
6435 			case R_META_TYPE_RUN:
6436 				/* TODO */
6437 				break;
6438 			default:
6439 				break;
6440 			}
6441 		}
6442 		r_asm_set_pc (core->rasm, core->offset + i);
6443 		ret = r_asm_disassemble (core->rasm, &asmop, buf + addrbytes * i,
6444 			nb_bytes - addrbytes * i);
6445 		if (midflags || midbb) {
6446 			RDisasmState ds = {
6447 				.oplen = ret,
6448 				.at = core->offset + i,
6449 				.midflags = midflags
6450 			};
6451 			int skip_bytes_flag = 0, skip_bytes_bb = 0;
6452 			if (midflags) {
6453 				skip_bytes_flag = handleMidFlags (core, &ds, true);
6454 			}
6455 			if (midbb) {
6456 				skip_bytes_bb = handleMidBB (core, &ds);
6457 			}
6458 			if (skip_bytes_flag && midflags > R_MIDFLAGS_SHOW) {
6459 				asmop.size = ret = skip_bytes_flag;
6460 			}
6461 			if (skip_bytes_bb && skip_bytes_bb < ret) {
6462 				asmop.size = ret = skip_bytes_bb;
6463 			}
6464 		}
6465 		if (fmt == 'C') {
6466 			const char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, core->offset + i);
6467 			if (comment) {
6468 				r_cons_printf ("0x%08" PFMT64x " %s\n", core->offset + i, comment);
6469 			}
6470 			i += ret;
6471 			continue;
6472 		}
6473 		// r_cons_printf ("0x%08"PFMT64x"  ", core->offset+i);
6474 		if (ret < 1) {
6475 			err = 1;
6476 			ret = asmop.size;
6477 			if (ret < 1) {
6478 				ret = 1;
6479 			}
6480 			if (show_bytes) {
6481 				r_cons_printf ("%18s%02x  ", "", buf[i]);
6482 			}
6483 			r_cons_println ("invalid"); // ???");
6484 		} else {
6485 			if (show_bytes) {
6486 				char *op_hex = r_asm_op_get_hex (&asmop);
6487 				r_cons_printf ("%20s  ", op_hex);
6488 				free (op_hex);
6489 			}
6490 			ret = asmop.size;
6491 			if (!asm_instr) {
6492 				r_cons_newline ();
6493 			} else if (!asm_immtrim && (decode || esil)) {
6494 				RAnalOp analop = {
6495 					0
6496 				};
6497 				char *tmpopstr, *opstr = NULL;
6498 				r_anal_op (core->anal, &analop, core->offset + i,
6499 					buf + addrbytes * i, nb_bytes - addrbytes * i, R_ANAL_OP_MASK_ALL);
6500 				tmpopstr = r_anal_op_to_string (core->anal, &analop);
6501 				if (fmt == 'e') { // pie
6502 					char *esil = (R_STRBUF_SAFEGET (&analop.esil));
6503 					r_cons_println (esil);
6504 				} else {
6505 					if (decode) {
6506 						opstr = tmpopstr? tmpopstr: r_asm_op_get_asm (&(asmop));
6507 					} else if (esil) {
6508 						opstr = (R_STRBUF_SAFEGET (&analop.esil));
6509 					}
6510 					if (asm_immtrim) {
6511 						char *res = r_parse_immtrim (opstr);
6512 						if (res) {
6513 							opstr = res;
6514 						}
6515 					}
6516 					r_cons_println (opstr);
6517 				}
6518 				r_anal_op_fini (&analop);
6519 			} else {
6520 				char opstr[128] = {
6521 					0
6522 				};
6523 				char *asm_str = r_asm_op_get_asm (&asmop);
6524 				if (asm_ucase) {
6525 					r_str_case (asm_str, 1);
6526 				}
6527 				if (asm_immtrim) {
6528 					char *res = r_parse_immtrim (asm_str);
6529 					if (res) {
6530 						asm_str = res;
6531 					}
6532 				}
6533 				if (subnames) {
6534 					RAnalHint *hint = r_anal_hint_get (core->anal, at);
6535 					r_parse_filter (core->parser, at, core->flags, hint,
6536 						asm_str, opstr, sizeof (opstr) - 1, core->print->big_endian);
6537 					r_anal_hint_free (hint);
6538 					asm_str = (char *)&opstr;
6539 				}
6540 				if (show_color) {
6541 					RAnalOp aop = {
6542 						0
6543 					};
6544 					RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset + i, R_ANAL_FCN_TYPE_NULL);
6545 					r_anal_op (core->anal, &aop, core->offset + i,
6546 						buf + addrbytes * i, nb_bytes - addrbytes * i, R_ANAL_OP_MASK_BASIC);
6547 					asm_str = r_print_colorize_opcode (core->print, asm_str, color_reg, color_num, false, f ? f->addr : 0);
6548 					r_cons_printf ("%s%s"Color_RESET "\n",
6549 						r_print_color_op_type (core->print, aop.type),
6550 						asm_str);
6551 					free (asm_str);
6552 					r_anal_op_fini (&aop);
6553 				} else {
6554 					r_cons_println (asm_str);
6555 				}
6556 			}
6557 		}
6558 		i += ret;
6559 	}
6560 	if (buf == core->block && nb_opcodes > 0 && j < nb_opcodes) {
6561 		r_core_seek (core, core->offset + i, true);
6562 		i = 0;
6563 		goto toro;
6564 	}
6565 	r_config_set_b (core->config, "asm.marks", asmmarks);
6566 	r_cons_break_pop ();
6567 	r_core_seek (core, old_offset, true);
6568 	return err;
6569 }
6570 
r_core_disasm_pdi(RCore * core,int nb_opcodes,int nb_bytes,int fmt)6571 R_API int r_core_disasm_pdi(RCore *core, int nb_opcodes, int nb_bytes, int fmt) {
6572 	const ut64 ocore_offset = core->offset;
6573 	int ret = -1;
6574 	if (handle_backwards_disasm(core, &nb_opcodes, &nb_bytes)) {
6575 		ret = r_core_disasm_pdi_with_buf (core, core->offset, NULL, nb_opcodes, nb_bytes, fmt);
6576 	}
6577 	r_core_seek (core, ocore_offset, true);
6578 	return ret;
6579 }
6580 
read_ahead(RIO * io,ut8 ** buf,size_t * buf_sz,ut64 address,size_t offset_into_buf,size_t bytes_to_read)6581 static bool read_ahead(RIO *io, ut8 **buf, size_t *buf_sz, ut64 address, size_t offset_into_buf, size_t bytes_to_read) {
6582 	if (offset_into_buf + bytes_to_read > *buf_sz) {
6583 		const size_t new_sz = *buf_sz * 2;
6584 		ut8 *tmp = realloc (*buf, new_sz);
6585 		if (!tmp) {
6586 			return false;
6587 		}
6588 		*buf_sz = new_sz;
6589 		*buf = tmp;
6590 	}
6591 	return r_io_read_at_mapped (io, address, *buf + offset_into_buf, bytes_to_read);
6592 }
6593 
r_core_disasm_pde(RCore * core,int nb_opcodes,int mode)6594 R_API int r_core_disasm_pde(RCore *core, int nb_opcodes, int mode) {
6595 	if (nb_opcodes < 1) {
6596 		return 0;
6597 	}
6598 	RReg *reg = core->anal->reg;
6599 	RRegItem *pc = r_reg_get (reg, "PC", R_REG_TYPE_ALL);
6600 	if (!pc) {
6601 		return -1;
6602 	}
6603 	PJ *pj = NULL;
6604 	if (mode == R_MODE_JSON) {
6605 		pj = r_core_pj_new (core);
6606 		if (!pj) {
6607 			return -1;
6608 		}
6609 		pj_a (pj);
6610 	}
6611 	if (!core->anal->esil) {
6612 		r_core_cmd0 (core, "aei");
6613 		if (!r_config_get_i (core->config, "cfg.debug")) {
6614 			r_core_cmd0 (core, "aeim");
6615 		}
6616 	}
6617 	RAnalEsil *esil = core->anal->esil;
6618 	RPVector ocache = core->io->cache;
6619 	RCache *ocacheb = core->io->buffer;
6620 	const int ocached = core->io->cached;
6621 	if (ocache.v.a) {
6622 		if (ocacheb && ocacheb->len) {
6623 			RCache *c = r_cache_new ();
6624 			r_cache_set (c, ocacheb->base, ocacheb->buf, ocacheb->len);
6625 			core->io->buffer = c;
6626 		}
6627 		RPVector *vec = (RPVector *)r_vector_clone ((RVector *)&ocache);
6628 		vec->v.free = NULL;
6629 		core->io->cache = *vec;
6630 		free (vec);
6631 	} else {
6632 		r_io_cache_init (core->io);
6633 	}
6634 	r_reg_arena_push (reg);
6635 	RConfigHold *chold = r_config_hold_new (core->config);
6636 	r_config_hold (chold, "io.cache", "asm.lines", NULL);
6637 	r_config_set_b (core->config, "io.cache", true);
6638 	r_config_set_b (core->config, "asm.lines", false);
6639 	const char *strip = r_config_get (core->config, "asm.strip");
6640 	const int max_op_size = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MAX_OP_SIZE);
6641 	int min_op_size = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
6642 	min_op_size = min_op_size > 0 ? min_op_size : 1;
6643 	const ut64 read_len = max_op_size > 0 ? max_op_size : 32;
6644 	size_t buf_sz = 0x100, block_sz = 0, block_instr = 0;
6645 	ut64 block_start = r_reg_get_value (reg, pc);
6646 	ut8 *buf = malloc (buf_sz);
6647 	size_t i;
6648 	for (i = 0; i < nb_opcodes; i++) {
6649 		const ut64 op_addr = r_reg_get_value (reg, pc);
6650 		if (!read_ahead (core->io, &buf, &buf_sz, op_addr, block_sz, read_len)) {
6651 			break;
6652 		}
6653 		RAnalOp op;
6654 		int ret = r_anal_op (core->anal, &op, op_addr, buf + block_sz, read_len, R_ANAL_OP_MASK_ESIL);
6655 		const bool invalid_instr = ret < 1 || op.size < 1 || op.type == R_ANAL_OP_TYPE_ILL;
6656 		bool end_of_block = false;
6657 		switch (op.type & R_ANAL_OP_TYPE_MASK & ~R_ANAL_OP_HINT_MASK) {
6658 		case R_ANAL_OP_TYPE_JMP:
6659 		case R_ANAL_OP_TYPE_UJMP:
6660 		case R_ANAL_OP_TYPE_CALL:
6661 		case R_ANAL_OP_TYPE_UCALL:
6662 		case R_ANAL_OP_TYPE_RET:
6663 			end_of_block = true;
6664 			break;
6665 		}
6666 		if (R_STR_ISNOTEMPTY (strip) && strstr (strip, r_anal_optype_to_string (op.type))) {
6667 			i--;
6668 		} else {
6669 			if (invalid_instr) {
6670 				block_sz += min_op_size;
6671 			} else {
6672 				block_sz += op.size;
6673 			}
6674 			if (invalid_instr || (i + 1 >= nb_opcodes)) {
6675 				end_of_block = true;
6676 			}
6677 			block_instr++;
6678 		}
6679 		if (end_of_block) {
6680 			if (op.delay) {
6681 				const ut64 ops_to_read = R_MIN (op.delay, nb_opcodes - (i + 1));
6682 				const ut64 bytes_to_read = ops_to_read * read_len;
6683 				if (!read_ahead (core->io, &buf, &buf_sz, op_addr + op.size, block_sz, bytes_to_read)) {
6684 					break;
6685 				}
6686 				block_instr += ops_to_read;
6687 				block_sz += bytes_to_read;
6688 				i += ops_to_read;
6689 			}
6690 			if (block_instr) {
6691 				switch (mode) {
6692 				case R_MODE_JSON:
6693 					r_core_print_disasm_json (core, block_start, buf, block_sz, block_instr, pj);
6694 					break;
6695 				case R_MODE_SIMPLE:
6696 					r_core_disasm_pdi_with_buf (core, block_start, buf, block_instr, block_sz, 0);
6697 					break;
6698 				case R_MODE_SIMPLEST:
6699 					r_core_print_disasm_instructions_with_buf (core, block_start, buf, block_sz, block_instr);
6700 					break;
6701 				default:
6702 					r_core_print_disasm (core->print, core, block_start, buf, block_sz, block_instr, 0, 0, false, NULL, NULL);
6703 					break;
6704 				}
6705 			}
6706 			block_sz = 0;
6707 			block_instr = 0;
6708 		}
6709 		if (invalid_instr) {
6710 			break;
6711 		}
6712 		r_anal_esil_set_pc (core->anal->esil, op_addr);
6713 		r_reg_set_value (reg, pc, op_addr + op.size);
6714 		const char *e = r_strbuf_get (&op.esil);
6715 		if (R_STR_ISNOTEMPTY (e)) {
6716 			r_anal_esil_parse (esil, e);
6717 		}
6718 		r_anal_op_fini (&op);
6719 
6720 		if (end_of_block) {
6721 			block_start = r_reg_get_value (reg, pc);
6722 			r_core_seek_arch_bits (core, block_start);
6723 		}
6724 	}
6725 	if (mode == R_MODE_JSON) {
6726 		pj_end (pj);
6727 		r_cons_print (pj_string (pj));
6728 		pj_free (pj);
6729 	}
6730 	free (buf);
6731 	r_reg_arena_pop (reg);
6732 	int len = r_pvector_len (&ocache);
6733 	if (r_pvector_len (&core->io->cache) > len) {
6734 		// TODO: Implement push/pop for IO.cache
6735 		while (len > 0) {
6736 			(void)r_pvector_pop_front (&core->io->cache);
6737 			len--;
6738 		}
6739 		core->io->cache.v.free = ocache.v.free;
6740 	}
6741 	r_io_cache_fini (core->io);
6742 	core->io->cache = ocache;
6743 	r_skyline_clear (&core->io->cache_skyline);
6744 	void **it;
6745 	r_pvector_foreach (&ocache, it) {
6746 		RIOCache *c = (RIOCache *)*it;
6747 		r_skyline_add (&core->io->cache_skyline, c->itv, c);
6748 	}
6749 	core->io->buffer = ocacheb;
6750 	core->io->cached = ocached;
6751 	r_config_hold_restore (chold);
6752 	r_config_hold_free (chold);
6753 	return i;
6754 }
6755