diff --git a/libr/core/cconfig.c b/libr/core/cconfig.c index 707b6a8d19b2c..3ecd70567c356 100644 --- a/libr/core/cconfig.c +++ b/libr/core/cconfig.c @@ -1826,6 +1826,7 @@ R_API int r_core_config_init(RCore *core) { SETPREF("asm.hints", "false", "Show hints for magic numbers in disasm"); SETPREF("asm.marks", "true", "Show marks before the disassembly"); SETPREF("asm.cmtrefs", "false", "Show flag and comments from refs in disasm"); + SETPREF("asm.cmtpatch", "false", "Show patch comments in disasm"); SETCB("bin.strpurge", "false", &cb_strpurge, "Try to purge false positive strings"); SETPREF("bin.libs", "false", "Try to load libraries after loading main binary"); SETCB("bin.strfilter", "", &cb_strfilter, "Filter strings (?:help, a:scii, e:mail, p:ath, u:rl, 8:utf8)"); diff --git a/libr/core/core.c b/libr/core/core.c index 9d0c1a05b9685..57d24e227596e 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -222,9 +222,36 @@ R_API RCore *r_core_cast(void *p) { return (RCore*)p; } -static int core_cmd_callback (void *user, const char *cmd) { +static void core_post_write_callback(void *user, ut64 maddr, ut8 *bytes, int cnt) { RCore *core = (RCore *)user; - return r_core_cmd0 (core, cmd); + + if (!r_config_get_i (core->config, "asm.cmtpatch")) { + return; + } + + char *hex_pairs = r_hex_bin2strdup (bytes, cnt); + if (!hex_pairs) { + eprintf ("core_post_write_callback: Cannot obtain hex pairs\n"); + return; + } + + char *comment = r_str_newf ("patch: %d bytes (%s)", cnt, hex_pairs); + free (hex_pairs); + if (!comment) { + eprintf ("core_post_write_callback: Cannot create comment\n"); + return; + } + + ut64 vaddr = r_io_section_maddr_to_vaddr (core->io, maddr); + vaddr = (vaddr == UT64_MAX) ? maddr : vaddr; + + r_meta_add (core->anal, R_META_TYPE_COMMENT, vaddr, vaddr, comment); + free (comment); +} + +static int core_cmd_callback (void *user, const char *cmd) { + RCore *core = (RCore *)user; + return r_core_cmd0 (core, cmd); } static char *core_cmdstr_callback (void *user, const char *cmd) { @@ -1509,6 +1536,7 @@ R_API int r_core_init(RCore *core) { core->io->user = (void *)core; core->io->cb_core_cmd = core_cmd_callback; core->io->cb_core_cmdstr = core_cmdstr_callback; + core->io->cb_core_post_write = core_post_write_callback; core->sign = r_sign_new (); core->search = r_search_new (R_SEARCH_KEYWORD); r_io_undo_enable (core->io, 1, 0); // TODO: configurable via eval diff --git a/libr/include/r_io.h b/libr/include/r_io.h index 682cb8f8fe33a..78aca2c467183 100644 --- a/libr/include/r_io.h +++ b/libr/include/r_io.h @@ -161,6 +161,8 @@ typedef struct r_io_t { void *user; int (*cb_core_cmd)(void *user, const char *str); char* (*cb_core_cmdstr)(void *user, const char *str); + /* Used for comment generation */ + void (*cb_core_post_write)(void *user, ut64 maddr, ut8 *orig_bytes, int orig_len); struct r_io_plugin_t *plugin_default; } RIO; diff --git a/libr/io/io.c b/libr/io/io.c index 951e856df937a..4a1fffa8e8d7e 100644 --- a/libr/io/io.c +++ b/libr/io/io.c @@ -576,6 +576,15 @@ R_API ut64 r_io_read_i(RIO *io, ut64 addr, int sz) { return ret; } +/* Same as r_io_read_at, but not consume bytes */ +R_API int r_io_peek_at(RIO *io, const ut64 addr, ut8 *buf, const int sz) { + int ret = -1; + r_io_seek (io, addr, R_IO_SEEK_SET); + ret = r_io_read (io, buf, sz); + r_io_seek (io, addr, R_IO_SEEK_SET); + return ret; +} + // TODO. this is a physical resize R_API bool r_io_resize(RIO *io, ut64 newsize) { if (io->plugin) { @@ -649,20 +658,34 @@ R_API int r_io_set_write_mask(RIO *io, const ut8 *buf, int len) { } R_API int r_io_write(RIO *io, const ut8 *buf, int len) { - int i, ret = -1; - ut8 *data = NULL; + ut64 maddr = io->off; + int i, ret = -1, orig_len = 0; + ut8 *data = NULL, *orig_bytes = NULL; /* check section permissions */ if (io->enforce_rwx & R_IO_WRITE) { if (!(r_io_section_get_rwx (io, io->off) & R_IO_WRITE)) { - return -1; + ret = -1; + goto cleanup; } } + orig_bytes = malloc (len); + if (!orig_bytes) { + eprintf ("Cannot allocate %d bytes", len); + ret = -1; + goto cleanup; + } + + orig_len = r_io_peek_at (io, io->off, orig_bytes, len); + if (io->cached) { ret = r_io_cache_write (io, io->off, buf, len); if (ret == len) { - return len; + if (orig_len > 0 && io->cb_core_post_write) { + io->cb_core_post_write (io->user, maddr, orig_bytes, orig_len); + } + goto cleanup; } if (ret > 0) { len -= ret; @@ -677,12 +700,11 @@ R_API int r_io_write(RIO *io, const ut8 *buf, int len) { data = (len > 0)? malloc (len): NULL; if (!data) { eprintf ("malloc failed in write_mask_fd"); - return -1; + ret = -1; + goto cleanup; } // memset (data, io->Oxff, len); - r_io_seek (io, io->off, R_IO_SEEK_SET); - r_io_read (io, data, len); - r_io_seek (io, io->off, R_IO_SEEK_SET); + r_io_peek_at (io, io->off, data, len); for (i = 0; i < len; i++) { data[i] = buf[i] & io->write_mask_buf[i % io->write_mask_len]; @@ -733,7 +755,15 @@ R_API int r_io_write(RIO *io, const ut8 *buf, int len) { io->off += ret; } } + + if (ret > 0 && orig_len > 0 && io->cb_core_post_write) { + io->cb_core_post_write (io->user, maddr, orig_bytes, orig_len); + } + +cleanup: free (data); + free (orig_bytes); + return ret; }