2018-01-27 00:25:12 +01:00
|
|
|
/* radare - LGPL - Copyright 2009-2018 - nibble, pancake, dso */
|
2012-08-23 12:46:55 +02:00
|
|
|
|
2011-06-04 03:14:04 +02:00
|
|
|
#include "r_core.h"
|
2013-07-19 00:20:23 +04:00
|
|
|
#include "r_cons.h"
|
|
|
|
|
2013-11-06 02:10:53 +01:00
|
|
|
#define HASRETRY 1
|
2014-06-25 02:30:42 +02:00
|
|
|
#define HAVE_LOCALS 1
|
2015-10-29 23:37:51 +01:00
|
|
|
#define DEFAULT_NARGS 4
|
2013-10-27 02:20:36 +01:00
|
|
|
|
2015-12-17 20:18:50 +01:00
|
|
|
#define R_MIDFLAGS_SHOW 1
|
|
|
|
#define R_MIDFLAGS_REALIGN 2
|
2016-11-02 12:10:50 +01:00
|
|
|
#define R_MIDFLAGS_SYMALIGN 3
|
2015-12-17 20:18:50 +01:00
|
|
|
|
2015-11-02 12:38:08 +01:00
|
|
|
#define COLOR(ds, field) (ds->show_color ? ds->field : "")
|
|
|
|
#define COLOR_CONST(ds, color) (ds->show_color ? Color_ ## color : "")
|
|
|
|
#define COLOR_RESET(ds) COLOR_CONST(ds, RESET)
|
|
|
|
|
2017-12-03 18:22:47 +01:00
|
|
|
// ugly globals but meh
|
|
|
|
static ut64 emustack_min = 0LL;
|
|
|
|
static ut64 emustack_max = 0LL;
|
|
|
|
|
2013-09-11 23:41:40 +02:00
|
|
|
static const char* r_vline_a[] = {
|
2016-10-24 11:54:03 +02:00
|
|
|
"|", // LINE_VERT
|
2013-07-19 00:20:23 +04:00
|
|
|
"|-", // LINE_CROSS
|
2016-10-24 11:54:03 +02:00
|
|
|
"-", // LINE_HORIZ
|
2017-10-31 02:14:00 +01:00
|
|
|
":", // LINE_UP
|
2016-10-24 11:54:03 +02:00
|
|
|
",", // LUP_CORNER
|
2013-07-19 00:20:23 +04:00
|
|
|
"\\", // RDWN_CORNER
|
2016-10-24 11:54:03 +02:00
|
|
|
"/", // RUP_CORNER
|
|
|
|
"`", // LDWN_CORNER
|
2013-07-19 00:20:23 +04:00
|
|
|
"->", // ARROW_RIGHT
|
|
|
|
"=<", // ARROW_LEFT
|
|
|
|
};
|
|
|
|
|
2013-09-11 23:41:40 +02:00
|
|
|
static const char* r_vline_u[] = {
|
2013-07-19 00:20:23 +04:00
|
|
|
"│", // LINE_VERT
|
|
|
|
"├", // LINE_CROSS
|
|
|
|
"─", // LINE_HORIZ
|
2017-10-31 02:14:00 +01:00
|
|
|
"⁝", // LINE_UP
|
|
|
|
// "↑", // LINE_UP
|
2017-05-08 20:21:06 +02:00
|
|
|
//"┌", // LUP_CORNER
|
|
|
|
"┘", // LUP_CORNER
|
2016-10-21 01:24:40 +02:00
|
|
|
"└", // RDWN_CORNER
|
|
|
|
"┌", // RUP_CORNER
|
|
|
|
"┐", // LDWN_CORNER
|
|
|
|
">", // ARROW_RIGHT
|
|
|
|
"<", // ARROW_LEFT
|
2013-07-19 00:20:23 +04:00
|
|
|
};
|
2011-06-04 03:14:04 +02:00
|
|
|
|
2017-10-08 16:39:27 +05:30
|
|
|
static const char* r_vline_uc[] = {
|
|
|
|
"│", // LINE_VERT
|
|
|
|
"├", // LINE_CROSS
|
|
|
|
"─", // LINE_HORIZ
|
|
|
|
"↑", // LINE_UP
|
|
|
|
//"┌", // LUP_CORNER
|
|
|
|
"╯", // LUP_CORNER
|
|
|
|
"╰", // RDWN_CORNER
|
|
|
|
"╭", // RUP_CORNER
|
|
|
|
"╮", // LDWN_CORNER
|
|
|
|
">", // ARROW_RIGHT
|
|
|
|
"<", // ARROW_LEFT
|
|
|
|
};
|
|
|
|
|
2018-02-06 15:30:10 +01:00
|
|
|
|
|
|
|
#define DS_PRE_NONE 0
|
|
|
|
#define DS_PRE_EMPTY 1
|
|
|
|
#define DS_PRE_FCN_HEAD 2
|
|
|
|
#define DS_PRE_FCN_MIDDLE 3
|
|
|
|
#define DS_PRE_FCN_TAIL 4
|
|
|
|
|
2014-01-20 01:42:16 +01:00
|
|
|
// TODO: what about using bit shifting and enum for keys? see libr/util/bitmap.c
|
|
|
|
// the problem of this is that the fields will be more opaque to bindings, but we will earn some bits
|
2017-11-23 18:35:13 +01:00
|
|
|
typedef struct {
|
2016-03-04 00:33:24 +01:00
|
|
|
RCore *core;
|
2015-02-08 00:30:25 +01:00
|
|
|
char str[1024], strsub[1024];
|
2017-11-30 00:14:08 +01:00
|
|
|
bool immtrim;
|
2017-11-04 16:13:10 +01:00
|
|
|
bool immstr;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool use_esil;
|
|
|
|
bool show_color;
|
2016-08-25 20:27:52 +02:00
|
|
|
bool show_color_bytes;
|
2014-01-16 11:04:42 -06:00
|
|
|
int colorop;
|
|
|
|
int acase;
|
2016-11-04 03:56:42 +01:00
|
|
|
bool capitalize;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_flgoff;
|
2017-04-28 05:50:04 +02:00
|
|
|
bool hasMidflag;
|
2014-01-16 11:04:42 -06:00
|
|
|
int atabs;
|
2015-07-15 15:14:51 +02:00
|
|
|
int atabsonce;
|
2015-07-15 17:30:34 +02:00
|
|
|
int atabsoff;
|
2014-01-16 11:04:42 -06:00
|
|
|
int decode;
|
2017-03-20 23:43:34 +01:00
|
|
|
bool pseudo;
|
2014-01-16 11:04:42 -06:00
|
|
|
int filter;
|
2014-12-10 23:54:35 +01:00
|
|
|
int interactive;
|
2018-01-16 01:50:42 -08:00
|
|
|
bool jmpsub;
|
2017-12-22 13:19:02 +01:00
|
|
|
bool varsub;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_lines;
|
|
|
|
bool show_lines_ret;
|
|
|
|
bool show_lines_call;
|
2014-01-16 11:04:42 -06:00
|
|
|
int linesright;
|
2014-11-02 02:19:31 +01:00
|
|
|
int tracespace;
|
2014-11-02 03:06:52 +01:00
|
|
|
int cyclespace;
|
2015-06-02 01:04:10 +02:00
|
|
|
int cmtfold;
|
2014-08-05 05:37:48 +02:00
|
|
|
int show_indent;
|
2016-05-31 23:37:17 +02:00
|
|
|
bool show_dwarf;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_size;
|
|
|
|
bool show_trace;
|
2017-11-14 23:36:04 +09:00
|
|
|
bool highlight;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_family;
|
|
|
|
bool asm_describe;
|
2014-01-16 11:04:42 -06:00
|
|
|
int linesout;
|
|
|
|
int adistrick;
|
2014-09-24 03:01:18 +02:00
|
|
|
int asm_demangle;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_offset;
|
2016-11-01 23:30:36 +01:00
|
|
|
bool show_offdec; // dupe for r_print->flags
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_bbline;
|
|
|
|
bool show_emu;
|
2018-01-30 00:41:30 +01:00
|
|
|
bool pre_emu;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_emu_str;
|
2018-02-10 18:10:22 +08:00
|
|
|
bool show_emu_stroff;
|
2018-04-05 15:54:44 +08:00
|
|
|
bool show_emu_strinv;
|
2018-04-07 21:35:12 +08:00
|
|
|
bool show_emu_strflag;
|
2017-12-03 18:22:47 +01:00
|
|
|
bool show_emu_stack;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_emu_write;
|
|
|
|
bool show_section;
|
2016-04-08 02:56:42 +02:00
|
|
|
int show_section_col;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_symbols;
|
2016-04-08 02:56:42 +02:00
|
|
|
int show_symbols_col;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_offseg;
|
|
|
|
bool show_flags;
|
2017-05-05 14:53:19 +02:00
|
|
|
bool bblined;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_bytes;
|
|
|
|
bool show_reloff;
|
2016-08-25 20:17:55 +02:00
|
|
|
bool show_reloff_flags;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_comments;
|
|
|
|
bool show_jmphints;
|
2016-06-20 09:46:03 +02:00
|
|
|
bool show_leahints;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_slow;
|
2014-11-13 03:36:48 +01:00
|
|
|
int cmtcol;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_fcnlines;
|
|
|
|
bool show_calls;
|
|
|
|
bool show_cmtflgrefs;
|
|
|
|
bool show_cycles;
|
|
|
|
bool show_stackptr;
|
2017-12-03 18:22:47 +01:00
|
|
|
int stackFd;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_xrefs;
|
|
|
|
bool show_cmtrefs;
|
2017-05-29 08:44:45 +08:00
|
|
|
const char *show_cmtoff;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_functions;
|
|
|
|
bool show_fcncalls;
|
|
|
|
bool show_hints;
|
|
|
|
bool show_marks;
|
2017-07-24 07:39:58 +08:00
|
|
|
bool show_asciidot;
|
2017-07-24 23:17:24 +08:00
|
|
|
RStrEnc strenc;
|
2014-01-16 11:04:42 -06:00
|
|
|
int cursor;
|
|
|
|
int show_comment_right_default;
|
|
|
|
int flagspace_ports;
|
2014-10-16 01:51:48 +02:00
|
|
|
int show_flag_in_bytes;
|
2014-01-16 11:04:42 -06:00
|
|
|
int lbytes;
|
|
|
|
int show_comment_right;
|
2018-02-06 15:30:10 +01:00
|
|
|
int pre;
|
2014-01-16 11:04:42 -06:00
|
|
|
char *ocomment;
|
|
|
|
int linesopts;
|
|
|
|
int lastfail;
|
|
|
|
int ocols;
|
|
|
|
int lcols;
|
|
|
|
int nb, nbytes;
|
|
|
|
int show_utf8;
|
|
|
|
int lines;
|
|
|
|
int oplen;
|
2016-08-25 18:54:07 +02:00
|
|
|
bool show_varxs;
|
|
|
|
bool show_vars;
|
2018-02-06 13:13:55 +01:00
|
|
|
int show_varsum;
|
2015-05-06 00:56:31 +02:00
|
|
|
int midflags;
|
2017-05-11 12:47:48 +02:00
|
|
|
bool midcursor;
|
2017-05-26 08:56:47 +08:00
|
|
|
bool show_noisy_comments;
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *pal_comment;
|
|
|
|
const char *color_comment;
|
2017-11-09 22:01:48 +01:00
|
|
|
const char *color_usrcmt;
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *color_fname;
|
|
|
|
const char *color_floc;
|
|
|
|
const char *color_fline;
|
|
|
|
const char *color_flow;
|
2017-01-16 00:41:31 +01:00
|
|
|
const char *color_flow2;
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *color_flag;
|
|
|
|
const char *color_label;
|
|
|
|
const char *color_other;
|
|
|
|
const char *color_nop;
|
|
|
|
const char *color_bin;
|
|
|
|
const char *color_math;
|
2017-12-10 11:06:03 +01:00
|
|
|
const char *color_btext;
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *color_jmp;
|
|
|
|
const char *color_cjmp;
|
|
|
|
const char *color_call;
|
|
|
|
const char *color_cmp;
|
|
|
|
const char *color_swi;
|
|
|
|
const char *color_trap;
|
|
|
|
const char *color_ret;
|
|
|
|
const char *color_push;
|
|
|
|
const char *color_pop;
|
|
|
|
const char *color_reg;
|
|
|
|
const char *color_num;
|
2014-05-16 04:07:03 +02:00
|
|
|
const char *color_mov;
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *color_invalid;
|
2014-12-06 12:25:02 +01:00
|
|
|
const char *color_gui_cflow;
|
|
|
|
const char *color_gui_dataoffset;
|
|
|
|
const char *color_gui_background;
|
|
|
|
const char *color_gui_alt_background;
|
|
|
|
const char *color_gui_border;
|
2014-01-16 11:04:42 -06:00
|
|
|
|
2015-01-12 10:45:41 +01:00
|
|
|
RFlagItem *lastflag;
|
2014-01-16 11:04:42 -06:00
|
|
|
RAnalHint *hint;
|
2016-05-30 12:35:39 +02:00
|
|
|
RPrint *print;
|
2014-01-16 11:04:42 -06:00
|
|
|
|
2016-06-08 21:16:00 +02:00
|
|
|
ut64 esil_old_pc;
|
|
|
|
ut8* esil_regstate;
|
2016-06-08 23:33:31 +02:00
|
|
|
bool esil_likely;
|
2016-06-08 21:16:00 +02:00
|
|
|
|
2014-01-16 11:04:42 -06:00
|
|
|
int l;
|
|
|
|
int middle;
|
2014-08-05 05:37:48 +02:00
|
|
|
int indent_level;
|
2015-08-12 10:40:24 +02:00
|
|
|
int indent_space;
|
2014-01-16 11:04:42 -06:00
|
|
|
char *line;
|
|
|
|
char *refline, *refline2;
|
|
|
|
char *comment;
|
|
|
|
char *opstr;
|
|
|
|
char *osl, *sl;
|
|
|
|
int stackptr, ostackptr;
|
|
|
|
int index;
|
2016-11-04 03:15:17 +01:00
|
|
|
ut64 at, vat, addr, dest;
|
2014-01-16 11:04:42 -06:00
|
|
|
int tries, cbytes, idx;
|
2017-10-09 14:40:35 +02:00
|
|
|
char chref;
|
2017-01-16 15:07:11 +01:00
|
|
|
bool retry;
|
|
|
|
bool mi_found;
|
2014-01-16 11:04:42 -06:00
|
|
|
RAsmOp asmop;
|
|
|
|
RAnalOp analop;
|
2016-02-23 18:30:32 +01:00
|
|
|
RAnalFunction *fcn;
|
2014-01-16 11:04:42 -06:00
|
|
|
const ut8 *buf;
|
|
|
|
int len;
|
2014-09-23 10:15:19 +02:00
|
|
|
int maxrefs;
|
2016-01-10 22:30:10 +01:00
|
|
|
char *prev_ins;
|
|
|
|
bool prev_ins_eq;
|
2016-01-11 22:28:22 +01:00
|
|
|
int prev_ins_count;
|
2016-01-10 22:30:10 +01:00
|
|
|
bool show_nodup;
|
2016-08-16 12:19:02 +02:00
|
|
|
bool has_description;
|
2016-03-04 00:33:24 +01:00
|
|
|
// caches
|
|
|
|
char *_tabsbuf;
|
|
|
|
int _tabsoff;
|
2016-11-23 10:30:44 +01:00
|
|
|
bool dwarfFile;
|
|
|
|
bool dwarfAbspath;
|
2017-05-08 20:21:06 +02:00
|
|
|
bool showpayloads;
|
2017-05-23 23:54:11 +02:00
|
|
|
bool showrelocs;
|
2017-11-24 23:19:26 +01:00
|
|
|
int cmtcount;
|
2017-11-25 00:28:21 +01:00
|
|
|
int shortcut_pos;
|
2017-11-28 10:52:04 +01:00
|
|
|
bool asm_anal;
|
2018-02-17 23:02:53 +08:00
|
|
|
ut64 printed_str_addr;
|
2018-02-22 23:24:37 +08:00
|
|
|
ut64 printed_flag_addr;
|
2018-02-20 10:51:44 +01:00
|
|
|
ut64 min_ref_addr;
|
2017-12-11 15:07:44 +01:00
|
|
|
|
|
|
|
bool use_json;
|
|
|
|
bool first_line;
|
2018-01-27 00:25:12 +01:00
|
|
|
const char *strip;
|
2014-01-16 11:04:42 -06:00
|
|
|
} RDisasmState;
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_setup_print_pre(RDisasmState *ds, bool tail, bool middle);
|
|
|
|
static void ds_setup_pre(RDisasmState *ds, bool tail, bool middle);
|
|
|
|
static void ds_print_pre(RDisasmState *ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
static void ds_beginline(RDisasmState *ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
static void ds_begin_json_line(RDisasmState *ds);
|
|
|
|
static void ds_newline(RDisasmState *ds);
|
2017-01-18 22:02:30 +01:00
|
|
|
static void ds_print_esil_anal(RDisasmState *ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_reflines_init(RDisasmState *ds);
|
|
|
|
static void ds_align_comment(RDisasmState *ds);
|
|
|
|
static RDisasmState * ds_init(RCore * core);
|
2018-02-03 19:21:54 +01:00
|
|
|
static void ds_build_op_str(RDisasmState *ds, bool print_color);
|
2018-02-06 15:30:10 +01:00
|
|
|
static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines);
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_show_xrefs(RDisasmState *ds);
|
|
|
|
static void ds_atabs_option(RDisasmState *ds);
|
|
|
|
static void ds_show_functions(RDisasmState *ds);
|
|
|
|
static void ds_show_comments_right(RDisasmState *ds);
|
|
|
|
static void ds_show_flags(RDisasmState *ds);
|
|
|
|
static void ds_update_ref_lines(RDisasmState *ds);
|
|
|
|
static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len);
|
|
|
|
static void ds_control_flow_comments(RDisasmState *ds);
|
|
|
|
static void ds_print_lines_right(RDisasmState *ds);
|
|
|
|
static void ds_print_lines_left(RDisasmState *ds);
|
|
|
|
static void ds_print_cycles(RDisasmState *ds);
|
|
|
|
static void ds_print_family(RDisasmState *ds);
|
|
|
|
static void ds_print_stackptr(RDisasmState *ds);
|
|
|
|
static void ds_print_offset(RDisasmState *ds);
|
|
|
|
static void ds_print_op_size(RDisasmState *ds);
|
|
|
|
static void ds_print_trace(RDisasmState *ds);
|
|
|
|
static void ds_adistrick_comments(RDisasmState *ds);
|
|
|
|
static int ds_print_meta_infos(RDisasmState *ds, ut8* buf, int len, int idx );
|
|
|
|
static void ds_print_opstr(RDisasmState *ds);
|
|
|
|
static void ds_print_color_reset(RDisasmState *ds);
|
|
|
|
static int ds_print_middle(RDisasmState *ds, int ret);
|
|
|
|
static bool ds_print_labels(RDisasmState *ds, RAnalFunction *f);
|
|
|
|
static void ds_print_import_name(RDisasmState *ds);
|
2016-07-03 14:12:30 +03:00
|
|
|
static void ds_print_sysregs(RDisasmState *ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_fcn_name(RDisasmState *ds);
|
|
|
|
static void ds_print_as_string(RDisasmState *ds);
|
2017-11-25 00:28:21 +01:00
|
|
|
static void ds_print_core_vmode(RDisasmState *ds, int pos);
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_dwarf(RDisasmState *ds);
|
2017-05-08 20:21:06 +02:00
|
|
|
static void ds_print_asmop_payload(RDisasmState *ds, const ut8 *buf);
|
2017-12-11 15:07:44 +01:00
|
|
|
static char *ds_esc_str(RDisasmState *ds, const char *str, int len, const char **prefix_out);
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_comments_right(RDisasmState *ds);
|
|
|
|
static void ds_print_ptr(RDisasmState *ds, int len, int idx);
|
2018-01-15 01:09:22 +08:00
|
|
|
static void ds_print_str(RDisasmState *ds, const char *str, int len, ut64 refaddr);
|
2018-01-16 01:50:42 -08:00
|
|
|
static char *ds_sub_jumps(RDisasmState *ds, char *str);
|
2014-01-20 01:42:16 +01:00
|
|
|
|
2016-11-04 03:15:17 +01:00
|
|
|
static ut64 p2v(RDisasmState *ds, ut64 addr) {
|
2017-08-22 07:42:16 +00:00
|
|
|
#if 0
|
2016-11-04 03:15:17 +01:00
|
|
|
if (ds->core->io->pava) {
|
|
|
|
ut64 at = r_io_section_get_vaddr (ds->core->io, addr);
|
|
|
|
if (at == UT64_MAX || (!at && ds->at)) {
|
|
|
|
addr = ds->at;
|
|
|
|
} else {
|
|
|
|
addr = at + addr;
|
|
|
|
}
|
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
#endif
|
2016-11-04 03:15:17 +01:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
2017-11-23 22:46:57 +01:00
|
|
|
static RAnalFunction *fcnIn(RDisasmState *ds, ut64 at, int type) {
|
2017-11-23 18:35:13 +01:00
|
|
|
if (ds->fcn && r_tinyrange_in (&ds->fcn->bbr, at)) {
|
|
|
|
return ds->fcn;
|
|
|
|
}
|
2017-11-23 22:46:57 +01:00
|
|
|
return r_anal_get_fcn_in (ds->core->anal, at, type);
|
2017-11-23 18:35:13 +01:00
|
|
|
}
|
|
|
|
|
2016-04-27 22:17:19 +02:00
|
|
|
static int cmpaddr(const void *_a, const void *_b) {
|
2015-06-16 00:16:29 +02:00
|
|
|
const RAnalBlock *a = _a, *b = _b;
|
2014-01-22 22:55:48 -06:00
|
|
|
return (a->addr > b->addr);
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
|
2016-03-15 11:47:13 +01:00
|
|
|
static void get_bits_comment(RCore *core, RAnalFunction *f, char *cmt, int cmt_size) {
|
2016-06-10 10:57:43 +02:00
|
|
|
if (core && f && cmt && cmt_size > 0 && f->bits && f->bits != core->assembler->bits) {
|
2016-06-02 03:19:31 +02:00
|
|
|
const char *asm_arch = r_config_get (core->config, "asm.arch");
|
|
|
|
if (asm_arch && *asm_arch && strstr (asm_arch, "arm")) {
|
2016-03-15 11:47:13 +01:00
|
|
|
switch (f->bits) {
|
|
|
|
case 16: strcpy (cmt, " (thumb)"); break;
|
|
|
|
case 32: strcpy (cmt, " (arm)"); break;
|
|
|
|
case 64: strcpy (cmt, " (aarch64)"); break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf (cmt, cmt_size, " (%d bits)", f->bits);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (cmt) {
|
|
|
|
cmt[0] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static const char * get_section_name(RCore *core, ut64 addr) {
|
2015-07-05 01:44:45 +02:00
|
|
|
static char section[128] = "";
|
2014-11-24 00:16:36 +01:00
|
|
|
static ut64 oaddr = UT64_MAX;
|
|
|
|
RIOSection *s;
|
2016-09-26 23:13:49 +02:00
|
|
|
if (oaddr == addr) {
|
2014-11-24 00:16:36 +01:00
|
|
|
return section;
|
2016-09-26 23:13:49 +02:00
|
|
|
}
|
2014-11-24 00:16:36 +01:00
|
|
|
s = r_io_section_vget (core->io, addr);
|
|
|
|
if (s) {
|
|
|
|
snprintf (section, sizeof (section)-1, "%10s ", s->name);
|
2015-06-01 15:22:03 +02:00
|
|
|
} else {
|
|
|
|
RListIter *iter;
|
|
|
|
RDebugMap *map;
|
|
|
|
*section = 0;
|
|
|
|
r_list_foreach (core->dbg->maps, iter, map) {
|
|
|
|
if (addr >= map->addr && addr < map->addr_end) {
|
2015-06-01 15:34:26 +02:00
|
|
|
const char *mn = r_str_lchr (map->name, '/');
|
|
|
|
if (mn) {
|
2016-09-26 23:13:49 +02:00
|
|
|
strncpy (section, mn + 1, sizeof (section) - 1);
|
2015-06-01 15:34:26 +02:00
|
|
|
} else {
|
2016-09-26 23:13:49 +02:00
|
|
|
strncpy (section, map->name, sizeof (section) - 1);
|
2015-06-01 15:34:26 +02:00
|
|
|
}
|
2015-06-01 15:22:03 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-24 00:16:36 +01:00
|
|
|
oaddr = addr;
|
|
|
|
return section;
|
|
|
|
}
|
|
|
|
|
2016-12-26 20:10:10 +01:00
|
|
|
// up means if this lines go up, it controls whether to insert `_
|
|
|
|
// nl if we have to insert new line, it controls whether to insert \n
|
|
|
|
static void _ds_comment_align_(RDisasmState *ds, bool up, bool nl) {
|
2017-11-24 23:19:26 +01:00
|
|
|
ds->cmtcount ++;
|
2016-12-24 18:16:54 +01:00
|
|
|
if (ds->show_comment_right) {
|
2016-12-29 00:37:40 +01:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_printf (ds->pal_comment);
|
|
|
|
}
|
2016-12-24 18:16:54 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-12-29 00:37:40 +01:00
|
|
|
//XXX fix this generate many dupes with section name
|
2017-11-24 23:19:26 +01:00
|
|
|
const char *sn = ds->show_section ? get_section_name (ds->core, ds->at) : "";
|
|
|
|
// if (ds->cmtcount == 0) {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
// }
|
2016-12-24 18:16:54 +01:00
|
|
|
sn = ds->show_section ? get_section_name (ds->core, ds->at) : "";
|
|
|
|
ds_align_comment (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
r_cons_print (COLOR_RESET (ds));
|
|
|
|
ds_print_pre (ds);
|
|
|
|
r_cons_printf ("%s%s%s%s%s %s %s", nl? "\n": "", sn,
|
2017-11-24 23:52:22 +01:00
|
|
|
COLOR (ds, color_flow),ds->refline, COLOR_RESET (ds),
|
2017-11-24 23:19:26 +01:00
|
|
|
up? "": ".-", COLOR (ds, color_comment));
|
|
|
|
#if 0
|
|
|
|
// r_cons_printf ("(%d)", ds->cmtcount);
|
|
|
|
if (ds->cmtcount == 1) {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
r_cons_printf ("%s%s%s%s%s%s%s %s %s", nl? "\n": "",
|
|
|
|
COLOR_RESET (ds), COLOR (ds, color_fline),
|
|
|
|
ds->pre, sn, ds->refline, COLOR_RESET (ds),
|
|
|
|
up? "": ".v", COLOR (ds, color_comment));
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s%s", COLOR (ds, color_comment), " "); //nl? "\n": "");
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (!up || ds->cmtcount > 1) {
|
|
|
|
r_cons_printf ("%s%s", COLOR (ds, color_comment), nl? "\n": "");
|
|
|
|
} else {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
r_cons_printf ("%s%s%s%s%s%s%s %s %s", nl? "\n": "",
|
|
|
|
COLOR_RESET (ds), COLOR (ds, color_fline),
|
|
|
|
ds->pre, sn, ds->refline, COLOR_RESET (ds),
|
|
|
|
up? "": "`-", COLOR (ds, color_comment));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2016-12-24 18:16:54 +01:00
|
|
|
}
|
2016-12-27 15:40:02 +01:00
|
|
|
#define ALIGN _ds_comment_align_ (ds, true, false)
|
|
|
|
|
2016-12-24 18:16:54 +01:00
|
|
|
static void ds_comment_lineup(RDisasmState *ds) {
|
2016-12-26 20:10:10 +01:00
|
|
|
_ds_comment_align_ (ds, true, false);
|
2016-12-24 18:16:54 +01:00
|
|
|
}
|
2016-12-26 17:21:00 +01:00
|
|
|
|
2018-02-03 19:21:54 +01:00
|
|
|
static void ds_begin_comment(RDisasmState *ds) {
|
|
|
|
if (ds->show_comment_right) {
|
|
|
|
ALIGN;
|
|
|
|
} else {
|
|
|
|
if (ds->use_json) {
|
|
|
|
ds_begin_json_line (ds);
|
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2018-02-03 19:21:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 16:54:31 +01:00
|
|
|
static void ds_comment(RDisasmState *ds, bool align, const char *format, ...) {
|
|
|
|
va_list ap;
|
|
|
|
va_start (ap, format);
|
2017-12-11 15:07:44 +01:00
|
|
|
|
2018-02-26 19:46:13 +08:00
|
|
|
if (ds->show_comments) {
|
|
|
|
if (ds->show_comment_right && align) {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
} else if (!ds->use_json) {
|
|
|
|
r_cons_printf ("%s", COLOR (ds, color_comment));
|
|
|
|
}
|
2016-12-26 17:21:00 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
|
|
|
|
if (!ds->use_json) {
|
|
|
|
r_cons_printf_list (format, ap);
|
|
|
|
} else {
|
|
|
|
char buffer[4096];
|
|
|
|
vsnprintf (buffer, sizeof(buffer), format, ap);
|
|
|
|
char *escstr = ds_esc_str (ds, (const char *)buffer, (int)strlen (buffer), NULL);
|
|
|
|
if (escstr) {
|
|
|
|
r_cons_printf ("%s", escstr);
|
|
|
|
free (escstr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ds->show_comment_right && align) {
|
|
|
|
ds_newline (ds);
|
|
|
|
}
|
|
|
|
|
2016-12-26 17:21:00 +01:00
|
|
|
va_end (ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ds_comment_esil(RDisasmState *ds, bool up, bool end, const char *format, ...) {
|
2016-12-24 18:16:54 +01:00
|
|
|
va_list ap;
|
|
|
|
va_start (ap, format);
|
2017-12-03 18:42:54 +08:00
|
|
|
if (ds->show_comments && up) {
|
|
|
|
ds->show_comment_right ? ds_align_comment (ds) : ds_comment_lineup (ds);
|
2017-01-31 10:00:24 +01:00
|
|
|
}
|
2016-12-24 18:16:54 +01:00
|
|
|
r_cons_printf_list (format, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
if (ds->show_comments && !ds->show_comment_right) {
|
|
|
|
if (end) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-12-24 18:16:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-14 18:35:32 +01:00
|
|
|
static void ds_print_esil_anal_fini(RDisasmState *ds) {
|
|
|
|
RCore *core = ds->core;
|
|
|
|
if (ds->show_emu && ds->esil_regstate) {
|
|
|
|
RCore* core = ds->core;
|
|
|
|
core->anal->last_disasm_reg = r_reg_arena_peek (core->anal->reg);
|
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
|
|
|
r_reg_arena_poke (core->anal->reg, ds->esil_regstate);
|
|
|
|
r_reg_setv (core->anal->reg, pc, ds->esil_old_pc);
|
|
|
|
R_FREE (ds->esil_regstate);
|
|
|
|
}
|
|
|
|
if (core && core->anal && core->anal->esil) {
|
|
|
|
// make sure to remove reference to ds to avoid UAF
|
|
|
|
core->anal->esil->user = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static RDisasmState * ds_init(RCore *core) {
|
2015-01-12 10:45:41 +01:00
|
|
|
RDisasmState *ds = R_NEW0 (RDisasmState);
|
2016-08-10 18:49:44 +02:00
|
|
|
if (!ds) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
ds->shortcut_pos = r_config_get_i (core->config, "asm.shortcut");
|
2016-03-04 00:33:24 +01:00
|
|
|
ds->core = core;
|
2018-01-27 00:25:12 +01:00
|
|
|
ds->strip = r_config_get (core->config, "asm.strip");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->pal_comment = core->cons->pal.comment;
|
2014-01-16 11:04:42 -06:00
|
|
|
#define P(x) (core->cons && core->cons->pal.x)? core->cons->pal.x
|
2014-04-01 16:22:29 -05:00
|
|
|
ds->color_comment = P(comment): Color_CYAN;
|
2017-11-09 22:01:48 +01:00
|
|
|
ds->color_usrcmt = P(usercomment): Color_CYAN;
|
2014-04-01 16:22:29 -05:00
|
|
|
ds->color_fname = P(fname): Color_RED;
|
|
|
|
ds->color_floc = P(floc): Color_MAGENTA;
|
|
|
|
ds->color_fline = P(fline): Color_CYAN;
|
|
|
|
ds->color_flow = P(flow): Color_CYAN;
|
2017-01-16 00:41:31 +01:00
|
|
|
ds->color_flow2 = P(flow2): Color_CYAN;
|
2014-04-01 16:22:29 -05:00
|
|
|
ds->color_flag = P(flag): Color_CYAN;
|
|
|
|
ds->color_label = P(label): Color_CYAN;
|
|
|
|
ds->color_other = P(other): Color_WHITE;
|
|
|
|
ds->color_nop = P(nop): Color_BLUE;
|
|
|
|
ds->color_bin = P(bin): Color_YELLOW;
|
|
|
|
ds->color_math = P(math): Color_YELLOW;
|
2017-12-10 11:06:03 +01:00
|
|
|
ds->color_btext = P(btext): Color_YELLOW;
|
2014-04-01 16:22:29 -05:00
|
|
|
ds->color_jmp = P(jmp): Color_GREEN;
|
|
|
|
ds->color_cjmp = P(cjmp): Color_GREEN;
|
|
|
|
ds->color_call = P(call): Color_BGREEN;
|
|
|
|
ds->color_cmp = P(cmp): Color_MAGENTA;
|
|
|
|
ds->color_swi = P(swi): Color_MAGENTA;
|
|
|
|
ds->color_trap = P(trap): Color_BRED;
|
|
|
|
ds->color_ret = P(ret): Color_RED;
|
|
|
|
ds->color_push = P(push): Color_YELLOW;
|
|
|
|
ds->color_pop = P(pop): Color_BYELLOW;
|
|
|
|
ds->color_reg = P(reg): Color_YELLOW;
|
2015-06-14 02:42:39 +02:00
|
|
|
ds->color_num = P(num): Color_CYAN;
|
2014-10-27 11:55:52 +01:00
|
|
|
ds->color_mov = P(mov): Color_WHITE;
|
2014-04-01 16:22:29 -05:00
|
|
|
ds->color_invalid = P(invalid): Color_BRED;
|
2014-12-06 12:25:02 +01:00
|
|
|
ds->color_gui_cflow = P(gui_cflow): Color_YELLOW;
|
|
|
|
ds->color_gui_dataoffset = P(gui_dataoffset): Color_YELLOW;
|
|
|
|
ds->color_gui_background = P(gui_background): Color_BLACK;
|
|
|
|
ds->color_gui_alt_background = P(gui_alt_background): Color_GRAY;
|
|
|
|
ds->color_gui_border = P(gui_border): Color_BGGRAY;
|
2014-10-27 11:55:52 +01:00
|
|
|
|
2017-11-04 16:13:10 +01:00
|
|
|
ds->immstr = r_config_get_i (core->config, "asm.immstr");
|
2017-11-30 00:14:08 +01:00
|
|
|
ds->immtrim = r_config_get_i (core->config, "asm.immtrim");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->use_esil = r_config_get_i (core->config, "asm.esil");
|
2018-01-30 00:41:30 +01:00
|
|
|
ds->pre_emu = r_config_get_i (core->config, "asm.emu.pre");
|
2016-03-04 00:33:24 +01:00
|
|
|
ds->show_flgoff = r_config_get_i (core->config, "asm.flgoff");
|
2016-01-10 22:30:10 +01:00
|
|
|
ds->show_nodup = r_config_get_i (core->config, "asm.nodup");
|
2017-11-28 10:52:04 +01:00
|
|
|
ds->asm_anal = r_config_get_i (core->config, "asm.anal");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_color = r_config_get_i (core->config, "scr.color");
|
2016-08-25 20:27:52 +02:00
|
|
|
ds->show_color_bytes = r_config_get_i (core->config, "scr.color.bytes"); // maybe rename to asm.color.bytes
|
|
|
|
ds->colorop = r_config_get_i (core->config, "scr.color.ops"); // XXX confusing name // asm.color.inst (mnemonic + operands) ?
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_utf8 = r_config_get_i (core->config, "scr.utf8");
|
|
|
|
ds->acase = r_config_get_i (core->config, "asm.ucase");
|
2016-11-04 03:56:42 +01:00
|
|
|
ds->capitalize = r_config_get_i (core->config, "asm.capitalize");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->atabs = r_config_get_i (core->config, "asm.tabs");
|
2015-07-15 15:14:51 +02:00
|
|
|
ds->atabsonce = r_config_get_i (core->config, "asm.tabsonce");
|
2015-07-15 17:30:34 +02:00
|
|
|
ds->atabsoff = r_config_get_i (core->config, "asm.tabsoff");
|
2015-05-06 00:56:31 +02:00
|
|
|
ds->midflags = r_config_get_i (core->config, "asm.midflags");
|
2017-05-11 12:47:48 +02:00
|
|
|
ds->midcursor = r_config_get_i (core->config, "asm.midcursor");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->decode = r_config_get_i (core->config, "asm.decode");
|
|
|
|
ds->pseudo = r_config_get_i (core->config, "asm.pseudo");
|
2017-02-06 00:56:51 +01:00
|
|
|
if (ds->pseudo) {
|
|
|
|
ds->atabs = 0;
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->filter = r_config_get_i (core->config, "asm.filter");
|
2014-12-10 23:54:35 +01:00
|
|
|
ds->interactive = r_config_get_i (core->config, "scr.interactive");
|
2018-01-16 01:50:42 -08:00
|
|
|
ds->jmpsub = r_config_get_i (core->config, "asm.jmpsub");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->varsub = r_config_get_i (core->config, "asm.varsub");
|
2015-11-19 23:12:08 +01:00
|
|
|
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
|
2017-03-17 11:54:34 +01:00
|
|
|
core->parser->localvar_only = r_config_get_i (core->config, "asm.varsub_only");
|
2017-12-09 13:14:37 +01:00
|
|
|
core->parser->retleave_asm = NULL;
|
2016-08-25 18:54:07 +02:00
|
|
|
ds->show_vars = r_config_get_i (core->config, "asm.vars");
|
2017-04-07 21:09:33 +02:00
|
|
|
ds->show_varsum = r_config_get_i (core->config, "asm.varsum");
|
2016-08-25 18:54:07 +02:00
|
|
|
ds->show_varxs = r_config_get_i (core->config, "asm.varxs");
|
2014-09-23 10:15:19 +02:00
|
|
|
ds->maxrefs = r_config_get_i (core->config, "asm.maxrefs");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_lines = r_config_get_i (core->config, "asm.lines");
|
|
|
|
ds->linesright = r_config_get_i (core->config, "asm.linesright");
|
2014-08-05 05:37:48 +02:00
|
|
|
ds->show_indent = r_config_get_i (core->config, "asm.indent");
|
2015-08-12 10:40:24 +02:00
|
|
|
ds->indent_space = r_config_get_i (core->config, "asm.indentspace");
|
2014-11-02 02:19:31 +01:00
|
|
|
ds->tracespace = r_config_get_i (core->config, "asm.tracespace");
|
2014-11-02 03:06:52 +01:00
|
|
|
ds->cyclespace = r_config_get_i (core->config, "asm.cyclespace");
|
2014-04-21 19:19:15 +04:00
|
|
|
ds->show_dwarf = r_config_get_i (core->config, "asm.dwarf");
|
2016-11-23 10:30:44 +01:00
|
|
|
ds->dwarfFile = r_config_get_i (ds->core->config, "asm.dwarf.file");
|
|
|
|
ds->dwarfAbspath = r_config_get_i (ds->core->config, "asm.dwarf.abspath");
|
2015-08-31 00:20:07 +02:00
|
|
|
ds->show_lines_call = r_config_get_i (core->config, "asm.lines.call");
|
|
|
|
ds->show_lines_ret = r_config_get_i (core->config, "asm.lines.ret");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_size = r_config_get_i (core->config, "asm.size");
|
|
|
|
ds->show_trace = r_config_get_i (core->config, "asm.trace");
|
|
|
|
ds->linesout = r_config_get_i (core->config, "asm.linesout");
|
|
|
|
ds->adistrick = r_config_get_i (core->config, "asm.middle"); // TODO: find better name
|
2014-09-24 03:01:18 +02:00
|
|
|
ds->asm_demangle = r_config_get_i (core->config, "asm.demangle");
|
2015-03-08 02:27:39 +01:00
|
|
|
ds->asm_describe = r_config_get_i (core->config, "asm.describe");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_offset = r_config_get_i (core->config, "asm.offset");
|
2016-11-01 23:30:36 +01:00
|
|
|
ds->show_offdec = r_config_get_i (core->config, "asm.decoff");
|
2015-11-23 01:40:35 +01:00
|
|
|
ds->show_bbline = r_config_get_i (core->config, "asm.bbline");
|
2014-11-22 05:39:52 +01:00
|
|
|
ds->show_section = r_config_get_i (core->config, "asm.section");
|
2016-04-08 02:56:42 +02:00
|
|
|
ds->show_section_col = r_config_get_i (core->config, "asm.section.col");
|
2016-03-29 02:03:17 +02:00
|
|
|
ds->show_symbols = r_config_get_i (core->config, "asm.symbol");
|
2016-04-08 02:56:42 +02:00
|
|
|
ds->show_symbols_col = r_config_get_i (core->config, "asm.symbol.col");
|
2015-09-11 23:46:09 +02:00
|
|
|
ds->show_emu = r_config_get_i (core->config, "asm.emu");
|
2018-01-30 10:21:31 -05:00
|
|
|
ds->show_emu_str = r_config_get_i (core->config, "asm.emu.str");
|
2018-02-10 18:10:22 +08:00
|
|
|
ds->show_emu_stroff = r_config_get_i (core->config, "asm.emu.stroff");
|
2018-04-05 15:54:44 +08:00
|
|
|
ds->show_emu_strinv = r_config_get_i (core->config, "asm.emu.strinv");
|
2018-04-07 21:35:12 +08:00
|
|
|
ds->show_emu_strflag = r_config_get_i (core->config, "asm.emu.strflag");
|
2018-01-30 10:21:31 -05:00
|
|
|
ds->show_emu_write = r_config_get_i (core->config, "asm.emu.write");
|
|
|
|
ds->show_emu_stack = r_config_get_i (core->config, "asm.emu.stack");
|
2017-12-03 18:22:47 +01:00
|
|
|
ds->stackFd = -1;
|
|
|
|
if (ds->show_emu_stack) {
|
|
|
|
// TODO: initialize fake stack in here
|
|
|
|
const char *uri = "malloc://32K";
|
|
|
|
ut64 size = r_num_get (core->num, "32K");
|
|
|
|
ut64 addr = r_reg_getv (core->anal->reg, "SP") - (size / 2);
|
|
|
|
emustack_min = addr;
|
|
|
|
emustack_max = addr + size;
|
|
|
|
ds->stackFd = r_io_fd_open (core->io, uri, R_IO_RW, 0);
|
|
|
|
RIOMap *map = r_io_map_add (core->io, ds->stackFd, R_IO_RW, 0LL, addr, size, true);
|
|
|
|
if (!map) {
|
|
|
|
r_io_fd_close (core->io, ds->stackFd);
|
|
|
|
eprintf ("Cannot create map for tha stack, fd %d got closed again\n", ds->stackFd);
|
|
|
|
ds->stackFd = -1;
|
|
|
|
} else {
|
|
|
|
r_io_map_set_name (map, "fake.stack");
|
|
|
|
}
|
|
|
|
}
|
2018-01-30 14:25:15 +01:00
|
|
|
ds->stackptr = core->anal->stackptr;
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_offseg = r_config_get_i (core->config, "asm.segoff");
|
|
|
|
ds->show_flags = r_config_get_i (core->config, "asm.flags");
|
|
|
|
ds->show_bytes = r_config_get_i (core->config, "asm.bytes");
|
2015-01-12 10:45:41 +01:00
|
|
|
ds->show_reloff = r_config_get_i (core->config, "asm.reloff");
|
2016-08-25 20:17:55 +02:00
|
|
|
ds->show_reloff_flags = r_config_get_i (core->config, "asm.reloff.flags");
|
2014-07-21 04:18:27 +02:00
|
|
|
ds->show_fcnlines = r_config_get_i (core->config, "asm.fcnlines");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_comments = r_config_get_i (core->config, "asm.comments");
|
2016-01-27 02:25:25 +01:00
|
|
|
ds->show_jmphints = r_config_get_i (core->config, "asm.jmphints");
|
2016-06-20 09:46:03 +02:00
|
|
|
ds->show_leahints = r_config_get_i (core->config, "asm.leahints");
|
2015-08-26 03:27:34 +02:00
|
|
|
ds->show_slow = r_config_get_i (core->config, "asm.slow");
|
2014-11-24 00:16:36 +01:00
|
|
|
ds->show_calls = r_config_get_i (core->config, "asm.calls");
|
2015-10-03 13:52:52 +02:00
|
|
|
ds->show_family = r_config_get_i (core->config, "asm.family");
|
2018-02-22 17:59:08 +01:00
|
|
|
ds->cmtcol = r_config_get_i (core->config, "asm.cmt.col");
|
|
|
|
ds->show_cmtflgrefs = r_config_get_i (core->config, "asm.cmt.flgrefs");
|
2014-02-10 23:01:19 +01:00
|
|
|
ds->show_cycles = r_config_get_i (core->config, "asm.cycles");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_stackptr = r_config_get_i (core->config, "asm.stackptr");
|
|
|
|
ds->show_xrefs = r_config_get_i (core->config, "asm.xrefs");
|
2018-02-22 17:59:08 +01:00
|
|
|
ds->show_cmtrefs = r_config_get_i (core->config, "asm.cmt.refs");
|
|
|
|
ds->cmtfold = r_config_get_i (core->config, "asm.cmt.fold");
|
|
|
|
ds->show_cmtoff = r_config_get (core->config, "asm.cmt.off");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->show_functions = r_config_get_i (core->config, "asm.functions");
|
2015-01-28 17:05:18 +01:00
|
|
|
ds->show_fcncalls = r_config_get_i (core->config, "asm.fcncalls");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->nbytes = r_config_get_i (core->config, "asm.nbytes");
|
2018-02-24 19:01:21 +08:00
|
|
|
ds->show_asciidot = !strcmp (core->print->strconv_mode, "asciidot");
|
2017-07-24 23:17:24 +08:00
|
|
|
const char *strenc_str = r_config_get (core->config, "asm.strenc");
|
|
|
|
if (!strcmp (strenc_str, "latin1")) {
|
|
|
|
ds->strenc = R_STRING_ENC_LATIN1;
|
|
|
|
} else if (!strcmp (strenc_str, "utf8")) {
|
|
|
|
ds->strenc = R_STRING_ENC_UTF8;
|
|
|
|
} else if (!strcmp (strenc_str, "utf16le")) {
|
|
|
|
ds->strenc = R_STRING_ENC_UTF16LE;
|
|
|
|
} else if (!strcmp (strenc_str, "utf32le")) {
|
|
|
|
ds->strenc = R_STRING_ENC_UTF32LE;
|
|
|
|
} else {
|
|
|
|
ds->strenc = R_STRING_ENC_GUESS;
|
|
|
|
}
|
2014-02-25 01:35:23 +01:00
|
|
|
core->print->bytespace = r_config_get_i (core->config, "asm.bytespace");
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->cursor = 0;
|
|
|
|
ds->nb = 0;
|
|
|
|
ds->flagspace_ports = r_flag_space_get (core->flags, "ports");
|
|
|
|
ds->lbytes = r_config_get_i (core->config, "asm.lbytes");
|
2018-02-22 17:59:08 +01:00
|
|
|
ds->show_comment_right_default = r_config_get_i (core->config, "asm.cmt.right");
|
2017-03-20 23:43:34 +01:00
|
|
|
ds->show_comment_right = ds->show_comment_right_default;
|
2014-12-10 23:54:35 +01:00
|
|
|
ds->show_flag_in_bytes = r_config_get_i (core->config, "asm.flagsinbytes");
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
ds->show_hints = r_config_get_i (core->config, "asm.hints");
|
2015-07-15 00:22:20 +02:00
|
|
|
ds->show_marks = r_config_get_i (core->config, "asm.marks");
|
2017-05-26 08:56:47 +08:00
|
|
|
ds->show_noisy_comments = r_config_get_i (core->config, "asm.noisy");
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_NONE;
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->ocomment = NULL;
|
|
|
|
ds->linesopts = 0;
|
|
|
|
ds->lastfail = 0;
|
|
|
|
ds->ocols = 0;
|
|
|
|
ds->lcols = 0;
|
2018-02-17 23:02:53 +08:00
|
|
|
ds->printed_str_addr = UT64_MAX;
|
2018-02-22 23:24:37 +08:00
|
|
|
ds->printed_flag_addr = UT64_MAX;
|
2016-05-30 04:18:48 +02:00
|
|
|
|
2016-06-08 21:16:00 +02:00
|
|
|
ds->esil_old_pc = UT64_MAX;
|
|
|
|
ds->esil_regstate = NULL;
|
2016-06-08 23:33:31 +02:00
|
|
|
ds->esil_likely = false;
|
2016-06-08 21:16:00 +02:00
|
|
|
|
2017-05-08 20:21:06 +02:00
|
|
|
ds->showpayloads = r_config_get_i (ds->core->config, "asm.payloads");
|
2017-05-23 23:54:11 +02:00
|
|
|
ds->showrelocs = r_config_get_i (core->config, "bin.relocs");
|
2018-02-20 10:51:44 +01:00
|
|
|
ds->min_ref_addr = r_config_get_i (core->config, "asm.minvalsub");
|
2017-05-08 20:21:06 +02:00
|
|
|
|
2014-10-16 02:16:52 +02:00
|
|
|
if (ds->show_flag_in_bytes) {
|
|
|
|
ds->show_flags = 0;
|
|
|
|
}
|
2015-09-08 23:21:35 +02:00
|
|
|
if (r_config_get_i (core->config, "asm.lineswide")) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->linesopts |= R_ANAL_REFLINE_TYPE_WIDE;
|
2015-09-08 23:21:35 +02:00
|
|
|
}
|
|
|
|
if (core->cons->vline) {
|
2016-08-16 13:38:40 +02:00
|
|
|
if (ds->show_utf8) {
|
2015-09-08 23:21:35 +02:00
|
|
|
ds->linesopts |= R_ANAL_REFLINE_TYPE_UTF8;
|
2016-08-16 13:38:40 +02:00
|
|
|
}
|
2015-09-08 23:21:35 +02:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_lines) {
|
|
|
|
ds->ocols += 10; // XXX
|
|
|
|
}
|
|
|
|
if (ds->show_offset) {
|
|
|
|
ds->ocols += 14;
|
|
|
|
}
|
2016-10-21 01:24:40 +02:00
|
|
|
ds->lcols = ds->ocols + 2;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_bytes) {
|
|
|
|
ds->ocols += 20;
|
|
|
|
}
|
|
|
|
if (ds->show_trace) {
|
|
|
|
ds->ocols += 8;
|
|
|
|
}
|
|
|
|
if (ds->show_stackptr) {
|
|
|
|
ds->ocols += 4;
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
/* disasm */ ds->ocols += 20;
|
2016-10-21 01:24:40 +02:00
|
|
|
ds->nb = ds->nbytes? (1 + ds->nbytes * 2): 0;
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->tries = 3;
|
2014-01-16 11:04:42 -06:00
|
|
|
if (core->print->cur_enabled) {
|
2016-05-30 04:18:48 +02:00
|
|
|
if (core->print->cur < 0) {
|
2014-01-16 11:04:42 -06:00
|
|
|
core->print->cur = 0;
|
2016-05-30 04:18:48 +02:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->cursor = core->print->cur;
|
2016-09-26 23:13:49 +02:00
|
|
|
} else {
|
|
|
|
ds->cursor = -1;
|
|
|
|
}
|
2015-09-08 23:21:35 +02:00
|
|
|
if (r_config_get_i (core->config, "asm.lineswide")) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->linesopts |= R_ANAL_REFLINE_TYPE_WIDE;
|
2015-09-08 23:21:35 +02:00
|
|
|
}
|
|
|
|
if (core->cons->vline) {
|
2016-10-21 01:24:40 +02:00
|
|
|
if (ds->show_utf8) {
|
2015-09-08 23:21:35 +02:00
|
|
|
ds->linesopts |= R_ANAL_REFLINE_TYPE_UTF8;
|
2016-09-26 23:13:49 +02:00
|
|
|
}
|
2015-09-08 23:21:35 +02:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
return ds;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2015-09-08 23:21:35 +02:00
|
|
|
static ut64 lastaddr = UT64_MAX;
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_reflines_fini(RDisasmState *ds) {
|
|
|
|
RAnal *anal = ds->core->anal;
|
2016-04-03 23:52:36 +02:00
|
|
|
r_list_free (anal->reflines);
|
|
|
|
r_list_free (anal->reflines2);
|
|
|
|
anal->reflines = NULL;
|
|
|
|
anal->reflines2 = NULL;
|
2016-04-04 00:17:57 +02:00
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2016-04-03 23:52:36 +02:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_reflines_init(RDisasmState *ds) {
|
|
|
|
RAnal *anal = ds->core->anal;
|
|
|
|
|
2015-09-08 23:21:35 +02:00
|
|
|
lastaddr = UT64_MAX;
|
2016-05-30 12:35:39 +02:00
|
|
|
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_lines) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_reflines_fini (ds);
|
2015-09-08 23:21:35 +02:00
|
|
|
anal->reflines = r_anal_reflines_get (anal,
|
2014-02-14 13:40:22 -06:00
|
|
|
ds->addr, ds->buf, ds->len, ds->l,
|
2015-08-31 00:20:07 +02:00
|
|
|
ds->linesout, ds->show_lines_call);
|
2015-09-08 23:21:35 +02:00
|
|
|
anal->reflines2 = r_anal_reflines_get (anal,
|
2014-02-14 13:40:22 -06:00
|
|
|
ds->addr, ds->buf, ds->len, ds->l,
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->linesout, 1);
|
2016-04-04 00:52:45 +02:00
|
|
|
} else {
|
|
|
|
r_list_free (anal->reflines);
|
|
|
|
r_list_free (anal->reflines2);
|
|
|
|
anal->reflines = anal->reflines2 = NULL;
|
|
|
|
}
|
2015-09-08 23:21:35 +02:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_reflines_fcn_init(RDisasmState *ds, RAnalFunction *fcn, const ut8* buf) {
|
|
|
|
RCore *core = ds->core;
|
2015-09-08 23:21:35 +02:00
|
|
|
RAnal *anal = core->anal;
|
2014-01-22 22:55:48 -06:00
|
|
|
if (ds->show_lines) {
|
2014-12-10 23:54:35 +01:00
|
|
|
// TODO: make anal->reflines implicit
|
2015-09-08 23:21:35 +02:00
|
|
|
free (anal->reflines); // TODO: leak
|
2016-09-23 16:28:48 +02:00
|
|
|
anal->reflines = r_anal_reflines_fcn_get (anal, fcn, -1, ds->linesout, ds->show_lines_call);
|
2015-09-08 23:21:35 +02:00
|
|
|
free (anal->reflines2); // TODO: leak
|
2016-09-23 16:28:48 +02:00
|
|
|
anal->reflines2 = r_anal_reflines_fcn_get (anal, fcn, -1, ds->linesout, 1);
|
2014-12-10 23:54:35 +01:00
|
|
|
} else {
|
2016-04-04 00:52:45 +02:00
|
|
|
r_list_free (anal->reflines);
|
|
|
|
r_list_free (anal->reflines2);
|
2015-09-08 23:21:35 +02:00
|
|
|
anal->reflines = anal->reflines2 = NULL;
|
2014-12-10 23:54:35 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_free(RDisasmState *ds) {
|
2017-01-22 09:44:35 +01:00
|
|
|
if (!ds) {
|
|
|
|
return;
|
|
|
|
}
|
2017-12-03 18:22:47 +01:00
|
|
|
if (ds->show_emu_stack) {
|
|
|
|
// TODO: destroy fake stack in here
|
|
|
|
eprintf ("Free fake stack\n");
|
|
|
|
if (ds->stackFd != -1) {
|
|
|
|
r_io_fd_close (ds->core->io, ds->stackFd);
|
|
|
|
}
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2015-09-28 11:21:23 +02:00
|
|
|
r_anal_hint_free (ds->hint);
|
2018-03-14 18:35:32 +01:00
|
|
|
ds_print_esil_anal_fini (ds);
|
|
|
|
ds_reflines_fini (ds);
|
|
|
|
ds_print_esil_anal_fini (ds);
|
2014-01-20 01:42:16 +01:00
|
|
|
free (ds->comment);
|
|
|
|
free (ds->line);
|
|
|
|
free (ds->refline);
|
|
|
|
free (ds->refline2);
|
|
|
|
free (ds->opstr);
|
|
|
|
free (ds->osl);
|
|
|
|
free (ds->sl);
|
2016-03-04 00:33:24 +01:00
|
|
|
free (ds->_tabsbuf);
|
2016-11-15 19:34:22 +01:00
|
|
|
R_FREE (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-09-22 12:19:21 +02:00
|
|
|
/* XXX move to r_print */
|
2018-02-03 19:21:54 +01:00
|
|
|
static char *colorize_asm_string(RCore *core, RDisasmState *ds, bool print_color) {
|
2014-08-05 01:09:28 +04:00
|
|
|
char *spacer = NULL;
|
|
|
|
char *source = ds->opstr? ds->opstr: ds->asmop.buf_asm;
|
2017-06-20 22:48:46 +02:00
|
|
|
char *hlstr = r_meta_get_string (ds->core->anal, R_META_TYPE_HIGHLIGHT, ds->at);
|
|
|
|
bool partial_reset = hlstr ? (*hlstr?true:false):false;
|
2014-08-05 01:09:28 +04:00
|
|
|
|
2015-11-02 12:38:08 +01:00
|
|
|
if (!ds->show_color || !ds->colorop) {
|
2015-10-20 23:37:20 +02:00
|
|
|
return strdup (source);
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2014-08-05 01:09:28 +04:00
|
|
|
|
2018-02-03 19:21:54 +01:00
|
|
|
if (print_color) {
|
|
|
|
r_cons_strcat (r_print_color_op_type (core->print, ds->analop.type));
|
|
|
|
}
|
|
|
|
|
2014-08-05 01:09:28 +04:00
|
|
|
|
|
|
|
// workaround dummy colorizer in case of paired commands (tms320 & friends)
|
|
|
|
|
2014-09-22 13:45:36 +02:00
|
|
|
spacer = strstr (source, "||");
|
2014-08-05 01:09:28 +04:00
|
|
|
if (spacer) {
|
2014-10-16 01:51:48 +02:00
|
|
|
char *scol1, *s1 = r_str_ndup (source, spacer - source);
|
2014-08-05 01:09:28 +04:00
|
|
|
char *scol2, *s2 = strdup (spacer + 2);
|
|
|
|
|
2017-06-20 22:48:46 +02:00
|
|
|
scol1 = r_print_colorize_opcode (ds->core->print, s1, ds->color_reg, ds->color_num, partial_reset);
|
2015-10-20 23:37:20 +02:00
|
|
|
free (s1);
|
2017-06-20 22:48:46 +02:00
|
|
|
scol2 = r_print_colorize_opcode (ds->core->print, s2, ds->color_reg, ds->color_num, partial_reset);
|
2015-10-20 23:37:20 +02:00
|
|
|
free (s2);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!scol1) {
|
|
|
|
scol1 = strdup ("");
|
|
|
|
}
|
|
|
|
if (!scol2) {
|
|
|
|
scol2 = strdup ("");
|
|
|
|
}
|
2014-08-05 01:09:28 +04:00
|
|
|
|
2016-10-27 01:42:00 +02:00
|
|
|
source = malloc (strlen (scol1) + strlen (scol2) + 2 + 1); // reuse source variable
|
2014-09-22 13:45:36 +02:00
|
|
|
sprintf (source, "%s||%s", scol1, scol2);
|
|
|
|
free (scol1);
|
|
|
|
free (scol2);
|
2014-08-05 01:09:28 +04:00
|
|
|
return source;
|
|
|
|
}
|
2018-02-03 19:21:54 +01:00
|
|
|
|
2017-06-20 22:48:46 +02:00
|
|
|
return r_print_colorize_opcode (ds->core->print, source, ds->color_reg, ds->color_num, partial_reset);
|
|
|
|
}
|
|
|
|
|
2018-01-27 00:25:12 +01:00
|
|
|
static bool ds_must_strip(RDisasmState *ds) {
|
|
|
|
if (ds && ds->strip && *ds->strip) {
|
|
|
|
const char * optype = r_anal_optype_to_string (ds->analop.type);
|
|
|
|
if (optype && *optype) {
|
2018-01-27 02:56:56 +01:00
|
|
|
return strstr (ds->strip, optype);
|
2018-01-27 00:25:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-20 22:48:46 +02:00
|
|
|
static void ds_highlight_word(RDisasmState * ds, char *word, char *color) {
|
|
|
|
char *source = ds->opstr? ds->opstr: ds->asmop.buf_asm;
|
|
|
|
char * asm_str = r_str_highlight (source, word, color);
|
|
|
|
ds->opstr = asm_str? asm_str:source;
|
2014-08-05 01:09:28 +04:00
|
|
|
}
|
|
|
|
|
2018-02-03 19:21:54 +01:00
|
|
|
static void ds_build_op_str(RDisasmState *ds, bool print_color) {
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2014-12-14 02:36:57 +01:00
|
|
|
if (!ds->opstr) {
|
2015-08-31 00:20:07 +02:00
|
|
|
ds->opstr = strdup (ds->asmop.buf_asm);
|
2014-12-14 02:36:57 +01:00
|
|
|
}
|
2015-09-28 01:00:06 +02:00
|
|
|
/* initialize */
|
|
|
|
core->parser->hint = ds->hint;
|
2017-03-27 08:18:55 +05:30
|
|
|
core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
|
|
|
|
core->parser->relsub_addr = 0;
|
2014-12-13 18:06:01 +01:00
|
|
|
if (ds->varsub && ds->opstr) {
|
2016-11-04 03:15:17 +01:00
|
|
|
ut64 at = ds->vat;
|
2017-11-23 22:46:57 +01:00
|
|
|
RAnalFunction *f = fcnIn (ds, at, R_ANAL_FCN_TYPE_NULL);
|
2016-11-04 03:15:17 +01:00
|
|
|
core->parser->varlist = r_anal_var_list_dynamic;
|
|
|
|
r_parse_varsub (core->parser, f, at, ds->analop.size,
|
|
|
|
ds->opstr, ds->strsub, sizeof (ds->strsub));
|
|
|
|
if (*ds->strsub) {
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (ds->strsub);
|
|
|
|
}
|
2017-03-27 08:18:55 +05:30
|
|
|
if (core->parser->relsub) {
|
|
|
|
RList *list = r_anal_refs_get (core->anal, at);
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
if ((ref->type == R_ANAL_REF_TYPE_DATA
|
|
|
|
|| ref->type == R_ANAL_REF_TYPE_STRING)
|
|
|
|
&& ds->analop.type == R_ANAL_OP_TYPE_LEA) {
|
|
|
|
core->parser->relsub_addr = ref->addr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-08-09 02:31:37 -07:00
|
|
|
r_list_free (list);
|
2017-03-27 08:18:55 +05:30
|
|
|
}
|
2014-12-13 18:06:01 +01:00
|
|
|
}
|
2018-02-03 19:21:54 +01:00
|
|
|
char *asm_str = colorize_asm_string (core, ds, print_color);
|
2018-01-16 01:50:42 -08:00
|
|
|
asm_str = ds_sub_jumps (ds, asm_str);
|
2017-11-30 00:14:08 +01:00
|
|
|
if (ds->immtrim) {
|
2017-11-29 18:56:12 +01:00
|
|
|
r_parse_immtrim (ds->opstr);
|
2017-09-30 02:18:48 +02:00
|
|
|
free (asm_str);
|
|
|
|
return;
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->decode) {
|
|
|
|
char *tmpopstr = r_anal_op_to_string (core->anal, &ds->analop);
|
|
|
|
// TODO: Use data from code analysis..not raw ds->analop here
|
2014-01-16 11:04:42 -06:00
|
|
|
// if we want to get more information
|
2014-08-05 05:37:48 +02:00
|
|
|
ds->opstr = tmpopstr? tmpopstr: asm_str? strdup (asm_str): strdup ("");
|
2015-03-30 12:52:04 +02:00
|
|
|
} else {
|
|
|
|
if (ds->hint && ds->hint->opcode) {
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (ds->hint->opcode);
|
|
|
|
}
|
|
|
|
if (ds->filter) {
|
|
|
|
int ofs = core->parser->flagspace;
|
|
|
|
int fs = ds->flagspace_ports;
|
|
|
|
if (ds->analop.type == R_ANAL_OP_TYPE_IO) {
|
|
|
|
core->parser->notin_flagspace = -1;
|
2014-01-16 11:04:42 -06:00
|
|
|
core->parser->flagspace = fs;
|
|
|
|
} else {
|
2015-03-30 12:52:04 +02:00
|
|
|
if (fs != -1) {
|
|
|
|
core->parser->notin_flagspace = fs;
|
|
|
|
core->parser->flagspace = fs;
|
|
|
|
} else {
|
|
|
|
core->parser->notin_flagspace = -1;
|
|
|
|
core->parser->flagspace = -1;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2017-02-03 08:53:57 +00:00
|
|
|
if (ds->analop.refptr) {
|
2017-03-27 08:18:55 +05:30
|
|
|
if (core->parser->relsub_addr == 0) {
|
2017-09-03 20:47:05 +02:00
|
|
|
ut64 killme = UT64_MAX;
|
2017-09-22 23:48:53 +02:00
|
|
|
const int be = core->assembler->big_endian;
|
2017-09-30 03:50:47 -05:00
|
|
|
r_io_read_i (core->io, ds->analop.ptr, &killme, ds->analop.refptr, be);
|
2017-08-22 07:42:16 +00:00
|
|
|
core->parser->relsub_addr = (int)killme;
|
2017-03-27 08:18:55 +05:30
|
|
|
}
|
2017-02-03 08:53:57 +00:00
|
|
|
}
|
2017-09-03 20:47:05 +02:00
|
|
|
r_parse_filter (core->parser, core->flags, asm_str,
|
|
|
|
ds->str, sizeof (ds->str), core->print->big_endian);
|
2015-03-30 12:52:04 +02:00
|
|
|
core->parser->flagspace = ofs;
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (ds->str);
|
|
|
|
} else {
|
2017-04-09 18:57:33 +02:00
|
|
|
free (ds->opstr);
|
2017-04-09 22:11:40 +08:00
|
|
|
ds->opstr = strdup (asm_str? asm_str: "");
|
2015-03-30 12:52:04 +02:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2017-06-20 22:48:46 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
int i = 0;
|
|
|
|
char *word = NULL;
|
|
|
|
char *bgcolor = NULL;
|
|
|
|
char *wcdata = r_meta_get_string (ds->core->anal, R_META_TYPE_HIGHLIGHT, ds->at);
|
|
|
|
int argc = 0;
|
|
|
|
char **wc_array = r_str_argv (wcdata, &argc);
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
bgcolor = strchr (wc_array[i], '\x1b');
|
|
|
|
word = r_str_newlen (wc_array[i], bgcolor - wc_array[i]);
|
|
|
|
ds_highlight_word (ds, word, bgcolor);
|
|
|
|
}
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->use_esil) {
|
|
|
|
if (*R_STRBUF_SAFEGET (&ds->analop.esil)) {
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (R_STRBUF_SAFEGET (&ds->analop.esil));
|
2014-01-16 11:04:42 -06:00
|
|
|
} else {
|
2016-06-10 19:09:13 +02:00
|
|
|
char *p = malloc (strlen (ds->opstr) + 6); /* What's up '\0' ? */
|
|
|
|
if (p) {
|
|
|
|
strcpy (p, "TODO,");
|
|
|
|
strcpy (p + 5, ds->opstr);
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = p;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
2014-04-01 16:22:29 -05:00
|
|
|
free (asm_str);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-08-10 18:49:44 +02:00
|
|
|
//removed hints bits from since r_anal_build_range_on_hints along with
|
|
|
|
//r_core_seek_archbits will be used instead. The ranges are built from hints
|
2016-04-27 22:17:19 +02:00
|
|
|
R_API RAnalHint *r_core_hint_begin(RCore *core, RAnalHint* hint, ut64 at) {
|
2013-01-24 03:48:24 +01:00
|
|
|
static char *hint_arch = NULL;
|
2015-05-10 00:12:33 +02:00
|
|
|
static char *hint_syntax = NULL;
|
2015-09-28 11:21:23 +02:00
|
|
|
r_anal_hint_free (hint);
|
2013-01-24 03:48:24 +01:00
|
|
|
hint = r_anal_hint_get (core->anal, at);
|
|
|
|
if (hint_arch) {
|
|
|
|
r_config_set (core->config, "asm.arch", hint_arch);
|
|
|
|
hint_arch = NULL;
|
|
|
|
}
|
2015-05-10 00:12:33 +02:00
|
|
|
if (hint_syntax) {
|
|
|
|
r_config_set (core->config, "asm.syntax", hint_syntax);
|
|
|
|
hint_syntax = NULL;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
if (hint) {
|
|
|
|
/* arch */
|
2018-03-26 14:11:33 +02:00
|
|
|
if (hint->arch && !core->fixedarch) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!hint_arch) {
|
|
|
|
hint_arch = strdup (r_config_get (core->config, "asm.arch"));
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
r_config_set (core->config, "asm.arch", hint->arch);
|
|
|
|
}
|
2018-03-26 14:11:33 +02:00
|
|
|
/* syntax */
|
2015-05-10 00:12:33 +02:00
|
|
|
if (hint->syntax) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!hint_syntax) {
|
|
|
|
hint_syntax = strdup (r_config_get (core->config, "asm.syntax"));
|
|
|
|
}
|
2015-05-10 00:12:33 +02:00
|
|
|
r_config_set (core->config, "asm.syntax", hint->syntax);
|
|
|
|
}
|
2017-11-14 23:36:04 +09:00
|
|
|
if (hint->high) {
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
return hint;
|
|
|
|
}
|
|
|
|
|
2018-02-06 15:30:10 +01:00
|
|
|
static void ds_beginline(RDisasmState *ds) {
|
2017-09-30 03:21:47 +02:00
|
|
|
ds_setup_pre (ds, false, false);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2016-04-08 02:56:42 +02:00
|
|
|
char *tmp = ds->line;
|
|
|
|
ds->line = ds->refline2;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_lines_left (ds);
|
2016-04-08 02:56:42 +02:00
|
|
|
ds->line = tmp;
|
2014-09-23 10:15:19 +02:00
|
|
|
}
|
|
|
|
|
2017-12-11 15:07:44 +01:00
|
|
|
static void ds_begin_json_line(RDisasmState *ds) {
|
|
|
|
if (!ds->use_json) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!ds->first_line) {
|
|
|
|
r_cons_print (",");
|
|
|
|
}
|
|
|
|
ds->first_line = false;
|
|
|
|
r_cons_printf ("{\"offset\":%"PFMT64d",\"text\":\"", ds->vat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ds_newline(RDisasmState *ds) {
|
|
|
|
if (ds->use_json) {
|
|
|
|
r_cons_printf ("\"}");
|
|
|
|
} else {
|
|
|
|
r_cons_newline ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 15:30:10 +01:00
|
|
|
static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines) {
|
|
|
|
ds_setup_pre (ds, false, false);
|
|
|
|
if (ds->pre != DS_PRE_NONE && ds->pre != DS_PRE_EMPTY) {
|
|
|
|
ds->pre = no_fcnlines ? DS_PRE_EMPTY : DS_PRE_FCN_MIDDLE;
|
2016-04-27 22:17:19 +02:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_pre (ds);
|
2016-04-27 22:17:19 +02:00
|
|
|
char *tmp = ds->line;
|
|
|
|
ds->line = ds->refline2;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_lines_left (ds);
|
2016-04-27 22:17:19 +02:00
|
|
|
ds->line = tmp;
|
|
|
|
}
|
2016-05-04 17:13:44 +02:00
|
|
|
|
2016-08-25 18:41:49 +02:00
|
|
|
static void ds_show_refs(RDisasmState *ds) {
|
|
|
|
RList *list;
|
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
|
|
|
RFlagItem *flagi, *flagat;
|
|
|
|
char *cmt;
|
|
|
|
|
|
|
|
if (!ds->show_cmtrefs) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
list = r_anal_xrefs_get_from (ds->core->anal, ds->at);
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
cmt = r_meta_get_string (ds->core->anal, R_META_TYPE_COMMENT, ref->addr);
|
|
|
|
flagi = r_flag_get_i (ds->core->flags, ref->addr);
|
2016-12-01 10:48:00 +01:00
|
|
|
flagat = r_flag_get_at (ds->core->flags, ref->addr, false);
|
2017-11-09 22:01:48 +01:00
|
|
|
// ds_align_comment (ds);
|
2016-08-25 18:41:49 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->color_comment);
|
|
|
|
}
|
|
|
|
if (flagi && flagat && (strcmp (flagi->name, flagat->name) != 0)) {
|
2016-12-27 15:40:02 +01:00
|
|
|
_ds_comment_align_ (ds, true, false);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; (%s)", flagi->name);
|
2016-08-25 18:41:49 +02:00
|
|
|
}
|
|
|
|
if (cmt) {
|
2016-12-27 15:40:02 +01:00
|
|
|
_ds_comment_align_ (ds, true, false);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; (%s)", cmt);
|
2016-08-25 18:41:49 +02:00
|
|
|
}
|
2016-09-26 23:13:49 +02:00
|
|
|
if (ref->type & R_ANAL_REF_TYPE_CALL) {
|
2016-09-12 19:41:11 +03:00
|
|
|
RAnalOp aop;
|
|
|
|
ut8 buf[12];
|
2016-09-26 23:13:49 +02:00
|
|
|
r_core_read_at (ds->core, ref->at, buf, sizeof (buf));
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (ds->core->anal, &aop, ref->at, buf, sizeof (buf), R_ANAL_OP_MASK_ALL);
|
2016-09-22 18:06:10 +02:00
|
|
|
if ((aop.type & R_ANAL_OP_TYPE_MASK) == R_ANAL_OP_TYPE_UCALL) {
|
2016-09-26 23:13:49 +02:00
|
|
|
RAnalFunction * fcn = r_anal_get_fcn_at (ds->core->anal,
|
|
|
|
ref->addr, R_ANAL_FCN_TYPE_NULL);
|
2016-12-27 15:40:02 +01:00
|
|
|
_ds_comment_align_ (ds, true, false);
|
2016-09-12 19:41:11 +03:00
|
|
|
if (fcn) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s", fcn->name);
|
2016-09-12 19:41:11 +03:00
|
|
|
} else {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; 0x%" PFMT64x"", ref->addr);
|
2016-09-12 19:41:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-25 18:41:49 +02:00
|
|
|
ds_print_color_reset (ds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_show_xrefs(RDisasmState *ds) {
|
2015-07-25 03:31:17 +02:00
|
|
|
RAnalRef *refi;
|
|
|
|
RListIter *iter;
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2016-02-07 21:44:35 +01:00
|
|
|
bool demangle = r_config_get_i (core->config, "bin.demangle");
|
|
|
|
const char *lang = demangle ? r_config_get (core->config, "bin.lang") : NULL;
|
|
|
|
char *name, *tmp;
|
2015-07-25 03:31:17 +02:00
|
|
|
int count = 0;
|
2016-12-27 15:40:02 +01:00
|
|
|
if (!ds->show_xrefs || !ds->show_comments) {
|
2016-02-07 21:44:35 +01:00
|
|
|
return;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-07-25 03:31:17 +02:00
|
|
|
/* show xrefs */
|
2017-12-11 18:00:14 +01:00
|
|
|
RList *xrefs = r_anal_xref_get (core->anal, ds->at);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!xrefs) {
|
|
|
|
return;
|
|
|
|
}
|
2017-12-22 15:38:06 +01:00
|
|
|
if (ds->maxrefs < 1) {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2018-03-05 07:08:50 +08:00
|
|
|
ds_comment (ds, false, "%s; XREFS(%d)\n",
|
2017-12-22 15:38:06 +01:00
|
|
|
ds->show_color? ds->pal_comment: "",
|
|
|
|
r_list_length (xrefs));
|
|
|
|
r_list_free (xrefs);
|
|
|
|
return;
|
|
|
|
}
|
2015-07-25 03:31:17 +02:00
|
|
|
if (r_list_length (xrefs) > ds->maxrefs) {
|
2016-02-16 03:24:47 +01:00
|
|
|
int cols = r_cons_get_size (NULL);
|
|
|
|
cols -= 15;
|
|
|
|
cols /= 23;
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2018-03-05 07:08:50 +08:00
|
|
|
ds_comment (ds, false, "%s; XREFS: ", ds->show_color? ds->pal_comment: "");
|
2014-09-23 10:15:19 +02:00
|
|
|
r_list_foreach (xrefs, iter, refi) {
|
2016-12-26 17:21:00 +01:00
|
|
|
ds_comment (ds, false, "%s 0x%08"PFMT64x" ",
|
2015-07-25 03:31:17 +02:00
|
|
|
r_anal_xrefs_type_tostring (refi->type), refi->addr);
|
2016-02-16 03:24:47 +01:00
|
|
|
if (count == cols) {
|
2015-07-25 03:31:17 +02:00
|
|
|
if (iter->n) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_color_reset (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2018-03-05 07:08:50 +08:00
|
|
|
ds_comment (ds, false, "%s; XREFS: ", ds->show_color? ds->pal_comment: "");
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2015-07-25 03:31:17 +02:00
|
|
|
count = 0;
|
2016-09-23 16:28:48 +02:00
|
|
|
} else {
|
|
|
|
count++;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_color_reset (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2014-09-23 10:15:19 +02:00
|
|
|
r_list_free (xrefs);
|
2015-07-25 03:31:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_list_foreach (xrefs, iter, refi) {
|
|
|
|
if (refi->at == ds->at) {
|
2017-11-23 22:46:57 +01:00
|
|
|
RAnalFunction *fun = fcnIn (ds, refi->addr, -1); //r_anal_get_fcn_in (core->anal, refi->addr, -1);
|
2017-01-24 01:41:12 +01:00
|
|
|
if (fun) {
|
|
|
|
name = strdup (fun->name);
|
|
|
|
} else {
|
|
|
|
RFlagItem *f = r_flag_get_at (core->flags, refi->addr, true);
|
|
|
|
if (f) {
|
|
|
|
name = r_str_newf ("%s + %d", f->name, refi->addr - f->offset);
|
|
|
|
} else {
|
|
|
|
name = strdup ("unk");
|
|
|
|
}
|
|
|
|
}
|
2016-02-07 21:44:35 +01:00
|
|
|
if (demangle) {
|
2016-11-22 14:58:42 +01:00
|
|
|
tmp = r_bin_demangle (core->bin->cur, lang, name, refi->addr);
|
2016-02-07 21:44:35 +01:00
|
|
|
if (tmp) {
|
|
|
|
free (name);
|
2016-05-24 21:22:15 +01:00
|
|
|
name = tmp;
|
2016-02-07 21:44:35 +01:00
|
|
|
}
|
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2018-03-05 07:08:50 +08:00
|
|
|
ds_comment (ds, false, "%s; %s XREF from 0x%08"PFMT64x" (%s)%s",
|
2017-05-08 20:21:06 +02:00
|
|
|
COLOR (ds, pal_comment), r_anal_xrefs_type_tostring (refi->type),
|
2016-12-26 20:10:10 +01:00
|
|
|
refi->addr, name, COLOR_RESET (ds));
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-02-07 21:44:35 +01:00
|
|
|
R_FREE (name);
|
2017-12-11 18:00:14 +01:00
|
|
|
} else {
|
|
|
|
eprintf ("Corrupted database?\n");
|
2015-07-25 03:31:17 +02:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2015-07-25 03:31:17 +02:00
|
|
|
r_list_free (xrefs);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_atabs_option(RDisasmState *ds) {
|
2015-03-16 02:52:26 +01:00
|
|
|
int n, i = 0, comma = 0, word = 0;
|
|
|
|
int size, brackets = 0;
|
|
|
|
char *t, *b;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!ds || !ds->atabs) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2016-10-24 14:31:03 +02:00
|
|
|
size = strlen (ds->asmop.buf_asm) * (ds->atabs + 1) * 4;
|
2016-09-27 00:00:09 +02:00
|
|
|
if (size < 1 || size < strlen (ds->asmop.buf_asm)) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
free (ds->opstr);
|
2016-09-27 00:00:09 +02:00
|
|
|
ds->opstr = b = malloc (size + 1);
|
|
|
|
strncpy (b, ds->asmop.buf_asm, R_MIN (size, R_ASM_BUFSIZE));
|
|
|
|
b[size] = 0;
|
2015-03-16 02:52:26 +01:00
|
|
|
for (; *b; b++, i++) {
|
2016-09-27 00:00:09 +02:00
|
|
|
if (*b == '(' || *b == '[') {
|
2016-09-23 16:28:48 +02:00
|
|
|
brackets++;
|
|
|
|
}
|
2016-09-27 00:00:09 +02:00
|
|
|
if (*b == ')' || *b == ']') {
|
2016-09-23 16:28:48 +02:00
|
|
|
brackets--;
|
|
|
|
}
|
2016-09-27 00:00:09 +02:00
|
|
|
if (*b == ',') {
|
2016-09-23 16:28:48 +02:00
|
|
|
comma = 1;
|
|
|
|
}
|
2016-09-27 00:00:09 +02:00
|
|
|
if (*b != ' ') {
|
2016-09-23 16:28:48 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (word > 0 && !comma) {
|
|
|
|
continue; //&& b[1]=='[') continue;
|
|
|
|
}
|
|
|
|
if (brackets > 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
comma = 0;
|
|
|
|
brackets = 0;
|
|
|
|
n = (ds->atabs-i);
|
2016-09-27 00:00:09 +02:00
|
|
|
t = strdup (b + 1); //XXX slow!
|
2016-09-23 16:28:48 +02:00
|
|
|
if (n < 1) {
|
|
|
|
n = 1;
|
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
memset (b, ' ', n);
|
|
|
|
b += n;
|
|
|
|
strcpy (b, t);
|
|
|
|
free (t);
|
|
|
|
i = 0;
|
|
|
|
word++;
|
2015-07-15 15:14:51 +02:00
|
|
|
if (ds->atabsonce) {
|
|
|
|
break;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-28 02:23:29 +01:00
|
|
|
static int handleMidFlags(RCore *core, RDisasmState *ds, bool print) {
|
|
|
|
int i;
|
2017-05-11 12:47:48 +02:00
|
|
|
|
2017-07-07 16:46:20 +02:00
|
|
|
ds->hasMidflag = false;
|
2017-05-11 12:49:03 +02:00
|
|
|
if (ds->midcursor && core->print->cur != -1) {
|
2017-05-11 12:47:48 +02:00
|
|
|
ut64 cur = core->offset + core->print->cur;
|
|
|
|
ut64 from = ds->at;
|
|
|
|
ut64 to = ds->at + ds->oplen;
|
|
|
|
if (cur > from && cur < to) {
|
|
|
|
return cur - from;
|
|
|
|
}
|
|
|
|
}
|
2015-11-28 02:23:29 +01:00
|
|
|
for (i = 1; i < ds->oplen; i++) {
|
2017-07-07 16:46:20 +02:00
|
|
|
RFlagItem *fi = r_flag_get_i (core->flags, ds->at + i);
|
|
|
|
if (fi && fi->name) {
|
|
|
|
if (ds->midflags == 2 && ((fi->name[0] == '$') || (fi->realname && fi->realname[0] == '$'))) {
|
2017-04-28 05:50:04 +02:00
|
|
|
i = 0;
|
|
|
|
} else if (!strncmp (fi->name, "hit.", 4)) { // use search.prefix ?
|
|
|
|
i = 0;
|
|
|
|
} else if (!strncmp (fi->name, "str.", 4)) {
|
2016-06-14 01:52:46 +02:00
|
|
|
ds->midflags = R_MIDFLAGS_REALIGN;
|
2017-04-28 05:50:04 +02:00
|
|
|
} else if (!strncmp (fi->name, "reloc.", 6)) {
|
2015-11-28 02:23:29 +01:00
|
|
|
if (print) {
|
2017-12-17 12:28:46 +01:00
|
|
|
ds_begin_json_line (ds);
|
|
|
|
r_cons_printf ("(%s)", fi->name);
|
|
|
|
ds_newline (ds);
|
2015-11-28 02:23:29 +01:00
|
|
|
}
|
|
|
|
continue;
|
2017-04-28 05:50:04 +02:00
|
|
|
} else if (ds->midflags == R_MIDFLAGS_SYMALIGN) {
|
|
|
|
if (strncmp (fi->name, "sym.", 4)) {
|
|
|
|
continue;
|
2016-11-02 12:10:50 +01:00
|
|
|
}
|
|
|
|
}
|
2017-04-28 05:50:04 +02:00
|
|
|
ds->hasMidflag = true;
|
2015-11-28 02:23:29 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_show_cursor(RDisasmState *ds) {
|
|
|
|
RCore *core = ds->core;
|
2015-11-28 02:23:29 +01:00
|
|
|
char res[] = " ";
|
2015-07-25 03:31:17 +02:00
|
|
|
void *p;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!ds->show_marks) {
|
2015-07-25 03:31:17 +02:00
|
|
|
return;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2017-05-13 12:41:30 +02:00
|
|
|
int q = core->print->cur_enabled &&
|
2014-05-04 19:21:05 +04:00
|
|
|
ds->cursor >= ds->index &&
|
2015-11-27 16:16:44 +01:00
|
|
|
ds->cursor < (ds->index + ds->asmop.size);
|
2015-07-25 03:31:17 +02:00
|
|
|
p = r_bp_get_at (core->dbg->bp, ds->at);
|
2017-05-13 12:41:30 +02:00
|
|
|
if (ds->midflags) {
|
|
|
|
(void)handleMidFlags (core, ds, false);
|
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
if (p) {
|
|
|
|
res[0] = 'b';
|
|
|
|
}
|
2017-04-28 05:50:04 +02:00
|
|
|
if (ds->hasMidflag) {
|
2016-09-23 16:28:48 +02:00
|
|
|
res[1] = '~';
|
|
|
|
}
|
2015-11-27 16:16:44 +01:00
|
|
|
if (q) {
|
|
|
|
if (ds->cursor == ds->index) {
|
2015-11-28 02:23:29 +01:00
|
|
|
res[2] = '*';
|
2015-11-27 16:16:44 +01:00
|
|
|
} else {
|
2015-11-28 02:23:29 +01:00
|
|
|
int i = 2, diff = ds->cursor - ds->index;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (diff > 9) {
|
|
|
|
res[i++] = '0' + (diff / 10);
|
|
|
|
}
|
2015-11-27 16:16:44 +01:00
|
|
|
res[i] = '0' + (diff % 10);
|
|
|
|
}
|
|
|
|
}
|
2015-11-27 14:09:37 +01:00
|
|
|
r_cons_strcat (res);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-03-04 00:33:24 +01:00
|
|
|
static int var_comparator(const RAnalVar *a, const RAnalVar *b){
|
2016-09-23 16:28:48 +02:00
|
|
|
if (a && b) {
|
|
|
|
return a->delta > b->delta;
|
|
|
|
}
|
2015-09-14 12:35:38 +02:00
|
|
|
return false;
|
2015-03-30 16:03:11 +02:00
|
|
|
}
|
|
|
|
|
2016-09-09 19:28:47 +02:00
|
|
|
//TODO: this function is a temporary fix. All analysis should be based on realsize. However, now for same architectures realisze is not used
|
2016-09-14 00:22:43 +02:00
|
|
|
static ut32 tmp_get_realsize (RAnalFunction *f) {
|
2016-09-09 19:28:47 +02:00
|
|
|
ut32 size = r_anal_fcn_realsize (f);
|
2016-09-14 00:22:43 +02:00
|
|
|
return (size > 0) ? size : r_anal_fcn_size (f);
|
2016-09-09 19:28:47 +02:00
|
|
|
}
|
|
|
|
|
2017-03-17 11:54:34 +01:00
|
|
|
static void ds_show_functions_argvar(RDisasmState *ds, RAnalVar *var, const char *base, bool is_var, char sign) {
|
|
|
|
int delta = sign == '+' ? var->delta : -var->delta;
|
|
|
|
const char *arg_or_var = is_var ? "var" : "arg";
|
|
|
|
r_cons_printf ("%s %s %s @ %s%c0x%x", arg_or_var, var->type, var->name,
|
|
|
|
base, sign, delta);
|
|
|
|
}
|
|
|
|
|
2018-02-06 13:13:55 +01:00
|
|
|
static void printVarSummary(RDisasmState *ds, RList *list) {
|
2018-02-10 00:30:55 +01:00
|
|
|
const char *numColor = ds->core->cons->pal.num;
|
2017-04-07 21:09:33 +02:00
|
|
|
RAnalVar *var;
|
|
|
|
RListIter *iter;
|
2018-02-06 13:13:55 +01:00
|
|
|
int bp_vars = 0;
|
|
|
|
int sp_vars = 0;
|
|
|
|
int rg_vars = 0;
|
|
|
|
int bp_args = 0;
|
|
|
|
int sp_args = 0;
|
|
|
|
int rg_args = 0;
|
2018-02-10 00:30:55 +01:00
|
|
|
const char *bp_vars_color = COLOR_RESET (ds);
|
|
|
|
const char *sp_vars_color = COLOR_RESET (ds);
|
|
|
|
const char *rg_vars_color = COLOR_RESET (ds);
|
|
|
|
const char *bp_args_color = COLOR_RESET (ds);
|
|
|
|
const char *sp_args_color = COLOR_RESET (ds);
|
|
|
|
const char *rg_args_color = COLOR_RESET (ds);
|
2017-04-07 21:09:33 +02:00
|
|
|
r_list_foreach (list, iter, var) {
|
|
|
|
if (var->delta > 0) {
|
2018-02-10 00:30:55 +01:00
|
|
|
switch (var->kind) {
|
2018-02-06 13:13:55 +01:00
|
|
|
case 'b':
|
|
|
|
bp_args++;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
sp_args++;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
rg_args++;
|
|
|
|
break;
|
|
|
|
}
|
2017-04-07 21:09:33 +02:00
|
|
|
} else {
|
2018-02-10 00:30:55 +01:00
|
|
|
switch (var->kind) {
|
2018-02-06 13:13:55 +01:00
|
|
|
case 'b':
|
|
|
|
bp_vars++;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
sp_vars++;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
rg_vars++;
|
|
|
|
break;
|
|
|
|
}
|
2017-04-07 21:09:33 +02:00
|
|
|
}
|
|
|
|
}
|
2018-02-10 00:30:55 +01:00
|
|
|
if (bp_vars) { bp_vars_color = numColor; }
|
|
|
|
if (sp_vars) { sp_vars_color = numColor; }
|
|
|
|
if (rg_vars) { rg_vars_color = numColor; }
|
|
|
|
if (bp_args) { bp_args_color = numColor; }
|
|
|
|
if (sp_args) { sp_args_color = numColor; }
|
|
|
|
if (rg_args) { rg_args_color = numColor; }
|
2018-02-06 13:13:55 +01:00
|
|
|
if (ds->show_varsum == 2) {
|
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2018-02-06 13:13:55 +01:00
|
|
|
r_cons_printf ("vars: %s%d%s %s%d%s %s%d%s",
|
|
|
|
bp_vars_color, bp_vars, COLOR_RESET (ds),
|
|
|
|
sp_vars_color, sp_vars, COLOR_RESET (ds),
|
|
|
|
rg_vars_color, rg_vars, COLOR_RESET (ds));
|
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2018-02-06 13:13:55 +01:00
|
|
|
r_cons_printf ("args: %s%d%s %s%d%s %s%d%s",
|
|
|
|
bp_args_color, bp_args, COLOR_RESET (ds),
|
|
|
|
sp_args_color, sp_args, COLOR_RESET (ds),
|
|
|
|
rg_args_color, rg_args, COLOR_RESET (ds));
|
|
|
|
ds_newline (ds);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-04 12:15:26 +01:00
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2018-02-06 13:13:55 +01:00
|
|
|
r_cons_printf ("bp: %s%d%s (vars %s%d%s, args %s%d%s)",
|
2018-02-10 00:30:55 +01:00
|
|
|
bp_args || bp_vars ? numColor : COLOR_RESET (ds), bp_args + bp_vars, COLOR_RESET (ds),
|
2018-02-06 13:13:55 +01:00
|
|
|
bp_vars_color, bp_vars, COLOR_RESET (ds),
|
|
|
|
bp_args_color, bp_args, COLOR_RESET (ds));
|
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2018-02-06 13:13:55 +01:00
|
|
|
r_cons_printf ("sp: %s%d%s (vars %s%d%s, args %s%d%s)",
|
2018-02-10 00:30:55 +01:00
|
|
|
sp_args || sp_vars ? numColor : COLOR_RESET (ds), sp_args+sp_vars, COLOR_RESET (ds),
|
2018-02-06 13:13:55 +01:00
|
|
|
sp_vars_color, sp_vars, COLOR_RESET (ds),
|
|
|
|
sp_args_color, sp_args, COLOR_RESET (ds));
|
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
2018-02-06 13:13:55 +01:00
|
|
|
r_cons_printf ("rg: %s%d%s (vars %s%d%s, args %s%d%s)",
|
2018-02-10 00:30:55 +01:00
|
|
|
rg_args || rg_vars ? numColor : COLOR_RESET (ds), rg_args+rg_vars, COLOR_RESET (ds),
|
2018-02-06 13:13:55 +01:00
|
|
|
rg_vars_color, rg_vars, COLOR_RESET (ds),
|
|
|
|
rg_args_color, rg_args, COLOR_RESET (ds));
|
2018-02-04 12:15:26 +01:00
|
|
|
ds_newline (ds);
|
2017-04-07 21:09:33 +02:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_show_functions(RDisasmState *ds) {
|
2015-03-16 02:52:26 +01:00
|
|
|
RAnalFunction *f;
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2016-05-14 12:04:07 +03:00
|
|
|
bool demangle, call;
|
2016-02-16 02:08:09 +01:00
|
|
|
const char *lang;
|
2016-02-07 21:44:35 +01:00
|
|
|
char *fcn_name;
|
2015-03-16 02:52:26 +01:00
|
|
|
char *sign;
|
2016-05-04 17:13:44 +02:00
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
if (!ds->show_functions) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-05-04 17:13:44 +02:00
|
|
|
}
|
2016-02-16 02:08:09 +01:00
|
|
|
demangle = r_config_get_i (core->config, "bin.demangle");
|
2016-05-14 12:04:07 +03:00
|
|
|
call = r_config_get_i (core->config, "asm.calls");
|
2016-02-16 02:08:09 +01:00
|
|
|
lang = demangle ? r_config_get (core->config, "bin.lang") : NULL;
|
2015-03-16 02:52:26 +01:00
|
|
|
f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2016-05-04 17:13:44 +02:00
|
|
|
if (!f || (f->addr != ds->at)) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-05-04 17:13:44 +02:00
|
|
|
}
|
2016-02-07 21:44:35 +01:00
|
|
|
if (demangle) {
|
2016-11-22 14:58:42 +01:00
|
|
|
fcn_name = r_bin_demangle (core->bin->cur, lang, f->name, f->addr);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!fcn_name) {
|
2016-02-07 21:44:35 +01:00
|
|
|
fcn_name = strdup (f->name);
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2016-02-07 21:44:35 +01:00
|
|
|
} else {
|
|
|
|
fcn_name = f->name;
|
2015-03-16 02:52:26 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2015-03-16 02:52:26 +01:00
|
|
|
sign = r_anal_fcn_to_string (core->anal, f);
|
|
|
|
if (f->type == R_ANAL_FCN_TYPE_LOC) {
|
2015-11-02 12:38:08 +01:00
|
|
|
r_cons_printf ("%s%s ", COLOR (ds, color_fline),
|
|
|
|
core->cons->vline[LINE_CROSS]); // |-
|
2017-12-11 15:07:44 +01:00
|
|
|
r_cons_printf ("%s%s%s %d", COLOR (ds, color_floc),
|
2016-05-15 14:37:22 +02:00
|
|
|
fcn_name, COLOR_RESET (ds), r_anal_fcn_size (f));
|
2015-03-16 02:52:26 +01:00
|
|
|
} else {
|
2015-11-02 12:38:08 +01:00
|
|
|
const char *fcntype;
|
2016-03-15 11:47:13 +01:00
|
|
|
char cmt[32];
|
|
|
|
get_bits_comment (core, f, cmt, sizeof (cmt));
|
2015-11-02 12:38:08 +01:00
|
|
|
|
|
|
|
switch (f->type) {
|
|
|
|
case R_ANAL_FCN_TYPE_FCN:
|
|
|
|
case R_ANAL_FCN_TYPE_SYM:
|
|
|
|
fcntype = "fcn"; break;
|
|
|
|
case R_ANAL_FCN_TYPE_IMP:
|
|
|
|
fcntype = "imp"; break;
|
|
|
|
default:
|
|
|
|
fcntype = "loc"; break;
|
|
|
|
}
|
2014-12-14 23:08:05 +01:00
|
|
|
#if SLOW_BUT_OK
|
2015-11-02 12:38:08 +01:00
|
|
|
int corner = (f->size <= ds->analop.size) ? RDWN_CORNER : LINE_VERT;
|
2015-03-16 02:52:26 +01:00
|
|
|
corner = LINE_VERT; // 99% of cases
|
|
|
|
RFlagItem *item = r_flag_get_i (core->flags, f->addr);
|
2015-11-02 12:38:08 +01:00
|
|
|
corner = item ? LINE_VERT : RDWN_CORNER;
|
|
|
|
if (item) {
|
2015-03-16 02:52:26 +01:00
|
|
|
corner = 0;
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
#endif
|
2018-02-06 15:30:10 +01:00
|
|
|
//ds_set_pre (ds, core->cons->vline[CORNER_TL]);
|
|
|
|
if (ds->show_fcnlines) {
|
|
|
|
ds->pre = DS_PRE_FCN_HEAD;
|
|
|
|
}
|
|
|
|
ds_print_pre (ds);
|
2016-03-04 00:33:24 +01:00
|
|
|
if (ds->show_flgoff) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_lines_left (ds);
|
|
|
|
ds_print_offset (ds);
|
2016-03-04 00:33:24 +01:00
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
r_cons_printf ("%s(%s) %s%s%s %d",
|
|
|
|
COLOR (ds, color_fname),
|
|
|
|
fcntype, fcn_name, cmt, COLOR_RESET (ds), tmp_get_realsize (f));
|
2015-03-16 02:52:26 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (sign) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
|
|
|
r_cons_printf ("// %s", sign);
|
|
|
|
ds_newline (ds);
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-07-25 03:31:17 +02:00
|
|
|
R_FREE (sign);
|
2016-05-04 17:13:44 +02:00
|
|
|
if (ds->show_fcnlines) {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_FCN_MIDDLE;
|
2016-05-04 17:13:44 +02:00
|
|
|
}
|
2017-01-31 10:00:24 +01:00
|
|
|
ds->stackptr = core->anal->stackptr;
|
2017-04-07 21:09:33 +02:00
|
|
|
if (ds->show_vars && ds->show_varsum) {
|
2018-02-06 13:13:55 +01:00
|
|
|
RList *vars = r_anal_var_list (core->anal, f, 'b');
|
|
|
|
r_list_join(vars, r_anal_var_list (core->anal, f, 'r'));
|
|
|
|
r_list_join(vars, r_anal_var_list (core->anal, f, 's'));
|
|
|
|
printVarSummary(ds, vars);
|
|
|
|
r_list_free (vars);
|
2017-04-07 21:09:33 +02:00
|
|
|
} else if (ds->show_vars) {
|
2015-03-16 02:52:26 +01:00
|
|
|
char spaces[32];
|
2016-05-14 12:04:07 +03:00
|
|
|
RAnalVar *var;
|
|
|
|
RListIter *iter;
|
2016-07-01 17:15:29 +03:00
|
|
|
RList *args = r_anal_var_list (core->anal, f, 'b');
|
|
|
|
RList *regs = r_anal_var_list (core->anal, f, 'r');
|
|
|
|
RList *sp_vars = r_anal_var_list (core->anal, f, 's');
|
2015-03-31 00:49:45 +02:00
|
|
|
r_list_sort (args, (RListComparator)var_comparator);
|
2016-06-06 01:33:42 +03:00
|
|
|
r_list_sort (regs, (RListComparator)var_comparator);
|
2016-05-01 15:48:04 +03:00
|
|
|
r_list_sort (sp_vars, (RListComparator)var_comparator);
|
2016-05-14 12:04:07 +03:00
|
|
|
if (call) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
r_cons_print (COLOR (ds, color_fline));
|
|
|
|
ds_print_pre (ds);
|
|
|
|
r_cons_printf ("%s %s %s%s (",
|
2016-05-14 12:04:07 +03:00
|
|
|
COLOR_RESET (ds), COLOR (ds, color_fname),
|
|
|
|
fcn_name, COLOR_RESET (ds));
|
2016-09-15 12:09:23 +03:00
|
|
|
bool comma = true;
|
|
|
|
bool arg_bp = false;
|
|
|
|
int tmp_len;
|
|
|
|
r_list_foreach (regs, iter, var) {
|
|
|
|
tmp_len = strlen (var->type);
|
|
|
|
r_cons_printf ("%s%s%s%s", var->type,
|
|
|
|
tmp_len && var->type[tmp_len - 1] == '*' ? "" : " ",
|
|
|
|
var->name, iter->n ? ", " : "");
|
|
|
|
}
|
2016-05-14 12:04:07 +03:00
|
|
|
r_list_foreach (args, iter, var) {
|
2016-09-15 12:09:23 +03:00
|
|
|
if (var->delta > 0) {
|
|
|
|
if (!r_list_empty (regs) && comma) {
|
|
|
|
r_cons_printf (", ");
|
|
|
|
comma = false;
|
|
|
|
}
|
|
|
|
arg_bp = true;
|
|
|
|
tmp_len = strlen (var->type);
|
|
|
|
r_cons_printf ("%s%s%s%s", var->type,
|
|
|
|
tmp_len && var->type[tmp_len - 1] =='*' ? "" : " ",
|
|
|
|
var->name, iter->n ? ", " : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
comma = true;
|
|
|
|
r_list_foreach (sp_vars, iter, var) {
|
2017-03-09 14:23:41 +02:00
|
|
|
if (var->delta > f->maxstack) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if ((arg_bp || !r_list_empty (regs)) && comma) {
|
2016-09-15 12:09:23 +03:00
|
|
|
comma = false;
|
|
|
|
r_cons_printf (", ");
|
|
|
|
}
|
|
|
|
tmp_len = strlen (var->type);
|
|
|
|
r_cons_printf ("%s%s%s%s", var->type,
|
|
|
|
tmp_len && var->type[tmp_len - 1] =='*' ? "" : " ",
|
|
|
|
var->name, iter->n ? ", " : "");
|
|
|
|
}
|
2016-05-14 12:04:07 +03:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
r_cons_printf (");");
|
|
|
|
ds_newline (ds);
|
2016-05-14 12:04:07 +03:00
|
|
|
}
|
2016-06-06 01:33:42 +03:00
|
|
|
r_list_join (args, sp_vars);
|
|
|
|
r_list_join (args, regs);
|
2015-03-30 16:03:11 +02:00
|
|
|
r_list_foreach (args, iter, var) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2016-05-19 01:22:43 +02:00
|
|
|
char *tmp;
|
2015-03-16 02:52:26 +01:00
|
|
|
int idx;
|
2016-06-06 01:33:42 +03:00
|
|
|
RAnal *anal = ds->core->anal;
|
2015-03-16 02:52:26 +01:00
|
|
|
memset (spaces, ' ', sizeof(spaces));
|
2015-11-02 12:38:08 +01:00
|
|
|
idx = 12 - strlen (var->name);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (idx < 0) {
|
|
|
|
idx = 0;
|
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
spaces[idx] = 0;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_setup_print_pre (ds, false, true);
|
2016-05-19 01:22:43 +02:00
|
|
|
|
|
|
|
tmp = ds->line;
|
|
|
|
ds->line = ds->refline2;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_lines_left (ds);
|
2016-05-19 01:22:43 +02:00
|
|
|
ds->line = tmp;
|
|
|
|
|
2016-04-05 00:56:48 +02:00
|
|
|
if (ds->show_flgoff) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_offset (ds);
|
2016-04-05 01:33:57 +02:00
|
|
|
r_cons_printf (" ");
|
2016-04-05 00:56:48 +02:00
|
|
|
}
|
2016-04-10 21:59:11 +03:00
|
|
|
r_cons_printf ("%s; ", COLOR (ds, color_other));
|
|
|
|
switch (var->kind) {
|
2017-03-17 11:54:34 +01:00
|
|
|
case 'b': {
|
|
|
|
char sign = var->delta > 0 ? '+' : '-';
|
|
|
|
bool is_var = var->delta <= 0;
|
|
|
|
ds_show_functions_argvar (ds, var,
|
|
|
|
anal->reg->name[R_REG_NAME_BP], is_var, sign);
|
2016-06-06 01:33:42 +03:00
|
|
|
}
|
|
|
|
break;
|
2016-07-01 17:15:29 +03:00
|
|
|
case 'r': {
|
2016-06-06 01:33:42 +03:00
|
|
|
RRegItem *i = r_reg_index_get (anal->reg, var->delta);
|
|
|
|
if (!i) {
|
|
|
|
eprintf("Register not found");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_cons_printf ("reg %s %s @ %s",
|
|
|
|
var->type, var->name, i->name);
|
2016-04-10 21:59:11 +03:00
|
|
|
}
|
|
|
|
break;
|
2017-03-17 11:54:34 +01:00
|
|
|
case 's': {
|
|
|
|
bool is_var = var->delta < f->maxstack;
|
|
|
|
ds_show_functions_argvar (ds, var,
|
|
|
|
anal->reg->name[R_REG_NAME_SP],
|
|
|
|
is_var, '+');
|
2016-06-06 01:33:42 +03:00
|
|
|
}
|
2016-05-01 15:48:04 +03:00
|
|
|
break;
|
2016-06-06 01:33:42 +03:00
|
|
|
}
|
2016-06-13 00:39:40 +03:00
|
|
|
char *comment = r_meta_get_var_comment (anal, var->kind, var->delta, f->addr);
|
2016-06-10 19:08:12 +03:00
|
|
|
if (comment) {
|
2017-12-11 15:07:44 +01:00
|
|
|
char *comment_esc = NULL;
|
|
|
|
if (ds->use_json) {
|
|
|
|
comment = comment_esc = ds_esc_str (ds, comment, (int)strlen (comment), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (comment) {
|
|
|
|
r_cons_printf (" %s; %s", COLOR (ds, color_comment), comment);
|
|
|
|
}
|
|
|
|
if (comment_esc) {
|
|
|
|
free (comment_esc);
|
|
|
|
}
|
2016-06-10 19:08:12 +03:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
r_cons_print (COLOR_RESET (ds));
|
|
|
|
ds_newline (ds);
|
2014-12-18 12:54:36 +01:00
|
|
|
}
|
2016-06-06 01:33:42 +03:00
|
|
|
r_list_free (regs);
|
2015-03-16 02:52:26 +01:00
|
|
|
// it's already empty, but rlist instance is still there
|
|
|
|
r_list_free (args);
|
2016-06-06 01:33:42 +03:00
|
|
|
r_list_free (sp_vars);
|
2014-12-13 18:06:01 +01:00
|
|
|
}
|
2016-09-26 23:13:49 +02:00
|
|
|
if (demangle) {
|
2016-02-07 21:44:35 +01:00
|
|
|
free (fcn_name);
|
2016-09-26 23:13:49 +02:00
|
|
|
}
|
2014-12-13 18:06:01 +01:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_setup_print_pre(RDisasmState *ds, bool tail, bool middle) {
|
|
|
|
ds_setup_pre (ds, tail, middle);
|
|
|
|
ds_print_pre (ds);
|
2016-04-27 22:17:19 +02:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_setup_pre(RDisasmState *ds, bool tail, bool middle) {
|
2017-11-24 23:19:26 +01:00
|
|
|
ds->cmtcount = 0;
|
2018-02-06 15:30:10 +01:00
|
|
|
if (!ds->show_functions || !ds->show_fcnlines) {
|
|
|
|
ds->pre = DS_PRE_NONE;
|
2016-09-23 16:28:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_EMPTY;
|
|
|
|
RAnalFunction *f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2016-03-04 00:33:24 +01:00
|
|
|
if (f) {
|
|
|
|
if (f->addr == ds->at) {
|
2016-05-19 01:22:43 +02:00
|
|
|
if (ds->analop.size == r_anal_fcn_size (f) && !middle) {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_FCN_TAIL;
|
2016-03-04 00:33:24 +01:00
|
|
|
} else {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_FCN_MIDDLE;
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2016-05-15 14:37:22 +02:00
|
|
|
} else if (f->addr + r_anal_fcn_size (f) - ds->analop.size == ds->at) {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_FCN_TAIL;
|
2016-05-14 16:37:24 +02:00
|
|
|
} else if (r_anal_fcn_is_in_offset (f, ds->at)) {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds->pre = DS_PRE_FCN_MIDDLE;
|
2016-03-04 00:33:24 +01:00
|
|
|
}
|
|
|
|
if (tail) {
|
2018-02-06 15:30:10 +01:00
|
|
|
if (ds->pre == DS_PRE_FCN_TAIL) {
|
|
|
|
ds->pre = DS_PRE_EMPTY;
|
|
|
|
}
|
|
|
|
if (ds->pre == DS_PRE_FCN_MIDDLE) {
|
|
|
|
ds->pre = DS_PRE_FCN_TAIL;
|
|
|
|
}
|
2016-03-04 00:33:24 +01:00
|
|
|
}
|
2016-04-27 22:17:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_pre(RDisasmState *ds) {
|
2018-02-06 15:30:10 +01:00
|
|
|
RCore *core = ds->core;
|
|
|
|
|
|
|
|
const char *c = NULL;
|
|
|
|
switch(ds->pre) {
|
|
|
|
case DS_PRE_FCN_HEAD:
|
|
|
|
c = core->cons->vline[CORNER_TL];
|
|
|
|
break;
|
|
|
|
case DS_PRE_FCN_MIDDLE:
|
|
|
|
c = core->cons->vline[LINE_VERT];
|
|
|
|
break;
|
|
|
|
case DS_PRE_FCN_TAIL:
|
|
|
|
c = core->cons->vline[CORNER_BL];
|
|
|
|
break;
|
|
|
|
case DS_PRE_EMPTY:
|
|
|
|
r_cons_print (" ");
|
|
|
|
case DS_PRE_NONE:
|
|
|
|
default:
|
2016-04-27 22:17:19 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
|
|
|
|
char *c_esc = NULL;
|
|
|
|
if (ds->use_json) {
|
|
|
|
c = c_esc = r_str_escape (c);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
r_cons_printf ("%s%s%s ",
|
|
|
|
COLOR (ds, color_fline), c,
|
|
|
|
COLOR_RESET (ds));
|
|
|
|
free (c_esc);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2018-02-22 17:59:08 +01:00
|
|
|
//XXX review this with asm.cmt.right
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_show_comments_right(RDisasmState *ds) {
|
2015-06-05 00:19:41 +02:00
|
|
|
int linelen, maxclen ;
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2015-03-16 02:52:26 +01:00
|
|
|
RFlagItem *item;
|
2014-01-16 11:04:42 -06:00
|
|
|
/* show comment at right? */
|
2015-06-05 00:19:41 +02:00
|
|
|
int scr = ds->show_comment_right;
|
2016-05-17 10:36:33 +02:00
|
|
|
if (!ds->show_comments) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-05-17 10:36:33 +02:00
|
|
|
}
|
2017-01-11 12:23:48 +01:00
|
|
|
//RAnalFunction *f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2015-03-16 02:52:26 +01:00
|
|
|
item = r_flag_get_i (core->flags, ds->at);
|
|
|
|
ds->comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ds->at);
|
2015-04-11 04:33:37 +02:00
|
|
|
if (!ds->comment && item && item->comment && *item->comment) {
|
2015-03-16 02:52:26 +01:00
|
|
|
ds->ocomment = item->comment;
|
|
|
|
ds->comment = strdup (item->comment);
|
|
|
|
}
|
2016-05-17 10:36:33 +02:00
|
|
|
if (!ds->comment) {
|
2015-03-16 02:52:26 +01:00
|
|
|
return;
|
2016-05-17 10:36:33 +02:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
maxclen = strlen (ds->comment) + 5;
|
2015-03-16 02:52:26 +01:00
|
|
|
linelen = maxclen;
|
|
|
|
if (ds->show_comment_right_default) {
|
2016-12-24 18:17:25 +01:00
|
|
|
if (ds->ocols + maxclen < core->cons->columns) {
|
2016-12-26 20:10:10 +01:00
|
|
|
if (ds->comment && *ds->comment && strlen (ds->comment) < maxclen) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!strchr (ds->comment, '\n')) { // more than one line?
|
2015-03-16 02:52:26 +01:00
|
|
|
ds->show_comment_right = 1;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ds->show_comment_right) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2016-12-26 20:10:10 +01:00
|
|
|
int mycols = ds->lcols;
|
2017-11-09 22:01:48 +01:00
|
|
|
if ((mycols + linelen + 10) > core->cons->columns) {
|
2015-03-16 02:52:26 +01:00
|
|
|
mycols = 0;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-03-16 02:52:26 +01:00
|
|
|
mycols /= 2;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
2015-06-02 01:04:10 +02:00
|
|
|
/* print multiline comment */
|
|
|
|
if (ds->cmtfold) {
|
2017-11-09 22:01:48 +01:00
|
|
|
char *p = strdup (ds->comment);
|
2016-04-08 02:56:42 +02:00
|
|
|
char *q = strchr (p, '\n');
|
2015-06-02 01:04:10 +02:00
|
|
|
if (q) {
|
|
|
|
*q = 0;
|
|
|
|
r_cons_strcat (p);
|
|
|
|
r_cons_strcat (" ; [z] unfold");
|
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
} else {
|
2016-12-26 20:10:10 +01:00
|
|
|
ds->comment = r_str_prefix_all (ds->comment, "; ");
|
2017-12-24 01:03:19 +01:00
|
|
|
if (ds->show_comment_right) {
|
|
|
|
ALIGN;
|
|
|
|
} else {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, false);
|
2017-12-24 01:03:19 +01:00
|
|
|
}
|
2017-11-09 22:01:48 +01:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->color_usrcmt);
|
|
|
|
}
|
2017-07-11 07:54:38 +02:00
|
|
|
ds_comment (ds, false, "%s", ds->comment);
|
2015-06-02 01:04:10 +02:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
ds_print_color_reset (ds);
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->comment);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2015-03-16 02:52:26 +01:00
|
|
|
/* flag one */
|
|
|
|
if (item && item->comment && ds->ocomment != item->comment) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2015-03-16 02:52:26 +01:00
|
|
|
r_cons_strcat (" ; ");
|
|
|
|
r_cons_strcat_justify (item->comment, mycols, ';');
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
ds_print_color_reset (ds);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
2015-06-05 00:19:41 +02:00
|
|
|
ds->show_comment_right = scr;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2018-02-12 14:53:35 -06:00
|
|
|
static int flagCmp(const void *a, const void *b) {
|
|
|
|
const RFlagItem *fa = a;
|
|
|
|
const RFlagItem *fb = b;
|
|
|
|
if (fa->realname && fb->realname) {
|
|
|
|
return !strcmp (fa->realname, fb->realname);
|
|
|
|
}
|
|
|
|
return !strcmp (fa->name, fb->name);
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_show_flags(RDisasmState *ds) {
|
2016-03-23 22:13:55 +01:00
|
|
|
//const char *beginch;
|
2016-03-04 00:33:24 +01:00
|
|
|
RFlagItem *flag;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalFunction *f;
|
|
|
|
const RList /*RFlagList*/ *flaglist;
|
|
|
|
if (!ds->show_flags) {
|
|
|
|
return;
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2017-11-23 18:35:13 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2017-11-23 22:46:57 +01:00
|
|
|
f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2016-03-04 00:33:24 +01:00
|
|
|
flaglist = r_flag_get_list (core->flags, ds->at);
|
2018-02-12 14:53:35 -06:00
|
|
|
RList *uniqlist = r_list_uniq (flaglist, flagCmp);
|
2018-02-12 16:00:14 -06:00
|
|
|
r_list_foreach (uniqlist, iter, flag) {
|
2016-03-04 00:33:24 +01:00
|
|
|
if (f && f->addr == flag->offset && !strcmp (flag->name, f->name)) {
|
|
|
|
// do not show flags that have the same name as the function
|
|
|
|
continue;
|
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_begin_json_line (ds);
|
2016-03-04 00:33:24 +01:00
|
|
|
if (ds->show_flgoff) {
|
2018-02-06 19:56:47 +01:00
|
|
|
ds_beginline (ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_offset (ds);
|
2016-03-04 00:33:24 +01:00
|
|
|
r_cons_printf (" ");
|
|
|
|
} else {
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_pre_xrefs (ds, true);
|
2017-12-24 13:18:20 +01:00
|
|
|
r_cons_printf (";-- ");
|
2016-03-04 00:33:24 +01:00
|
|
|
}
|
2016-12-20 14:54:29 +01:00
|
|
|
if (ds->show_color) {
|
2017-11-24 23:52:22 +01:00
|
|
|
bool hasColor = false;
|
|
|
|
if (flag->color) {
|
2018-02-23 19:00:47 +01:00
|
|
|
char *color = r_cons_pal_parse (flag->color, NULL);
|
2017-11-24 23:52:22 +01:00
|
|
|
if (color) {
|
|
|
|
r_cons_strcat (color);
|
|
|
|
free (color);
|
|
|
|
ds->lastflag = flag;
|
|
|
|
hasColor = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!hasColor) {
|
|
|
|
r_cons_strcat (ds->color_flag);
|
|
|
|
}
|
2016-12-20 14:54:29 +01:00
|
|
|
}
|
2016-08-23 13:11:30 +02:00
|
|
|
if (ds->asm_demangle && flag->realname) {
|
2016-03-04 00:33:24 +01:00
|
|
|
const char *lang = r_config_get (core->config, "bin.lang");
|
2016-11-22 14:58:42 +01:00
|
|
|
char *name = r_bin_demangle (core->bin->cur, lang, flag->realname, flag->offset);
|
2017-11-24 23:52:22 +01:00
|
|
|
r_cons_printf ("%s:", name? name: flag->realname);
|
2016-03-04 00:33:24 +01:00
|
|
|
R_FREE (name);
|
|
|
|
} else {
|
2017-11-24 23:52:22 +01:00
|
|
|
r_cons_printf ("%s:", flag->name);
|
|
|
|
}
|
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (Color_RESET);
|
2015-01-17 01:56:20 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2018-02-12 16:00:14 -06:00
|
|
|
r_list_free (uniqlist);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_update_ref_lines(RDisasmState *ds) {
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_lines) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->line = r_anal_reflines_str (ds->core, ds->at, ds->linesopts);
|
2016-04-04 00:17:57 +02:00
|
|
|
free (ds->refline);
|
2016-04-04 22:30:11 +02:00
|
|
|
ds->refline = ds->line? strdup (ds->line): NULL;
|
2016-04-04 00:17:57 +02:00
|
|
|
free (ds->refline2);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->refline2 = r_anal_reflines_str (ds->core, ds->at,
|
2015-11-06 15:46:14 +01:00
|
|
|
ds->linesopts | R_ANAL_REFLINE_TYPE_MIDDLE);
|
2015-08-30 23:34:21 +02:00
|
|
|
if (ds->line) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (strchr (ds->line, '<')) {
|
2015-08-30 23:34:21 +02:00
|
|
|
ds->indent_level++;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
|
|
|
if (strchr (ds->line, '>')) {
|
2015-08-30 23:34:21 +02:00
|
|
|
ds->indent_level--;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-08-30 23:34:21 +02:00
|
|
|
} else {
|
|
|
|
ds->indent_level = 0;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
} else {
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->line);
|
2014-01-20 01:42:16 +01:00
|
|
|
free (ds->refline);
|
|
|
|
free (ds->refline2);
|
|
|
|
ds->refline = strdup ("");
|
|
|
|
ds->refline2 = strdup ("");
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static int ds_disassemble(RDisasmState *ds, ut8 *buf, int len) {
|
|
|
|
RCore *core = ds->core;
|
2016-04-21 01:38:08 +02:00
|
|
|
int ret;
|
2017-02-03 08:53:57 +00:00
|
|
|
const char *info;
|
2017-01-29 20:30:17 +01:00
|
|
|
Sdb *s = core->anal->sdb_meta;
|
|
|
|
char key[100];
|
2017-01-31 23:33:27 +01:00
|
|
|
ut64 mt_sz = UT64_MAX;
|
2017-01-29 20:30:17 +01:00
|
|
|
|
|
|
|
//handle meta info to fix ds->oplen
|
|
|
|
snprintf (key, sizeof (key) - 1, "meta.0x%"PFMT64x, ds->at);
|
|
|
|
info = sdb_const_get (s, key, 0);
|
|
|
|
if (info) {
|
|
|
|
for (;*info; info++) {
|
2017-01-31 23:33:27 +01:00
|
|
|
switch (*info) {
|
|
|
|
case R_META_TYPE_DATA:
|
|
|
|
case R_META_TYPE_STRING:
|
|
|
|
case R_META_TYPE_FORMAT:
|
|
|
|
case R_META_TYPE_MAGIC:
|
|
|
|
case R_META_TYPE_HIDE:
|
2017-02-03 08:53:57 +00:00
|
|
|
snprintf (key, sizeof (key) - 1,
|
2017-01-31 23:33:27 +01:00
|
|
|
"meta.%c.0x%"PFMT64x, *info, ds->at);
|
2017-02-03 08:53:57 +00:00
|
|
|
sdb_const_get (s, key, 0);
|
2017-01-31 23:33:27 +01:00
|
|
|
mt_sz = sdb_array_get_num (s, key, 0, 0);
|
2017-08-25 18:12:12 +02:00
|
|
|
//if (mt_sz) { break; }
|
2017-01-29 20:30:17 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-21 01:38:08 +02:00
|
|
|
|
2016-05-30 04:18:48 +02:00
|
|
|
if (ds->hint && ds->hint->size) {
|
|
|
|
ds->oplen = ds->hint->size;
|
|
|
|
}
|
2016-04-21 01:38:08 +02:00
|
|
|
if (ds->hint && ds->hint->opcode) {
|
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (ds->hint->opcode);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
ret = r_asm_disassemble (core->assembler, &ds->asmop, buf, len);
|
2016-08-10 18:49:44 +02:00
|
|
|
if (ds->asmop.size < 1) {
|
|
|
|
ds->asmop.size = 1;
|
|
|
|
}
|
2015-11-02 21:30:55 +01:00
|
|
|
|
2016-01-10 22:30:10 +01:00
|
|
|
if (ds->show_nodup) {
|
2016-01-11 22:28:22 +01:00
|
|
|
const char *opname = (ret < 1)? "invalid": ds->asmop.buf_asm;
|
|
|
|
if (ds->prev_ins && !strcmp (ds->prev_ins, opname)) {
|
2016-01-10 22:30:10 +01:00
|
|
|
if (!ds->prev_ins_eq) {
|
2016-01-11 22:28:22 +01:00
|
|
|
ds->prev_ins_eq = true;
|
|
|
|
r_cons_printf ("...");
|
2016-01-10 22:30:10 +01:00
|
|
|
}
|
2017-01-29 20:30:17 +01:00
|
|
|
ds->prev_ins_count++;
|
2016-01-10 22:30:10 +01:00
|
|
|
return -31337;
|
|
|
|
}
|
2016-01-11 22:28:22 +01:00
|
|
|
if (ds->prev_ins_eq) {
|
|
|
|
r_cons_printf ("dup (%d)\n", ds->prev_ins_count);
|
|
|
|
}
|
|
|
|
ds->prev_ins_count = 0;
|
2016-01-10 22:30:10 +01:00
|
|
|
ds->prev_ins_eq = false;
|
|
|
|
if (ds->prev_ins) {
|
|
|
|
R_FREE (ds->prev_ins);
|
|
|
|
}
|
|
|
|
ds->prev_ins = strdup (ds->asmop.buf_asm);
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->oplen = ds->asmop.size;
|
2014-01-16 11:04:42 -06:00
|
|
|
|
2015-11-02 21:30:55 +01:00
|
|
|
if (ret < 1) {
|
2014-01-16 11:04:42 -06:00
|
|
|
ret = -1;
|
|
|
|
#if HASRETRY
|
2015-11-02 21:30:55 +01:00
|
|
|
if (!ds->cbytes && ds->tries > 0) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->addr = core->assembler->pc;
|
|
|
|
ds->tries--;
|
|
|
|
ds->idx = 0;
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->retry = true;
|
2014-01-16 11:04:42 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->lastfail = 1;
|
2016-09-23 16:28:48 +02:00
|
|
|
ds->asmop.size = (ds->hint && ds->hint->size) ? ds->hint->size : 1;
|
2016-05-30 04:18:48 +02:00
|
|
|
ds->oplen = ds->asmop.size;
|
2014-01-16 11:04:42 -06:00
|
|
|
} else {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->lastfail = 0;
|
2017-02-03 08:53:57 +00:00
|
|
|
ds->asmop.size = (ds->hint && ds->hint->size)
|
|
|
|
? ds->hint->size
|
2017-01-29 20:30:17 +01:00
|
|
|
: r_asm_op_get_size (&ds->asmop);
|
2014-12-21 04:18:56 +01:00
|
|
|
ds->oplen = ds->asmop.size;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->pseudo) {
|
2017-02-03 08:53:57 +00:00
|
|
|
r_parse_parse (core->parser, ds->opstr
|
2017-05-08 20:21:06 +02:00
|
|
|
? ds->opstr
|
2017-02-03 08:53:57 +00:00
|
|
|
: ds->asmop.buf_asm,
|
2017-01-29 20:30:17 +01:00
|
|
|
ds->str);
|
2014-01-20 01:42:16 +01:00
|
|
|
free (ds->opstr);
|
|
|
|
ds->opstr = strdup (ds->str);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->acase) {
|
|
|
|
r_str_case (ds->asmop.buf_asm, 1);
|
2016-11-04 03:56:42 +01:00
|
|
|
} else if (ds->capitalize) {
|
|
|
|
ds->asmop.buf_asm[0] = toupper (ds->asmop.buf_asm[0]);
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2017-01-31 23:33:27 +01:00
|
|
|
if (info && mt_sz != UT64_MAX) {
|
2017-01-29 20:30:17 +01:00
|
|
|
ds->oplen = mt_sz;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_control_flow_comments(RDisasmState *ds) {
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_comments && ds->show_cmtflgrefs) {
|
2014-01-16 11:04:42 -06:00
|
|
|
RFlagItem *item;
|
2017-11-28 10:52:04 +01:00
|
|
|
if (ds->asm_anal) {
|
|
|
|
switch (ds->analop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
|
|
|
r_core_cmdf (ds->core, "af @ 0x%"PFMT64x, ds->analop.jump);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
switch (ds->analop.type) {
|
2014-01-16 11:04:42 -06:00
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
2016-05-30 12:35:39 +02:00
|
|
|
item = r_flag_get_i (ds->core->flags, ds->analop.jump);
|
2014-01-16 11:04:42 -06:00
|
|
|
if (item && item->comment) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_align_comment (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf (" ; ref to %s: %s\n", item->name, item->comment);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_color_reset (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_lines_right(RDisasmState *ds){
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->linesright && ds->show_lines && ds->line) {
|
2015-11-02 12:38:08 +01:00
|
|
|
r_cons_printf ("%s%s%s", COLOR (ds, color_flow), ds->line, COLOR_RESET (ds));
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
2014-12-21 04:18:56 +01:00
|
|
|
|
2016-04-27 22:17:19 +02:00
|
|
|
static void printCol(RDisasmState *ds, char *sect, int cols, const char *color) {
|
2016-04-08 02:56:42 +02:00
|
|
|
int pre, post;
|
|
|
|
if (cols < 8) cols = 8;
|
|
|
|
int outsz = cols + 32;
|
|
|
|
char *out = malloc (outsz);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!out) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-08 02:56:42 +02:00
|
|
|
memset (out, ' ', outsz);
|
|
|
|
int sect_len = strlen (sect);
|
|
|
|
|
|
|
|
if (sect_len > cols) {
|
|
|
|
sect[cols-2] = '.';
|
|
|
|
sect[cols-1] = '.';
|
|
|
|
sect[cols] = 0;
|
|
|
|
}
|
|
|
|
if (ds->show_color) {
|
|
|
|
pre = strlen (color) + 1;
|
|
|
|
post = strlen (color) + 1 + strlen (Color_RESET);
|
|
|
|
snprintf (out, outsz-pre, "%s %s", color, sect);
|
|
|
|
strcat (out, Color_RESET);
|
|
|
|
out[outsz-1] = 0;
|
|
|
|
} else {
|
|
|
|
strcpy (out + 1, sect);
|
|
|
|
pre = 1;
|
|
|
|
post = 0;
|
|
|
|
}
|
|
|
|
out[strlen (out)] = ' ';
|
|
|
|
out[cols + post] = 0;
|
|
|
|
r_cons_strcat (out);
|
|
|
|
free (out);
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_lines_left(RDisasmState *ds) {
|
|
|
|
RCore *core = ds->core;
|
|
|
|
|
2014-11-22 05:39:52 +01:00
|
|
|
if (ds->show_section) {
|
2016-05-30 12:35:39 +02:00
|
|
|
char *sect = strdup (get_section_name (core, ds->at));
|
2016-04-08 02:56:42 +02:00
|
|
|
printCol (ds, sect, ds->show_section_col, ds->color_reg);
|
|
|
|
free (sect);
|
2014-11-22 05:39:52 +01:00
|
|
|
}
|
2016-03-29 02:03:17 +02:00
|
|
|
if (ds->show_symbols) {
|
2017-03-25 02:30:00 +01:00
|
|
|
static RFlagItem sfi = R_EMPTY;
|
2016-03-29 02:03:17 +02:00
|
|
|
const char *name = "";
|
|
|
|
int delta = 0;
|
|
|
|
if (ds->fcn) {
|
|
|
|
sfi.offset = ds->fcn->addr;
|
|
|
|
sfi.name = ds->fcn->name;
|
|
|
|
ds->lastflag = &sfi;
|
|
|
|
} else {
|
2016-12-01 10:48:00 +01:00
|
|
|
RFlagItem *fi = r_flag_get_at (core->flags, ds->at, false);
|
2017-11-26 22:42:56 +01:00
|
|
|
if (fi) { // && (!ds->lastflag || fi->offset != ds->at))
|
2016-03-29 02:03:17 +02:00
|
|
|
sfi.offset = fi->offset;
|
|
|
|
sfi.name = fi->name;
|
|
|
|
ds->lastflag = &sfi;
|
|
|
|
}
|
|
|
|
}
|
2016-04-08 02:56:42 +02:00
|
|
|
if (ds->lastflag && ds->lastflag->name) {
|
2016-03-29 02:03:17 +02:00
|
|
|
name = ds->lastflag->name;
|
|
|
|
delta = ds->at - ds->lastflag->offset;
|
|
|
|
}
|
2016-04-08 02:56:42 +02:00
|
|
|
{
|
|
|
|
char * str = r_str_newf ("%s + %-4d", name, delta);
|
|
|
|
printCol (ds, str, ds->show_symbols_col, ds->color_num);
|
|
|
|
free (str);
|
|
|
|
}
|
2016-03-29 02:03:17 +02:00
|
|
|
}
|
2017-11-26 22:42:56 +01:00
|
|
|
if (ds->line) {
|
|
|
|
if (ds->show_color) {
|
|
|
|
if (!ds->linesright && ds->show_lines) {
|
|
|
|
r_cons_printf ("%s%s%s", COLOR (ds, color_flow), ds->line, COLOR_RESET (ds));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s", ds->line);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_family(RDisasmState *ds) {
|
2015-10-03 13:52:52 +02:00
|
|
|
if (ds->show_family) {
|
|
|
|
const char *familystr = r_anal_op_family_to_string (ds->analop.family);
|
|
|
|
r_cons_printf ("%5s ", familystr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_cycles(RDisasmState *ds) {
|
2014-02-26 00:03:42 +01:00
|
|
|
if (ds->show_cycles) {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!ds->analop.failcycles) {
|
2014-02-26 00:03:42 +01:00
|
|
|
r_cons_printf ("%3d ", ds->analop.cycles);
|
2016-09-23 16:28:48 +02:00
|
|
|
} else {
|
|
|
|
r_cons_printf ("%3d %3d ", ds->analop.cycles, ds->analop.failcycles);
|
|
|
|
}
|
2014-02-26 00:03:42 +01:00
|
|
|
}
|
2014-11-02 03:06:52 +01:00
|
|
|
if (ds->cyclespace) {
|
|
|
|
char spaces [32];
|
|
|
|
int times = R_MIN (ds->analop.cycles/4, 30); // limit to 30
|
|
|
|
memset (spaces, ' ', sizeof (spaces));
|
|
|
|
spaces[times] = 0;
|
|
|
|
r_cons_strcat (spaces);
|
|
|
|
}
|
2014-02-10 23:01:19 +01:00
|
|
|
}
|
|
|
|
|
2018-01-30 14:25:15 +01:00
|
|
|
static void ds_update_stackptr(RDisasmState *ds, RAnalOp *op) {
|
2018-02-01 15:53:05 +01:00
|
|
|
//ds->stackptr = ds->core->anal->stackptr;
|
2018-01-30 14:25:15 +01:00
|
|
|
ds->ostackptr = ds->stackptr;
|
|
|
|
switch (op->stackop) {
|
|
|
|
case R_ANAL_STACK_RESET:
|
|
|
|
ds->stackptr = 0;
|
|
|
|
break;
|
|
|
|
case R_ANAL_STACK_SET:
|
|
|
|
ds->stackptr = op->stackptr;
|
|
|
|
break;
|
|
|
|
case R_ANAL_STACK_INC:
|
|
|
|
ds->stackptr += op->stackptr;
|
|
|
|
break;
|
2018-02-01 15:53:05 +01:00
|
|
|
default:
|
|
|
|
/* nothing to do here */
|
|
|
|
break;
|
2018-01-30 14:25:15 +01:00
|
|
|
}
|
|
|
|
/* XXX if we reset the stackptr 'ret 0x4' has not effect.
|
|
|
|
* Use RAnalFunction->RAnalOp->stackptr? */
|
|
|
|
if (op->type == R_ANAL_OP_TYPE_RET) {
|
|
|
|
ds->stackptr = 0;
|
|
|
|
}
|
2018-02-01 15:53:05 +01:00
|
|
|
// ds->ostackptr = ds->stackptr;
|
|
|
|
//ds->core->anal->stackptr = ds->stackptr;
|
2018-01-30 14:25:15 +01:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_stackptr(RDisasmState *ds) {
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_stackptr) {
|
2016-04-08 02:56:42 +02:00
|
|
|
r_cons_printf ("%5d%s", ds->stackptr,
|
2016-05-11 12:59:32 +02:00
|
|
|
ds->analop.type == R_ANAL_OP_TYPE_CALL?">":
|
2016-04-13 23:33:30 +02:00
|
|
|
ds->analop.stackop == R_ANAL_STACK_ALIGN? "=":
|
|
|
|
ds->stackptr > ds->ostackptr? "+":
|
|
|
|
ds->stackptr < ds->ostackptr? "-": " ");
|
2018-01-30 14:25:15 +01:00
|
|
|
ds_update_stackptr (ds, &ds->analop);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_offset(RDisasmState *ds) {
|
|
|
|
RCore *core = ds->core;
|
2016-11-04 03:15:17 +01:00
|
|
|
ut64 at = ds->vat;
|
2016-05-30 12:35:39 +02:00
|
|
|
|
2017-11-24 23:52:22 +01:00
|
|
|
bool hasCustomColor = false;
|
|
|
|
// probably tooslow
|
|
|
|
RFlagItem *f = r_flag_get_at (core->flags, at, 1);
|
|
|
|
if (ds->show_color && f) { // ds->lastflag) {
|
|
|
|
const char *color = f->color;
|
|
|
|
if (ds->at >= f->offset && ds->at < f->offset + f->size) {
|
|
|
|
// if (r_itv_inrange (f->itv, ds->at))
|
|
|
|
if (color && *color) {
|
2018-02-23 19:00:47 +01:00
|
|
|
char *k = r_cons_pal_parse (f->color, NULL);
|
2017-11-24 23:52:22 +01:00
|
|
|
if (k) {
|
|
|
|
r_cons_printf ("%s", k);
|
|
|
|
hasCustomColor = true;
|
|
|
|
free (k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-04 01:30:35 +01:00
|
|
|
r_print_set_screenbounds (core->print, at);
|
2015-01-12 00:11:06 +01:00
|
|
|
if (ds->show_offset) {
|
2017-03-25 02:30:00 +01:00
|
|
|
static RFlagItem sfi = R_EMPTY;
|
2016-08-25 20:17:55 +02:00
|
|
|
const char *label = NULL;
|
2015-01-18 03:02:56 +01:00
|
|
|
RFlagItem *fi;
|
2016-08-25 20:17:55 +02:00
|
|
|
int delta = -1;
|
2017-06-06 10:00:57 +02:00
|
|
|
bool show_trace = false;
|
2018-03-12 12:37:35 +01:00
|
|
|
unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
|
|
|
|
|
2015-01-12 10:45:41 +01:00
|
|
|
if (ds->show_reloff) {
|
2016-11-04 01:30:35 +01:00
|
|
|
RAnalFunction *f = r_anal_get_fcn_at (core->anal, at, R_ANAL_FCN_TYPE_NULL);
|
2016-08-25 20:17:55 +02:00
|
|
|
if (!f) {
|
2017-11-23 22:46:57 +01:00
|
|
|
f = fcnIn (ds, at, R_ANAL_FCN_TYPE_NULL); // r_anal_get_fcn_in (core->anal, at, R_ANAL_FCN_TYPE_NULL);
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
2015-01-18 03:02:56 +01:00
|
|
|
if (f) {
|
2016-11-04 01:30:35 +01:00
|
|
|
delta = at - f->addr;
|
2016-03-29 02:03:17 +02:00
|
|
|
sfi.name = f->name;
|
2015-01-18 03:02:56 +01:00
|
|
|
sfi.offset = f->addr;
|
|
|
|
ds->lastflag = &sfi;
|
2016-08-25 20:17:55 +02:00
|
|
|
label = f->name;
|
2015-01-18 03:02:56 +01:00
|
|
|
} else {
|
2016-08-25 20:17:55 +02:00
|
|
|
if (ds->show_reloff_flags) {
|
|
|
|
/* XXX: this is wrong if starting to disasm after a flag */
|
2016-11-04 01:30:35 +01:00
|
|
|
fi = r_flag_get_i (core->flags, at);
|
2016-08-25 20:17:55 +02:00
|
|
|
if (fi) {
|
|
|
|
ds->lastflag = fi;
|
|
|
|
}
|
|
|
|
if (ds->lastflag) {
|
2016-11-04 01:30:35 +01:00
|
|
|
if (ds->lastflag->offset == at) {
|
2016-08-25 20:17:55 +02:00
|
|
|
delta = 0;
|
|
|
|
} else {
|
2016-11-04 01:30:35 +01:00
|
|
|
delta = at - ds->lastflag->offset;
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
2015-01-18 03:02:56 +01:00
|
|
|
} else {
|
2016-11-04 01:30:35 +01:00
|
|
|
delta = at - core->offset;
|
2016-08-25 20:17:55 +02:00
|
|
|
}
|
|
|
|
if (ds->lastflag) {
|
|
|
|
label = ds->lastflag->name;
|
2015-01-18 03:02:56 +01:00
|
|
|
}
|
2015-01-12 10:45:41 +01:00
|
|
|
}
|
|
|
|
}
|
2016-08-25 20:17:55 +02:00
|
|
|
if (!ds->lastflag) {
|
|
|
|
delta = 0;
|
|
|
|
}
|
2015-01-12 10:45:41 +01:00
|
|
|
}
|
2017-06-06 10:00:57 +02:00
|
|
|
if (ds->show_trace) {
|
2017-11-14 23:36:04 +09:00
|
|
|
RDebugTracepoint *tp = r_debug_trace_get (ds->core->dbg, ds->at);
|
|
|
|
show_trace = (tp? !!tp->count: false);
|
|
|
|
}
|
|
|
|
if (ds->hint && ds->hint->high) {
|
|
|
|
show_trace = true;
|
2017-06-06 10:00:57 +02:00
|
|
|
}
|
2017-11-24 23:52:22 +01:00
|
|
|
if (hasCustomColor) {
|
|
|
|
int of = core->print->flags;
|
|
|
|
core->print->flags = 0;
|
2018-03-12 12:37:35 +01:00
|
|
|
r_print_offset_sg (core->print, at, (at == ds->dest) || show_trace,
|
|
|
|
ds->show_offseg, seggrn, ds->show_offdec, delta, label);
|
2017-11-24 23:52:22 +01:00
|
|
|
core->print->flags = of;
|
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
} else {
|
2018-03-12 12:37:35 +01:00
|
|
|
r_print_offset_sg (core->print, at, (at == ds->dest) || show_trace,
|
|
|
|
ds->show_offseg, seggrn, ds->show_offdec, delta, label);
|
2017-11-24 23:52:22 +01:00
|
|
|
}
|
2015-01-12 00:11:06 +01:00
|
|
|
}
|
2016-03-04 00:33:24 +01:00
|
|
|
if (ds->atabsoff > 0) {
|
|
|
|
if (ds->_tabsoff != ds->atabsoff) {
|
|
|
|
char *b = ds->_tabsbuf;
|
|
|
|
// TODO optimize to avoid down resizing
|
|
|
|
b = malloc (ds->atabsoff + 1);
|
|
|
|
if (b) {
|
|
|
|
memset (b, ' ', ds->atabsoff);
|
|
|
|
b[ds->atabsoff] = 0;
|
|
|
|
free (ds->_tabsbuf);
|
|
|
|
ds->_tabsbuf = b;
|
|
|
|
ds->_tabsoff = ds->atabsoff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_strcat (ds->_tabsbuf);
|
2015-07-15 17:30:34 +02:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_op_size(RDisasmState *ds) {
|
2016-05-30 04:18:48 +02:00
|
|
|
if (ds->show_size) {
|
|
|
|
int size = ds->oplen;
|
|
|
|
r_cons_printf ("%d ", size); //ds->analop.size);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_trace(RDisasmState *ds) {
|
2014-11-02 03:06:52 +01:00
|
|
|
RDebugTracepoint *tp = NULL;
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_trace) {
|
2016-05-30 12:35:39 +02:00
|
|
|
tp = r_debug_trace_get (ds->core->dbg, ds->at);
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf ("%02x:%04x ", tp?tp->times:0, tp?tp->count:0);
|
2014-11-02 03:06:52 +01:00
|
|
|
}
|
|
|
|
if (ds->tracespace) {
|
|
|
|
char spaces [32];
|
|
|
|
int times;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!tp) {
|
2016-05-30 12:35:39 +02:00
|
|
|
tp = r_debug_trace_get (ds->core->dbg, ds->at);
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2014-11-02 03:06:52 +01:00
|
|
|
if (tp) {
|
|
|
|
times = R_MIN (tp->times, 30); // limit to 30
|
2014-11-02 02:19:31 +01:00
|
|
|
memset (spaces, ' ', sizeof (spaces));
|
|
|
|
spaces[times] = 0;
|
|
|
|
r_cons_strcat (spaces);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_adistrick_comments(RDisasmState *ds) {
|
2015-11-06 15:46:14 +01:00
|
|
|
if (ds->adistrick) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->middle = r_anal_reflines_middle (ds->core->anal,
|
|
|
|
ds->core->anal->reflines, ds->at, ds->analop.size);
|
2015-11-06 15:46:14 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2017-03-10 18:09:23 +01:00
|
|
|
static bool ds_print_data_type(RDisasmState *ds, const ut8 *buf, int ib, int size) {
|
|
|
|
RCore *core = ds->core;
|
2016-05-21 19:47:49 +02:00
|
|
|
const char *type = NULL;
|
|
|
|
char msg[64];
|
|
|
|
const int isSigned = (ib == 1 || ib == 8 || ib == 10)? 1: 0;
|
|
|
|
switch (size) {
|
|
|
|
case 1: type = isSigned? ".char": ".byte"; break;
|
|
|
|
case 2: type = isSigned? ".int16": ".word"; break;
|
2017-11-09 12:57:51 +01:00
|
|
|
case 3: type = "htons"; break;
|
2016-05-21 19:47:49 +02:00
|
|
|
case 4: type = isSigned? ".int32": ".dword"; break;
|
|
|
|
case 8: type = isSigned? ".int64": ".qword"; break;
|
|
|
|
default: return false;
|
|
|
|
}
|
2016-05-24 21:22:15 +01:00
|
|
|
ut64 n = r_read_ble (buf, core->print->big_endian, size * 8);
|
2017-03-10 18:09:23 +01:00
|
|
|
{
|
|
|
|
int q = core->print->cur_enabled &&
|
|
|
|
ds->cursor >= ds->index &&
|
|
|
|
ds->cursor < (ds->index + size);
|
|
|
|
if (q) {
|
|
|
|
if (ds->cursor > ds->index) {
|
|
|
|
int diff = ds->cursor - ds->index;
|
|
|
|
r_cons_printf (" %d ", diff);
|
|
|
|
} else if (ds->cursor == ds->index) {
|
|
|
|
r_cons_printf (" * ");
|
|
|
|
} else {
|
2017-11-09 12:57:51 +01:00
|
|
|
r_cons_printf (" ");
|
2017-03-10 18:09:23 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
r_cons_printf (" ");
|
|
|
|
}
|
|
|
|
}
|
2016-05-21 19:47:49 +02:00
|
|
|
|
|
|
|
switch (ib) {
|
|
|
|
case 1:
|
|
|
|
r_str_bits (msg, buf, size * 8, NULL);
|
|
|
|
r_cons_printf ("%s %sb", type, msg);
|
|
|
|
break;
|
2017-11-09 12:57:51 +01:00
|
|
|
case 3:
|
|
|
|
r_cons_printf ("%s %d", type, ntohs (n & 0xFFFF));
|
|
|
|
break;
|
2016-05-21 19:47:49 +02:00
|
|
|
case 8:
|
|
|
|
r_cons_printf ("%s %oo", type, n);
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
r_cons_printf ("%s %d", type, n);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
switch (size) {
|
|
|
|
case 1:
|
|
|
|
r_cons_printf ("%s 0x%02x", type, n);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r_cons_printf ("%s 0x%04x", type, n);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r_cons_printf ("%s 0x%08x", type, n);
|
|
|
|
break;
|
|
|
|
case 8:
|
2016-09-21 00:58:06 +02:00
|
|
|
r_cons_printf ("%s 0x%016" PFMT64x, type, n);
|
2016-05-21 19:47:49 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size == 4 || size == 8) {
|
2017-03-24 01:07:42 +01:00
|
|
|
if (r_str_startswith (r_config_get (core->config, "asm.arch"), "arm")) {
|
|
|
|
ut64 bits = r_config_get_i (core->config, "asm.bits");
|
|
|
|
//adjust address for arm/thumb address
|
|
|
|
if (bits < 64) {
|
|
|
|
if (n & 1) {
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-20 10:51:44 +01:00
|
|
|
if (n >= ds->min_ref_addr) {
|
|
|
|
const RList *flags = r_flag_get_list (core->flags, n);
|
|
|
|
RListIter *iter;
|
|
|
|
RFlagItem *fi;
|
|
|
|
r_list_foreach (flags, iter, fi) {
|
|
|
|
r_cons_printf (" ; %s", fi->name);
|
|
|
|
}
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
2016-05-21 19:47:49 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static int ds_print_meta_infos(RDisasmState *ds, ut8* buf, int len, int idx) {
|
2014-03-08 02:36:33 +01:00
|
|
|
int ret = 0;
|
|
|
|
const char *infos, *metas;
|
2015-06-15 10:55:05 +02:00
|
|
|
char key[100];
|
2014-03-08 02:36:33 +01:00
|
|
|
RAnalMetaItem MI, *mi = &MI;
|
2017-10-25 22:28:36 +08:00
|
|
|
RCore *core = ds->core;
|
2014-03-08 02:36:33 +01:00
|
|
|
Sdb *s = core->anal->sdb_meta;
|
|
|
|
|
2017-10-25 22:28:36 +08:00
|
|
|
snprintf (key, sizeof (key), "meta.0x%" PFMT64x, ds->at);
|
2014-03-08 02:36:33 +01:00
|
|
|
infos = sdb_const_get (s, key, 0);
|
2016-09-22 18:06:10 +02:00
|
|
|
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = false;
|
2016-09-22 18:06:10 +02:00
|
|
|
if (infos) {
|
2017-10-25 22:28:36 +08:00
|
|
|
for (; *infos; infos++) {
|
2016-09-22 18:06:10 +02:00
|
|
|
if (*infos == ',') {
|
2015-06-15 10:55:05 +02:00
|
|
|
continue;
|
|
|
|
}
|
2017-10-25 22:28:36 +08:00
|
|
|
snprintf (key, sizeof (key), "meta.%c.0x%" PFMT64x, *infos, ds->at);
|
2016-09-22 18:06:10 +02:00
|
|
|
metas = sdb_const_get (s, key, 0);
|
2017-10-25 23:42:24 +08:00
|
|
|
if (!metas) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!r_meta_deserialize_val (mi, *infos, ds->at, metas)) {
|
|
|
|
continue;
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
|
|
|
// TODO: implement ranged meta find (if not at the begging of function..
|
|
|
|
char *out = NULL;
|
|
|
|
int hexlen;
|
|
|
|
int delta;
|
|
|
|
if (mi) {
|
|
|
|
switch (mi->type) {
|
|
|
|
case R_META_TYPE_STRING:
|
|
|
|
{
|
2017-12-11 23:08:18 +01:00
|
|
|
char *quote = "\"";
|
2017-12-24 21:52:42 +08:00
|
|
|
bool esc_bslash = ds->use_json ? true : core->print->esc_bslash;
|
2017-12-11 23:08:18 +01:00
|
|
|
|
2017-12-24 20:17:25 +08:00
|
|
|
switch (mi->subtype) {
|
|
|
|
case R_STRING_ENC_UTF8:
|
|
|
|
out = r_str_escape_utf8 (mi->str, false, esc_bslash);
|
|
|
|
break;
|
|
|
|
case 0: /* temporary legacy workaround */
|
|
|
|
esc_bslash = false;
|
2017-12-27 18:31:09 +01:00
|
|
|
/* fallthrough */
|
2017-12-24 20:17:25 +08:00
|
|
|
default:
|
|
|
|
out = r_str_escape_latin1 (mi->str, false, esc_bslash);
|
|
|
|
}
|
2017-12-11 23:08:18 +01:00
|
|
|
if (!out) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ds->use_json) {
|
|
|
|
// escape twice for json
|
|
|
|
char *out2 = out;
|
|
|
|
out = r_str_escape (out2);
|
|
|
|
free (out2);
|
|
|
|
if (!out) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
quote = "\\\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
r_cons_printf (" .string %s%s%s%s%s ; len=%"PFMT64d,
|
|
|
|
COLOR (ds, color_btext), quote, out, quote, COLOR_RESET (ds),
|
2016-09-22 18:06:10 +02:00
|
|
|
mi->size);
|
|
|
|
free (out);
|
|
|
|
delta = ds->at - mi->from;
|
|
|
|
ds->oplen = mi->size - delta;
|
|
|
|
ds->asmop.size = (int)mi->size;
|
|
|
|
//i += mi->size-1; // wtf?
|
|
|
|
R_FREE (ds->line);
|
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = true;
|
2016-09-22 18:06:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R_META_TYPE_HIDE:
|
2017-08-25 13:47:39 -04:00
|
|
|
r_cons_printf ("(%"PFMT64d" bytes hidden)", mi->size);
|
2016-09-22 18:06:10 +02:00
|
|
|
ds->asmop.size = mi->size;
|
|
|
|
ds->oplen = mi->size;
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = true;
|
2016-09-22 18:06:10 +02:00
|
|
|
break;
|
2016-11-06 01:16:02 +01:00
|
|
|
case R_META_TYPE_RUN:
|
|
|
|
r_core_cmdf (core, "%s @ 0x%"PFMT64x, mi->str, ds->at);
|
|
|
|
ds->asmop.size = mi->size;
|
|
|
|
ds->oplen = mi->size;
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = true;
|
2016-11-06 01:16:02 +01:00
|
|
|
break;
|
2016-09-22 18:06:10 +02:00
|
|
|
case R_META_TYPE_DATA:
|
|
|
|
hexlen = len - idx;
|
2017-01-16 15:07:11 +01:00
|
|
|
delta = ds->at - mi->from;
|
2016-09-22 18:06:10 +02:00
|
|
|
if (mi->size < hexlen) {
|
|
|
|
hexlen = mi->size;
|
|
|
|
}
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->oplen = mi->size - delta;
|
2016-09-22 18:06:10 +02:00
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_HEADER;
|
2017-03-10 18:09:23 +01:00
|
|
|
if (!ds_print_data_type (ds, buf + idx, ds->hint? ds->hint->immbase: 0, mi->size)) {
|
2016-09-22 18:06:10 +02:00
|
|
|
r_cons_printf ("hex length=%" PFMT64d " delta=%d\n", mi->size , delta);
|
2017-06-06 00:20:49 +00:00
|
|
|
r_print_hexdump (core->print, ds->at, buf+idx, hexlen-delta, 16, 1, 1);
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
2017-01-16 15:07:11 +01:00
|
|
|
core->inc = 16; // ds->oplen; //
|
2016-09-22 18:06:10 +02:00
|
|
|
core->print->flags |= R_PRINT_FLAGS_HEADER;
|
|
|
|
ds->asmop.size = ret = (int)mi->size; //-delta;
|
|
|
|
R_FREE (ds->line);
|
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = true;
|
2016-09-22 18:06:10 +02:00
|
|
|
break;
|
|
|
|
case R_META_TYPE_FORMAT:
|
|
|
|
r_cons_printf ("format %s {\n", mi->str);
|
|
|
|
r_print_format (core->print, ds->at, buf+idx, len-idx, mi->str, R_PRINT_MUSTSEE, NULL, NULL);
|
|
|
|
r_cons_printf ("} %d", mi->size);
|
|
|
|
ds->oplen = ds->asmop.size = ret = (int)mi->size;
|
|
|
|
R_FREE (ds->line);
|
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = true;
|
2016-09-22 18:06:10 +02:00
|
|
|
break;
|
2014-09-03 10:25:29 +02:00
|
|
|
}
|
2014-03-08 02:36:33 +01:00
|
|
|
}
|
2016-09-22 18:06:10 +02:00
|
|
|
if (MI.str) {
|
|
|
|
free (MI.str);
|
|
|
|
MI.str = NULL;
|
|
|
|
}
|
2014-05-04 19:21:05 +04:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_instruction_mov_lea(RDisasmState *ds, int idx) {
|
|
|
|
RCore *core = ds->core;
|
2014-01-16 11:04:42 -06:00
|
|
|
RAnalValue *src;
|
2017-09-04 12:41:09 -07:00
|
|
|
const int addrbytes = core->io->addrbytes;
|
2016-05-30 12:35:39 +02:00
|
|
|
|
2014-01-20 01:42:16 +01:00
|
|
|
switch (ds->analop.type) {
|
2015-03-24 00:08:48 +01:00
|
|
|
case R_ANAL_OP_TYPE_LENGTH:
|
|
|
|
case R_ANAL_OP_TYPE_CAST:
|
2015-10-18 22:14:06 +02:00
|
|
|
case R_ANAL_OP_TYPE_CMOV:
|
2014-01-16 11:04:42 -06:00
|
|
|
case R_ANAL_OP_TYPE_MOV:
|
2014-01-20 01:42:16 +01:00
|
|
|
src = ds->analop.src[0];
|
2017-11-25 00:05:37 +01:00
|
|
|
if (src && src->memref>0 && src->reg && core->anal->reg) {
|
|
|
|
const char *pc = core->anal->reg->name[R_REG_NAME_PC];
|
|
|
|
RAnalValue *dst = ds->analop.dst;
|
|
|
|
if (dst && dst->reg && dst->reg->name) {
|
|
|
|
if (src->reg->name && pc && !strcmp (src->reg->name, pc)) {
|
|
|
|
RFlagItem *item;
|
|
|
|
ut8 b[8];
|
|
|
|
ut64 ptr = addrbytes * idx + ds->addr + src->delta + ds->analop.size;
|
|
|
|
ut64 off = 0LL;
|
|
|
|
r_core_read_at (core, ptr, b, src->memref);
|
|
|
|
off = r_mem_get_num (b, src->memref);
|
|
|
|
item = r_flag_get_i (core->flags, off);
|
|
|
|
//TODO: introduce env for this print?
|
|
|
|
r_cons_printf ("; MOV %s = [0x%"PFMT64x"] = 0x%"PFMT64x" %s\n",
|
2017-11-28 10:52:04 +01:00
|
|
|
dst->reg->name, ptr, off, item?item->name: "");
|
|
|
|
if (ds->asm_anal) {
|
|
|
|
if (r_io_is_valid_offset (core->io, off, 0)) {
|
|
|
|
r_anal_ref_add (core->anal, ds->addr, off, 'd');
|
|
|
|
}
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// TODO: get from meta anal?
|
|
|
|
case R_ANAL_OP_TYPE_LEA:
|
2014-01-20 01:42:16 +01:00
|
|
|
src = ds->analop.src[0];
|
2014-05-22 13:21:34 +02:00
|
|
|
if (src && src->reg && core->anal->reg && *(core->anal->reg->name)) {
|
2014-01-16 11:04:42 -06:00
|
|
|
const char *pc = core->anal->reg->name[R_REG_NAME_PC];
|
2014-01-20 01:42:16 +01:00
|
|
|
RAnalValue *dst = ds->analop.dst;
|
2016-09-07 20:06:36 +02:00
|
|
|
if (dst && dst->reg && src->reg->name && pc && !strcmp (src->reg->name, pc)) {
|
2014-01-18 01:55:03 +01:00
|
|
|
int index = 0;
|
2014-01-16 11:04:42 -06:00
|
|
|
int memref = core->assembler->bits/8;
|
|
|
|
RFlagItem *item;
|
|
|
|
ut8 b[64];
|
2017-11-28 10:52:04 +01:00
|
|
|
ut64 ptr = index + ds->addr + src->delta + ds->analop.size;
|
2014-01-16 11:04:42 -06:00
|
|
|
ut64 off = 0LL;
|
|
|
|
r_core_read_at (core, ptr, b, sizeof (b)); //memref);
|
2016-04-26 19:09:15 +10:00
|
|
|
off = r_mem_get_num (b, memref);
|
2014-01-16 11:04:42 -06:00
|
|
|
item = r_flag_get_i (core->flags, off);
|
2016-09-05 20:42:04 +02:00
|
|
|
if (ds->show_leahints) {
|
|
|
|
char s[64];
|
|
|
|
r_str_ncpy (s, (const char *)b, sizeof (s));
|
2017-08-18 05:27:29 +02:00
|
|
|
r_str_filter (s, -1);
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; LEA %s = [0x%"PFMT64x"] = 0x%"PFMT64x" \"%s\"",
|
|
|
|
dst->reg->name, ptr, off, item?item->name: s);
|
2017-11-28 10:52:04 +01:00
|
|
|
if (ds->asm_anal) {
|
|
|
|
if (r_io_is_valid_offset (core->io, off, 0)) {
|
|
|
|
r_anal_ref_add (core->anal, ds->addr, ptr, 'd');
|
|
|
|
}
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
static st64 revert_cdiv_magic(st64 magic) {
|
2016-08-30 15:44:52 +02:00
|
|
|
ut64 amagic = llabs (magic);
|
2016-06-16 23:48:01 +02:00
|
|
|
const st64 N = ST64_MAX;
|
2016-06-17 12:37:18 +02:00
|
|
|
st64 E, candidate;
|
|
|
|
short s;
|
|
|
|
|
2016-08-30 15:44:52 +02:00
|
|
|
if (amagic < 0xFFFFFF || amagic > UT32_MAX) {
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (magic < 0) {
|
2016-06-17 12:37:18 +02:00
|
|
|
magic += 1LL << 32;
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
}
|
2016-06-17 12:37:18 +02:00
|
|
|
for (s = 0; s < 16; s++) {
|
|
|
|
E = 1LL << (32 + s);
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
candidate = (E + magic - 1) / magic;
|
2016-08-30 15:44:52 +02:00
|
|
|
if (candidate > 0) {
|
|
|
|
if ( ((N * magic) >> (32 + s)) == (N / candidate) ) {
|
|
|
|
return candidate;
|
|
|
|
}
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ds_cdiv_optimization(RDisasmState *ds) {
|
|
|
|
char *esil;
|
|
|
|
char *end, *comma;
|
|
|
|
st64 imm;
|
|
|
|
st64 divisor;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!ds->show_hints) {
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
return;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
switch (ds->analop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_MOV:
|
|
|
|
case R_ANAL_OP_TYPE_MUL:
|
|
|
|
esil = R_STRBUF_SAFEGET (&ds->analop.esil);
|
|
|
|
while (esil) {
|
|
|
|
comma = strstr (esil, ",");
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!comma) {
|
|
|
|
break;
|
|
|
|
}
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
imm = strtol (esil, &end, 10);
|
|
|
|
if (comma && comma == end) {
|
|
|
|
divisor = revert_cdiv_magic (imm);
|
|
|
|
if (divisor) {
|
|
|
|
r_cons_printf (" ; CDIV: %lld * 2^n", divisor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-30 15:44:52 +02:00
|
|
|
esil = comma + 1;
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
}
|
|
|
|
}
|
2016-07-05 23:44:53 +03:00
|
|
|
// /TODO: check following SHR instructions
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_show_bytes(RDisasmState *ds) {
|
|
|
|
RCore* core = ds->core;
|
2014-10-16 01:51:48 +02:00
|
|
|
char *nstr, *str = NULL, pad[64];
|
2015-01-17 01:56:20 +01:00
|
|
|
char *flagstr = NULL;
|
2016-08-25 20:27:52 +02:00
|
|
|
int oldFlags = core->print->flags;
|
2017-06-15 00:06:33 +02:00
|
|
|
char extra[128];
|
2016-08-25 20:27:52 +02:00
|
|
|
int j, k;
|
|
|
|
|
|
|
|
if (!ds->show_bytes || ds->nb < 1) {
|
2014-10-16 01:51:48 +02:00
|
|
|
return;
|
2016-06-29 16:17:41 +02:00
|
|
|
}
|
2016-08-25 20:27:52 +02:00
|
|
|
if (!ds->show_color_bytes) {
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_COLOR;
|
2016-06-29 16:17:41 +02:00
|
|
|
}
|
2014-10-16 01:51:48 +02:00
|
|
|
strcpy (extra, " ");
|
2015-01-17 01:56:20 +01:00
|
|
|
if (ds->show_flag_in_bytes) {
|
|
|
|
flagstr = r_flag_get_liststr (core->flags, ds->at);
|
|
|
|
}
|
|
|
|
if (flagstr) {
|
|
|
|
str = flagstr;
|
2015-10-30 03:07:22 +01:00
|
|
|
if (ds->nb > 0) {
|
2016-08-25 20:27:52 +02:00
|
|
|
k = ds->nb-strlen (flagstr) - 1;
|
2016-06-09 18:17:51 +02:00
|
|
|
if (k < 0 || k > sizeof(pad)) k = 0;
|
2016-08-25 20:27:52 +02:00
|
|
|
for (j = 0; j < k; j++) {
|
2015-04-06 18:31:35 -04:00
|
|
|
pad[j] = ' ';
|
2016-08-25 20:27:52 +02:00
|
|
|
}
|
2015-04-06 18:31:35 -04:00
|
|
|
pad[j] = '\0';
|
2016-08-08 23:40:56 +02:00
|
|
|
} else {
|
2017-05-08 20:21:06 +02:00
|
|
|
pad[0] = 0;
|
2016-06-09 18:17:51 +02:00
|
|
|
}
|
2014-10-16 01:51:48 +02:00
|
|
|
} else {
|
|
|
|
if (ds->show_flag_in_bytes) {
|
2016-06-09 18:17:51 +02:00
|
|
|
k = ds->nb - 1;
|
2016-08-25 20:27:52 +02:00
|
|
|
if (k < 0 || k > sizeof (pad)) {
|
|
|
|
k = 0;
|
|
|
|
}
|
|
|
|
for (j = 0; j < k; j++) {
|
2014-10-16 01:51:48 +02:00
|
|
|
pad[j] = ' ';
|
2016-08-25 20:27:52 +02:00
|
|
|
}
|
2014-10-16 01:51:48 +02:00
|
|
|
pad[j] = '\0';
|
|
|
|
str = strdup ("");
|
|
|
|
} else {
|
2014-01-20 01:42:16 +01:00
|
|
|
str = strdup (ds->asmop.buf_hex);
|
|
|
|
if (r_str_ansi_len (str) > ds->nb) {
|
|
|
|
char *p = (char *)r_str_ansi_chrn (str, ds->nb);
|
2014-01-16 11:04:42 -06:00
|
|
|
if (p) {
|
|
|
|
p[0] = '.';
|
|
|
|
p[1] = '\0';
|
|
|
|
}
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->print->cur_enabled = (ds->cursor != -1);
|
|
|
|
nstr = r_print_hexpair (ds->print, str, ds->index);
|
|
|
|
if (ds->print->bytespace) {
|
2016-01-08 01:23:33 +01:00
|
|
|
k = (ds->nb + (ds->nb / 2)) - r_str_ansi_len (nstr) + 2;
|
2014-02-25 01:35:23 +01:00
|
|
|
} else {
|
2016-08-25 20:27:52 +02:00
|
|
|
k = ds->nb - r_str_ansi_len (nstr) + 1;
|
2014-02-25 01:35:23 +01:00
|
|
|
}
|
2016-01-08 01:23:33 +01:00
|
|
|
if (k > 0) {
|
2016-06-29 16:17:41 +02:00
|
|
|
// setting to sizeof screw up the disasm
|
|
|
|
if (k > sizeof (pad)) {
|
|
|
|
k = 18;
|
|
|
|
}
|
2016-01-08 01:23:33 +01:00
|
|
|
for (j = 0; j < k; j++) {
|
2015-04-06 18:31:35 -04:00
|
|
|
pad[j] = ' ';
|
2016-01-08 01:23:33 +01:00
|
|
|
}
|
2015-04-06 18:31:35 -04:00
|
|
|
pad[j] = 0;
|
|
|
|
if (ds->lbytes) {
|
|
|
|
// hack to align bytes left
|
|
|
|
strcpy (extra, pad);
|
|
|
|
*pad = 0;
|
|
|
|
}
|
2015-04-08 22:28:21 +02:00
|
|
|
} else {
|
|
|
|
pad[0] = 0;
|
|
|
|
}
|
2014-02-25 01:35:23 +01:00
|
|
|
free (str);
|
|
|
|
str = nstr;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
2016-12-29 00:37:40 +01:00
|
|
|
r_cons_printf ("%s%s %s", pad, str, extra);
|
2014-10-16 01:51:48 +02:00
|
|
|
free (str);
|
2016-08-25 20:27:52 +02:00
|
|
|
core->print->flags = oldFlags;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_indent(RDisasmState *ds) {
|
2014-08-05 05:37:48 +02:00
|
|
|
if (ds->show_indent) {
|
|
|
|
char indent[128];
|
2015-08-12 10:40:24 +02:00
|
|
|
int num = ds->indent_level * ds->indent_space;
|
2016-06-29 16:17:41 +02:00
|
|
|
if (num < 0) {
|
|
|
|
num = 0;
|
|
|
|
}
|
|
|
|
if (num >= sizeof (indent)) {
|
|
|
|
num = sizeof (indent) - 1;
|
|
|
|
}
|
2014-08-17 20:30:28 +02:00
|
|
|
memset (indent, ' ', num);
|
2014-08-05 05:37:48 +02:00
|
|
|
indent[num] = 0;
|
|
|
|
r_cons_strcat (indent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_opstr(RDisasmState *ds) {
|
|
|
|
ds_print_indent (ds);
|
2017-12-24 18:03:28 +01:00
|
|
|
if (ds->use_json) {
|
|
|
|
char *escaped_str = r_str_escape(ds->opstr);
|
|
|
|
if (escaped_str) {
|
|
|
|
r_cons_strcat(escaped_str);
|
|
|
|
}
|
|
|
|
free(escaped_str);
|
|
|
|
} else {
|
|
|
|
r_cons_strcat (ds->opstr);
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_color_reset (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_color_reset(RDisasmState *ds) {
|
2016-06-29 16:17:41 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static int ds_print_middle(RDisasmState *ds, int ret) {
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->middle != 0) {
|
|
|
|
ret -= ds->middle;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_align_comment (ds);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
2015-11-05 02:07:20 +01:00
|
|
|
r_cons_printf (" ; *middle* %d", ret);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static bool ds_print_labels(RDisasmState *ds, RAnalFunction *f) {
|
|
|
|
RCore *core = ds->core;
|
2014-09-23 09:35:37 +02:00
|
|
|
const char *label;
|
2016-08-25 20:27:52 +02:00
|
|
|
if (!f) {
|
2017-11-23 18:35:13 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, ds->at, 0);
|
2017-11-23 22:46:57 +01:00
|
|
|
f = fcnIn (ds, ds->at, 0);
|
2016-08-25 20:27:52 +02:00
|
|
|
}
|
2014-09-23 09:35:37 +02:00
|
|
|
label = r_anal_fcn_label_at (core->anal, f, ds->at);
|
2016-08-25 20:27:52 +02:00
|
|
|
if (!label) {
|
2015-10-30 03:07:22 +01:00
|
|
|
return false;
|
2016-08-25 20:27:52 +02:00
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->color_label);
|
|
|
|
r_cons_printf (" .%s:\n", label);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_color_reset (ds);
|
2015-11-02 12:38:08 +01:00
|
|
|
} else {
|
|
|
|
r_cons_printf (" .%s:\n", label);
|
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
return true;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_import_name(RDisasmState *ds) {
|
2014-04-03 00:30:39 +04:00
|
|
|
RListIter *iter = NULL;
|
|
|
|
RBinReloc *rel = NULL;
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore * core = ds->core;
|
|
|
|
|
2014-04-03 00:30:39 +04:00
|
|
|
switch (ds->analop.type) {
|
2016-06-29 16:17:41 +02:00
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
|
|
|
if (core->bin->cur->o->imports && core->bin->cur->o->relocs) {
|
|
|
|
r_list_foreach (core->bin->cur->o->relocs, iter, rel) {
|
|
|
|
if ((rel->vaddr == ds->analop.jump) &&
|
|
|
|
(rel->import != NULL)) {
|
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->color_fname);
|
2014-04-03 00:30:39 +04:00
|
|
|
}
|
2016-06-29 16:17:41 +02:00
|
|
|
// TODO: handle somehow ordinals import
|
|
|
|
ds_align_comment (ds);
|
|
|
|
r_cons_printf (" ; (imp.%s)", rel->import->name);
|
|
|
|
ds_print_color_reset (ds);
|
2014-04-03 00:30:39 +04:00
|
|
|
}
|
|
|
|
}
|
2016-06-29 16:17:41 +02:00
|
|
|
}
|
2014-04-03 00:30:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-03 14:12:30 +03:00
|
|
|
static void ds_print_sysregs(RDisasmState *ds) {
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2016-06-29 16:17:41 +02:00
|
|
|
if (!ds->show_comments) {
|
2014-11-18 23:53:27 +01:00
|
|
|
return;
|
2016-06-29 16:17:41 +02:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
switch (ds->analop.type) {
|
2016-07-03 14:12:30 +03:00
|
|
|
// Syscalls first
|
2016-06-29 16:17:41 +02:00
|
|
|
case R_ANAL_OP_TYPE_IO:
|
|
|
|
{
|
|
|
|
const int imm = (int)ds->analop.val;
|
2016-07-03 14:12:30 +03:00
|
|
|
RSyscall *sc = core->anal->syscall;
|
2016-06-29 16:17:41 +02:00
|
|
|
const char *ioname = r_syscall_get_io (sc, imm);
|
|
|
|
if (ioname && *ioname) {
|
2016-12-27 15:40:02 +01:00
|
|
|
ALIGN;
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; IO %s", ioname);
|
2016-08-16 12:19:02 +02:00
|
|
|
ds->has_description = true;
|
2016-06-29 16:17:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2016-07-03 14:12:30 +03:00
|
|
|
// Then sysregs
|
|
|
|
case R_ANAL_OP_TYPE_MOV:
|
|
|
|
case R_ANAL_OP_TYPE_LEA:
|
|
|
|
case R_ANAL_OP_TYPE_LOAD:
|
|
|
|
case R_ANAL_OP_TYPE_STORE:
|
|
|
|
{
|
|
|
|
const int imm = (int)ds->analop.ptr;
|
2018-01-24 15:12:33 +01:00
|
|
|
const char *sr = r_syscall_sysreg (core->anal->syscall, "reg", imm);
|
2016-07-03 14:12:30 +03:00
|
|
|
if (sr) {
|
|
|
|
ALIGN;
|
2018-01-24 15:12:33 +01:00
|
|
|
ds_comment (ds, true, "; REG %s - %s", sr, "");
|
|
|
|
// TODO: add register description description
|
2016-07-03 14:12:30 +03:00
|
|
|
ds->has_description = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ds_print_fcn_name(RDisasmState *ds) {
|
|
|
|
int delta;
|
|
|
|
const char *label;
|
|
|
|
RAnalFunction *f;
|
|
|
|
RCore *core = ds->core;
|
|
|
|
if (!ds->show_comments) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (ds->analop.type) {
|
2015-05-14 01:17:35 +02:00
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
2017-11-23 18:35:13 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, ds->analop.jump, R_ANAL_FCN_TYPE_NULL);
|
2017-11-23 22:46:57 +01:00
|
|
|
f = fcnIn (ds, ds->analop.jump, R_ANAL_FCN_TYPE_NULL);
|
2016-12-27 15:40:02 +01:00
|
|
|
if (f && f->name && ds->opstr && !strstr (ds->opstr, f->name)) {
|
2015-05-14 01:17:35 +02:00
|
|
|
//beginline (core, ds, f);
|
|
|
|
// print label
|
|
|
|
delta = ds->analop.jump - f->addr;
|
|
|
|
label = r_anal_fcn_label_at (core->anal, f, ds->analop.jump);
|
2018-03-22 17:31:05 +01:00
|
|
|
if (!ds->show_comment_right) {
|
|
|
|
ds_begin_json_line (ds);
|
|
|
|
}
|
2015-05-14 01:17:35 +02:00
|
|
|
if (label) {
|
2016-12-27 15:40:02 +01:00
|
|
|
ALIGN;
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s.%s", f->name, label);
|
2015-05-14 01:17:35 +02:00
|
|
|
} else {
|
2017-11-23 22:46:57 +01:00
|
|
|
RAnalFunction *f2 = fcnIn (ds, ds->at, 0); //r_anal_get_fcn_in (core->anal, ds->at, 0);
|
2015-05-14 01:17:35 +02:00
|
|
|
if (f != f2) {
|
2016-12-27 15:40:02 +01:00
|
|
|
ALIGN;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (delta > 0) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s+0x%x", f->name, delta);
|
2016-09-23 16:28:48 +02:00
|
|
|
} else if (delta < 0) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s-0x%x", f->name, -delta);
|
2015-05-14 01:17:35 +02:00
|
|
|
} else {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s", f->name);
|
2015-04-12 01:28:26 +02:00
|
|
|
}
|
2015-04-12 01:06:10 +02:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2015-05-14 01:17:35 +02:00
|
|
|
}
|
|
|
|
break;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
|
2017-11-25 00:28:21 +01:00
|
|
|
static void ds_print_shortcut(RDisasmState *ds, ut64 addr, int pos) {
|
|
|
|
char *shortcut = r_core_add_asmqjmp (ds->core, addr);
|
|
|
|
if (!pos && !shortcut) {
|
|
|
|
r_cons_printf (" ");
|
|
|
|
return;
|
|
|
|
}
|
2017-11-25 00:32:15 +01:00
|
|
|
if (pos) {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
char *ch = pos? ";": "";
|
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
|
|
|
if (shortcut) {
|
|
|
|
if (ds->core->is_asmqjmps_letter) {
|
|
|
|
r_cons_printf ("%s[g%s]", ch, shortcut);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s[%s]", ch, shortcut);
|
|
|
|
}
|
|
|
|
free (shortcut);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("%s[?]", ch);
|
|
|
|
}
|
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 11:29:19 +01:00
|
|
|
static bool ds_print_core_vmode_jump_hit(RDisasmState *ds, int pos) {
|
|
|
|
RCore *core = ds->core;
|
|
|
|
RAnal *a = core->anal;
|
|
|
|
RAnalHint *hint = r_anal_hint_get (a, ds->at);
|
|
|
|
|
|
|
|
if (hint) {
|
|
|
|
if (hint->jump != UT64_MAX) {
|
|
|
|
ds_print_shortcut (ds, hint->jump, pos);
|
|
|
|
r_anal_hint_free (hint);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
r_anal_hint_free (hint);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-25 00:28:21 +01:00
|
|
|
static void ds_print_core_vmode(RDisasmState *ds, int pos) {
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2017-11-25 00:28:21 +01:00
|
|
|
bool gotShortcut = false;
|
2015-10-08 20:00:31 +02:00
|
|
|
|
2016-06-20 09:46:03 +02:00
|
|
|
if (!ds->show_jmphints) {
|
|
|
|
return;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
if (core->vmode) {
|
2017-11-25 00:28:21 +01:00
|
|
|
switch (ds->analop.type) {
|
2016-05-30 02:12:17 +02:00
|
|
|
case R_ANAL_OP_TYPE_LEA:
|
2016-06-20 09:46:03 +02:00
|
|
|
if (ds->show_leahints) {
|
2017-11-25 00:28:21 +01:00
|
|
|
ds_print_shortcut (ds, ds->analop.ptr, pos);
|
|
|
|
gotShortcut = true;
|
2016-05-30 02:12:17 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-10-06 03:38:28 +02:00
|
|
|
case R_ANAL_OP_TYPE_UCALL:
|
|
|
|
case R_ANAL_OP_TYPE_UCALL | R_ANAL_OP_TYPE_REG | R_ANAL_OP_TYPE_IND:
|
|
|
|
case R_ANAL_OP_TYPE_UCALL | R_ANAL_OP_TYPE_IND:
|
2017-11-26 00:52:58 +01:00
|
|
|
#if 0
|
|
|
|
if (ds->analop.jump == 0 && ds->analop.ptr) {
|
|
|
|
ut8 buf[sizeof(ut64)] = {0};
|
|
|
|
r_io_read_at (core->io, ds->analop.ptr, buf, sizeof (buf));
|
|
|
|
ut32 n32 = r_read_ble32 (buf, 0);
|
|
|
|
// is valid address
|
|
|
|
// ut32 n64 = r_read_ble32 (buf, 0);
|
|
|
|
ds_print_shortcut (ds, n32, pos);
|
|
|
|
} else {
|
|
|
|
// ds_print_shortcut (ds, ds->analop.jump, pos);
|
|
|
|
ds_print_shortcut (ds, ds->analop.ptr, pos);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (ds->analop.jump != UT64_MAX) {
|
|
|
|
ds_print_shortcut (ds, ds->analop.jump, pos);
|
|
|
|
} else {
|
|
|
|
ds_print_shortcut (ds, ds->analop.ptr, pos);
|
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
gotShortcut = true;
|
2016-09-26 23:13:49 +02:00
|
|
|
break;
|
2016-10-06 03:38:28 +02:00
|
|
|
case R_ANAL_OP_TYPE_RCALL:
|
|
|
|
break;
|
2014-01-16 11:04:42 -06:00
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
2014-09-22 17:00:18 +02:00
|
|
|
case R_ANAL_OP_TYPE_COND | R_ANAL_OP_TYPE_CALL:
|
2017-11-25 00:28:21 +01:00
|
|
|
ds_print_shortcut (ds, ds->analop.jump, pos);
|
|
|
|
gotShortcut = true;
|
2014-01-16 11:04:42 -06:00
|
|
|
break;
|
2018-03-21 11:29:19 +01:00
|
|
|
default:
|
|
|
|
if (ds_print_core_vmode_jump_hit (ds, pos))
|
|
|
|
gotShortcut = true;
|
|
|
|
break;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
if (!gotShortcut) {
|
|
|
|
r_cons_strcat (" ");
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-13 03:36:48 +01:00
|
|
|
// align for comment
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_align_comment(RDisasmState *ds) {
|
2016-03-04 00:33:24 +01:00
|
|
|
if (ds->show_comment_right_default) {
|
2017-05-09 02:21:56 +08:00
|
|
|
const int cmtcol = ds->cmtcol - 1;
|
2017-01-23 22:42:27 +01:00
|
|
|
int cstrlen = 0;
|
|
|
|
char *ll = r_cons_lastline (&cstrlen);
|
2016-03-13 03:13:27 +01:00
|
|
|
if (ll) {
|
|
|
|
int cols, ansilen = r_str_ansi_len (ll);
|
|
|
|
int utf8len = r_utf8_strlen ((const ut8*)ll);
|
2016-09-23 16:28:48 +02:00
|
|
|
int cells = utf8len - (cstrlen - ansilen);
|
2017-01-24 02:19:12 +01:00
|
|
|
if (cstrlen < 20) {
|
|
|
|
ds_print_pre (ds);
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
cols = ds->interactive ? ds->core->cons->columns : 1024;
|
2017-01-24 11:36:02 +01:00
|
|
|
if (cells < cmtcol) {
|
2017-01-24 02:59:02 +01:00
|
|
|
int len = cmtcol - cells;
|
2017-01-24 11:36:02 +01:00
|
|
|
if (len < cols && len > 0) {
|
2016-03-13 03:13:27 +01:00
|
|
|
r_cons_memset (' ', len);
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2016-03-13 03:13:27 +01:00
|
|
|
}
|
2017-05-09 02:21:56 +08:00
|
|
|
r_cons_print (" ");
|
2014-11-13 03:36:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_dwarf(RDisasmState *ds) {
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->show_dwarf) {
|
2017-03-20 23:43:34 +01:00
|
|
|
int len = ds->opstr? strlen (ds->opstr): 0;
|
2016-05-31 22:13:33 +02:00
|
|
|
if (len < 30) {
|
|
|
|
len = 30 - len;
|
|
|
|
}
|
2016-11-23 10:30:44 +01:00
|
|
|
// TODO: cache value in ds
|
|
|
|
int dwarfFile = (int)ds->dwarfFile + (int)ds->dwarfAbspath;
|
|
|
|
free (ds->sl);
|
2016-11-22 23:59:04 +01:00
|
|
|
ds->sl = r_bin_addr2text (ds->core->bin, ds->at, dwarfFile);
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->sl) {
|
|
|
|
if ((!ds->osl || (ds->osl && strcmp (ds->sl, ds->osl)))) {
|
2016-05-31 22:13:33 +02:00
|
|
|
char *chopstr, *line = strdup (ds->sl);
|
|
|
|
if (!line) {
|
|
|
|
return;
|
|
|
|
}
|
2014-11-25 02:07:01 +01:00
|
|
|
r_str_replace_char (line, '\t', ' ');
|
|
|
|
r_str_replace_char (line, '\x1b', ' ');
|
|
|
|
r_str_replace_char (line, '\r', ' ');
|
|
|
|
r_str_replace_char (line, '\n', '\x00');
|
2018-01-08 03:22:26 +01:00
|
|
|
chopstr = r_str_trim (line);
|
2016-05-31 22:13:33 +02:00
|
|
|
if (!*chopstr) {
|
|
|
|
free (line);
|
|
|
|
return;
|
|
|
|
}
|
2014-12-18 12:54:36 +01:00
|
|
|
// handle_set_pre (ds, " ");
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_align_comment (ds);
|
2015-11-02 12:38:08 +01:00
|
|
|
if (ds->show_color) {
|
2017-05-09 02:21:56 +08:00
|
|
|
r_cons_printf ("%s; %s"Color_RESET, ds->pal_comment, chopstr);
|
2015-11-02 12:38:08 +01:00
|
|
|
} else {
|
2017-05-09 02:21:56 +08:00
|
|
|
r_cons_printf ("; %s", chopstr);
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
free (ds->osl);
|
|
|
|
ds->osl = ds->sl;
|
|
|
|
ds->sl = NULL;
|
2014-11-25 02:07:01 +01:00
|
|
|
free (line);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-08 20:21:06 +02:00
|
|
|
static void ds_print_asmop_payload(RDisasmState *ds, const ut8 *buf) {
|
2016-08-25 18:54:07 +02:00
|
|
|
if (ds->show_varxs) {
|
2015-01-11 04:29:15 +01:00
|
|
|
// XXX asume analop is filled
|
|
|
|
//r_anal_op (core->anal, &ds->analop, ds->at, core->block+i, core->blocksize-i);
|
|
|
|
int v = ds->analop.ptr;
|
|
|
|
switch (ds->analop.stackop) {
|
2015-11-05 02:07:20 +01:00
|
|
|
case R_ANAL_STACK_GET:
|
2016-09-23 16:28:48 +02:00
|
|
|
if (v < 0) {
|
2015-11-05 02:07:20 +01:00
|
|
|
r_cons_printf (" ; local.get %d", -v);
|
|
|
|
} else {
|
|
|
|
r_cons_printf (" ; arg.get %d", v);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R_ANAL_STACK_SET:
|
2016-09-23 16:28:48 +02:00
|
|
|
if (v < 0) {
|
2015-11-05 02:07:20 +01:00
|
|
|
r_cons_printf (" ; local.set %d", -v);
|
|
|
|
} else {
|
|
|
|
r_cons_printf (" ; arg.set %d", v);
|
|
|
|
}
|
|
|
|
break;
|
2015-01-11 04:29:15 +01:00
|
|
|
}
|
|
|
|
}
|
2017-05-08 20:21:06 +02:00
|
|
|
if (ds->asmop.payload != 0) {
|
2017-12-27 21:33:58 +04:00
|
|
|
r_cons_printf ("\n; .. payload of %d byte(s)", ds->asmop.payload);
|
2017-05-08 20:21:06 +02:00
|
|
|
if (ds->showpayloads) {
|
2017-05-23 03:01:45 +02:00
|
|
|
int mod = ds->asmop.payload % ds->core->assembler->dataalign;
|
2017-05-08 20:21:06 +02:00
|
|
|
int x;
|
|
|
|
for (x = 0; x < ds->asmop.payload; ++x) {
|
2017-05-23 03:01:45 +02:00
|
|
|
r_cons_printf ("\n 0x%02x", buf[ds->oplen + x]);
|
|
|
|
}
|
|
|
|
for (x = 0; x < mod; ++x) {
|
|
|
|
r_cons_printf ("\n 0x%02x ; alignment", buf[ds->oplen + ds->asmop.payload + x]);
|
2017-05-08 20:21:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2017-11-15 23:45:30 +08:00
|
|
|
static char *ds_esc_str(RDisasmState *ds, const char *str, int len, const char **prefix_out) {
|
2017-08-02 00:18:47 +08:00
|
|
|
int str_len;
|
2017-11-15 23:45:30 +08:00
|
|
|
char *escstr = NULL;
|
2017-07-24 23:17:24 +08:00
|
|
|
const char *prefix = "";
|
2018-03-12 22:54:05 +08:00
|
|
|
bool esc_bslash = ds->core->print->esc_bslash;
|
2017-07-24 23:17:24 +08:00
|
|
|
switch (ds->strenc) {
|
|
|
|
case R_STRING_ENC_LATIN1:
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash);
|
2017-07-24 23:17:24 +08:00
|
|
|
break;
|
|
|
|
case R_STRING_ENC_UTF8:
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_utf8 (str, ds->show_asciidot, esc_bslash);
|
2017-07-24 23:17:24 +08:00
|
|
|
break;
|
|
|
|
case R_STRING_ENC_UTF16LE:
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_utf16le (str, len, ds->show_asciidot, esc_bslash);
|
2017-07-24 23:17:24 +08:00
|
|
|
prefix = "u";
|
|
|
|
break;
|
|
|
|
case R_STRING_ENC_UTF32LE:
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_utf32le (str, len, ds->show_asciidot, esc_bslash);
|
2017-07-24 23:17:24 +08:00
|
|
|
prefix = "U";
|
|
|
|
break;
|
|
|
|
default:
|
2017-08-02 00:18:47 +08:00
|
|
|
str_len = strlen (str);
|
2017-10-09 18:13:27 +08:00
|
|
|
if ((str_len == 1 && len > 3 && str[2] && !str[3])
|
2017-10-09 14:40:35 +02:00
|
|
|
|| (str_len == 3 && len > 5 && !memcmp (str, "\xff\xfe", 2) && str[4] && !str[5])) {
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_utf16le (str, len, ds->show_asciidot, esc_bslash);
|
2017-08-02 21:55:00 +08:00
|
|
|
prefix = "u";
|
2017-08-06 09:08:17 +08:00
|
|
|
} else if (str_len == 1 && len > 7 && !str[2] && !str[3] && str[4] && !str[5]) {
|
|
|
|
RStrEnc enc = R_STRING_ENC_UTF32LE;
|
|
|
|
RRune ch;
|
|
|
|
const char *ptr, *end;
|
|
|
|
end = (const char *)r_mem_mem_aligned ((ut8 *)str, len, (ut8 *)"\0\0\0\0", 4, 4);
|
|
|
|
if (!end) {
|
|
|
|
end = str + len - 1;
|
|
|
|
}
|
|
|
|
for (ptr = str; ptr < end; ptr += 4) {
|
|
|
|
if (r_utf32le_decode ((ut8 *)ptr, end - ptr, &ch) > 0 && ch > 0x10ffff) {
|
|
|
|
enc = R_STRING_ENC_LATIN1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (enc == R_STRING_ENC_UTF32LE) {
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_utf32le (str, len, ds->show_asciidot, esc_bslash);
|
2017-08-06 09:08:17 +08:00
|
|
|
prefix = "U";
|
|
|
|
} else {
|
2018-03-12 22:54:05 +08:00
|
|
|
escstr = r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash);
|
2017-08-06 09:08:17 +08:00
|
|
|
}
|
2017-07-24 23:17:24 +08:00
|
|
|
} else {
|
2017-08-02 00:18:47 +08:00
|
|
|
RStrEnc enc = R_STRING_ENC_LATIN1;
|
|
|
|
const char *ptr = str, *end = str + str_len;
|
|
|
|
for (; ptr < end; ptr++) {
|
|
|
|
if (r_utf8_decode ((ut8 *)ptr, end - ptr, NULL) > 1) {
|
|
|
|
enc = R_STRING_ENC_UTF8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
escstr = (enc == R_STRING_ENC_UTF8 ?
|
2018-03-12 22:54:05 +08:00
|
|
|
r_str_escape_utf8 (str, ds->show_asciidot, esc_bslash) :
|
|
|
|
r_str_escape_latin1 (str, ds->show_asciidot, esc_bslash));
|
2017-06-12 17:37:28 +08:00
|
|
|
}
|
|
|
|
}
|
2017-11-15 23:45:30 +08:00
|
|
|
if (prefix_out) {
|
|
|
|
*prefix_out = prefix;
|
|
|
|
}
|
|
|
|
return escstr;
|
|
|
|
}
|
|
|
|
|
2018-01-15 01:09:22 +08:00
|
|
|
static void ds_print_str(RDisasmState *ds, const char *str, int len, ut64 refaddr) {
|
2017-11-15 23:45:30 +08:00
|
|
|
const char *prefix;
|
2018-02-15 20:42:05 +08:00
|
|
|
if (!r_bin_string_filter (ds->core->bin, str, refaddr)) {
|
2018-01-18 03:34:53 +08:00
|
|
|
return;
|
2018-01-06 21:31:41 +08:00
|
|
|
}
|
2017-11-15 23:45:30 +08:00
|
|
|
char *escstr = ds_esc_str (ds, str, len, &prefix);
|
2017-07-24 23:17:24 +08:00
|
|
|
if (escstr) {
|
2018-04-05 15:54:44 +08:00
|
|
|
bool inv = ds->show_color && !ds->show_emu_strinv;
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2018-04-05 15:54:44 +08:00
|
|
|
ds_comment (ds, true, "; %s%s\"%s\"%s", inv ? Color_INVERT : "", prefix, escstr,
|
|
|
|
inv ? Color_INVERT_RESET : "");
|
2018-02-17 23:02:53 +08:00
|
|
|
ds->printed_str_addr = refaddr;
|
2017-07-24 23:17:24 +08:00
|
|
|
free (escstr);
|
|
|
|
}
|
2017-06-12 17:37:28 +08:00
|
|
|
}
|
|
|
|
|
2017-05-26 08:56:47 +08:00
|
|
|
static inline bool is_filtered_flag(RDisasmState *ds, const char *name) {
|
|
|
|
if (ds->show_noisy_comments || strncmp (name, "str.", 4)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ut64 refaddr = ds->analop.ptr;
|
|
|
|
char *anal_flag = r_meta_get_string (ds->core->anal, R_META_TYPE_STRING, refaddr);
|
|
|
|
if (anal_flag) {
|
|
|
|
anal_flag = strdup (anal_flag);
|
|
|
|
if (anal_flag) {
|
|
|
|
r_name_filter (anal_flag, -1);
|
|
|
|
if (!strcmp (&name[4], anal_flag)) {
|
|
|
|
free (anal_flag);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
free (anal_flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-05 14:52:21 +02:00
|
|
|
/* convert numeric value in opcode to ascii char or number */
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
|
|
|
|
RCore *core = ds->core;
|
2014-09-05 00:11:28 +02:00
|
|
|
ut64 p = ds->analop.ptr;
|
2016-09-12 23:11:38 +02:00
|
|
|
ut64 v = ds->analop.val;
|
2017-03-27 08:18:55 +05:30
|
|
|
ut64 refaddr = p;
|
2017-12-24 01:03:19 +01:00
|
|
|
bool aligned = false;
|
2017-10-16 20:17:34 +08:00
|
|
|
int refptr = ds->analop.refptr;
|
2017-05-02 21:18:59 +08:00
|
|
|
RFlagItem *f;
|
2016-12-24 18:17:25 +01:00
|
|
|
if (!ds->show_comments || !ds->show_slow) {
|
2015-08-26 03:27:34 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-11-04 16:13:10 +01:00
|
|
|
|
2017-10-09 14:40:35 +02:00
|
|
|
ds->chref = 0;
|
2017-11-14 05:25:04 +09:00
|
|
|
if ((char)v > 0 && v >= '!') {
|
2017-11-04 16:13:10 +01:00
|
|
|
ds->chref = (char)v;
|
2017-11-04 20:22:14 +01:00
|
|
|
if (ds->immstr) {
|
2017-11-14 03:59:24 +09:00
|
|
|
char *str = r_str_from_ut64 (r_read_ble64 (&v, core->print->big_endian));
|
|
|
|
if (str && *str) {
|
2017-11-22 01:01:00 +01:00
|
|
|
ALIGN;
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; '%s'", str);
|
2017-11-14 03:59:24 +09:00
|
|
|
}
|
2017-11-04 16:13:10 +01:00
|
|
|
free (str);
|
2017-11-04 20:22:14 +01:00
|
|
|
} else {
|
2017-11-14 03:59:24 +09:00
|
|
|
if ((char)v > 0 && v >= '!' && v <= '~') {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-24 01:03:19 +01:00
|
|
|
aligned = true;
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; '%c'", (char)v);
|
2017-11-14 03:59:24 +09:00
|
|
|
}
|
2017-11-04 16:13:10 +01:00
|
|
|
}
|
2016-09-12 23:11:38 +02:00
|
|
|
}
|
2017-03-27 08:18:55 +05:30
|
|
|
RList *list = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
|
|
|
list = r_anal_refs_get (core->anal, ds->at);
|
|
|
|
r_list_foreach (list, iter, ref) {
|
|
|
|
if (ref->type == R_ANAL_REF_TYPE_STRING || ref->type == R_ANAL_REF_TYPE_DATA) {
|
|
|
|
if ((f = r_flag_get_i (core->flags, ref->addr))) {
|
|
|
|
refaddr = ref->addr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-09 02:31:37 -07:00
|
|
|
r_list_free (list);
|
2017-10-16 20:17:34 +08:00
|
|
|
if (ds->analop.type == (R_ANAL_OP_TYPE_MOV | R_ANAL_OP_TYPE_REG)
|
|
|
|
&& ds->analop.stackop == R_ANAL_STACK_SET
|
|
|
|
&& ds->analop.val != UT64_MAX && ds->analop.val > 10) {
|
|
|
|
const char *arch = r_config_get (core->config, "asm.arch");
|
|
|
|
if (arch && !strcmp (arch, "x86")) {
|
|
|
|
p = refaddr = ds->analop.val;
|
|
|
|
refptr = 0;
|
|
|
|
}
|
|
|
|
}
|
2017-05-01 16:49:41 +08:00
|
|
|
bool flag_printed = false;
|
2017-05-02 21:18:59 +08:00
|
|
|
bool refaddr_printed = false;
|
2017-06-30 23:45:47 +08:00
|
|
|
bool string_printed = false;
|
2018-03-19 22:19:29 +08:00
|
|
|
if (refaddr == UT64_MAX) {
|
2014-11-07 00:41:29 +01:00
|
|
|
/* do nothing */
|
2017-03-27 08:18:55 +05:30
|
|
|
} else if (((st64)p) > 0 || ((st64)refaddr) > 0) {
|
2014-11-07 00:41:29 +01:00
|
|
|
const char *kind;
|
2016-06-10 19:09:13 +02:00
|
|
|
char *msg = calloc (sizeof (char), len);
|
2017-03-27 08:18:55 +05:30
|
|
|
if (((st64)p) > 0) {
|
|
|
|
f = r_flag_get_i (core->flags, p);
|
|
|
|
if (f) {
|
|
|
|
refaddr = p;
|
2017-05-26 08:56:47 +08:00
|
|
|
if (!flag_printed && !is_filtered_flag (ds, f->name)
|
|
|
|
&& (!ds->opstr || !strstr (ds->opstr, f->name))) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s", f->name);
|
2018-02-22 23:24:37 +08:00
|
|
|
ds->printed_flag_addr = p;
|
2017-05-01 16:49:41 +08:00
|
|
|
flag_printed = true;
|
|
|
|
}
|
2017-03-27 08:18:55 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
r_io_read_at (core->io, refaddr, (ut8*)msg, len - 1);
|
2017-10-16 20:17:34 +08:00
|
|
|
if (refptr) {
|
|
|
|
ut64 num = r_read_ble (msg, core->print->big_endian, refptr * 8);
|
2016-05-04 17:13:44 +02:00
|
|
|
st64 n = (st64)num;
|
|
|
|
st32 n32 = (st32)(n & UT32_MAX);
|
2015-04-03 17:25:07 +02:00
|
|
|
if (ds->analop.type == R_ANAL_OP_TYPE_LEA) {
|
2017-06-28 06:56:22 +08:00
|
|
|
char str[128] = {0};
|
2017-03-27 08:18:55 +05:30
|
|
|
f = r_flag_get_i (core->flags, refaddr);
|
2017-06-28 06:56:22 +08:00
|
|
|
if (!f && ds->show_slow) {
|
|
|
|
r_io_read_at (ds->core->io, ds->analop.ptr,
|
2017-08-22 23:16:04 +02:00
|
|
|
(ut8 *)str, sizeof (str) - 1);
|
2016-11-30 18:00:23 +01:00
|
|
|
str[sizeof (str) - 1] = 0;
|
2017-06-30 23:45:47 +08:00
|
|
|
if (!string_printed && str[0] && r_str_is_printable_incl_newlines (str)) {
|
2018-01-15 01:09:22 +08:00
|
|
|
ds_print_str (ds, str, sizeof (str), ds->analop.ptr);
|
2017-06-30 23:45:47 +08:00
|
|
|
string_printed = true;
|
2016-11-30 18:00:23 +01:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-04-03 17:25:07 +02:00
|
|
|
} else {
|
2015-07-17 11:33:16 +02:00
|
|
|
f = NULL;
|
2016-06-10 19:09:13 +02:00
|
|
|
if (n == UT32_MAX || n == UT64_MAX) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; [0x%" PFMT64x":%d]=-1",
|
|
|
|
refaddr, refptr);
|
2016-12-24 18:17:25 +01:00
|
|
|
} else if (n == n32 && (n32 > -512 && n32 < 512)) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-05-09 02:21:56 +08:00
|
|
|
ds_comment (ds, true, "; [0x%" PFMT64x
|
2017-12-11 15:07:44 +01:00
|
|
|
":%d]=%"PFMT64d, refaddr, refptr, n);
|
2015-04-03 17:25:07 +02:00
|
|
|
} else {
|
2015-07-08 18:46:35 +02:00
|
|
|
const char *kind, *flag = "";
|
|
|
|
char *msg2 = NULL;
|
2015-04-03 17:25:07 +02:00
|
|
|
f = r_flag_get_i (core->flags, n);
|
2015-07-08 18:46:35 +02:00
|
|
|
if (f) {
|
|
|
|
flag = f->name;
|
|
|
|
} else {
|
2015-07-15 16:45:24 +02:00
|
|
|
msg2 = calloc (sizeof (char), len);
|
2016-06-02 03:19:31 +02:00
|
|
|
r_io_read_at (core->io, n, (ut8*)msg2, len - 1);
|
2017-12-24 01:03:19 +01:00
|
|
|
msg2[len - 1] = 0;
|
2017-03-27 08:18:55 +05:30
|
|
|
kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg2, len - 1);
|
2015-07-08 18:46:35 +02:00
|
|
|
if (kind && !strcmp (kind, "text")) {
|
|
|
|
r_str_filter (msg2, 0);
|
|
|
|
if (*msg2) {
|
|
|
|
char *lala = r_str_newf ("\"%s\"", msg2);
|
|
|
|
free (msg2);
|
|
|
|
flag = msg2 = lala;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-03-30 02:20:22 +02:00
|
|
|
{
|
|
|
|
const char *refptrstr = "";
|
|
|
|
if (core->print->flags & R_PRINT_FLAGS_SECSUB) {
|
2017-08-22 07:42:16 +00:00
|
|
|
RIOSection *s = r_io_section_vget (core->io, n);
|
2017-03-30 02:20:22 +02:00
|
|
|
if (s) {
|
|
|
|
refptrstr = s->name;
|
|
|
|
}
|
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; [0x%" PFMT64x":%d]=%s%s0x%" PFMT64x "%s%s",
|
2017-10-16 20:17:34 +08:00
|
|
|
refaddr, refptr, refptrstr, *refptrstr?".":"",
|
2017-12-11 15:07:44 +01:00
|
|
|
n, (flag && *flag) ? " " : "", flag);
|
2017-03-30 02:20:22 +02:00
|
|
|
}
|
2015-07-08 18:46:35 +02:00
|
|
|
free (msg2);
|
2015-04-03 17:25:07 +02:00
|
|
|
}
|
2017-05-02 21:18:59 +08:00
|
|
|
refaddr_printed = true;
|
|
|
|
}
|
|
|
|
}
|
2017-05-29 08:44:45 +08:00
|
|
|
if (!strcmp (ds->show_cmtoff, "true")) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; 0x%" PFMT64x, refaddr);
|
2017-05-29 08:44:45 +08:00
|
|
|
refaddr_printed = true;
|
|
|
|
} else if (!refaddr_printed && strcmp (ds->show_cmtoff, "false")) {
|
2017-05-02 21:18:59 +08:00
|
|
|
char addrstr[sizeof (refaddr) * 2 + 3];
|
|
|
|
snprintf (addrstr, sizeof (addrstr), "0x%" PFMT64x, refaddr);
|
|
|
|
if (!ds->opstr || !strstr (ds->opstr, addrstr)) {
|
|
|
|
snprintf (addrstr, sizeof (addrstr), "0x%08" PFMT64x, refaddr);
|
|
|
|
if (!ds->opstr || !strstr (ds->opstr, addrstr)) {
|
|
|
|
bool print_refaddr = true;
|
|
|
|
if (refaddr < 10) {
|
|
|
|
snprintf (addrstr, sizeof (addrstr), "%" PFMT64u, refaddr);
|
|
|
|
if (ds->opstr && strstr (ds->opstr, addrstr)) {
|
|
|
|
print_refaddr = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (print_refaddr) {
|
2017-12-24 01:03:19 +01:00
|
|
|
if (!aligned) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-24 01:03:19 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; 0x%" PFMT64x, refaddr);
|
2017-05-02 21:18:59 +08:00
|
|
|
refaddr_printed = true;
|
|
|
|
}
|
2015-07-15 16:45:24 +02:00
|
|
|
}
|
2014-11-07 00:41:29 +01:00
|
|
|
}
|
|
|
|
}
|
2014-11-14 03:42:07 +01:00
|
|
|
#if 1
|
2017-10-09 18:13:27 +08:00
|
|
|
if (!(IS_PRINTABLE (*msg) || ISWHITECHAR (*msg)
|
2017-10-09 14:40:35 +02:00
|
|
|
|| (len > 1 && !memcmp (msg, "\xff\xfe", 2)))) {
|
2014-11-14 03:42:07 +01:00
|
|
|
*msg = 0;
|
2016-09-22 18:06:10 +02:00
|
|
|
} else {
|
2016-12-09 17:05:19 +01:00
|
|
|
msg[len - 1] = 0;
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
2014-11-14 03:42:07 +01:00
|
|
|
#endif
|
2017-03-27 08:18:55 +05:30
|
|
|
f = r_flag_get_i (core->flags, refaddr);
|
2014-08-05 05:37:48 +02:00
|
|
|
if (f) {
|
2017-04-23 16:47:24 +08:00
|
|
|
if (strlen (msg) != 1) {
|
2017-05-14 15:50:01 +08:00
|
|
|
char *msg2 = r_str_new (msg);
|
|
|
|
if (msg2) {
|
|
|
|
r_str_filter (msg2, 0);
|
|
|
|
if (!strncmp (msg2, "UH..", 4)) {
|
|
|
|
*msg = 0;
|
|
|
|
}
|
|
|
|
free (msg2);
|
|
|
|
}
|
2016-12-26 04:06:33 +01:00
|
|
|
}
|
2014-11-10 19:26:09 +01:00
|
|
|
if (*msg) {
|
2017-06-30 23:45:47 +08:00
|
|
|
if (!string_printed) {
|
2018-01-15 01:09:22 +08:00
|
|
|
ds_print_str (ds, msg, len, refaddr);
|
2017-06-30 23:45:47 +08:00
|
|
|
string_printed = true;
|
|
|
|
}
|
2017-05-26 08:56:47 +08:00
|
|
|
} else if (!flag_printed && (!ds->opstr || !strstr (ds->opstr, f->name))) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %s", f->name);
|
2018-02-22 23:24:37 +08:00
|
|
|
ds->printed_flag_addr = refaddr;
|
2017-05-26 08:56:47 +08:00
|
|
|
flag_printed = true;
|
2014-11-10 19:26:09 +01:00
|
|
|
}
|
2014-08-05 05:37:48 +02:00
|
|
|
} else {
|
2017-03-27 08:18:55 +05:30
|
|
|
if (refaddr == UT64_MAX || refaddr == UT32_MAX) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; -1");
|
2017-03-27 08:18:55 +05:30
|
|
|
} else if (((char)refaddr > 0) && refaddr >= '!' && refaddr <= '~') {
|
|
|
|
char ch = refaddr;
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-10-09 14:40:35 +02:00
|
|
|
if (ch != ds->chref) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; '%c'", ch);
|
2017-10-09 14:40:35 +02:00
|
|
|
}
|
2017-03-27 08:18:55 +05:30
|
|
|
} else if (refaddr > 10) {
|
|
|
|
if ((st64)refaddr < 0) {
|
2014-09-22 13:45:36 +02:00
|
|
|
// resolve local var if possible
|
2017-03-27 08:18:55 +05:30
|
|
|
RAnalVar *v = r_anal_var_get (core->anal, ds->at, 'v', 1, (int)refaddr);
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2014-09-22 13:45:36 +02:00
|
|
|
if (v) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; var %s", v->name);
|
2014-09-22 13:45:36 +02:00
|
|
|
r_anal_var_free (v);
|
|
|
|
} else {
|
2017-12-19 00:17:43 +01:00
|
|
|
ds_comment (ds, true, "; var %d", -(int)refaddr);
|
2014-09-22 13:45:36 +02:00
|
|
|
}
|
|
|
|
} else {
|
2017-03-27 08:18:55 +05:30
|
|
|
if (r_core_anal_address (core, refaddr) & R_ANAL_ADDR_TYPE_ASCII) {
|
2017-06-30 23:45:47 +08:00
|
|
|
if (!string_printed && *msg) {
|
2018-01-15 01:09:22 +08:00
|
|
|
ds_print_str (ds, msg, len, refaddr);
|
2017-06-30 23:45:47 +08:00
|
|
|
string_printed = true;
|
2014-11-19 00:26:26 +01:00
|
|
|
}
|
2014-11-11 18:06:20 +01:00
|
|
|
}
|
2014-11-10 19:26:09 +01:00
|
|
|
}
|
|
|
|
}
|
2016-12-24 18:17:25 +01:00
|
|
|
//XXX this should be refactored with along the above
|
2017-03-27 08:18:55 +05:30
|
|
|
kind = r_anal_data_kind (core->anal, refaddr, (const ut8*)msg, len - 1);
|
2014-11-10 19:26:09 +01:00
|
|
|
if (kind) {
|
|
|
|
if (!strcmp (kind, "text")) {
|
2017-06-30 23:45:47 +08:00
|
|
|
if (!string_printed && *msg) {
|
2018-01-15 01:09:22 +08:00
|
|
|
ds_print_str (ds, msg, len, refaddr);
|
2017-06-30 23:45:47 +08:00
|
|
|
string_printed = true;
|
2014-11-10 19:26:09 +01:00
|
|
|
}
|
2016-11-09 02:52:26 +01:00
|
|
|
} else if (!strcmp (kind, "invalid")) {
|
2017-03-27 08:18:55 +05:30
|
|
|
int *n = (int*)&refaddr;
|
2017-02-24 02:33:11 +01:00
|
|
|
ut64 p = ds->analop.val;
|
|
|
|
if (p == UT64_MAX || p == UT32_MAX) {
|
|
|
|
p = ds->analop.ptr;
|
|
|
|
}
|
2016-11-09 02:52:26 +01:00
|
|
|
/* avoid double ; -1 */
|
|
|
|
if (p != UT64_MAX && p != UT32_MAX) {
|
|
|
|
if (*n > -0xfff && *n < 0xfff) {
|
2017-12-24 01:03:19 +01:00
|
|
|
if (!aligned) {
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_comment (ds);
|
2017-12-24 01:03:19 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_comment (ds, true, "; %"PFMT64d, p);
|
2016-11-09 02:52:26 +01:00
|
|
|
}
|
2014-11-13 03:59:51 +01:00
|
|
|
}
|
2014-11-10 19:26:09 +01:00
|
|
|
} else {
|
2016-11-09 02:52:26 +01:00
|
|
|
// r_cons_printf (" ; %s", kind);
|
2014-09-22 13:45:36 +02:00
|
|
|
}
|
2014-11-10 19:26:09 +01:00
|
|
|
// TODO: check for more data kinds
|
2014-09-05 00:11:28 +02:00
|
|
|
}
|
2014-08-05 05:37:48 +02:00
|
|
|
}
|
2015-03-06 00:56:10 +01:00
|
|
|
free (msg);
|
2016-09-21 11:00:52 +02:00
|
|
|
} else {
|
|
|
|
ds_print_as_string (ds);
|
|
|
|
}
|
2017-11-24 23:19:26 +01:00
|
|
|
#if 0
|
|
|
|
if (!ds->show_comment_right && ds->cmtcount > 0) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2017-11-24 23:19:26 +01:00
|
|
|
}
|
|
|
|
#endif
|
2017-01-02 15:56:08 +01:00
|
|
|
#if DEADCODE
|
2016-09-21 11:00:52 +02:00
|
|
|
if (aligned && ds->show_color) {
|
|
|
|
r_cons_printf (Color_RESET);
|
|
|
|
}
|
2017-01-02 15:56:08 +01:00
|
|
|
#endif
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2014-11-03 16:24:04 +01:00
|
|
|
// TODO: Use sdb in rbin to accelerate this
|
|
|
|
// we shuold use aligned reloc addresses instead of iterating all of them
|
|
|
|
static RBinReloc *getreloc(RCore *core, ut64 addr, int size) {
|
|
|
|
RList *list;
|
|
|
|
RBinReloc *r;
|
|
|
|
RListIter *iter;
|
2016-09-23 16:28:48 +02:00
|
|
|
if (size < 1 || addr == UT64_MAX) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-11-03 16:24:04 +01:00
|
|
|
list = r_bin_get_relocs (core->bin);
|
|
|
|
r_list_foreach (list, iter, r) {
|
2016-12-24 18:17:25 +01:00
|
|
|
if ((r->vaddr >= addr) && (r->vaddr < (addr + size))) {
|
2014-11-03 16:24:04 +01:00
|
|
|
return r;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2014-11-03 16:24:04 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_relocs(RDisasmState *ds) {
|
2017-05-23 23:54:11 +02:00
|
|
|
if (!ds->showrelocs || !ds->show_slow) {
|
|
|
|
return;
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2014-11-03 16:24:04 +01:00
|
|
|
RBinReloc *rel = getreloc (core, ds->at, ds->analop.size);
|
2016-05-30 12:35:39 +02:00
|
|
|
|
2014-11-03 16:24:04 +01:00
|
|
|
if (rel) {
|
2016-11-01 01:14:23 +01:00
|
|
|
const int cmtcol = ds->cmtcol;
|
2017-01-23 22:42:27 +01:00
|
|
|
int cstrlen = 0;
|
|
|
|
char *ll = r_cons_lastline (&cstrlen);
|
2016-11-04 03:15:17 +01:00
|
|
|
int ansilen = r_str_ansi_len (ll);
|
2016-11-01 01:14:23 +01:00
|
|
|
int utf8len = r_utf8_strlen ((const ut8*)ll);
|
|
|
|
int cells = utf8len - (cstrlen - ansilen);
|
|
|
|
int len = cmtcol - cells;
|
|
|
|
r_cons_memset (' ', len);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (rel->import) {
|
2014-11-07 00:41:29 +01:00
|
|
|
r_cons_printf (" ; RELOC %d %s", rel->type, rel->import->name);
|
2016-09-23 16:28:48 +02:00
|
|
|
} else if (rel->symbol) {
|
2014-11-07 00:41:29 +01:00
|
|
|
r_cons_printf (" ; RELOC %d %s", rel->type, rel->symbol->name);
|
2016-09-23 16:28:48 +02:00
|
|
|
} else {
|
|
|
|
r_cons_printf (" ; RELOC %d ", rel->type);
|
|
|
|
}
|
2014-11-03 16:24:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-29 23:37:51 +01:00
|
|
|
static int mymemwrite0(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mymemwrite1(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-12-03 18:22:47 +01:00
|
|
|
static int mymemwrite2(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
|
|
|
|
return (addr >= emustack_min && addr < emustack_max);
|
|
|
|
}
|
|
|
|
|
2017-11-15 23:45:30 +08:00
|
|
|
#define R_DISASM_MAX_STR 512
|
2016-10-18 16:59:38 +02:00
|
|
|
static int myregwrite(RAnalEsil *esil, const char *name, ut64 *val) {
|
2015-09-10 22:28:04 +02:00
|
|
|
char str[64], *msg = NULL;
|
2015-09-10 04:20:09 +02:00
|
|
|
ut32 *n32 = (ut32*)str;
|
2016-11-15 19:34:22 +01:00
|
|
|
RDisasmState *ds = NULL;
|
|
|
|
if (!esil) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ds = esil->user;
|
2018-02-26 22:27:58 +08:00
|
|
|
if (!ds) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ds->esil_likely = true;
|
|
|
|
if (!ds->show_slow) {
|
|
|
|
return 0;
|
2015-09-10 04:20:09 +02:00
|
|
|
}
|
|
|
|
memset (str, 0, sizeof (str));
|
2018-02-26 22:27:58 +08:00
|
|
|
if (*val) {
|
2018-04-07 21:35:12 +08:00
|
|
|
bool emu_str_printed = false;
|
2018-02-20 00:56:59 +01:00
|
|
|
char *type = NULL;
|
2016-10-18 16:59:38 +02:00
|
|
|
(void)r_io_read_at (esil->anal->iob.io, *val, (ut8*)str, sizeof (str)-1);
|
2016-06-10 19:09:13 +02:00
|
|
|
str[sizeof (str)-1] = 0;
|
2018-02-20 00:56:59 +01:00
|
|
|
// support cstring here
|
|
|
|
{
|
|
|
|
ut64 *cstr = (ut64*) str;
|
|
|
|
ut64 addr = cstr[0];
|
|
|
|
if (!(*val >> 32)) {
|
|
|
|
addr = addr & UT32_MAX;
|
|
|
|
}
|
|
|
|
if (cstr[0] == 0 && cstr[1] < 0x1000) {
|
|
|
|
ut64 addr = cstr[2];
|
|
|
|
if (!(*val >> 32)) {
|
|
|
|
addr = addr & UT32_MAX;
|
|
|
|
}
|
|
|
|
(void)r_io_read_at (esil->anal->iob.io, addr,
|
|
|
|
(ut8*)str, sizeof (str)-1);
|
|
|
|
// eprintf ("IS CSTRING 0x%llx %s\n", addr, str);
|
|
|
|
type = r_str_newf ("(cstr 0x%08"PFMT64x") ", addr);
|
|
|
|
ds->printed_str_addr = cstr[2];
|
|
|
|
} else if (r_io_is_valid_offset (esil->anal->iob.io, addr, 0)) {
|
|
|
|
ds->printed_str_addr = cstr[0];
|
|
|
|
type = r_str_newf ("(pstr 0x%08"PFMT64x") ", addr);
|
|
|
|
(void)r_io_read_at (esil->anal->iob.io, addr,
|
|
|
|
(ut8*)str, sizeof (str)-1);
|
|
|
|
// eprintf ("IS PSTRING 0x%llx %s\n", addr, str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-01 08:49:34 +08:00
|
|
|
if (*str && !r_bin_strpurge (ds->core->bin, str, *val) && r_str_is_printable_incl_newlines (str)
|
2018-02-17 23:02:53 +08:00
|
|
|
&& (ds->printed_str_addr == UT64_MAX || *val != ds->printed_str_addr)) {
|
2017-11-28 21:59:29 +08:00
|
|
|
bool jump_op = false;
|
2018-02-20 00:56:59 +01:00
|
|
|
bool ignored = false;
|
2017-11-28 21:59:29 +08:00
|
|
|
switch (ds->analop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_UJMP:
|
|
|
|
case R_ANAL_OP_TYPE_RJMP:
|
|
|
|
case R_ANAL_OP_TYPE_IJMP:
|
|
|
|
case R_ANAL_OP_TYPE_IRJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_MJMP:
|
|
|
|
case R_ANAL_OP_TYPE_UCJMP:
|
|
|
|
jump_op = true;
|
2018-02-20 00:56:59 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_TRAP:
|
|
|
|
case R_ANAL_OP_TYPE_RET:
|
|
|
|
ignored = true;
|
|
|
|
break;
|
2017-11-28 21:59:29 +08:00
|
|
|
}
|
2018-02-20 00:56:59 +01:00
|
|
|
if (!jump_op && !ignored) {
|
2017-11-28 21:59:29 +08:00
|
|
|
const char *prefix;
|
2018-01-10 13:45:37 +01:00
|
|
|
ut32 len = sizeof (str) -1;
|
2018-01-06 23:21:45 +01:00
|
|
|
#if 0
|
2018-01-10 13:45:37 +01:00
|
|
|
RCore *core = ds->core;
|
2017-11-28 21:59:29 +08:00
|
|
|
ut32 len = core->blocksize + 256;
|
|
|
|
if (len < core->blocksize || len > R_DISASM_MAX_STR) {
|
|
|
|
len = R_DISASM_MAX_STR;
|
|
|
|
}
|
2018-01-06 23:21:45 +01:00
|
|
|
#endif
|
2018-02-20 00:56:59 +01:00
|
|
|
char *escstr = ds_esc_str (ds, str, (int)len, &prefix);
|
2018-03-22 22:09:52 +01:00
|
|
|
const char *escquote = ds->use_json ? "\\\"" : "\"";
|
2017-11-28 21:59:29 +08:00
|
|
|
if (escstr) {
|
2018-02-21 03:44:50 +01:00
|
|
|
if (ds->show_color) {
|
2018-04-05 15:54:44 +08:00
|
|
|
bool inv = ds->show_emu_strinv;
|
|
|
|
msg = r_str_newf ("%s%s%s%s%s%s%s",
|
|
|
|
prefix, type ? type : "", inv ? Color_INVERT : "",
|
|
|
|
escquote, escstr, escquote, inv ? Color_INVERT_RESET : "");
|
2018-02-21 03:44:50 +01:00
|
|
|
} else {
|
2018-03-22 22:09:52 +01:00
|
|
|
msg = r_str_newf ("%s%s%s%s%s", prefix, type? type: "", escquote, escstr, escquote);
|
2018-02-21 03:44:50 +01:00
|
|
|
}
|
2018-04-07 21:35:12 +08:00
|
|
|
emu_str_printed = true;
|
2017-11-28 21:59:29 +08:00
|
|
|
free (escstr);
|
|
|
|
}
|
2017-11-09 23:13:14 +08:00
|
|
|
}
|
2016-06-10 19:09:13 +02:00
|
|
|
} else {
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!*n32) {
|
2016-06-10 19:09:13 +02:00
|
|
|
// msg = strdup ("NULL");
|
|
|
|
} else if (*n32 == UT32_MAX) {
|
|
|
|
/* nothing */
|
|
|
|
} else {
|
2018-02-26 22:27:58 +08:00
|
|
|
if (!ds->show_emu_str) {
|
2017-12-04 20:57:19 +08:00
|
|
|
msg = r_str_newf ("-> 0x%x", *n32);
|
2016-06-10 19:09:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-20 00:56:59 +01:00
|
|
|
R_FREE (type);
|
2018-04-07 21:35:12 +08:00
|
|
|
if ((ds->printed_flag_addr == UT64_MAX || *val != ds->printed_flag_addr)
|
|
|
|
&& (ds->show_emu_strflag || !emu_str_printed)) {
|
2018-02-22 23:24:37 +08:00
|
|
|
RFlagItem *fi = r_flag_get_i (esil->anal->flb.f, *val);
|
|
|
|
if (fi && (!ds->opstr || !strstr (ds->opstr, fi->name))) {
|
|
|
|
msg = r_str_appendf (msg, "%s%s", msg && *msg ? " " : "", fi->name);
|
|
|
|
}
|
2016-06-10 19:09:13 +02:00
|
|
|
}
|
2015-09-10 04:20:09 +02:00
|
|
|
}
|
2018-02-26 22:27:58 +08:00
|
|
|
if (ds->show_emu_str) {
|
|
|
|
if (msg && *msg) {
|
|
|
|
if (ds->show_emu_stroff && *msg == '"') {
|
|
|
|
ds_comment_esil (ds, true, false, "; 0x%"PFMT64x" %s", *val, msg);
|
2017-12-03 02:02:13 +01:00
|
|
|
} else {
|
2018-02-26 22:27:58 +08:00
|
|
|
ds_comment_esil (ds, true, false, "; %s", msg);
|
2017-12-03 02:02:13 +01:00
|
|
|
}
|
2017-01-18 22:02:30 +01:00
|
|
|
if (ds->show_comments && !ds->show_comment_right) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-12-24 18:16:54 +01:00
|
|
|
}
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2018-02-26 22:27:58 +08:00
|
|
|
} else {
|
|
|
|
if (msg && *msg) {
|
|
|
|
ds_comment_esil (ds, true, false, "; %s=0x%"PFMT64x" %s", name, *val, msg);
|
|
|
|
} else {
|
|
|
|
ds_comment_esil (ds, true, false, "; %s=0x%"PFMT64x, name, *val);
|
|
|
|
}
|
|
|
|
if (ds->show_comments && !ds->show_comment_right) {
|
|
|
|
ds_newline (ds);
|
|
|
|
}
|
2016-11-20 17:37:27 +01:00
|
|
|
}
|
2015-09-10 04:20:09 +02:00
|
|
|
free (msg);
|
2015-09-10 00:34:21 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-01-30 00:41:30 +01:00
|
|
|
static void ds_pre_emulation(RDisasmState *ds) {
|
2018-01-30 14:25:15 +01:00
|
|
|
bool do_esil = ds->show_emu;
|
|
|
|
if (!ds->pre_emu) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-30 00:41:30 +01:00
|
|
|
RFlagItem *f = r_flag_get_at (ds->core->flags, ds->core->offset, true);
|
|
|
|
if (!f) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ut64 base = f->offset;
|
|
|
|
RAnalEsil *esil = ds->core->anal->esil;
|
|
|
|
int i, end = ds->core->offset - base;
|
|
|
|
int maxemu = 1024 * 1024;
|
2018-02-16 12:42:54 +08:00
|
|
|
RAnalEsilHookRegWriteCB orig_cb = esil->cb.hook_reg_write;
|
2018-01-30 00:41:30 +01:00
|
|
|
if (end < 0 || end > maxemu) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-30 14:25:15 +01:00
|
|
|
ds->stackptr = ds->core->anal->stackptr;
|
2018-02-16 12:42:54 +08:00
|
|
|
esil->cb.hook_reg_write = NULL;
|
2018-01-30 00:41:30 +01:00
|
|
|
for (i = 0; i < end; i++) {
|
|
|
|
ut64 addr = base + i;
|
|
|
|
RAnalOp* op = r_core_anal_op (ds->core, addr);
|
|
|
|
if (op) {
|
2018-01-30 14:25:15 +01:00
|
|
|
if (do_esil) {
|
|
|
|
r_anal_esil_set_pc (esil, addr);
|
|
|
|
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&op->esil));
|
|
|
|
if (op->size > 0) {
|
|
|
|
i += op->size - 1;
|
|
|
|
}
|
2018-01-30 00:41:30 +01:00
|
|
|
}
|
2018-01-30 14:25:15 +01:00
|
|
|
ds_update_stackptr (ds, op);
|
2018-01-30 00:41:30 +01:00
|
|
|
r_anal_op_free (op);
|
|
|
|
}
|
|
|
|
}
|
2018-02-16 12:42:54 +08:00
|
|
|
esil->cb.hook_reg_write = orig_cb;
|
2018-01-30 00:41:30 +01:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_esil_anal_init(RDisasmState *ds) {
|
|
|
|
RCore *core = ds->core;
|
2015-09-10 01:42:56 +02:00
|
|
|
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
2016-06-08 21:16:00 +02:00
|
|
|
ds->esil_old_pc = r_reg_getv (core->anal->reg, pc);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!ds->esil_old_pc || ds->esil_old_pc == UT64_MAX) {
|
|
|
|
ds->esil_old_pc = core->offset;
|
|
|
|
}
|
2015-09-11 23:46:09 +02:00
|
|
|
if (!ds->show_emu) {
|
2018-01-30 14:25:15 +01:00
|
|
|
// XXX. stackptr not computed without asm.emu, when its not required
|
2015-09-10 01:42:56 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!core->anal->esil) {
|
|
|
|
int iotrap = r_config_get_i (core->config, "esil.iotrap");
|
2017-03-27 03:39:13 +02:00
|
|
|
int esd = r_config_get_i (core->config, "esil.stack.depth");
|
Fix #9595 (#9673)
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* RTTI: Read MSVC Complete Object Locator
* RTTI: Read MSVC Class Hierarchy Descriptor
* VTable End on Reference
* RTTI: Read MSVC Type Descriptor
* RTTI: Read MSVC Base Class Array, Better Printing
* Add anal.cpp.abi
* Minor Code Style Changes in RTTI
* Fix rahash2 entropy to show non truncated double (#9629)
* Anal - whitespace fixes
* Honor CFLAGS on the static build test compilation (#9677)
* change coding style tab width to 4 (#9670)
* Meson: use more built-in options (#9678)
* Add support for extended regex in asm search (#9675)
* Fix #9665 - Backwardly handle scr.color={bool}
* Fix #9676 - Infinite loop in ecs with scr.color=2
* Adding help for redirection (#9679)
* Refactores function r_str_split_list to receive the character to split by (#9672)
* Fix #9666 - lines with comments do not use Unicode reflines
* Fix uninitialized optypes_list issue in cmd_debug
* update asan.sh to actually take the env for ASAN
* removed incorrect return (#9685)
* Fix UB in ESIL
* Initial import of the CoreUndo API and uc command
* Initial implementation of cmd.pdc to select pseudo-decompiler
* Handle recursive pdc calls
* Fix RPrint.strconv_mode memleak
* Fix leaks in RSyscall.srdb
* Use r_syscall_ref to avoid dblfree-or-leak issue
* Arm thumb/thumb selector for the armass (#9681)
* added function to translate number to imm12
* added function to get thumb shifts easily
* added selector, newfangled implementation of adc
* add bitmask for command suffixes
* added new routine for parsing suffixes to opcodes. Error check added in getnum. Bugfixes.
* Few improvements to 8051 memory mapping (#9686)
* update memory map when idata/sfr/xdata regs change
* set address space name on map
* fix regression, remove debug output
* fix regression, enable map name
* Some fixups for #9682 (#9688)
* Fix: coredump generation for huge programs (#9680)
* Refix #9666 - lines with comments do not use Unicode reflines
* Removed code unnecessary due to dcf3db025085c45124ec21890550a4ef19bd015c
* Fixed free const warning
* Fix another memleak in RSyscall
* Fix more memleaks
* Fix leak in RConsPal.rainbow
* Fix 18K leak in anal.x86.cs
* Fix some more memleaks in disasm and fix issue in str overlap
* Fix memleak in RCore.anal_refs and fix regression
* Revert "Fix some more memleaks in disasm and fix issue in str overlap"
This reverts commit a902df837b0d499e1723179ed5c957c078703b51.
* Fix memleak regressions
* Bring back another memleak fix
* Fix an undefined behaviour in RParse.filter
* Fix memleaks in disasm.c
* Add cundo.c to Meson (#9694)
* Bring back an ugly buffer pack access issue to make it work
* Cast to void * in R_FREE (#9692)
* Set anal.cpp.abi to msvc for pe
* Add better help for av
* Split avr into avr and avra
* Make av, avr and avra breakable
* Add RTTI struct specific print functions
* RTTI: Support MSVC x86_64
* PE: Fix too short section name.
* PDB: define a constant to store the max length of a section name and use id.
* PDB: dump the size of structure and union in JSON mode.
* Fix cast issue in eprintf for debug.core.linux
* Move the asm and anal plugins for x86.udis to extras
Available via r2pm -ci udis86
* Remove more udis86 references
* Fix warnings
* fix pcache ptr-fuckup
* Fix defragger theme
* Fix crash in asl and fix its behaviour
* Fix memory leak in blaze anal and silent a warning
* Implement ?q to be like ?v but in quiet mode
* Fix Meson build
* Add missing 8, 16, 32 bit registers (and flags) for the linux-arm64 debugger reg profile
* Fix 'Cannot find function at UT64_MAX message'
* Add some Pingu to fortunes.fun
* Loading Core (x86, x86_64, aarch64) (#9669)
* Ragg2-cc -> Ragg2 merge (#9658)
- change of 'access' function for 'r_file_exists' for windows portability
- several changes in the way ragg2.c is done, see PR #9658 pancake comments
- change function for the remove of 'file'.text
- open changed for r_file_dump
- some elt of cEnv_t are now const
- skip all the pointers verification in set_cEnv but do them in check_cEnv instead
- add 2 r_str_sanitize for file and CC in parseCFile
- rewrite the removal of .o, .tmp, .bin, .s files, with cleaner code
- changed the long command with sed and grep to 2 C functions.
- The function parseCompiled that basically does what the command was doing
- And r_str_stripLines that is equivalent to "grep -v" (maybe we should put this one in str.c ?)
- simplify a bit getCompiler function with a const char* array
- add ternary operator for armOrMips condition
- use r_file_path for finding path to compilers
- new file created in libr/egg which contains all the C file parser
- modifications of 2 files to match the change :
- libr/egg/r_egg.h
- libr/egg/Makefile
- the function r_str_stripLine is simplier (the mallocs wasn't needed)
- the function r_str_stripLine is moved to libr/util/str.c
- libr/include/r_util/r_str.h is changed accordingly
* Revert bd3465c9a3fbeddf83980dc07eaac588320f7d (warning remains fixed)
This reverts commit titled "Fixed free const warning".
* Added an address mask inside the RAnalEsil struct in order to be sure that the address accessed is relevant with the asm.bits of the file + Changed the calls to r_anal_esil_new
* Corrected the addrmask in r_anal_esil_new
* Cleanup expressions in esil.c (addr &=...)
* Corrected r_anal_esil_new definition in r_anal.h
* Added an address size max in the ESIL config (maximum address size reachable by the ESIL VM)
2018-03-16 10:45:17 +01:00
|
|
|
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
|
|
|
|
|
|
|
|
if (!(core->anal->esil = r_anal_esil_new (esd, iotrap, addrsize))) {
|
2016-06-08 21:16:00 +02:00
|
|
|
R_FREE (ds->esil_regstate);
|
2016-01-20 16:13:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-08-05 14:35:44 +03:00
|
|
|
r_anal_esil_setup (core->anal->esil, core->anal, 0, 0, 1);
|
2015-09-10 01:42:56 +02:00
|
|
|
}
|
2016-06-10 16:14:07 +02:00
|
|
|
core->anal->esil->user = ds;
|
2016-06-08 21:16:00 +02:00
|
|
|
free (ds->esil_regstate);
|
2016-10-24 14:31:03 +02:00
|
|
|
R_FREE (core->anal->last_disasm_reg);
|
2016-04-21 02:25:49 +02:00
|
|
|
if (core->anal->gp) {
|
2016-05-27 13:24:42 +02:00
|
|
|
r_reg_setv (core->anal->reg, "gp", core->anal->gp);
|
2016-04-21 02:25:49 +02:00
|
|
|
}
|
2016-06-08 21:16:00 +02:00
|
|
|
ds->esil_regstate = r_reg_arena_peek (core->anal->reg);
|
2018-01-30 00:41:30 +01:00
|
|
|
|
|
|
|
// TODO: emulate N instructions BEFORE the current offset to get proper full function emulation
|
2018-01-30 14:25:15 +01:00
|
|
|
ds_pre_emulation (ds);
|
2015-09-10 01:42:56 +02:00
|
|
|
}
|
|
|
|
|
2017-05-20 14:37:51 +02:00
|
|
|
static void ds_print_bbline(RDisasmState *ds, bool force) {
|
2018-02-23 10:45:53 +01:00
|
|
|
if (ds->show_bbline) {
|
|
|
|
RAnalBlock *bb = r_anal_fcn_bbget (ds->fcn, ds->at);
|
|
|
|
if (force || (ds->fcn && bb)) {
|
|
|
|
ds_begin_json_line (ds);
|
|
|
|
ds_setup_print_pre (ds, false, false);
|
|
|
|
ds_update_ref_lines (ds);
|
|
|
|
if (!ds->linesright && ds->show_lines && ds->line) {
|
|
|
|
r_cons_printf ("%s%s%s", COLOR (ds, color_flow),
|
|
|
|
ds->refline2, COLOR_RESET (ds));
|
|
|
|
}
|
2018-03-02 15:04:42 +01:00
|
|
|
r_cons_printf("|");
|
2018-02-23 10:45:53 +01:00
|
|
|
ds_newline (ds);
|
2015-11-23 01:40:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-24 18:17:25 +01:00
|
|
|
static void print_fcn_arg(RCore *core, const char *type, const char *name,
|
|
|
|
const char *fmt, const ut64 addr,
|
|
|
|
const int on_stack) {
|
2016-11-01 13:32:22 +01:00
|
|
|
//r_cons_newline ();
|
|
|
|
r_cons_printf ("%s", type);
|
2016-12-24 18:17:25 +01:00
|
|
|
r_core_cmdf (core, "pf %s%s %s @ 0x%08" PFMT64x,
|
2017-05-08 20:21:06 +02:00
|
|
|
(on_stack == 1) ? "*" : "", fmt, name, addr);
|
2016-11-01 13:32:22 +01:00
|
|
|
r_cons_chop ();
|
|
|
|
r_cons_chop ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void delete_last_comment(RDisasmState *ds) {
|
|
|
|
if (ds->show_comment_right_default) {
|
2017-01-23 22:42:27 +01:00
|
|
|
int len = 0;
|
|
|
|
char *ll = r_cons_lastline (&len);
|
2016-11-01 13:32:22 +01:00
|
|
|
if (ll) {
|
2017-01-24 00:50:22 +01:00
|
|
|
const char *begin = r_str_nstr (ll, "; ", len);
|
2016-11-01 13:32:22 +01:00
|
|
|
if (begin) {
|
2017-01-24 13:57:17 +01:00
|
|
|
// const int cstrlen = begin + len - ll;
|
2017-01-24 11:36:02 +01:00
|
|
|
// r_cons_drop (cstrlen - (int)(begin - ll));
|
2018-03-22 22:09:52 +01:00
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2016-11-01 13:32:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static char * resolve_fcn_name(RAnal *anal, const char * func_name) {
|
|
|
|
const char * name = NULL;
|
|
|
|
const char * str = func_name;
|
|
|
|
if (r_anal_type_func_exist (anal, func_name)) {
|
|
|
|
return strdup (func_name);
|
|
|
|
}
|
|
|
|
name = func_name;
|
|
|
|
while ((str = strchr (str, '.'))) {
|
2016-11-09 02:52:26 +01:00
|
|
|
name = str + 1;
|
2016-11-01 13:32:22 +01:00
|
|
|
str++;
|
|
|
|
}
|
|
|
|
if (r_anal_type_func_exist (anal, name)) {
|
|
|
|
return strdup (name);
|
|
|
|
}
|
|
|
|
return r_anal_type_func_guess (anal, (char*)func_name);
|
|
|
|
}
|
|
|
|
|
2016-11-20 17:37:27 +01:00
|
|
|
static bool can_emulate_metadata(RCore * core, ut64 at) {
|
|
|
|
const char *infos;
|
2018-01-30 10:21:31 -05:00
|
|
|
const char *emuskipmeta = r_config_get (core->config, "asm.emu.skip");
|
2016-11-20 17:37:27 +01:00
|
|
|
char key[32];
|
|
|
|
Sdb *s = core->anal->sdb_meta;
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.0x%"PFMT64x, at);
|
|
|
|
infos = sdb_const_get (s, key, 0);
|
|
|
|
if (!infos) {
|
|
|
|
/* no metadata: let's emulate this */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for (; *infos; infos++) {
|
|
|
|
/*
|
|
|
|
* don't emulate if at least one metadata type
|
|
|
|
* can't be emulated
|
|
|
|
*/
|
|
|
|
if (*infos != ',' && strchr(emuskipmeta, *infos)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-24 00:58:03 +01:00
|
|
|
// modifies anal register state
|
2017-01-18 22:02:30 +01:00
|
|
|
static void ds_print_esil_anal(RDisasmState *ds) {
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
2015-09-10 00:34:21 +02:00
|
|
|
RAnalEsil *esil = core->anal->esil;
|
|
|
|
const char *pc;
|
2017-06-08 18:20:48 +02:00
|
|
|
int (*hook_mem_write)(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) = NULL;
|
2016-12-24 18:16:54 +01:00
|
|
|
int i, nargs;
|
2016-11-04 03:15:17 +01:00
|
|
|
ut64 at = p2v (ds, ds->at);
|
2017-01-18 22:02:30 +01:00
|
|
|
RConfigHold *hc = r_config_hold_new (core->config);
|
2018-01-31 19:48:51 +05:30
|
|
|
/* apply hint */
|
|
|
|
RAnalHint *hint = r_anal_hint_get (core->anal, at);
|
|
|
|
r_anal_op_hint (&ds->analop, hint);
|
|
|
|
r_anal_hint_free (hint);
|
2017-08-11 04:22:37 -07:00
|
|
|
if (!hc) {
|
|
|
|
return;
|
|
|
|
}
|
2016-08-07 19:05:55 +02:00
|
|
|
if (!esil) {
|
|
|
|
ds_print_esil_anal_init (ds);
|
|
|
|
esil = core->anal->esil;
|
|
|
|
}
|
2017-05-08 20:21:06 +02:00
|
|
|
if (!ds->show_emu) {
|
2016-03-04 00:33:24 +01:00
|
|
|
goto beach;
|
2015-09-10 00:41:19 +02:00
|
|
|
}
|
2016-11-20 17:37:27 +01:00
|
|
|
if (!can_emulate_metadata (core, at)) {
|
|
|
|
goto beach;
|
2016-04-11 10:16:47 +02:00
|
|
|
}
|
2016-10-06 03:42:49 +02:00
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
2015-09-10 01:42:56 +02:00
|
|
|
esil = core->anal->esil;
|
2015-09-10 00:34:21 +02:00
|
|
|
pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
|
2016-11-04 01:30:35 +01:00
|
|
|
r_reg_setv (core->anal->reg, pc, at + ds->analop.size);
|
2016-12-24 18:16:54 +01:00
|
|
|
esil->cb.user = ds;
|
2015-09-10 01:42:56 +02:00
|
|
|
esil->cb.hook_reg_write = myregwrite;
|
2017-06-08 18:20:48 +02:00
|
|
|
hook_mem_write = esil->cb.hook_mem_write;
|
2017-12-03 18:22:47 +01:00
|
|
|
if (ds->show_emu_stack) {
|
|
|
|
esil->cb.hook_mem_write = mymemwrite2;
|
2015-10-29 23:37:51 +01:00
|
|
|
} else {
|
2017-12-03 18:22:47 +01:00
|
|
|
if (ds->show_emu_write) {
|
|
|
|
esil->cb.hook_mem_write = mymemwrite0;
|
|
|
|
} else {
|
|
|
|
esil->cb.hook_mem_write = mymemwrite1;
|
|
|
|
}
|
2015-10-29 23:37:51 +01:00
|
|
|
}
|
2016-06-08 21:16:00 +02:00
|
|
|
ds->esil_likely = 0;
|
2016-11-04 01:30:35 +01:00
|
|
|
r_anal_esil_set_pc (esil, at);
|
2015-09-10 00:34:21 +02:00
|
|
|
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&ds->analop.esil));
|
|
|
|
r_anal_esil_stack_free (esil);
|
2017-01-08 17:28:01 +01:00
|
|
|
r_config_save_num (hc, "io.cache", NULL);
|
|
|
|
r_config_set (core->config, "io.cache", "true");
|
2017-01-19 21:44:48 +01:00
|
|
|
if (!ds->show_comments) {
|
2017-01-08 18:04:13 +01:00
|
|
|
goto beach;
|
|
|
|
}
|
2015-10-29 23:37:51 +01:00
|
|
|
switch (ds->analop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_SWI: {
|
|
|
|
char *s = cmd_syscall_dostr (core, -1);
|
2015-10-29 11:22:49 +01:00
|
|
|
if (s) {
|
2017-12-03 18:42:54 +08:00
|
|
|
ds_comment_esil (ds, true, true, "; %s", s);
|
2015-10-29 11:22:49 +01:00
|
|
|
free (s);
|
|
|
|
}
|
2015-10-29 23:37:51 +01:00
|
|
|
} break;
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
2017-01-18 22:02:30 +01:00
|
|
|
ds_comment_esil (ds, true, true, ds->esil_likely? "; likely" : "; unlikely");
|
2015-10-29 23:37:51 +01:00
|
|
|
break;
|
|
|
|
case R_ANAL_OP_TYPE_UCALL:
|
2016-09-22 13:42:06 +02:00
|
|
|
case R_ANAL_OP_TYPE_ICALL:
|
|
|
|
case R_ANAL_OP_TYPE_RCALL:
|
|
|
|
case R_ANAL_OP_TYPE_IRCALL:
|
2015-10-29 23:37:51 +01:00
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
|
|
|
{
|
2016-04-03 18:13:12 +02:00
|
|
|
RAnalFunction *fcn;
|
2018-02-22 10:51:41 +05:30
|
|
|
RAnalFuncArg *arg;
|
|
|
|
RListIter *iter;
|
|
|
|
RListIter *nextele;
|
2016-11-01 13:32:22 +01:00
|
|
|
const char *fcn_name = NULL;
|
2018-02-22 12:45:54 +01:00
|
|
|
char *key = NULL;
|
2016-04-03 18:13:12 +02:00
|
|
|
ut64 pcv = ds->analop.jump;
|
|
|
|
if (pcv == UT64_MAX) {
|
2016-04-03 18:41:50 +02:00
|
|
|
pcv = ds->analop.ptr; // call [reloc-addr] // windows style
|
2016-12-24 18:16:54 +01:00
|
|
|
if (pcv == UT64_MAX || !pcv) {
|
2016-11-03 09:05:33 +01:00
|
|
|
r_anal_esil_reg_read (esil, "$jt", &pcv, NULL);
|
2016-12-24 18:16:54 +01:00
|
|
|
if (pcv == UT64_MAX || !pcv) {
|
2016-11-03 09:05:33 +01:00
|
|
|
pcv = r_reg_getv (core->anal->reg, pc);
|
|
|
|
}
|
2016-04-03 18:13:12 +02:00
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
}
|
2016-04-03 18:13:12 +02:00
|
|
|
fcn = r_anal_get_fcn_at (core->anal, pcv, 0);
|
2015-10-29 23:37:51 +01:00
|
|
|
if (fcn) {
|
2016-11-01 13:32:22 +01:00
|
|
|
fcn_name = fcn->name;
|
2015-10-29 23:37:51 +01:00
|
|
|
} else {
|
2015-10-30 03:07:22 +01:00
|
|
|
RFlagItem *item = r_flag_get_i (core->flags, pcv);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (item) {
|
2016-11-01 13:32:22 +01:00
|
|
|
fcn_name = item->name;
|
2016-09-23 16:28:48 +02:00
|
|
|
}
|
2015-10-30 03:07:22 +01:00
|
|
|
}
|
2016-11-01 13:32:22 +01:00
|
|
|
if (fcn_name) {
|
2018-02-22 10:51:41 +05:30
|
|
|
key = resolve_fcn_name (core->anal, fcn_name);
|
|
|
|
}
|
|
|
|
if (key) {
|
|
|
|
const char *fcn_type = r_anal_type_func_ret (core->anal, key);
|
|
|
|
int nargs = r_anal_type_func_args_count (core->anal, key);
|
|
|
|
// remove other comments
|
|
|
|
delete_last_comment (ds);
|
|
|
|
if (ds->show_color) {
|
|
|
|
ds_comment_esil (ds, true, false, ds->pal_comment);
|
|
|
|
}
|
|
|
|
if (fcn_type) {
|
2017-01-31 10:00:24 +01:00
|
|
|
ds_comment_esil (ds, ds->show_color? false : true, false,
|
2018-02-22 10:51:41 +05:30
|
|
|
"; %s%s%s(", r_str_get (fcn_type), (*fcn_type &&
|
2016-12-24 18:16:54 +01:00
|
|
|
fcn_type[strlen (fcn_type) - 1] == '*') ? "" : " ",
|
2017-01-31 10:00:24 +01:00
|
|
|
r_str_get (key));
|
2016-12-24 18:16:54 +01:00
|
|
|
if (!nargs) {
|
2016-12-27 15:40:02 +01:00
|
|
|
ds_comment_esil (ds, false, true, "void)");
|
2016-11-01 13:32:22 +01:00
|
|
|
break;
|
|
|
|
}
|
2018-02-22 10:51:41 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
ut64 s_width = (core->anal->bits == 64)? 8: 4;
|
|
|
|
const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
|
|
|
|
ut64 spv = r_reg_getv (core->anal->reg, sp);
|
|
|
|
r_reg_setv (core->anal->reg, sp, spv + s_width); // temporarily set stack ptr to sync with carg.c
|
|
|
|
RList *list = r_core_get_func_args (core, fcn_name);
|
|
|
|
if (!r_list_empty (list)) {
|
|
|
|
bool warning = false;
|
|
|
|
bool on_stack = false;
|
|
|
|
r_list_foreach (list, iter, arg) {
|
|
|
|
if (arg->cc_source && !strncmp (arg->cc_source, "stack", 5)) {
|
|
|
|
on_stack = true;
|
2016-11-01 13:32:22 +01:00
|
|
|
}
|
2018-02-22 10:51:41 +05:30
|
|
|
if (!arg->size) {
|
|
|
|
ds_comment_esil (ds, false, false, "%s: unk_size", arg->c_type);
|
|
|
|
warning = true;
|
|
|
|
}
|
|
|
|
nextele = r_list_iter_get_next (iter);
|
|
|
|
if (!arg->fmt) {
|
|
|
|
if (!warning) {
|
|
|
|
ds_comment_esil (ds, false, false, "%s : unk_format", arg->c_type);
|
2016-11-01 13:32:22 +01:00
|
|
|
} else {
|
2018-02-22 10:51:41 +05:30
|
|
|
ds_comment_esil (ds, false, false, "_format");
|
2016-11-01 13:32:22 +01:00
|
|
|
}
|
2018-02-22 10:51:41 +05:30
|
|
|
ds_comment_esil (ds, false, false, nextele?", ":")");
|
|
|
|
} else {
|
|
|
|
//print_fcn_arg may need ds_comment_esil
|
|
|
|
print_fcn_arg (core, arg->orig_c_type,
|
|
|
|
arg->name, arg->fmt, arg->src, on_stack);
|
|
|
|
ds_comment_esil (ds, false, false, nextele?", ":")");
|
2016-11-01 13:32:22 +01:00
|
|
|
}
|
|
|
|
}
|
2018-03-19 11:51:04 +01:00
|
|
|
// ds_comment_esil (ds, false, true, "");
|
2018-02-22 10:51:41 +05:30
|
|
|
break;
|
2015-10-30 03:07:22 +01:00
|
|
|
} else {
|
2016-11-01 13:32:22 +01:00
|
|
|
// function name not resolved
|
|
|
|
nargs = DEFAULT_NARGS;
|
|
|
|
if (fcn) {
|
|
|
|
nargs = fcn->nargs;
|
|
|
|
}
|
2016-12-26 20:10:10 +01:00
|
|
|
if (nargs > 0) {
|
|
|
|
ds_comment_esil (ds, true, false, "; CALL: ");
|
|
|
|
for (i = 0; i < nargs; i++) {
|
|
|
|
ut64 v = r_debug_arg_get (core->dbg, R_ANAL_CC_TYPE_STDCALL, i);
|
|
|
|
ds_comment_esil (ds, false, false, "%s0x%"PFMT64x, i?", ":"", v);
|
|
|
|
}
|
|
|
|
ds_comment_esil (ds, false, true, "");
|
2015-10-30 03:07:22 +01:00
|
|
|
}
|
2015-10-29 23:37:51 +01:00
|
|
|
}
|
2018-02-22 10:51:41 +05:30
|
|
|
r_reg_setv (core->anal->reg, sp, spv); // reset stack ptr
|
2015-10-29 23:37:51 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-09-10 00:34:21 +02:00
|
|
|
}
|
2018-02-02 16:58:38 +01:00
|
|
|
ds_print_color_reset (ds);
|
2017-01-02 15:56:08 +01:00
|
|
|
beach:
|
2017-06-08 18:20:48 +02:00
|
|
|
if (esil) {
|
|
|
|
esil->cb.hook_mem_write = hook_mem_write;
|
|
|
|
}
|
2016-12-24 18:16:54 +01:00
|
|
|
r_config_restore (hc);
|
|
|
|
r_config_hold_free (hc);
|
2015-09-10 00:34:21 +02:00
|
|
|
}
|
2016-09-21 11:00:52 +02:00
|
|
|
|
2016-09-14 17:49:19 +03:00
|
|
|
static void ds_print_calls_hints(RDisasmState *ds) {
|
2016-11-01 13:32:22 +01:00
|
|
|
int emu = r_config_get_i (ds->core->config, "asm.emu");
|
2018-01-30 10:21:31 -05:00
|
|
|
int emuwrite = r_config_get_i (ds->core->config, "asm.emu.write");
|
2016-11-01 13:32:22 +01:00
|
|
|
if (emu && emuwrite) {
|
|
|
|
// this is done by ESIL
|
|
|
|
return;
|
|
|
|
}
|
2016-09-14 17:49:19 +03:00
|
|
|
RAnal *anal = ds->core->anal;
|
2017-11-23 18:35:13 +01:00
|
|
|
// RAnalFunction *fcn = r_anal_get_fcn_in (anal, ds->analop.jump, -1);
|
2017-11-23 22:46:57 +01:00
|
|
|
RAnalFunction *fcn = fcnIn (ds, ds->analop.jump, -1);
|
2016-09-14 17:49:19 +03:00
|
|
|
char *name;
|
|
|
|
if (!fcn) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (r_anal_type_func_exist (anal, fcn->name)) {
|
|
|
|
name = strdup (fcn->name);
|
|
|
|
} else if (!(name = r_anal_type_func_guess (anal, fcn->name))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ds->show_color) {
|
|
|
|
r_cons_strcat (ds->pal_comment);
|
|
|
|
}
|
|
|
|
ds_align_comment (ds);
|
2016-09-14 19:23:11 +03:00
|
|
|
const char *fcn_type = r_anal_type_func_ret (anal, name);
|
2016-11-15 20:33:43 +01:00
|
|
|
if (fcn_type && *fcn_type) {
|
2016-11-15 19:38:18 +01:00
|
|
|
r_cons_printf (
|
2017-05-09 02:21:56 +08:00
|
|
|
"; %s%s%s(", fcn_type,
|
2016-11-15 19:38:18 +01:00
|
|
|
fcn_type[strlen (fcn_type) - 1] == '*' ? "" : " ",
|
|
|
|
name);
|
|
|
|
}
|
2016-09-14 17:49:19 +03:00
|
|
|
int i, arg_max = r_anal_type_func_args_count (anal, name);
|
2016-09-23 16:28:48 +02:00
|
|
|
if (!arg_max) {
|
2016-12-27 15:40:02 +01:00
|
|
|
r_cons_printf ("void)");
|
2016-09-15 12:09:23 +03:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < arg_max; i++) {
|
|
|
|
char *type = r_anal_type_func_args_type (anal, name, i);
|
2016-11-15 20:33:43 +01:00
|
|
|
if (type && *type) {
|
|
|
|
r_cons_printf ("%s%s%s%s%s", i == 0 ? "": " ", type,
|
2017-12-24 00:20:51 +01:00
|
|
|
type[strlen (type) -1] == '*' ? "": " ",
|
|
|
|
r_anal_type_func_args_name (anal, name, i),
|
|
|
|
i == arg_max - 1 ? ")": ",");
|
2016-11-15 20:33:43 +01:00
|
|
|
}
|
2016-09-15 12:09:23 +03:00
|
|
|
free (type);
|
|
|
|
}
|
2016-09-14 17:49:19 +03:00
|
|
|
}
|
2018-02-02 12:54:06 +01:00
|
|
|
ds_print_color_reset (ds);
|
2016-09-14 17:49:19 +03:00
|
|
|
free (name);
|
|
|
|
}
|
2016-09-21 11:00:52 +02:00
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_comments_right(RDisasmState *ds) {
|
2015-03-08 02:27:39 +01:00
|
|
|
char *desc = NULL;
|
2016-05-30 12:35:39 +02:00
|
|
|
RCore *core = ds->core;
|
|
|
|
ds_print_relocs (ds);
|
2016-08-16 12:19:02 +02:00
|
|
|
if (ds->asm_describe && !ds->has_description) {
|
|
|
|
char *op, *locase = strdup (ds->asmop.buf_asm);
|
|
|
|
if (!locase) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
op = strchr (locase, ' ');
|
2016-12-24 18:17:25 +01:00
|
|
|
if (op) {
|
|
|
|
*op = 0;
|
|
|
|
}
|
2015-07-15 14:55:00 +02:00
|
|
|
r_str_case (locase, 0);
|
|
|
|
desc = r_asm_describe (core->assembler, locase);
|
|
|
|
free (locase);
|
2015-03-08 02:27:39 +01:00
|
|
|
}
|
|
|
|
if (ds->show_comments) {
|
2016-05-31 23:37:17 +02:00
|
|
|
if (desc && *desc) {
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_align_comment (ds);
|
2015-11-02 12:38:08 +01:00
|
|
|
if (ds->show_color) {
|
2015-03-08 02:27:39 +01:00
|
|
|
r_cons_strcat (ds->color_comment);
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2017-06-19 19:00:53 +02:00
|
|
|
r_cons_strcat ("; ");
|
2015-03-08 02:27:39 +01:00
|
|
|
r_cons_strcat (desc);
|
2017-12-14 21:46:40 +01:00
|
|
|
ds_print_color_reset (ds);
|
2015-03-08 02:27:39 +01:00
|
|
|
}
|
|
|
|
if (ds->show_comment_right && ds->comment) {
|
2018-01-08 03:22:26 +01:00
|
|
|
char *comment = r_str_trim (ds->comment);
|
2016-05-31 23:37:17 +02:00
|
|
|
if (*comment) {
|
|
|
|
if (!desc) {
|
|
|
|
ds_align_comment (ds);
|
|
|
|
}
|
2015-11-02 12:38:08 +01:00
|
|
|
if (ds->show_color) {
|
2017-11-09 22:01:48 +01:00
|
|
|
// r_cons_strcat (ds->color_comment);
|
|
|
|
r_cons_strcat (ds->color_usrcmt);
|
2015-11-02 12:38:08 +01:00
|
|
|
}
|
2017-11-25 00:05:37 +01:00
|
|
|
if (strchr (comment, '\n')) {
|
2017-12-11 15:07:44 +01:00
|
|
|
comment = strdup (comment);
|
2018-02-06 15:30:10 +01:00
|
|
|
if (comment) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
2018-02-06 15:30:10 +01:00
|
|
|
int lines_count;
|
|
|
|
int *line_indexes = r_str_split_lines (comment, &lines_count);
|
|
|
|
if (line_indexes) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < lines_count; i++) {
|
|
|
|
char *c = comment + line_indexes[i];
|
|
|
|
char *escstr = NULL;
|
|
|
|
if (ds->use_json) {
|
|
|
|
c = escstr = ds_esc_str (ds, c, (int)strlen (c), NULL);
|
2017-12-11 15:07:44 +01:00
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
|
|
|
r_cons_printf ("; %s", c);
|
|
|
|
ds_newline (ds);
|
|
|
|
ds_begin_json_line (ds);
|
|
|
|
free (escstr);
|
2017-12-24 00:20:51 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
free (line_indexes);
|
2017-12-11 15:07:44 +01:00
|
|
|
}
|
|
|
|
free (comment);
|
2017-11-25 00:05:37 +01:00
|
|
|
} else {
|
2017-12-11 15:07:44 +01:00
|
|
|
char *escstr = NULL;
|
|
|
|
if (ds->use_json) {
|
|
|
|
comment = escstr = ds_esc_str (ds, comment, (int)strlen (comment), NULL);
|
|
|
|
}
|
|
|
|
if (comment) {
|
|
|
|
r_cons_printf ("; %s", comment);
|
|
|
|
}
|
|
|
|
free (escstr);
|
2017-11-25 00:05:37 +01:00
|
|
|
}
|
2015-03-08 02:27:39 +01:00
|
|
|
}
|
2017-11-25 00:05:37 +01:00
|
|
|
//r_cons_strcat_justify (comment, strlen (ds->refline) + 5, ';');
|
2017-12-03 02:02:13 +01:00
|
|
|
ds_print_color_reset (ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->comment);
|
2015-03-08 02:27:39 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2015-03-08 02:27:39 +01:00
|
|
|
free (desc);
|
2016-09-14 17:49:19 +03:00
|
|
|
if (ds->analop.type == R_ANAL_OP_TYPE_CALL && ds->show_calls) {
|
|
|
|
ds_print_calls_hints (ds);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-06-19 01:11:53 +02:00
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
static void ds_print_as_string(RDisasmState *ds) {
|
2016-10-06 11:24:39 +02:00
|
|
|
char *str = r_num_as_string (NULL, ds->analop.ptr, true);
|
2014-05-07 02:51:04 +02:00
|
|
|
if (str) {
|
2016-12-24 18:16:54 +01:00
|
|
|
ds_comment (ds, false, "%s; \"%s\"%s", COLOR (ds, pal_comment),
|
2015-11-02 12:38:08 +01:00
|
|
|
str, COLOR_RESET (ds));
|
2014-05-07 02:51:04 +02:00
|
|
|
}
|
|
|
|
free (str);
|
|
|
|
}
|
|
|
|
|
2018-01-16 01:50:42 -08:00
|
|
|
static char *_find_next_number(char *op) {
|
|
|
|
char *p = op;
|
|
|
|
if (p) {
|
|
|
|
while (*p) {
|
|
|
|
// look for start of next separator or ANSI sequence
|
|
|
|
while (*p && !ISSEPARATOR (*p) && *p != 0x1b) p++;
|
|
|
|
if (*p == 0x1b) {
|
|
|
|
// skip to end of ANSI sequence (lower or uppercase char)
|
|
|
|
while (*p && !(*p >= 'A' && *p <= 'Z') && !(*p >= 'a' && *p <= 'z')) p++;
|
|
|
|
if (*p) p++;
|
|
|
|
}
|
|
|
|
if (ISSEPARATOR (*p)) {
|
|
|
|
// skip to end of separator
|
|
|
|
while (*p && ISSEPARATOR (*p)) p++;
|
|
|
|
}
|
|
|
|
if (IS_DIGIT (*p)) {
|
|
|
|
// we found the start of the next number
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *ds_sub_jumps(RDisasmState *ds, char *str) {
|
|
|
|
RAnal *anal = ds->core->anal;
|
|
|
|
RFlag *f = ds->core->flags;
|
|
|
|
int optype;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
RFlagItem *flag;
|
|
|
|
ut64 addr;
|
|
|
|
const char *name = 0;
|
|
|
|
|
|
|
|
if (!ds->jmpsub || !anal) {
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
optype = ds->analop.type & 0xFFFF;
|
|
|
|
if (optype < R_ANAL_OP_TYPE_JMP || optype >= R_ANAL_OP_TYPE_RET) {
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
addr = ds->analop.jump;
|
|
|
|
|
2018-02-20 20:03:57 -08:00
|
|
|
fcn = r_anal_get_fcn_at (anal, addr, 0);
|
2018-01-16 01:50:42 -08:00
|
|
|
if (fcn) {
|
|
|
|
name = fcn->name;
|
|
|
|
} else if (f) {
|
|
|
|
flag = r_flag_get_i2 (f, addr);
|
|
|
|
if (flag) {
|
|
|
|
name = flag->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
char *nptr, *ptr;
|
|
|
|
ut64 numval;
|
|
|
|
ptr = str;
|
|
|
|
while ((nptr = _find_next_number (ptr))) {
|
|
|
|
ptr = nptr;
|
|
|
|
numval = r_num_get (NULL, ptr);
|
|
|
|
if (numval == addr) {
|
|
|
|
while (*nptr && !ISSEPARATOR (*nptr) && *nptr != 0x1b) nptr++;
|
|
|
|
char* numstr = r_str_ndup (ptr, nptr-ptr);
|
|
|
|
str = r_str_replace (str, numstr, name, 0);
|
|
|
|
free (numstr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2014-01-16 11:04:42 -06:00
|
|
|
// int l is for lines
|
2017-12-11 15:07:44 +01:00
|
|
|
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) {
|
2014-01-16 11:04:42 -06:00
|
|
|
int continueoninvbreak = (len == l) && invbreak;
|
2015-12-14 10:19:07 +01:00
|
|
|
RAnalFunction *of = NULL;
|
2014-01-16 11:04:42 -06:00
|
|
|
RAnalFunction *f = NULL;
|
2018-02-23 10:46:39 +01:00
|
|
|
bool calc_row_offsets = p->calc_row_offsets;
|
2016-02-22 23:45:36 +01:00
|
|
|
int ret, i, inc, skip_bytes = 0, idx = 0;
|
2015-12-14 10:19:07 +01:00
|
|
|
int dorepeat = 1;
|
2014-01-16 11:04:42 -06:00
|
|
|
ut8 *nbuf = NULL;
|
2017-09-04 12:41:09 -07:00
|
|
|
const int addrbytes = core->io->addrbytes;
|
2014-02-14 13:40:22 -06:00
|
|
|
|
2014-01-20 01:42:16 +01:00
|
|
|
// TODO: All those ds must be print flags
|
2017-09-30 02:18:48 +02:00
|
|
|
RDisasmState *ds = ds_init (core);
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->cbytes = cbytes;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->print = p;
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->l = l;
|
|
|
|
ds->buf = buf;
|
|
|
|
ds->len = len;
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->addr = addr;
|
2015-09-28 11:21:23 +02:00
|
|
|
ds->hint = NULL;
|
2017-12-11 15:07:44 +01:00
|
|
|
ds->use_json = json;
|
|
|
|
ds->first_line = true;
|
2018-02-23 10:46:39 +01:00
|
|
|
|
|
|
|
// disable row_offsets to prevent other commands to overwrite computed info
|
|
|
|
p->calc_row_offsets = false;
|
|
|
|
|
2015-12-14 10:19:07 +01:00
|
|
|
//r_cons_printf ("len =%d l=%d ib=%d limit=%d\n", len, l, invbreak, p->limit);
|
|
|
|
// TODO: import values from debugger is possible
|
|
|
|
// TODO: allow to get those register snapshots from traces
|
|
|
|
// TODO: per-function register state trace
|
|
|
|
// XXX - is there a better way to reset a the analysis counter so that
|
|
|
|
// when code is disassembled, it can actually find the correct offsets
|
2016-06-10 16:14:07 +02:00
|
|
|
{ /* used by asm.emu */
|
2015-12-14 10:19:07 +01:00
|
|
|
r_reg_arena_push (core->anal->reg);
|
|
|
|
}
|
|
|
|
if (core->anal->cur && core->anal->cur->reset_counter) {
|
|
|
|
core->anal->cur->reset_counter (core->anal, addr);
|
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_reflines_init (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
core->inc = 0;
|
2015-10-08 20:00:31 +02:00
|
|
|
/* reset jmp table if not asked to keep it */
|
|
|
|
if (!core->keep_asmqjmps) { // hack
|
|
|
|
core->asmqjmps_count = 0;
|
|
|
|
core->asmqjmps_size = R_CORE_ASMQJMPS_NUM;
|
|
|
|
core->asmqjmps = realloc (core->asmqjmps, core->asmqjmps_size * sizeof (ut64));
|
|
|
|
if (core->asmqjmps) {
|
|
|
|
for (i = 0; i < R_CORE_ASMQJMPS_NUM; i++) {
|
|
|
|
core->asmqjmps[i] = UT64_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
if (ds->use_json) {
|
|
|
|
r_cons_print ("[");
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
toro:
|
|
|
|
// uhm... is this necesary? imho can be removed
|
2016-11-04 03:15:17 +01:00
|
|
|
r_asm_set_pc (core->assembler, p2v (ds, ds->addr + idx));
|
2017-10-08 16:39:27 +05:30
|
|
|
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;
|
2014-01-16 11:04:42 -06:00
|
|
|
|
|
|
|
if (core->print->cur_enabled) {
|
|
|
|
// TODO: support in-the-middle-of-instruction too
|
2016-04-04 00:52:45 +02:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2016-03-04 00:33:24 +01:00
|
|
|
if (r_anal_op (core->anal, &ds->analop, core->offset + core->print->cur,
|
2018-03-15 12:31:01 +01:00
|
|
|
buf + core->print->cur, (int)(len - core->print->cur), R_ANAL_OP_MASK_ALL)) {
|
2014-01-20 01:42:16 +01:00
|
|
|
// TODO: check for ds->analop.type and ret
|
|
|
|
ds->dest = ds->analop.jump;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* highlight eip */
|
|
|
|
const char *pc = core->anal->reg->name[R_REG_NAME_PC];
|
2016-03-04 00:33:24 +01:00
|
|
|
RFlagItem *item = r_flag_get (core->flags, pc);
|
2016-08-07 17:37:33 +02:00
|
|
|
if (item) {
|
|
|
|
ds->dest = item->offset;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_esil_anal_init (ds);
|
2016-02-22 23:45:36 +01:00
|
|
|
inc = 0;
|
2016-08-07 17:37:33 +02:00
|
|
|
if (!ds->l) {
|
2016-02-22 23:53:29 +01:00
|
|
|
len = ds->l = core->blocksize;
|
2016-02-22 23:45:36 +01:00
|
|
|
}
|
2016-08-10 18:49:44 +02:00
|
|
|
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2017-01-18 22:02:30 +01:00
|
|
|
r_anal_build_range_on_hints (core->anal);
|
2017-08-05 03:20:17 -07:00
|
|
|
for (i = idx = ret = 0; addrbytes * idx < len && ds->lines < ds->l; idx += inc, i++, ds->index += inc, ds->lines++) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->at = ds->addr + idx;
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->vat = p2v (ds, ds->at);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (r_cons_is_breaked ()) {
|
2014-11-01 23:54:51 +01:00
|
|
|
dorepeat = 0;
|
2017-07-30 16:15:51 +08:00
|
|
|
R_FREE (nbuf);
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2018-03-14 18:35:32 +01:00
|
|
|
ds_free (ds);
|
2016-09-20 00:11:59 +02:00
|
|
|
return 0; //break;
|
2014-11-01 23:54:51 +01:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
r_core_seek_archbits (core, ds->at); // slow but safe
|
2016-08-16 13:54:59 +02:00
|
|
|
ds->has_description = false;
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
|
2018-02-17 23:02:53 +08:00
|
|
|
ds->printed_str_addr = UT64_MAX;
|
2018-02-22 23:24:37 +08:00
|
|
|
ds->printed_flag_addr = UT64_MAX;
|
2018-01-27 00:25:12 +01:00
|
|
|
// XXX. this must be done in ds_update_pc()
|
|
|
|
// ds_update_pc (ds, ds->at);
|
|
|
|
r_asm_set_pc (core->assembler, ds->at);
|
|
|
|
ds_update_ref_lines (ds);
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * idx, (int)(len - addrbytes * idx), R_ANAL_OP_MASK_ALL);
|
2018-01-27 00:25:12 +01:00
|
|
|
if (ds_must_strip (ds)) {
|
|
|
|
inc = ds->analop.size;
|
|
|
|
// inc = ds->asmop.payload + (ds->asmop.payload % ds->core->assembler->dataalign);
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2018-01-27 00:25:12 +01:00
|
|
|
continue;
|
|
|
|
}
|
2017-11-23 18:35:13 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2017-11-23 22:46:57 +01:00
|
|
|
f = ds->fcn = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2016-05-14 16:37:24 +02:00
|
|
|
if (f && f->folded && r_anal_fcn_is_in_offset (f, ds->at)) {
|
2016-05-15 14:37:22 +02:00
|
|
|
int delta = (ds->at <= f->addr)? (ds->at - f->addr + r_anal_fcn_size (f)): 0;
|
2015-12-14 10:19:07 +01:00
|
|
|
if (of != f) {
|
2016-03-15 11:47:13 +01:00
|
|
|
char cmt[32];
|
2016-09-21 11:00:52 +02:00
|
|
|
get_bits_comment (core, f, cmt, sizeof (cmt));
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_comments_right (ds);
|
2016-03-15 11:47:13 +01:00
|
|
|
r_cons_printf ("%s%s%s (fcn) %s%s%s\n",
|
2016-10-21 01:24:40 +02:00
|
|
|
COLOR (ds, color_fline), core->cons->vline[CORNER_TL],
|
2016-03-15 11:47:13 +01:00
|
|
|
COLOR (ds, color_fname), f->name, cmt, COLOR_RESET (ds));
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_setup_print_pre (ds, true, false);
|
|
|
|
ds_print_lines_left (ds);
|
|
|
|
ds_print_offset (ds);
|
2016-05-15 14:37:22 +02:00
|
|
|
r_cons_printf ("(%d byte folded function)\n", r_anal_fcn_size (f));
|
2015-12-15 00:18:44 +01:00
|
|
|
//r_cons_printf ("%s%s%s\n", COLOR (ds, color_fline), core->cons->vline[RDWN_CORNER], COLOR_RESET (ds));
|
2016-08-07 17:37:33 +02:00
|
|
|
if (delta < 0) {
|
|
|
|
delta = -delta;
|
|
|
|
}
|
2015-12-15 00:18:44 +01:00
|
|
|
ds->addr += delta + idx;
|
2015-12-14 10:19:07 +01:00
|
|
|
r_io_read_at (core->io, ds->addr, buf, len);
|
|
|
|
inc = 0; //delta;
|
|
|
|
idx = 0;
|
|
|
|
of = f;
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2016-08-07 17:37:33 +02:00
|
|
|
if (len == l) {
|
2015-12-16 15:30:13 +01:00
|
|
|
break;
|
2016-08-07 17:37:33 +02:00
|
|
|
}
|
2015-12-14 10:19:07 +01:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
ds->lines--;
|
2015-12-15 00:37:33 +01:00
|
|
|
ds->addr += 1;
|
|
|
|
r_io_read_at (core->io, ds->addr, buf, len);
|
|
|
|
inc = 0; //delta;
|
|
|
|
idx = 0;
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2015-12-14 10:19:07 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_comments_right (ds);
|
2016-11-04 01:30:35 +01:00
|
|
|
// TRY adding here
|
2016-07-05 23:44:53 +03:00
|
|
|
char *link_key = sdb_fmt (-1, "link.%08"PFMT64x, ds->addr + idx);
|
|
|
|
const char *link_type = sdb_const_get (core->anal->sdb_types, link_key, 0);
|
|
|
|
if (link_type) {
|
|
|
|
char *fmt = r_anal_type_format (core->anal, link_type);
|
|
|
|
if (fmt) {
|
|
|
|
r_cons_printf ("(%s)\n", link_type);
|
2016-07-05 23:25:16 +02:00
|
|
|
r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, ds->addr + idx);
|
|
|
|
inc += r_anal_type_get_size (core->anal, link_type) / 8;
|
|
|
|
free (fmt);
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2016-07-05 23:25:16 +02:00
|
|
|
continue;
|
2016-07-05 23:44:53 +03:00
|
|
|
}
|
|
|
|
} else {
|
2017-06-05 12:42:11 +02:00
|
|
|
if (idx >= 0) {
|
2017-08-05 03:20:17 -07:00
|
|
|
ret = ds_disassemble (ds, buf + addrbytes * idx, len - addrbytes * idx);
|
2017-06-05 12:42:11 +02:00
|
|
|
if (ret == -31337) {
|
|
|
|
inc = ds->oplen;
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2017-06-05 12:42:11 +02:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-05 23:44:53 +03:00
|
|
|
}
|
2016-01-10 22:30:10 +01:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->retry) {
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->retry = false;
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2014-01-16 11:04:42 -06:00
|
|
|
goto retry;
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_atabs_option (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
// TODO: store previous oplen in core->dec
|
2016-09-22 18:06:10 +02:00
|
|
|
if (!core->inc) {
|
2014-01-20 01:42:16 +01:00
|
|
|
core->inc = ds->oplen;
|
2015-11-02 21:30:55 +01:00
|
|
|
}
|
2018-01-27 00:25:12 +01:00
|
|
|
// OOPs. double analysis here?
|
|
|
|
#if 0
|
2016-04-04 01:03:31 +02:00
|
|
|
if (ds->analop.mnemonic || !ds->lastfail) {
|
2015-03-24 03:23:56 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
|
|
|
}
|
2015-11-02 21:30:55 +01:00
|
|
|
if (!ds->lastfail) {
|
2017-08-05 03:20:17 -07:00
|
|
|
r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * idx, (int)(len - addrbytes * idx));
|
2015-11-02 21:30:55 +01:00
|
|
|
}
|
2018-01-27 00:25:12 +01:00
|
|
|
#else
|
|
|
|
if (ds->analop.addr != ds->at) {
|
|
|
|
r_anal_op_fini (&ds->analop);
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop, ds->at, buf + addrbytes * idx, (int)(len - addrbytes * idx), R_ANAL_OP_MASK_ALL);
|
2018-01-27 00:25:12 +01:00
|
|
|
}
|
|
|
|
#endif
|
2015-11-02 21:30:55 +01:00
|
|
|
if (ret < 1) {
|
2018-03-14 19:52:09 +01:00
|
|
|
r_strbuf_fini (&ds->analop.esil);
|
2014-01-20 01:42:16 +01:00
|
|
|
r_strbuf_init (&ds->analop.esil);
|
|
|
|
ds->analop.type = R_ANAL_OP_TYPE_ILL;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->hint) {
|
2016-08-10 18:49:44 +02:00
|
|
|
if (ds->hint->size) {
|
|
|
|
ds->analop.size = ds->hint->size;
|
|
|
|
}
|
|
|
|
if (ds->hint->ptr) {
|
|
|
|
ds->analop.ptr = ds->hint->ptr;
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2017-05-20 14:37:51 +02:00
|
|
|
ds_print_bbline (ds, false);
|
2016-04-04 01:59:30 +02:00
|
|
|
if (ds->at >= addr) {
|
2018-02-23 10:46:39 +01:00
|
|
|
r_print_set_rowoff (core->print, ds->lines, ds->at - addr, calc_row_offsets);
|
2016-04-04 01:59:30 +02:00
|
|
|
}
|
2015-12-17 20:18:50 +01:00
|
|
|
if (ds->midflags) {
|
|
|
|
skip_bytes = handleMidFlags (core, ds, true);
|
2016-06-14 01:52:46 +02:00
|
|
|
if (skip_bytes && ds->midflags == R_MIDFLAGS_SHOW) {
|
2015-12-17 20:18:50 +01:00
|
|
|
ds->at += skip_bytes;
|
2016-06-14 01:52:46 +02:00
|
|
|
}
|
2015-12-17 20:18:50 +01:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_flags (ds);
|
2016-06-13 15:05:48 +02:00
|
|
|
if (skip_bytes && ds->midflags == R_MIDFLAGS_SHOW) {
|
2015-12-17 20:18:50 +01:00
|
|
|
ds->at -= skip_bytes;
|
2016-06-13 15:05:48 +02:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_control_flow_comments (ds);
|
|
|
|
ds_adistrick_comments (ds);
|
2014-01-16 11:04:42 -06:00
|
|
|
/* XXX: This is really cpu consuming.. need to be fixed */
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_functions (ds);
|
|
|
|
ds_show_xrefs (ds);
|
2015-11-02 21:30:55 +01:00
|
|
|
|
2016-01-27 03:33:52 +01:00
|
|
|
if (ds->show_comments && !ds->show_comment_right) {
|
2017-05-29 20:22:16 +08:00
|
|
|
ds_instruction_mov_lea (ds, idx);
|
2016-12-27 15:40:02 +01:00
|
|
|
ds_show_refs (ds);
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_build_op_str (ds, false);
|
2016-12-27 15:40:02 +01:00
|
|
|
ds_print_ptr (ds, len + 256, idx);
|
2017-04-03 18:01:07 +08:00
|
|
|
if (!ds->pseudo) {
|
|
|
|
R_FREE (ds->opstr);
|
|
|
|
}
|
2016-07-03 14:12:30 +03:00
|
|
|
ds_print_sysregs (ds);
|
2016-12-27 15:40:02 +01:00
|
|
|
ds_print_fcn_name (ds);
|
|
|
|
ds_print_color_reset (ds);
|
2016-01-27 03:33:52 +01:00
|
|
|
if (ds->show_emu) {
|
2017-01-18 22:02:30 +01:00
|
|
|
ds_print_esil_anal (ds);
|
2016-01-27 03:33:52 +01:00
|
|
|
}
|
2016-01-27 02:35:45 +01:00
|
|
|
}
|
2017-12-11 15:07:44 +01:00
|
|
|
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_begin_json_line (ds);
|
2017-12-11 15:07:44 +01:00
|
|
|
|
2016-12-26 18:13:52 +01:00
|
|
|
ds_setup_print_pre (ds, false, false);
|
|
|
|
ds_print_lines_left (ds);
|
2017-11-23 18:35:13 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, ds->addr, 0);
|
2017-11-23 22:46:57 +01:00
|
|
|
f = fcnIn (ds, ds->addr, 0);
|
2016-05-30 12:35:39 +02:00
|
|
|
if (ds_print_labels (ds, f)) {
|
|
|
|
ds_show_functions (ds);
|
|
|
|
ds_show_xrefs (ds);
|
|
|
|
ds_setup_print_pre (ds, false, false);
|
|
|
|
ds_print_lines_left (ds);
|
|
|
|
}
|
|
|
|
ds_print_offset (ds);
|
2017-11-25 00:28:21 +01:00
|
|
|
if (ds->shortcut_pos == 0) {
|
|
|
|
ds_print_core_vmode (ds, ds->shortcut_pos);
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_op_size (ds);
|
|
|
|
ds_print_trace (ds);
|
|
|
|
ds_print_cycles (ds);
|
|
|
|
ds_print_family (ds);
|
|
|
|
ds_print_stackptr (ds);
|
|
|
|
ret = ds_print_meta_infos (ds, buf, len, idx);
|
2014-12-21 04:18:56 +01:00
|
|
|
if (!ds->mi_found) {
|
|
|
|
/* show cursor */
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_show_cursor (ds);
|
|
|
|
ds_print_show_bytes (ds);
|
|
|
|
ds_print_lines_right (ds);
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_build_op_str (ds, true);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_opstr (ds);
|
|
|
|
ds_print_dwarf (ds);
|
|
|
|
ret = ds_print_middle (ds, ret);
|
|
|
|
|
2017-08-05 03:20:17 -07:00
|
|
|
ds_print_asmop_payload (ds, buf + addrbytes * idx);
|
2014-12-21 04:18:56 +01:00
|
|
|
if (core->assembler->syntax != R_ASM_SYNTAX_INTEL) {
|
|
|
|
RAsmOp ao; /* disassemble for the vm .. */
|
|
|
|
int os = core->assembler->syntax;
|
|
|
|
r_asm_set_syntax (core->assembler, R_ASM_SYNTAX_INTEL);
|
2017-08-05 03:20:17 -07:00
|
|
|
r_asm_disassemble (core->assembler, &ao, buf + addrbytes * idx, len - addrbytes * idx + 5);
|
2014-12-21 04:18:56 +01:00
|
|
|
r_asm_set_syntax (core->assembler, os);
|
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
if (ds->shortcut_pos > 0) {
|
|
|
|
ds_print_core_vmode (ds, ds->shortcut_pos);
|
|
|
|
}
|
2016-11-04 01:30:35 +01:00
|
|
|
// ds_print_cc_update (ds);
|
2017-04-09 06:53:55 +08:00
|
|
|
|
|
|
|
ds_cdiv_optimization (ds);
|
|
|
|
if (ds->show_comments && ds->show_comment_right) {
|
2017-05-29 20:22:16 +08:00
|
|
|
ds_instruction_mov_lea (ds, idx);
|
2017-04-09 06:53:55 +08:00
|
|
|
ds_print_ptr (ds, len + 256, idx);
|
2016-07-03 14:12:30 +03:00
|
|
|
ds_print_sysregs (ds);
|
2017-04-09 06:53:55 +08:00
|
|
|
ds_print_fcn_name (ds);
|
|
|
|
ds_print_color_reset (ds);
|
|
|
|
ds_print_comments_right (ds);
|
|
|
|
ds_print_esil_anal (ds);
|
|
|
|
ds_show_refs (ds);
|
|
|
|
}
|
2014-12-21 04:18:56 +01:00
|
|
|
} else {
|
2017-04-09 06:53:55 +08:00
|
|
|
if (ds->show_comments && ds->show_comment_right) {
|
|
|
|
ds_print_color_reset (ds);
|
|
|
|
ds_print_comments_right (ds);
|
|
|
|
}
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = false;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2016-12-24 18:16:54 +01:00
|
|
|
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2017-05-20 14:37:51 +02:00
|
|
|
if (ds->show_bbline && !ds->bblined && !ds->fcn) {
|
2017-05-05 14:53:19 +02:00
|
|
|
switch (ds->analop.type) {
|
|
|
|
case R_ANAL_OP_TYPE_MJMP:
|
|
|
|
case R_ANAL_OP_TYPE_UJMP:
|
|
|
|
case R_ANAL_OP_TYPE_IJMP:
|
|
|
|
case R_ANAL_OP_TYPE_RJMP:
|
|
|
|
case R_ANAL_OP_TYPE_IRJMP:
|
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
|
|
|
case R_ANAL_OP_TYPE_RET:
|
2017-05-20 14:37:51 +02:00
|
|
|
ds_print_bbline (ds, true);
|
2017-05-05 14:53:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->line) {
|
2015-08-31 00:20:07 +02:00
|
|
|
if (ds->show_lines_ret && ds->analop.type == R_ANAL_OP_TYPE_RET) {
|
2015-11-02 12:38:08 +01:00
|
|
|
if (strchr (ds->line, '>')) {
|
2014-01-20 01:42:16 +01:00
|
|
|
memset (ds->line, ' ', r_str_len_utf8 (ds->line));
|
2015-09-02 10:01:53 +02:00
|
|
|
}
|
2018-02-06 15:30:10 +01:00
|
|
|
ds_print_pre (ds);
|
|
|
|
r_cons_printf ("%s%s%s; --------------------------------------\n",
|
|
|
|
COLOR (ds, color_flow), ds->line, COLOR_RESET (ds));
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2016-04-04 00:52:45 +02:00
|
|
|
R_FREE (ds->line);
|
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2016-01-10 22:30:10 +01:00
|
|
|
R_FREE (ds->opstr);
|
2015-05-06 00:56:31 +02:00
|
|
|
inc = ds->oplen;
|
2016-06-14 01:52:46 +02:00
|
|
|
|
|
|
|
if (ds->midflags == R_MIDFLAGS_REALIGN && skip_bytes) {
|
2015-12-17 20:18:50 +01:00
|
|
|
inc = skip_bytes;
|
2016-06-14 01:52:46 +02:00
|
|
|
}
|
|
|
|
if (inc < 1) {
|
2016-02-07 21:44:35 +01:00
|
|
|
inc = 1;
|
2016-06-14 01:52:46 +02:00
|
|
|
}
|
2017-05-23 03:01:45 +02:00
|
|
|
inc += ds->asmop.payload + (ds->asmop.payload % ds->core->assembler->dataalign);
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2018-03-14 19:52:09 +01:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2017-12-11 15:07:44 +01:00
|
|
|
|
2016-12-20 00:20:56 +01:00
|
|
|
R_FREE (nbuf);
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2014-01-16 11:04:42 -06:00
|
|
|
|
|
|
|
#if HASRETRY
|
2016-09-22 18:06:10 +02:00
|
|
|
if (!ds->cbytes && ds->lines < ds->l && dorepeat) {
|
|
|
|
ds->addr = ds->at + inc;
|
2014-01-16 11:04:42 -06:00
|
|
|
retry:
|
2016-08-10 18:49:44 +02:00
|
|
|
if (len < 4) {
|
|
|
|
len = 4;
|
|
|
|
}
|
2017-08-13 05:01:00 -07:00
|
|
|
if (nbuf) {
|
|
|
|
free (nbuf);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
buf = nbuf = malloc (len);
|
2016-07-05 23:25:16 +02:00
|
|
|
if (ds->tries > 0) {
|
2016-12-19 23:40:09 +01:00
|
|
|
if (r_core_read_at (core, ds->addr, buf, len)) {
|
2014-01-16 11:04:42 -06:00
|
|
|
goto toro;
|
|
|
|
}
|
2013-01-24 03:48:24 +01:00
|
|
|
}
|
2016-07-05 23:25:16 +02:00
|
|
|
if (ds->lines < ds->l) {
|
2014-08-15 04:06:51 +02:00
|
|
|
//ds->addr += idx;
|
2017-08-22 07:42:16 +00:00
|
|
|
if (!r_core_read_at (core, ds->addr, buf, len)) {
|
2014-01-20 01:42:16 +01:00
|
|
|
//ds->tries = -1;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
|
|
|
goto toro;
|
2013-01-24 03:48:24 +01:00
|
|
|
}
|
2016-06-10 16:14:07 +02:00
|
|
|
if (continueoninvbreak) {
|
2014-01-16 11:04:42 -06:00
|
|
|
goto toro;
|
2016-06-10 16:14:07 +02:00
|
|
|
}
|
2016-12-20 00:20:56 +01:00
|
|
|
R_FREE (nbuf);
|
2013-01-24 03:48:24 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
#endif
|
2017-12-11 23:08:18 +01:00
|
|
|
if (ds->use_json) {
|
2018-02-01 15:12:27 +01:00
|
|
|
r_cons_print ("]");
|
2017-12-11 23:08:18 +01:00
|
|
|
}
|
2018-02-23 10:46:39 +01:00
|
|
|
r_print_set_rowoff (core->print, ds->lines, ds->at - addr, calc_row_offsets);
|
|
|
|
r_print_set_rowoff (core->print, ds->lines + 1, UT32_MAX, calc_row_offsets);
|
2015-09-12 19:12:57 +02:00
|
|
|
// TODO: this too (must review)
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_esil_anal_fini (ds);
|
|
|
|
ds_reflines_fini (ds);
|
|
|
|
ds_free (ds);
|
2016-12-20 02:13:33 +01:00
|
|
|
R_FREE (nbuf);
|
2018-02-23 10:46:39 +01:00
|
|
|
p->calc_row_offsets = calc_row_offsets;
|
2016-07-05 23:25:16 +02:00
|
|
|
/* used by asm.emu */
|
|
|
|
r_reg_arena_pop (core->anal->reg);
|
2017-08-05 03:20:17 -07:00
|
|
|
return addrbytes * idx; //-ds->lastfail;
|
2013-08-11 15:38:42 +02:00
|
|
|
}
|
|
|
|
|
2014-08-23 07:23:55 +02:00
|
|
|
/* Disassemble either `nb_opcodes` instructions, or
|
|
|
|
* `nb_bytes` bytes; both can be negative.
|
|
|
|
* Set to 0 the parameter you don't use */
|
2016-08-10 18:49:44 +02:00
|
|
|
R_API int r_core_print_disasm_instructions(RCore *core, int nb_bytes, int nb_opcodes) {
|
2014-01-22 16:58:23 -06:00
|
|
|
RDisasmState *ds = NULL;
|
2016-06-06 10:36:09 +02:00
|
|
|
int i, j, ret, len = 0;
|
2014-01-20 01:42:16 +01:00
|
|
|
char *tmpopstr;
|
2014-08-23 07:23:55 +02:00
|
|
|
const ut64 old_offset = core->offset;
|
2015-11-05 02:07:20 +01:00
|
|
|
bool hasanal = false;
|
2016-11-05 00:46:00 +01:00
|
|
|
int nbytes = 0;
|
2017-09-04 12:41:09 -07:00
|
|
|
const int addrbytes = core->io->addrbytes;
|
2014-08-23 07:23:55 +02:00
|
|
|
|
2016-04-26 19:09:15 +10:00
|
|
|
r_reg_arena_push (core->anal->reg);
|
2014-08-23 07:23:55 +02:00
|
|
|
if (!nb_bytes) {
|
|
|
|
nb_bytes = core->blocksize;
|
|
|
|
if (nb_opcodes < 0) {
|
|
|
|
/* Backward disassembly or nb_opcodes opcodes
|
|
|
|
* - We compute the new starting offset
|
|
|
|
* - Read at the new offset */
|
|
|
|
nb_opcodes = -nb_opcodes;
|
2016-11-04 23:15:54 +01:00
|
|
|
|
|
|
|
// We have some anal_info.
|
|
|
|
if (r_core_prevop_addr (core, core->offset, nb_opcodes, &core->offset)) {
|
|
|
|
nbytes = old_offset - core->offset;
|
|
|
|
} else {
|
|
|
|
// core->offset is modified by r_core_prevop_addr
|
2017-01-05 00:11:57 +01:00
|
|
|
core->offset = old_offset;
|
2016-11-04 23:15:54 +01:00
|
|
|
r_core_asm_bwdis_len (core, &nbytes, &core->offset, nb_opcodes);
|
|
|
|
}
|
2017-02-11 13:05:25 +01:00
|
|
|
if (nbytes > core->blocksize) {
|
|
|
|
r_core_block_size (core, nbytes);
|
|
|
|
}
|
2016-11-04 23:15:54 +01:00
|
|
|
r_core_read_at (core, core->offset, core->block, nbytes);
|
2014-08-23 07:23:55 +02:00
|
|
|
}
|
2014-12-18 00:27:12 +01:00
|
|
|
} else {
|
2014-08-23 07:23:55 +02:00
|
|
|
if (nb_bytes < 0) { // Disassemble backward `nb_bytes` bytes
|
|
|
|
nb_bytes = -nb_bytes;
|
|
|
|
core->offset -= nb_bytes;
|
2017-09-15 17:26:30 +02:00
|
|
|
if (nb_bytes > core->blocksize) {
|
|
|
|
ut64 obsz = core->blocksize;
|
|
|
|
r_core_block_size (core, nb_bytes);
|
|
|
|
if (core->blocksize == nb_bytes) {
|
|
|
|
r_core_read_at (core, core->offset, core->block, nb_bytes);
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot read that much!\n");
|
2018-04-05 18:27:26 +02:00
|
|
|
r_core_block_size (core, obsz);
|
|
|
|
len = -1;
|
|
|
|
goto err_offset;
|
2017-09-15 17:26:30 +02:00
|
|
|
}
|
|
|
|
r_core_block_size (core, obsz);
|
|
|
|
} else {
|
|
|
|
r_core_read_at (core, core->offset, core->block, nb_bytes);
|
|
|
|
}
|
2017-05-19 00:36:18 +02:00
|
|
|
} else {
|
|
|
|
if (nb_bytes > core->blocksize) {
|
|
|
|
r_core_block_size (core, nb_bytes);
|
|
|
|
r_core_read_at (core, core->offset, core->block, nb_bytes);
|
|
|
|
}
|
2014-08-23 07:23:55 +02:00
|
|
|
}
|
|
|
|
}
|
2013-11-07 02:07:10 +01:00
|
|
|
|
2014-02-14 13:40:22 -06:00
|
|
|
// XXX - is there a better way to reset a the analysis counter so that
|
|
|
|
// when code is disassembled, it can actually find the correct offsets
|
2016-07-05 05:25:29 +02:00
|
|
|
if (core->anal->cur && core->anal->cur->reset_counter) {
|
2014-02-14 13:40:22 -06:00
|
|
|
core->anal->cur->reset_counter (core->anal, core->offset);
|
2016-07-05 05:25:29 +02:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds = ds_init (core);
|
2014-08-23 07:23:55 +02:00
|
|
|
ds->l = nb_opcodes;
|
2015-10-21 00:26:32 +02:00
|
|
|
ds->len = nb_opcodes * 8;
|
2011-06-04 03:14:04 +02:00
|
|
|
|
2015-10-21 01:51:34 +02:00
|
|
|
if (ds->len > core->blocksize) {
|
|
|
|
if (core->fixedblock) {
|
|
|
|
nb_bytes = ds->len = core->blocksize;
|
|
|
|
} else {
|
|
|
|
r_core_block_size (core, ds->len);
|
2016-08-15 13:56:23 -05:00
|
|
|
r_core_block_read (core);
|
2015-10-21 01:51:34 +02:00
|
|
|
}
|
|
|
|
}
|
2016-08-10 18:49:44 +02:00
|
|
|
if (!ds->l) {
|
2014-08-23 07:23:55 +02:00
|
|
|
ds->l = ds->len;
|
2016-07-05 23:25:16 +02:00
|
|
|
}
|
2016-08-10 18:49:44 +02:00
|
|
|
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-08-10 18:49:44 +02:00
|
|
|
//build ranges to map addr with bits
|
2017-01-18 22:02:30 +01:00
|
|
|
r_anal_build_range_on_hints (core->anal);
|
2017-08-05 18:28:23 -07:00
|
|
|
#define isNotTheEnd (nb_opcodes ? j < nb_opcodes: addrbytes * i < nb_bytes)
|
|
|
|
for (i = j = 0; isNotTheEnd; i += ret, j++) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->at = core->offset +i;
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->vat = p2v (ds, ds->at);
|
2015-11-05 02:07:20 +01:00
|
|
|
hasanal = false;
|
2014-01-20 01:42:16 +01:00
|
|
|
r_core_seek_archbits (core, ds->at);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (r_cons_is_breaked ()) {
|
2014-11-01 23:54:51 +01:00
|
|
|
break;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
|
2016-08-16 13:54:59 +02:00
|
|
|
ds->has_description = false;
|
2014-01-20 01:42:16 +01:00
|
|
|
r_asm_set_pc (core->assembler, ds->at);
|
2014-01-16 11:04:42 -06:00
|
|
|
// XXX copypasta from main disassembler function
|
2017-11-23 22:46:57 +01:00
|
|
|
// r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
2017-01-31 23:33:27 +01:00
|
|
|
ret = r_asm_disassemble (core->assembler, &ds->asmop,
|
2017-08-05 18:28:23 -07:00
|
|
|
core->block + addrbytes * i, core->blocksize - addrbytes * i);
|
2017-04-16 11:03:02 +02:00
|
|
|
ds->oplen = ret;
|
|
|
|
if (ds->midflags) {
|
|
|
|
int skip_bytes = handleMidFlags (core, ds, true);
|
|
|
|
if (skip_bytes && ds->midflags > R_MIDFLAGS_SHOW) {
|
|
|
|
ret = skip_bytes;
|
|
|
|
}
|
|
|
|
}
|
2016-04-04 00:17:57 +02:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2015-06-04 13:05:02 +02:00
|
|
|
if (ds->show_color && !hasanal) {
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop, ds->at, core->block + addrbytes * i, core->blocksize - addrbytes * i, R_ANAL_OP_MASK_ALL);
|
2015-11-05 02:07:20 +01:00
|
|
|
hasanal = true;
|
2015-06-04 13:05:02 +02:00
|
|
|
}
|
2018-01-27 00:25:12 +01:00
|
|
|
if (ds_must_strip (ds)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// r_conf = s_printf ("0x%08"PFMT64x" ", core->offset+i);
|
2016-05-30 04:18:48 +02:00
|
|
|
if (ds->hint && ds->hint->size) {
|
2014-01-20 01:42:16 +01:00
|
|
|
ret = ds->hint->size;
|
2016-05-30 04:18:48 +02:00
|
|
|
ds->oplen = ret;
|
|
|
|
ds->analop.size = ret;
|
|
|
|
ds->asmop.size = ret;
|
|
|
|
}
|
2017-02-10 12:03:28 +01:00
|
|
|
/* fix infinite loop */
|
|
|
|
if (ret < 1) {
|
|
|
|
ret = 1;
|
|
|
|
}
|
2016-06-06 10:36:09 +02:00
|
|
|
len += R_MAX (0, ret);
|
2014-01-20 01:42:16 +01:00
|
|
|
if (ds->hint && ds->hint->opcode) {
|
2014-05-09 17:40:28 +02:00
|
|
|
free (ds->opstr);
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->opstr = strdup (ds->hint->opcode);
|
2014-01-16 11:04:42 -06:00
|
|
|
} else {
|
2017-11-30 00:14:08 +01:00
|
|
|
if (ds->decode && !ds->immtrim) {
|
2017-09-30 03:21:47 +02:00
|
|
|
free (ds->opstr);
|
|
|
|
if (!hasanal) {
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop, ds->at, core->block+i, core->blocksize-i, R_ANAL_OP_MASK_ALL);
|
2017-09-30 03:21:47 +02:00
|
|
|
hasanal = true;
|
|
|
|
}
|
|
|
|
tmpopstr = r_anal_op_to_string (core->anal, &ds->analop);
|
|
|
|
ds->opstr = (tmpopstr)? tmpopstr: strdup (ds->asmop.buf_asm);
|
2017-11-30 00:14:08 +01:00
|
|
|
} else if (ds->immtrim) {
|
2017-09-30 03:21:47 +02:00
|
|
|
ds->opstr = strdup (ds->asmop.buf_asm);
|
2017-11-29 18:56:12 +01:00
|
|
|
r_parse_immtrim (ds->opstr);
|
2017-09-30 03:21:47 +02:00
|
|
|
} else if (ds->use_esil) {
|
2015-06-04 13:05:02 +02:00
|
|
|
if (!hasanal) {
|
2015-11-05 02:07:20 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop,
|
2017-09-30 03:21:47 +02:00
|
|
|
ds->at, core->block + i,
|
2018-03-15 12:31:01 +01:00
|
|
|
core->blocksize - i, R_ANAL_OP_MASK_ALL);
|
2015-11-05 02:07:20 +01:00
|
|
|
hasanal = true;
|
2015-06-04 13:05:02 +02:00
|
|
|
}
|
2014-01-20 01:42:16 +01:00
|
|
|
if (*R_STRBUF_SAFEGET (&ds->analop.esil)) {
|
2014-05-09 17:40:28 +02:00
|
|
|
free (ds->opstr);
|
2014-01-20 01:42:16 +01:00
|
|
|
ds->opstr = strdup (R_STRBUF_SAFEGET (&ds->analop.esil));
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-11-07 04:27:57 +01:00
|
|
|
} else if (ds->filter) {
|
2015-10-20 23:37:20 +02:00
|
|
|
char *asm_str;
|
2014-11-07 04:27:57 +01:00
|
|
|
int ofs = core->parser->flagspace;
|
|
|
|
int fs = ds->flagspace_ports;
|
|
|
|
if (ds->analop.type == R_ANAL_OP_TYPE_IO) {
|
|
|
|
core->parser->notin_flagspace = -1;
|
|
|
|
core->parser->flagspace = fs;
|
|
|
|
} else {
|
|
|
|
if (fs != -1) {
|
|
|
|
core->parser->notin_flagspace = fs;
|
|
|
|
core->parser->flagspace = fs;
|
|
|
|
} else {
|
|
|
|
core->parser->notin_flagspace = -1;
|
|
|
|
core->parser->flagspace = -1;
|
|
|
|
}
|
|
|
|
}
|
2015-10-20 23:37:20 +02:00
|
|
|
core->parser->hint = ds->hint;
|
2017-02-10 12:03:28 +01:00
|
|
|
r_parse_filter (core->parser, core->flags, ds->asmop.buf_asm, ds->str,
|
|
|
|
sizeof (ds->str), core->print->big_endian);
|
2015-10-20 23:37:20 +02:00
|
|
|
ds->opstr = strdup (ds->str);
|
2018-02-03 19:21:54 +01:00
|
|
|
asm_str = colorize_asm_string (core, ds, true);
|
2014-11-07 04:27:57 +01:00
|
|
|
core->parser->flagspace = ofs;
|
|
|
|
free (ds->opstr);
|
2015-10-20 23:37:20 +02:00
|
|
|
ds->opstr = asm_str;
|
2014-11-07 04:27:57 +01:00
|
|
|
core->parser->flagspace = ofs; // ???
|
2015-10-20 23:37:20 +02:00
|
|
|
} else {
|
|
|
|
ds->opstr = strdup (ds->asmop.buf_asm);
|
|
|
|
}
|
2017-11-30 00:14:08 +01:00
|
|
|
if (ds->immtrim) {
|
2017-09-30 03:21:47 +02:00
|
|
|
ds->opstr = strdup (ds->asmop.buf_asm);
|
2017-11-29 18:56:12 +01:00
|
|
|
r_parse_immtrim (ds->opstr);
|
2013-07-04 03:34:28 +02:00
|
|
|
}
|
2013-07-03 17:43:20 +02:00
|
|
|
}
|
2015-11-02 18:57:01 +01:00
|
|
|
{
|
2015-06-04 13:05:02 +02:00
|
|
|
const char *opcolor = NULL;
|
|
|
|
if (ds->show_color) {
|
|
|
|
opcolor = r_print_color_op_type (core->print, ds->analop.type);
|
2015-08-09 22:16:17 +02:00
|
|
|
r_cons_printf ("%s%s" Color_RESET "\n", opcolor, ds->opstr);
|
|
|
|
} else {
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_println (ds->opstr);
|
2015-06-04 13:05:02 +02:00
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->opstr);
|
2013-01-22 18:08:33 +01:00
|
|
|
}
|
2014-03-11 02:47:10 +01:00
|
|
|
if (ds->hint) {
|
|
|
|
r_anal_hint_free (ds->hint);
|
|
|
|
ds->hint = NULL;
|
|
|
|
}
|
2013-01-22 18:08:33 +01:00
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_free (ds);
|
2018-04-05 18:27:26 +02:00
|
|
|
err_offset:
|
2014-08-23 07:23:55 +02:00
|
|
|
core->offset = old_offset;
|
2016-06-06 10:36:09 +02:00
|
|
|
r_reg_arena_pop (core->anal->reg);
|
|
|
|
|
|
|
|
return len;
|
2013-01-22 18:08:33 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
|
2014-08-23 07:23:55 +02:00
|
|
|
R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int nb_bytes, int nb_opcodes) {
|
2014-01-16 11:04:42 -06:00
|
|
|
RAsmOp asmop;
|
2014-12-05 14:08:53 +01:00
|
|
|
RDisasmState *ds;
|
|
|
|
RAnalFunction *f;
|
2016-03-09 11:59:17 +01:00
|
|
|
int i, j, k, oplen, ret, line;
|
2015-06-04 16:53:04 +02:00
|
|
|
ut64 old_offset = core->offset;
|
2014-12-17 21:25:24 +01:00
|
|
|
ut64 at;
|
|
|
|
int dis_opcodes = 0;
|
2017-02-05 01:24:50 +01:00
|
|
|
//r_cons_printf ("[");
|
2015-04-08 10:41:42 +02:00
|
|
|
int limit_by = 'b';
|
2017-07-17 20:03:28 +02:00
|
|
|
char str[512];
|
2014-02-14 13:40:22 -06:00
|
|
|
|
2015-04-08 10:41:42 +02:00
|
|
|
if (nb_opcodes != 0) {
|
|
|
|
limit_by = 'o';
|
|
|
|
}
|
2015-02-17 00:54:55 +01:00
|
|
|
if (nb_opcodes) { // Disassemble `nb_opcodes` opcodes.
|
2014-08-23 07:23:55 +02:00
|
|
|
if (nb_opcodes < 0) {
|
2015-02-17 00:54:55 +01:00
|
|
|
int count, nbytes = 0;
|
2016-06-29 00:21:46 +03:00
|
|
|
|
2014-08-23 07:23:55 +02:00
|
|
|
/* Backward disassembly of `nb_opcodes` opcodes:
|
|
|
|
* - We compute the new starting offset
|
|
|
|
* - Read at the new offset */
|
|
|
|
nb_opcodes = -nb_opcodes;
|
2015-06-04 16:53:04 +02:00
|
|
|
|
|
|
|
if (nb_opcodes > 0xffff) {
|
|
|
|
eprintf ("Too many backward instructions\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2016-06-29 00:21:46 +03:00
|
|
|
|
|
|
|
if (r_core_prevop_addr (core, core->offset, nb_opcodes, &addr)) {
|
2016-11-04 23:15:54 +01:00
|
|
|
nbytes = old_offset - addr;
|
2016-06-29 00:21:46 +03:00
|
|
|
} else if (!r_core_asm_bwdis_len (core, &nbytes, &addr, nb_opcodes)) {
|
2015-06-04 16:53:04 +02:00
|
|
|
/* workaround to avoid empty arrays */
|
|
|
|
#define BWRETRY 0
|
|
|
|
#if BWRETRY
|
2016-08-16 13:54:59 +02:00
|
|
|
nb_opcodes ++;
|
2015-06-04 16:53:04 +02:00
|
|
|
if (!r_core_asm_bwdis_len (core, &nbytes, &addr, nb_opcodes)) {
|
|
|
|
#endif
|
|
|
|
r_cons_printf ("]");
|
2015-09-14 12:35:38 +02:00
|
|
|
return false;
|
2015-06-04 16:53:04 +02:00
|
|
|
#if BWRETRY
|
|
|
|
}
|
|
|
|
#endif
|
2016-08-16 13:54:59 +02:00
|
|
|
nb_opcodes --;
|
2014-12-19 20:44:44 +01:00
|
|
|
}
|
2015-02-17 00:54:55 +01:00
|
|
|
count = R_MIN (nb_bytes, nbytes);
|
2016-08-16 13:54:59 +02:00
|
|
|
if (count > 0) {
|
2015-02-17 00:54:55 +01:00
|
|
|
r_core_read_at (core, addr, buf, count);
|
|
|
|
r_core_read_at (core, addr+count, buf+count, nb_bytes-count);
|
|
|
|
} else {
|
2016-08-16 13:54:59 +02:00
|
|
|
if (nb_bytes > 0) {
|
2015-04-06 18:31:35 -04:00
|
|
|
memset (buf, 0xff, nb_bytes);
|
2016-08-16 13:54:59 +02:00
|
|
|
}
|
2015-02-17 00:54:55 +01:00
|
|
|
}
|
2014-12-17 21:25:24 +01:00
|
|
|
} else {
|
|
|
|
// If we are disassembling a positive number of lines, enable dis_opcodes
|
|
|
|
// to be used to finish the loop
|
|
|
|
// If we are disasembling a negative number of lines, we just calculate
|
|
|
|
// the equivalent addr and nb_size and scan a positive number of BYTES
|
|
|
|
// so keep dis_opcodes = 0;
|
|
|
|
dis_opcodes = 1;
|
2014-12-18 00:27:12 +01:00
|
|
|
r_core_read_at (core, addr, buf, nb_bytes);
|
2014-08-23 07:23:55 +02:00
|
|
|
}
|
2016-02-16 21:48:07 +01:00
|
|
|
} else { // Disassemble `nb_bytes` bytes
|
2014-08-23 07:23:55 +02:00
|
|
|
if (nb_bytes < 0) {
|
|
|
|
//Backward disassembly of `nb_bytes` bytes
|
|
|
|
nb_bytes = -nb_bytes;
|
|
|
|
addr -= nb_bytes;
|
|
|
|
r_core_read_at (core, addr, buf, nb_bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
core->offset = addr;
|
|
|
|
|
2014-02-14 13:40:22 -06:00
|
|
|
// XXX - is there a better way to reset a the analysis counter so that
|
|
|
|
// when code is disassembled, it can actually find the correct offsets
|
2014-11-25 12:24:37 +01:00
|
|
|
if (core->anal && core->anal->cur && core->anal->cur->reset_counter) {
|
2014-02-14 13:40:22 -06:00
|
|
|
core->anal->cur->reset_counter (core->anal, addr);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
// TODO: add support for anal hints
|
2014-12-18 00:27:12 +01:00
|
|
|
// If using #bytes i = j
|
|
|
|
// If using #opcodes, j is the offset from start address. i is the
|
|
|
|
// offset in current disassembly buffer (256 by default)
|
2016-03-09 11:59:17 +01:00
|
|
|
i = k = j = line = 0;
|
2015-04-10 01:57:17 +02:00
|
|
|
// i = number of bytes
|
|
|
|
// j = number of instructions
|
2016-03-09 11:59:17 +01:00
|
|
|
// k = delta from addr
|
2016-09-28 16:47:16 +02:00
|
|
|
ds = ds_init (core);
|
2014-12-18 00:27:12 +01:00
|
|
|
for (;;) {
|
2016-03-09 11:59:17 +01:00
|
|
|
bool end_nbopcodes, end_nbbytes;
|
|
|
|
|
|
|
|
at = addr + k;
|
2017-07-17 20:03:28 +02:00
|
|
|
ds->hint = r_core_hint_begin (core, ds->hint, ds->at);
|
2014-01-16 11:04:42 -06:00
|
|
|
r_asm_set_pc (core->assembler, at);
|
2014-12-18 00:27:12 +01:00
|
|
|
// 32 is the biggest opcode length in intel
|
|
|
|
// Make sure we have room for it
|
2016-03-09 11:59:17 +01:00
|
|
|
if (dis_opcodes == 1 && i >= nb_bytes - 32) {
|
2014-12-18 00:27:12 +01:00
|
|
|
// Read another nb_bytes bytes into buf from current offset
|
2014-12-17 21:25:24 +01:00
|
|
|
r_core_read_at (core, at, buf, nb_bytes);
|
2016-03-09 11:59:17 +01:00
|
|
|
i = 0;
|
2014-12-17 21:25:24 +01:00
|
|
|
}
|
2016-03-09 11:59:17 +01:00
|
|
|
|
2015-04-08 10:41:42 +02:00
|
|
|
if (limit_by == 'o') {
|
2016-03-09 11:59:17 +01:00
|
|
|
if (j >= nb_opcodes) {
|
2015-04-08 10:41:42 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-03-09 11:59:17 +01:00
|
|
|
} else if (i >= nb_bytes) {
|
|
|
|
break;
|
2015-04-08 03:20:11 +02:00
|
|
|
}
|
2016-03-09 11:59:17 +01:00
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf + i, nb_bytes - i);
|
|
|
|
if (ret < 1) {
|
|
|
|
r_cons_printf (j > 0 ? ",{" : "{");
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf ("\"offset\":%"PFMT64d, at);
|
|
|
|
r_cons_printf (",\"size\":1,\"type\":\"invalid\"}");
|
|
|
|
i++;
|
2016-03-09 11:59:17 +01:00
|
|
|
k++;
|
2014-12-18 00:27:12 +01:00
|
|
|
j++;
|
2014-01-16 11:04:42 -06:00
|
|
|
continue;
|
|
|
|
}
|
2017-12-22 13:54:11 +01:00
|
|
|
char *opstr = strdup (asmop.buf_asm);
|
2016-09-12 22:43:05 +02:00
|
|
|
|
2016-08-16 13:54:59 +02:00
|
|
|
ds->has_description = false;
|
2016-08-10 21:10:00 +02:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop, at, buf + i, nb_bytes - i, R_ANAL_OP_MASK_ALL);
|
2016-09-12 22:43:05 +02:00
|
|
|
|
2016-08-03 01:17:27 +02:00
|
|
|
if (ds->pseudo) {
|
|
|
|
r_parse_parse (core->parser, asmop.buf_asm, asmop.buf_asm);
|
|
|
|
}
|
2017-07-17 20:03:28 +02:00
|
|
|
|
2017-11-23 22:46:57 +01:00
|
|
|
// f = r_anal_get_fcn_in (core->anal, at,
|
|
|
|
f = fcnIn (ds, at, R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
2014-12-15 20:36:34 +01:00
|
|
|
if (ds->varsub && f) {
|
2016-09-12 22:43:05 +02:00
|
|
|
core->parser->varlist = r_anal_var_list_dynamic;
|
2015-11-19 23:12:08 +01:00
|
|
|
r_parse_varsub (core->parser, f, at, ds->analop.size,
|
2014-12-15 20:36:34 +01:00
|
|
|
asmop.buf_asm, asmop.buf_asm, sizeof (asmop.buf_asm));
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
oplen = r_asm_op_get_size (&asmop);
|
2017-04-16 11:03:11 +02:00
|
|
|
ds->oplen = oplen;
|
|
|
|
ds->at = at;
|
|
|
|
if (ds->midflags) {
|
2017-07-09 16:04:19 -04:00
|
|
|
int skip_bytes = handleMidFlags (core, ds, false);
|
2017-04-16 11:03:11 +02:00
|
|
|
if (skip_bytes && ds->midflags > R_MIDFLAGS_SHOW) {
|
|
|
|
oplen = ds->oplen = ret = skip_bytes;
|
|
|
|
}
|
|
|
|
}
|
2017-12-22 13:54:11 +01:00
|
|
|
{
|
|
|
|
ut64 killme = UT64_MAX;
|
|
|
|
bool be = core->print->big_endian;
|
|
|
|
if (r_io_read_i (core->io, ds->analop.ptr, &killme, ds->analop.refptr, be)) {
|
|
|
|
core->parser->relsub_addr = killme;
|
|
|
|
}
|
|
|
|
}
|
2017-11-01 10:50:27 +00:00
|
|
|
r_parse_filter (core->parser, core->flags, asmop.buf_asm, str,
|
2017-07-17 20:03:28 +02:00
|
|
|
sizeof (str), core->print->big_endian);
|
|
|
|
|
2016-08-03 01:17:27 +02:00
|
|
|
r_cons_printf (j > 0 ? ",{" : "{");
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf ("\"offset\":%"PFMT64d, at);
|
2016-11-16 22:59:01 +01:00
|
|
|
if (ds->analop.ptr != UT64_MAX) {
|
|
|
|
r_cons_printf (",\"ptr\":%"PFMT64d, ds->analop.ptr);
|
|
|
|
}
|
|
|
|
if (ds->analop.val != UT64_MAX) {
|
|
|
|
r_cons_printf (",\"val\":%"PFMT64d, ds->analop.val);
|
|
|
|
}
|
|
|
|
r_cons_printf (",\"esil\":\"%s\"", R_STRBUF_SAFEGET (&ds->analop.esil));
|
|
|
|
r_cons_printf (",\"refptr\":%s", r_str_bool (ds->analop.refptr));
|
2014-12-05 13:29:33 +01:00
|
|
|
if (f) {
|
|
|
|
r_cons_printf (",\"fcn_addr\":%"PFMT64d, f->addr);
|
2016-05-15 14:37:22 +02:00
|
|
|
r_cons_printf (",\"fcn_last\":%"PFMT64d, f->addr + r_anal_fcn_size (f) - oplen);
|
2014-12-05 13:29:33 +01:00
|
|
|
} else {
|
|
|
|
r_cons_printf (",\"fcn_addr\":0");
|
|
|
|
r_cons_printf (",\"fcn_last\":0");
|
|
|
|
}
|
2017-04-16 11:20:16 +02:00
|
|
|
r_cons_printf (",\"size\":%d", ds->analop.size);
|
2014-12-19 17:49:42 +01:00
|
|
|
{
|
2017-12-24 18:03:28 +01:00
|
|
|
char *escaped_str = r_str_utf16_encode (opstr, -1);
|
2017-12-26 21:15:00 +08:00
|
|
|
if (escaped_str) {
|
|
|
|
r_cons_printf (",\"opcode\":\"%s\"", escaped_str);
|
2017-12-24 18:03:28 +01:00
|
|
|
}
|
|
|
|
free (escaped_str);
|
|
|
|
|
|
|
|
escaped_str = r_str_utf16_encode (str, -1);
|
2017-12-26 21:15:00 +08:00
|
|
|
if (escaped_str) {
|
|
|
|
r_cons_printf (",\"disasm\":\"%s\"", escaped_str);
|
2017-10-19 10:06:31 -04:00
|
|
|
}
|
2015-06-15 05:04:29 +02:00
|
|
|
free (escaped_str);
|
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf (",\"bytes\":\"%s\"", asmop.buf_hex);
|
2015-10-08 17:02:22 +02:00
|
|
|
r_cons_printf (",\"family\":\"%s\"",
|
2016-08-10 21:10:00 +02:00
|
|
|
r_anal_op_family_to_string (ds->analop.family));
|
|
|
|
r_cons_printf (",\"type\":\"%s\"", r_anal_optype_to_string (ds->analop.type));
|
2014-08-09 22:39:50 -05:00
|
|
|
// wanted the numerical values of the type information
|
2016-08-10 21:10:00 +02:00
|
|
|
r_cons_printf (",\"type_num\":%"PFMT64d, ds->analop.type);
|
|
|
|
r_cons_printf (",\"type2_num\":%"PFMT64d, ds->analop.type2);
|
2014-08-09 22:39:50 -05:00
|
|
|
// handle switch statements
|
2016-08-10 21:10:00 +02:00
|
|
|
if (ds->analop.switch_op && r_list_length (ds->analop.switch_op->cases) > 0) {
|
2014-08-10 21:52:53 -05:00
|
|
|
// XXX - the java caseop will still be reported in the assembly,
|
|
|
|
// this is an artifact to make ensure the disassembly is properly
|
|
|
|
// represented during the analysis
|
2014-08-09 22:39:50 -05:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalCaseOp *caseop;
|
2016-08-10 21:10:00 +02:00
|
|
|
int cnt = r_list_length (ds->analop.switch_op->cases);
|
2014-08-09 22:39:50 -05:00
|
|
|
r_cons_printf (", \"switch\":[");
|
2016-08-10 21:10:00 +02:00
|
|
|
r_list_foreach (ds->analop.switch_op->cases, iter, caseop ) {
|
2014-08-09 22:39:50 -05:00
|
|
|
cnt--;
|
|
|
|
r_cons_printf ("{");
|
|
|
|
r_cons_printf ("\"addr\":%"PFMT64d, caseop->addr);
|
|
|
|
r_cons_printf (", \"value\":%"PFMT64d, (st64) caseop->value);
|
|
|
|
r_cons_printf (", \"jump\":%"PFMT64d, caseop->jump);
|
|
|
|
r_cons_printf ("}");
|
2016-12-20 00:20:56 +01:00
|
|
|
if (cnt > 0) {
|
|
|
|
r_cons_printf (",");
|
|
|
|
}
|
2014-08-09 22:39:50 -05:00
|
|
|
}
|
|
|
|
r_cons_printf ("]");
|
|
|
|
}
|
2016-08-10 21:10:00 +02:00
|
|
|
if (ds->analop.jump != UT64_MAX ) {
|
|
|
|
r_cons_printf (",\"jump\":%"PFMT64d, ds->analop.jump);
|
|
|
|
if (ds->analop.fail != UT64_MAX) {
|
|
|
|
r_cons_printf (",\"fail\":%"PFMT64d, ds->analop.fail);
|
2016-03-09 11:59:17 +01:00
|
|
|
}
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-11-20 01:14:47 +01:00
|
|
|
/* add flags */
|
|
|
|
{
|
|
|
|
const RList *flags = r_flag_get_list (core->flags, at);
|
|
|
|
RFlagItem *flag;
|
|
|
|
RListIter *iter;
|
|
|
|
if (flags && !r_list_empty (flags)) {
|
|
|
|
r_cons_printf (",\"flags\":[");
|
|
|
|
r_list_foreach (flags, iter, flag) {
|
|
|
|
r_cons_printf ("%s\"%s\"", iter->p?",":"",flag->name);
|
|
|
|
}
|
|
|
|
r_cons_printf ("]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* add comments */
|
|
|
|
{
|
|
|
|
// TODO: slow because we are decoding and encoding b64
|
|
|
|
char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, at);
|
|
|
|
if (comment) {
|
|
|
|
char *b64comment = sdb_encode ((const ut8*)comment, -1);
|
|
|
|
r_cons_printf (",\"comment\":\"%s\"", b64comment);
|
|
|
|
free (comment);
|
|
|
|
free (b64comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* add xrefs */
|
|
|
|
{
|
|
|
|
RAnalRef *ref;
|
|
|
|
RListIter *iter;
|
|
|
|
RList *xrefs = r_anal_xref_get (core->anal, at);
|
|
|
|
if (xrefs && !r_list_empty (xrefs)) {
|
|
|
|
r_cons_printf (",\"xrefs\":[");
|
|
|
|
r_list_foreach (xrefs, iter, ref) {
|
|
|
|
r_cons_printf ("%s{\"addr\":%"PFMT64d",\"type\":\"%s\"}",
|
2014-12-05 13:29:33 +01:00
|
|
|
iter->p?",":"", ref->addr,
|
2014-11-20 01:14:47 +01:00
|
|
|
r_anal_xrefs_type_tostring (ref->type));
|
|
|
|
}
|
|
|
|
r_cons_printf ("]");
|
|
|
|
}
|
2015-01-16 00:56:54 +01:00
|
|
|
r_list_free (xrefs);
|
2014-11-20 01:14:47 +01:00
|
|
|
}
|
|
|
|
|
2014-01-16 11:04:42 -06:00
|
|
|
r_cons_printf ("}");
|
2017-05-23 03:01:45 +02:00
|
|
|
i += oplen + asmop.payload + (ds->asmop.payload % ds->core->assembler->dataalign); // bytes
|
|
|
|
k += oplen + asmop.payload + (ds->asmop.payload % ds->core->assembler->dataalign); // delta from addr
|
2016-03-09 11:59:17 +01:00
|
|
|
j++; // instructions
|
2014-08-22 00:39:31 +02:00
|
|
|
line++;
|
2016-03-09 11:59:17 +01:00
|
|
|
|
2017-12-22 13:54:11 +01:00
|
|
|
free (opstr);
|
2016-03-09 11:59:17 +01:00
|
|
|
end_nbopcodes = dis_opcodes == 1 && nb_opcodes > 0 && line>=nb_opcodes;
|
|
|
|
end_nbbytes = dis_opcodes == 0 && nb_bytes > 0 && i>=nb_bytes;
|
2016-09-28 16:47:16 +02:00
|
|
|
if (end_nbopcodes || end_nbbytes) {
|
|
|
|
break;
|
|
|
|
}
|
2014-12-18 00:27:12 +01:00
|
|
|
}
|
2017-02-05 01:24:50 +01:00
|
|
|
// r_cons_printf ("]");
|
2014-08-23 07:23:55 +02:00
|
|
|
core->offset = old_offset;
|
2016-08-10 21:10:00 +02:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2017-07-17 20:03:28 +02:00
|
|
|
ds_free (ds);
|
2015-09-14 12:35:38 +02:00
|
|
|
return true;
|
2014-01-16 11:04:42 -06:00
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
|
2016-06-25 03:09:30 +02:00
|
|
|
R_API int r_core_print_disasm_all(RCore *core, ut64 addr, int l, int len, int mode) {
|
|
|
|
const bool scr_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
int i, ret, err = 0, count = 0;
|
|
|
|
ut8 *buf = core->block;
|
|
|
|
char str[128];
|
|
|
|
RAsmOp asmop;
|
|
|
|
if (l < 1) {
|
|
|
|
l = len;
|
|
|
|
}
|
2016-11-04 03:15:17 +01:00
|
|
|
RDisasmState *ds = ds_init (core);
|
2016-06-25 03:09:30 +02:00
|
|
|
if (l > core->blocksize || addr != core->offset) {
|
|
|
|
buf = malloc (l + 1);
|
|
|
|
r_core_read_at (core, addr, buf, l);
|
|
|
|
}
|
|
|
|
if (mode == 'j') {
|
|
|
|
r_cons_printf ("[");
|
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-06-25 03:09:30 +02:00
|
|
|
for (i = 0; i < l; i++) {
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->at = addr + i;
|
|
|
|
ds->vat = p2v (ds, ds->at);
|
|
|
|
r_asm_set_pc (core->assembler, ds->vat);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (r_cons_is_breaked ()) {
|
2016-06-25 03:09:30 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf + i, l - i);
|
|
|
|
if (ret < 1) {
|
|
|
|
ret = err = 1;
|
|
|
|
switch (mode) {
|
|
|
|
case 'j':
|
|
|
|
case '=':
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
r_cons_printf ("???\n");
|
|
|
|
break;
|
|
|
|
default:
|
2016-11-04 03:15:17 +01:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" ???\n", ds->vat);
|
2016-06-25 03:09:30 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
count ++;
|
|
|
|
switch (mode) {
|
|
|
|
case 'i':
|
|
|
|
r_parse_filter (core->parser, core->flags, asmop.buf_asm,
|
|
|
|
str, sizeof (str), core->print->big_endian);
|
|
|
|
if (scr_color) {
|
|
|
|
char *buf_asm;
|
|
|
|
RAnalOp aop;
|
2018-03-15 12:31:01 +01:00
|
|
|
r_anal_op (core->anal, &aop, addr, buf+i, l-i, R_ANAL_OP_MASK_ALL);
|
2017-03-28 22:55:58 +02:00
|
|
|
buf_asm = r_print_colorize_opcode (core->print, str,
|
2017-06-20 22:48:46 +02:00
|
|
|
core->cons->pal.reg, core->cons->pal.num, false);
|
2016-06-25 03:09:30 +02:00
|
|
|
r_cons_printf ("%s%s\n",
|
|
|
|
r_print_color_op_type (core->print, aop.type),
|
|
|
|
buf_asm);
|
|
|
|
free (buf_asm);
|
|
|
|
} else {
|
2016-06-26 00:51:17 -04:00
|
|
|
r_cons_println (asmop.buf_asm);
|
2016-06-25 03:09:30 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '=':
|
|
|
|
if (i < 28) {
|
|
|
|
char *str = r_str_newf ("0x%08"PFMT64x" %60s %s\n",
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->vat, "", asmop.buf_asm);
|
2016-06-25 03:09:30 +02:00
|
|
|
char *sp = strchr (str, ' ');
|
|
|
|
if (sp) {
|
|
|
|
char *end = sp + 60 + 1;
|
|
|
|
const char *src = asmop.buf_hex;
|
|
|
|
char *dst = sp + 1 + (i * 2);
|
|
|
|
int len = strlen (src);
|
|
|
|
if (dst < end) {
|
|
|
|
if (dst + len >= end) {
|
|
|
|
len = end - dst;
|
|
|
|
dst[len] = '.';
|
|
|
|
}
|
|
|
|
memcpy (dst, src, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_strcat (str);
|
|
|
|
free (str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
r_cons_printf ("{\"addr\":%08"PFMT64d",\"bytes\":\"%s\",\"inst\":\"%s\"}%s",
|
|
|
|
addr + i, asmop.buf_hex, asmop.buf_asm, ",");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %20s %s\n",
|
|
|
|
addr + i, asmop.buf_hex, asmop.buf_asm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2016-06-25 03:09:30 +02:00
|
|
|
if (buf != core->block) {
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
if (mode == 'j') {
|
|
|
|
r_cons_printf ("{}]\n");
|
|
|
|
}
|
2016-11-04 03:15:17 +01:00
|
|
|
ds_free (ds);
|
2016-06-25 03:09:30 +02:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2014-01-22 22:55:48 -06:00
|
|
|
R_API int r_core_print_fcn_disasm(RPrint *p, RCore *core, ut64 addr, int l, int invbreak, int cbytes) {
|
2014-09-26 15:40:17 +02:00
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
2015-04-23 01:46:28 +03:00
|
|
|
ut32 cur_buf_sz = 0;
|
|
|
|
ut8 *buf = NULL;
|
|
|
|
ut32 len = 0;
|
2014-01-22 22:55:48 -06:00
|
|
|
int ret, idx = 0, i;
|
|
|
|
RListIter *bb_iter;
|
|
|
|
RAnalBlock *bb = NULL;
|
|
|
|
RDisasmState *ds;
|
2015-04-23 01:46:28 +03:00
|
|
|
RList *bb_list = NULL;
|
|
|
|
|
2016-09-22 18:06:10 +02:00
|
|
|
if (!fcn) {
|
2015-04-23 01:46:28 +03:00
|
|
|
return -1;
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
2015-04-23 01:46:28 +03:00
|
|
|
|
2016-05-15 14:37:22 +02:00
|
|
|
cur_buf_sz = r_anal_fcn_size (fcn) + 1;
|
2015-04-23 01:46:28 +03:00
|
|
|
buf = malloc (cur_buf_sz);
|
2016-09-22 18:06:10 +02:00
|
|
|
if (!buf) {
|
|
|
|
return -1;
|
|
|
|
}
|
2016-05-15 14:37:22 +02:00
|
|
|
len = r_anal_fcn_size (fcn);
|
2015-04-23 01:46:28 +03:00
|
|
|
bb_list = r_list_new();
|
2016-05-24 21:22:15 +01:00
|
|
|
if (!bb_list) {
|
|
|
|
free (buf);
|
|
|
|
return -1;
|
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
//r_cons_printf ("len =%d l=%d ib=%d limit=%d\n", len, l, invbreak, p->limit);
|
|
|
|
// TODO: import values from debugger is possible
|
|
|
|
// TODO: allow to get those register snapshots from traces
|
|
|
|
// TODO: per-function register state trace
|
|
|
|
idx = 0;
|
|
|
|
memset (buf, 0, cur_buf_sz);
|
|
|
|
|
2014-02-14 13:40:22 -06:00
|
|
|
// XXX - is there a better way to reset a the analysis counter so that
|
|
|
|
// when code is disassembled, it can actually find the correct offsets
|
2014-04-09 04:53:34 +02:00
|
|
|
if (core->anal->cur && core->anal->cur->reset_counter) {
|
2014-02-14 13:40:22 -06:00
|
|
|
core->anal->cur->reset_counter (core->anal, addr);
|
|
|
|
}
|
|
|
|
|
2014-01-22 22:55:48 -06:00
|
|
|
// TODO: All those ds must be print flags
|
2016-05-30 12:35:39 +02:00
|
|
|
ds = ds_init (core);
|
2014-01-22 22:55:48 -06:00
|
|
|
ds->cbytes = cbytes;
|
2016-05-30 12:35:39 +02:00
|
|
|
ds->print = p;
|
2014-01-22 22:55:48 -06:00
|
|
|
ds->l = l;
|
|
|
|
ds->buf = buf;
|
2016-05-15 14:37:22 +02:00
|
|
|
ds->len = r_anal_fcn_size (fcn);
|
2014-01-22 22:55:48 -06:00
|
|
|
ds->addr = fcn->addr;
|
2016-02-23 18:30:32 +01:00
|
|
|
ds->fcn = fcn;
|
2017-01-31 10:00:24 +01:00
|
|
|
ds->stackptr = core->anal->stackptr;
|
2014-01-22 22:55:48 -06:00
|
|
|
|
|
|
|
r_list_foreach (fcn->bbs, bb_iter, bb) {
|
|
|
|
r_list_add_sorted (bb_list, bb, cmpaddr);
|
|
|
|
}
|
|
|
|
// Premptively read the bb data locs for ref lines
|
|
|
|
r_list_foreach (bb_list, bb_iter, bb) {
|
2016-09-22 18:06:10 +02:00
|
|
|
if (idx >= cur_buf_sz) {
|
|
|
|
break;
|
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
r_core_read_at (core, bb->addr, buf+idx, bb->size);
|
|
|
|
//ret = r_asm_disassemble (core->assembler, &ds->asmop, buf+idx, bb->size);
|
|
|
|
//if (ret > 0) eprintf ("%s\n",ds->asmop.buf_asm);
|
|
|
|
idx += bb->size;
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_reflines_fcn_init (ds, fcn, buf);
|
2014-01-22 22:55:48 -06:00
|
|
|
core->inc = 0;
|
2017-10-08 16:39:27 +05:30
|
|
|
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;
|
2016-09-22 18:06:10 +02:00
|
|
|
i = idx = 0;
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_push (NULL, NULL);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_esil_anal_init (ds);
|
2015-10-01 19:32:30 +02:00
|
|
|
|
2016-09-22 18:06:10 +02:00
|
|
|
if (core->io && core->io->debug) {
|
2015-10-01 19:32:30 +02:00
|
|
|
r_debug_map_sync (core->dbg);
|
2016-09-22 18:06:10 +02:00
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
r_list_foreach (bb_list, bb_iter, bb) {
|
|
|
|
ut32 bb_size_consumed = 0;
|
|
|
|
// internal loop to consume bb that contain case-like operations
|
|
|
|
ds->at = bb->addr;
|
2016-11-04 03:15:17 +01:00
|
|
|
ds->vat = p2v (ds, ds->at);
|
2014-01-22 22:55:48 -06:00
|
|
|
ds->addr = bb->addr;
|
|
|
|
len = bb->size;
|
|
|
|
|
|
|
|
if (len > cur_buf_sz) {
|
2014-05-09 17:40:28 +02:00
|
|
|
free (buf);
|
2014-01-22 22:55:48 -06:00
|
|
|
buf = malloc (cur_buf_sz);
|
|
|
|
ds->buf = buf;
|
2017-11-14 23:36:04 +09:00
|
|
|
if (buf) {
|
|
|
|
cur_buf_sz = len;
|
|
|
|
} else {
|
|
|
|
cur_buf_sz = 0;
|
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
}
|
|
|
|
do {
|
2018-02-17 23:02:53 +08:00
|
|
|
ds->printed_str_addr = UT64_MAX;
|
2018-02-22 23:24:37 +08:00
|
|
|
ds->printed_flag_addr = UT64_MAX;
|
2014-01-22 22:55:48 -06:00
|
|
|
// XXX - why is it necessary to set this everytime?
|
|
|
|
r_asm_set_pc (core->assembler, ds->at);
|
2017-11-14 23:36:04 +09:00
|
|
|
if (ds->lines >= ds->l) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
break;
|
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_update_ref_lines (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
/* show type links */
|
|
|
|
r_core_cmdf (core, "tf 0x%08"PFMT64x, ds->at);
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_comments_right (ds);
|
|
|
|
ret = ds_disassemble (ds, buf+idx, len - bb_size_consumed);
|
|
|
|
ds_atabs_option (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
// TODO: store previous oplen in core->dec
|
2016-11-20 19:20:14 +01:00
|
|
|
if (!core->inc) {
|
2016-05-30 04:18:48 +02:00
|
|
|
core->inc = ds->oplen;
|
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
r_anal_op_fini (&ds->analop);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (!ds->lastfail) {
|
2014-02-20 03:08:12 +01:00
|
|
|
r_anal_op (core->anal, &ds->analop,
|
|
|
|
ds->at+bb_size_consumed, buf+idx,
|
2018-03-15 12:31:01 +01:00
|
|
|
len-bb_size_consumed, R_ANAL_OP_MASK_ALL);
|
2016-11-20 19:20:14 +01:00
|
|
|
}
|
2016-05-30 04:18:48 +02:00
|
|
|
if (ret < 1) {
|
2014-01-22 22:55:48 -06:00
|
|
|
r_strbuf_init (&ds->analop.esil);
|
|
|
|
ds->analop.type = R_ANAL_OP_TYPE_ILL;
|
|
|
|
}
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_instruction_mov_lea (ds, idx);
|
|
|
|
ds_control_flow_comments (ds);
|
|
|
|
ds_adistrick_comments (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
/* XXX: This is really cpu consuming.. need to be fixed */
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_show_functions (ds);
|
|
|
|
if (ds_print_labels (ds, fcn)) {
|
|
|
|
ds_show_functions (ds);
|
|
|
|
}
|
|
|
|
ds_show_xrefs (ds);
|
|
|
|
ds_show_flags (ds);
|
|
|
|
ds_setup_print_pre (ds, false, false);
|
|
|
|
ds_print_lines_left (ds);
|
|
|
|
ds_print_offset (ds);
|
|
|
|
ds_print_op_size (ds);
|
|
|
|
ds_print_trace (ds);
|
|
|
|
ds_print_cycles (ds);
|
|
|
|
ds_print_family (ds);
|
|
|
|
ds_print_stackptr (ds);
|
|
|
|
ret = ds_print_meta_infos (ds, buf, len, idx);
|
2014-01-22 22:55:48 -06:00
|
|
|
if (ds->mi_found) {
|
2017-01-16 15:07:11 +01:00
|
|
|
ds->mi_found = false;
|
2014-09-23 11:55:11 +02:00
|
|
|
continue;
|
2014-01-22 22:55:48 -06:00
|
|
|
}
|
|
|
|
/* show cursor */
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_show_cursor (ds);
|
|
|
|
ds_print_show_bytes (ds);
|
|
|
|
ds_print_lines_right (ds);
|
2018-02-03 19:21:54 +01:00
|
|
|
ds_build_op_str (ds, true);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_opstr (ds);
|
2016-07-03 14:12:30 +03:00
|
|
|
ds_print_sysregs (ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_fcn_name (ds);
|
|
|
|
ds_print_import_name (ds);
|
|
|
|
ds_print_color_reset (ds);
|
|
|
|
ds_print_dwarf (ds);
|
|
|
|
ret = ds_print_middle (ds, ret);
|
2017-05-08 20:21:06 +02:00
|
|
|
ds_print_asmop_payload (ds, buf + idx);
|
2014-01-22 22:55:48 -06:00
|
|
|
if (core->assembler->syntax != R_ASM_SYNTAX_INTEL) {
|
|
|
|
RAsmOp ao; /* disassemble for the vm .. */
|
|
|
|
int os = core->assembler->syntax;
|
2014-02-20 03:08:12 +01:00
|
|
|
r_asm_set_syntax (core->assembler,
|
|
|
|
R_ASM_SYNTAX_INTEL);
|
|
|
|
r_asm_disassemble (core->assembler, &ao,
|
|
|
|
buf+idx, len-bb_size_consumed);
|
2014-01-22 22:55:48 -06:00
|
|
|
r_asm_set_syntax (core->assembler, os);
|
|
|
|
}
|
2017-11-25 00:28:21 +01:00
|
|
|
if (ds->shortcut_pos > 0) {
|
|
|
|
ds_print_core_vmode (ds, ds->shortcut_pos);
|
|
|
|
}
|
2016-07-27 14:50:14 +03:00
|
|
|
//ds_print_cc_update (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
/*if (ds->analop.refptr) {
|
2014-11-07 00:41:29 +01:00
|
|
|
handle_print_refptr (core, ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
} else {
|
2014-11-07 00:41:29 +01:00
|
|
|
handle_print_ptr (core, ds, len, idx);
|
2014-01-22 22:55:48 -06:00
|
|
|
}*/
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_ptr (ds, len, idx);
|
Add asm.hints and handle CDOV deoptimization
CDIV deoptimization
===================
This patch implements hints in the disassembler that
aim to assist the user in reading compiler-optimized divisions
by analysing the involved magic number.
Background
==========
Since integer divisions are usually very expensive on most architectures,
compilers try very hard to substitute them with cheaper operations.
One of the more advanced substitutions is described in the book __Hacker's Delight__,
chapter 10.
An actual implementation of the described algorithm in LLVM can be found in the
functions: `TargetLowering::BuildSDIV()` and `APInt::magic()`.
The optimization approximately transforms e.g.
```asm
xor edx, edx
idiv 39
```
into
```asm
mov eax, edi
mov edx, 0xd20d20d3
imul edx
lea eax, [rdx + rdi]
sar edi, 0x1f
sar eax, 5
sub eax, edi
```
Reading the optimized version and __seeing__ the constant 39 seems difficult.
Therefore I try to provide a small hint to the user.
Limitations
===========
* The current implementation only takes the magic number into account,
therefore it may result in false positives.
* Due to the nature of the optimization, the given hint may be off by a power of two.
Fixing this would require to analyse the following shift instructions.
* The hint is only shown in the line containing the magic number.
The user still has to know which of the following instructions belong to the optimization.
TODO
====
* Implement the corresponding analysis for unsigned integers
* Implement the corresponding analysis for 64-bit integers.
* Improve the heuristic by also looking at the next few instructions.
( I don't really know how to iterate over the instructions in the disassember
in a non-deprecated way. Maybe someone can drop me a hint? )
* Implement an exact analysis using the actual dataflow in radeco and use it
to revert the optimization. ( I suppose this is outside the scope of radare )
2016-06-15 15:18:04 +02:00
|
|
|
ds_cdiv_optimization (ds);
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_comments_right (ds);
|
2016-08-25 18:41:49 +02:00
|
|
|
ds_show_refs (ds);
|
2017-01-18 22:02:30 +01:00
|
|
|
ds_print_esil_anal (ds);
|
2016-11-20 19:20:14 +01:00
|
|
|
if (!(ds->show_comments && ds->show_comment_right && ds->comment)) {
|
2017-12-11 15:07:44 +01:00
|
|
|
ds_newline (ds);
|
2016-03-04 00:33:24 +01:00
|
|
|
}
|
2014-01-22 22:55:48 -06:00
|
|
|
if (ds->line) {
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->line);
|
|
|
|
R_FREE (ds->refline);
|
|
|
|
R_FREE (ds->refline2);
|
2014-01-22 22:55:48 -06:00
|
|
|
}
|
2017-05-20 14:37:51 +02:00
|
|
|
ds_print_bbline (ds, false);
|
2016-03-04 00:33:24 +01:00
|
|
|
|
2014-01-22 22:55:48 -06:00
|
|
|
bb_size_consumed += ds->oplen;
|
|
|
|
ds->index += ds->oplen;
|
|
|
|
idx += ds->oplen;
|
|
|
|
ds->at += ds->oplen;
|
|
|
|
ds->addr += ds->oplen;
|
|
|
|
ds->lines++;
|
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
R_FREE (ds->opstr);
|
2014-01-22 22:55:48 -06:00
|
|
|
} while (bb_size_consumed < len);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
free (buf);
|
2016-11-20 19:20:14 +01:00
|
|
|
r_cons_break_pop ();
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_print_esil_anal_fini (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
|
2016-05-30 12:35:39 +02:00
|
|
|
ds_free (ds);
|
2014-01-22 22:55:48 -06:00
|
|
|
r_list_free (bb_list);
|
2014-01-27 01:12:16 +01:00
|
|
|
return idx;
|
2014-01-22 22:55:48 -06:00
|
|
|
}
|
2017-04-16 11:12:41 +02:00
|
|
|
|
|
|
|
static inline bool pdi_check_end(int nb_opcodes, int nb_bytes, int i, int j) {
|
2017-09-30 11:05:30 +02:00
|
|
|
if (nb_opcodes > 0) {
|
|
|
|
if (nb_bytes > 0) {
|
2017-04-16 11:12:41 +02:00
|
|
|
return j < nb_opcodes && i < nb_bytes;
|
|
|
|
}
|
|
|
|
return j < nb_opcodes;
|
|
|
|
}
|
|
|
|
return i < nb_bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_core_disasm_pdi(RCore *core, int nb_opcodes, int nb_bytes, int fmt) {
|
|
|
|
int show_offset = r_config_get_i (core->config, "asm.offset");
|
|
|
|
int show_bytes = r_config_get_i (core->config, "asm.bytes");
|
|
|
|
int decode = r_config_get_i (core->config, "asm.decode");
|
|
|
|
int filter = r_config_get_i (core->config, "asm.filter");
|
|
|
|
int show_color = r_config_get_i (core->config, "scr.color");
|
|
|
|
bool asm_ucase = r_config_get_i (core->config, "asm.ucase");
|
|
|
|
int esil = r_config_get_i (core->config, "asm.esil");
|
|
|
|
int flags = r_config_get_i (core->config, "asm.flags");
|
2017-11-30 00:14:08 +01:00
|
|
|
bool asm_immtrim = r_config_get_i (core->config, "asm.immtrim");
|
2017-04-16 11:12:41 +02:00
|
|
|
int i = 0, j, ret, err = 0;
|
|
|
|
ut64 old_offset = core->offset;
|
|
|
|
RAsmOp asmop;
|
|
|
|
const char *color_reg = R_CONS_COLOR_DEF (reg, Color_YELLOW);
|
|
|
|
const char *color_num = R_CONS_COLOR_DEF (num, Color_CYAN);
|
2017-09-04 12:41:09 -07:00
|
|
|
const int addrbytes = core->io->addrbytes;
|
2017-04-16 11:12:41 +02:00
|
|
|
|
|
|
|
if (fmt == 'e') {
|
|
|
|
show_bytes = 0;
|
|
|
|
decode = 1;
|
|
|
|
}
|
|
|
|
if (!nb_opcodes && !nb_bytes) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!nb_opcodes) {
|
2017-09-30 11:05:30 +02:00
|
|
|
nb_opcodes = -1;
|
2017-04-16 11:12:41 +02:00
|
|
|
if (nb_bytes < 0) {
|
|
|
|
// Backward disasm `nb_bytes` bytes
|
|
|
|
nb_bytes = -nb_bytes;
|
|
|
|
core->offset -= nb_bytes;
|
|
|
|
r_core_read_at (core, core->offset, core->block, nb_bytes);
|
|
|
|
}
|
|
|
|
} else if (!nb_bytes) {
|
|
|
|
if (nb_opcodes < 0) {
|
|
|
|
ut64 start;
|
|
|
|
/* Backward disassembly of `ilen` opcodes
|
|
|
|
* - We compute the new starting offset
|
|
|
|
* - Read at the new offset */
|
|
|
|
nb_opcodes = -nb_opcodes;
|
|
|
|
if (r_core_prevop_addr (core, core->offset, nb_opcodes, &start)) {
|
|
|
|
// We have some anal_info.
|
|
|
|
nb_bytes = core->offset - start;
|
|
|
|
} else {
|
|
|
|
// anal ignorance.
|
|
|
|
r_core_asm_bwdis_len (core, &nb_bytes, &core->offset,
|
|
|
|
nb_opcodes);
|
|
|
|
}
|
2017-09-04 12:41:09 -07:00
|
|
|
nb_bytes *= core->io->addrbytes;
|
2017-04-16 11:12:41 +02:00
|
|
|
if (nb_bytes > core->blocksize) {
|
|
|
|
r_core_block_size (core, nb_bytes);
|
|
|
|
}
|
|
|
|
r_core_read_at (core, core->offset, core->block, nb_bytes);
|
|
|
|
} else {
|
|
|
|
// workaround for the `for` loop below
|
|
|
|
nb_bytes = core->blocksize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX - is there a better way to reset a the analysis counter so that
|
|
|
|
// when code is disassembled, it can actually find the correct offsets
|
|
|
|
if (core->anal && core->anal->cur && core->anal->cur->reset_counter) {
|
|
|
|
core->anal->cur->reset_counter (core->anal, core->offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
int len = (nb_opcodes + nb_bytes) * 5;
|
|
|
|
if (core->fixedblock) {
|
|
|
|
len = core->blocksize;
|
|
|
|
} else {
|
|
|
|
if (len > core->blocksize) {
|
|
|
|
r_core_block_size (core, len);
|
|
|
|
r_core_block_read (core);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_cons_break_push (NULL, NULL);
|
|
|
|
|
|
|
|
int midflags = r_config_get_i (core->config, "asm.midflags");
|
2017-09-30 11:05:30 +02:00
|
|
|
i = 0;
|
|
|
|
j = 0;
|
|
|
|
toro:
|
|
|
|
for (; pdi_check_end (nb_opcodes, nb_bytes, addrbytes * i, j); j++) {
|
2017-04-16 11:12:41 +02:00
|
|
|
RFlagItem *item;
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
err = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RAnalMetaItem *meta = r_meta_find (core->anal, core->offset + i,
|
|
|
|
R_META_TYPE_ANY, R_META_WHERE_HERE);
|
|
|
|
if (meta && meta->size > 0) {
|
|
|
|
switch (meta->type) {
|
|
|
|
case R_META_TYPE_DATA:
|
|
|
|
r_cons_printf (".data: %s\n", meta->str);
|
|
|
|
i += meta->size;
|
|
|
|
continue;
|
|
|
|
case R_META_TYPE_STRING:
|
|
|
|
r_cons_printf (".string: %s\n", meta->str);
|
|
|
|
i += meta->size;
|
|
|
|
continue;
|
|
|
|
case R_META_TYPE_FORMAT:
|
|
|
|
r_cons_printf (".format : %s\n", meta->str);
|
|
|
|
i += meta->size;
|
|
|
|
continue;
|
|
|
|
case R_META_TYPE_MAGIC:
|
|
|
|
r_cons_printf (".magic : %s\n", meta->str);
|
|
|
|
i += meta->size;
|
|
|
|
continue;
|
|
|
|
case R_META_TYPE_RUN:
|
|
|
|
/* TODO */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_asm_set_pc (core->assembler, core->offset + i);
|
2017-08-08 03:08:33 -07:00
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, core->block + addrbytes * i,
|
|
|
|
core->blocksize - addrbytes * i);
|
2017-04-16 11:12:41 +02:00
|
|
|
if (midflags) {
|
|
|
|
RDisasmState ds = {
|
|
|
|
.oplen = ret,
|
|
|
|
.at = core->offset + i,
|
|
|
|
.midflags = midflags
|
|
|
|
};
|
|
|
|
int skip_bytes = handleMidFlags (core, &ds, true);
|
|
|
|
if (skip_bytes && midflags > R_MIDFLAGS_SHOW) {
|
|
|
|
ret = skip_bytes;
|
|
|
|
asmop.size = ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fmt == 'C') {
|
|
|
|
char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, core->offset + i);
|
|
|
|
if (comment) {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x " %s\n", core->offset + i, comment);
|
|
|
|
free (comment);
|
|
|
|
}
|
|
|
|
i += ret;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (flags) {
|
|
|
|
if (fmt != 'e') { // pie
|
|
|
|
item = r_flag_get_i (core->flags, core->offset + i);
|
|
|
|
if (item) {
|
|
|
|
if (show_offset) {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x " ", core->offset + i);
|
|
|
|
}
|
|
|
|
r_cons_printf (" %s:\n", item->name);
|
|
|
|
}
|
|
|
|
} // do not show flags in pie
|
|
|
|
}
|
2017-04-27 15:18:37 +02:00
|
|
|
ut64 at = core->offset + i;
|
2017-04-16 11:12:41 +02:00
|
|
|
if (show_offset) {
|
|
|
|
const int show_offseg = (core->print->flags & R_PRINT_FLAGS_SEGOFF) != 0;
|
|
|
|
const int show_offdec = (core->print->flags & R_PRINT_FLAGS_ADDRDEC) != 0;
|
2018-03-12 12:37:35 +01:00
|
|
|
unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
|
|
|
|
|
|
|
|
r_print_offset_sg (core->print, at, 0, show_offseg, seggrn, show_offdec, 0, NULL);
|
2017-04-16 11:12:41 +02:00
|
|
|
}
|
|
|
|
// r_cons_printf ("0x%08"PFMT64x" ", core->offset+i);
|
|
|
|
if (ret < 1) {
|
|
|
|
err = 1;
|
|
|
|
ret = asmop.size;
|
|
|
|
if (ret < 1) {
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
if (show_bytes) {
|
2017-04-27 15:18:37 +02:00
|
|
|
r_cons_printf ("%18s%02x ", "", core->block[i]);
|
2017-04-16 11:12:41 +02:00
|
|
|
}
|
|
|
|
r_cons_println ("invalid"); // ???");
|
|
|
|
} else {
|
|
|
|
if (show_bytes) {
|
2017-04-27 15:18:37 +02:00
|
|
|
r_cons_printf ("%20s ", asmop.buf_hex);
|
2017-04-16 11:12:41 +02:00
|
|
|
}
|
|
|
|
ret = asmop.size;
|
2017-11-30 00:14:08 +01:00
|
|
|
if (!asm_immtrim && (decode || esil)) {
|
2017-04-16 11:12:41 +02:00
|
|
|
RAnalOp analop = {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
char *tmpopstr, *opstr = NULL;
|
|
|
|
r_anal_op (core->anal, &analop, core->offset + i,
|
2018-03-15 12:31:01 +01:00
|
|
|
core->block + addrbytes * i, core->blocksize - addrbytes * i, R_ANAL_OP_MASK_ALL);
|
2017-04-16 11:12:41 +02:00
|
|
|
tmpopstr = r_anal_op_to_string (core->anal, &analop);
|
|
|
|
if (fmt == 'e') { // pie
|
|
|
|
char *esil = (R_STRBUF_SAFEGET (&analop.esil));
|
|
|
|
r_cons_println (esil);
|
|
|
|
} else {
|
|
|
|
if (decode) {
|
|
|
|
opstr = (tmpopstr)? tmpopstr: (asmop.buf_asm);
|
|
|
|
} else if (esil) {
|
|
|
|
opstr = (R_STRBUF_SAFEGET (&analop.esil));
|
|
|
|
}
|
2017-11-30 00:14:08 +01:00
|
|
|
if (asm_immtrim ) {
|
2017-11-29 18:56:12 +01:00
|
|
|
r_parse_immtrim (opstr);
|
2017-09-30 03:21:47 +02:00
|
|
|
}
|
2017-04-16 11:12:41 +02:00
|
|
|
r_cons_println (opstr);
|
|
|
|
}
|
|
|
|
} else {
|
2017-04-26 20:07:11 +03:00
|
|
|
char opstr[128] = {
|
|
|
|
0
|
|
|
|
};
|
2017-04-27 15:18:37 +02:00
|
|
|
char *asm_str = (char *)&asmop.buf_asm;
|
|
|
|
if (asm_ucase) {
|
2017-04-26 20:07:11 +03:00
|
|
|
r_str_case (asm_str, 1);
|
|
|
|
}
|
2017-11-30 00:14:08 +01:00
|
|
|
if (asm_immtrim) {
|
2017-11-29 18:56:12 +01:00
|
|
|
r_parse_immtrim (asm_str);
|
2017-09-30 03:21:47 +02:00
|
|
|
}
|
2017-04-16 11:12:41 +02:00
|
|
|
if (filter) {
|
2017-04-27 15:18:37 +02:00
|
|
|
core->parser->hint = r_anal_hint_get (core->anal, at);
|
2017-04-26 20:07:11 +03:00
|
|
|
r_parse_filter (core->parser, core->flags,
|
|
|
|
asm_str, opstr, sizeof (opstr) - 1, core->print->big_endian);
|
2017-04-26 19:35:37 +02:00
|
|
|
asm_str = (char *)&opstr;
|
2017-04-26 20:07:11 +03:00
|
|
|
}
|
|
|
|
if (show_color) {
|
|
|
|
RAnalOp aop = {
|
2017-04-16 11:12:41 +02:00
|
|
|
0
|
|
|
|
};
|
2017-04-26 20:07:11 +03:00
|
|
|
r_anal_op (core->anal, &aop, core->offset + i,
|
2018-03-15 12:31:01 +01:00
|
|
|
core->block + addrbytes * i, core->blocksize - addrbytes * i, R_ANAL_OP_MASK_ALL);
|
2017-06-20 22:48:46 +02:00
|
|
|
asm_str = r_print_colorize_opcode (core->print, asm_str, color_reg, color_num, false);
|
2017-04-26 20:07:11 +03:00
|
|
|
r_cons_printf ("%s%s"Color_RESET "\n",
|
|
|
|
r_print_color_op_type (core->print, aop.type),
|
|
|
|
asm_str);
|
2017-09-04 09:34:18 -07:00
|
|
|
free (asm_str);
|
2017-08-09 02:31:37 -07:00
|
|
|
r_anal_op_fini (&aop);
|
2017-04-16 11:12:41 +02:00
|
|
|
} else {
|
2017-04-26 20:07:11 +03:00
|
|
|
r_cons_println (asm_str);
|
2017-04-16 11:12:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i += ret;
|
2017-09-30 11:05:30 +02:00
|
|
|
}
|
|
|
|
if (nb_opcodes > 0 && j < nb_opcodes) {
|
|
|
|
r_core_seek (core, core->offset + i, 1);
|
|
|
|
i = 0;
|
|
|
|
goto toro;
|
2017-04-16 11:12:41 +02:00
|
|
|
}
|
|
|
|
r_cons_break_pop ();
|
2017-09-30 11:05:30 +02:00
|
|
|
r_core_seek (core, old_offset, 1);
|
2017-04-16 11:12:41 +02:00
|
|
|
return err;
|
|
|
|
}
|