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