From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48507) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVeoA-0007Bl-87 for qemu-devel@nongnu.org; Wed, 11 Mar 2015 07:28:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YVeo6-0007xN-Su for qemu-devel@nongnu.org; Wed, 11 Mar 2015 07:28:14 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:41411) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YVeo0-0007pn-Bo for qemu-devel@nongnu.org; Wed, 11 Mar 2015 07:28:10 -0400 Message-ID: <550026B0.4060705@huawei.com> Date: Wed, 11 Mar 2015 19:27:44 +0800 From: Gonglei MIME-Version: 1.0 References: <1426071808-2513-1-git-send-email-hw.claudio@gmail.com> In-Reply-To: <1426071808-2513-1-git-send-email-hw.claudio@gmail.com> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [RFC] monitor: add memory search commands s, sp List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: hw.claudio@gmail.com, qemu-devel@nongnu.org Cc: Claudio Fontana On 2015/3/11 19:03, hw.claudio@gmail.com wrote: > From: Claudio Fontana > > usage is similar to the commands x, xp. > > Example with string: looking for "ELF" header in memory: > > (qemu) s/1000000cb 0x40001000 "ELF" > searching memory area [0000000040001000-00000000400f5240] > 0000000040090001 > (qemu) x/20b 0x40090000 > 0000000040090000: '\x7f' 'E' 'L' 'F' '\x02' '\x01' '\x01' '\x03' > 0000000040090008: '\x00' '\x00' '\x00' '\x00' '\x00' '\x00' '\x00' '\x00' > 0000000040090010: '\x02' '\x00' '\xb7' '\x00' > > Example with value: looking for 64bit variable value 0x990088 > > (qemu) s/1000000xg 0xffff900042000000 0x990088 > searching memory area [ffff900042000000-ffff9000427a1200] > ffff9000424b3000 > ffff9000424c1000 > > Signed-off-by: Claudio Fontana > --- > hmp-commands.hx | 28 ++++++++++++ > monitor.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 167 insertions(+) > Hi, Claudio checkpatch.pl reports some warnings. Regards, -Gonglei > Please note that this has been only loosely tested with LE host / LE guest, > more testing needed for heterogeneous host/target, and for matches overlapping > chunks. > > Of course it is possible to dump the guest memory and then use other tools > to look for the needed data. Personally I found it handy to have this available > in qemu, I wonder whether it can be handy in general. > > Ciao, > > Claudio > > diff --git a/hmp-commands.hx b/hmp-commands.hx > index d5022d8..2bf5737 100644 > --- a/hmp-commands.hx > +++ b/hmp-commands.hx > @@ -432,6 +432,34 @@ Start gdbserver session (default @var{port}=1234) > ETEXI > > { > + .name = "s", > + .args_type = "fmt:/,addr:l,data:s", > + .params = "/fmt addr data", > + .help = "search virtual memory starting at 'addr' for 'data'", > + .mhandler.cmd = hmp_memory_search, > + }, > + > +STEXI > +@item s/fmt @var{addr} @var{data} > +@findex s > +Virtual memory search starting at @var{addr} for data described by @var{data}. > +ETEXI > + > + { > + .name = "sp", > + .args_type = "fmt:/,addr:l,data:s", > + .params = "/fmt addr data", > + .help = "search physical memory starting at 'addr' for 'data'", > + .mhandler.cmd = hmp_physical_memory_search, > + }, > + > +STEXI > +@item sp/fmt @var{addr} @var{data} > +@findex sp > +Physical memory search starting at @var{addr} for data described by @var{data}. > +ETEXI > + > + { > .name = "x", > .args_type = "fmt:/,addr:l", > .params = "/fmt addr", > diff --git a/monitor.c b/monitor.c > index c86a89e..60a2e0d 100644 > --- a/monitor.c > +++ b/monitor.c > @@ -1208,6 +1208,123 @@ static void monitor_printc(Monitor *mon, int c) > monitor_printf(mon, "'"); > } > > +static void monitor_print_addr(Monitor *mon, hwaddr addr, bool is_physical) > +{ > + if (is_physical) > + monitor_printf(mon, TARGET_FMT_plx "\n", addr); > + else > + monitor_printf(mon, TARGET_FMT_lx "\n", (target_ulong)addr); > +} > + > +/* simple memory search for a byte sequence. The sequence is generated from > + * a numeric value to look for in guest memory, or from a string. > + */ > +static void memory_search(Monitor *mon, int count, int format, int wsize, > + hwaddr addr, const char *data_str, bool is_physical) > +{ > + int pos, len; /* pos in the search area, len of area */ > + char *hay; /* buffer for haystack */ > + int hay_size; /* haystack size. Needle size is wsize. */ > + const char *needle; /* needle to search in the haystack */ > + const char *format_str; /* numeric input format string */ > + > +#define MONITOR_S_CHUNK_SIZE 16000 > + > + len = wsize * count; > + if (len < 1) { > + monitor_printf(mon, "invalid search area length.\n"); > + return; > + } > + switch (format) { > + case 'i': > + monitor_printf(mon, "format '%c' not supported.\n", format); > + return; > + case 'c': > + needle = data_str; > + wsize = strlen(data_str); > + if (wsize > MONITOR_S_CHUNK_SIZE) { > + monitor_printf(mon, "search string too long [max %d].\n", > + MONITOR_S_CHUNK_SIZE); > + return; > + } > + break; > + case 'o': > + format_str = "%" SCNo64; > + break; > + default: > + case 'x': > + format_str = "%" SCNx64; > + break; > + case 'u': > + format_str = "%" SCNu64; > + break; > + case 'd': > + format_str = "%" SCNd64; > + break; > + } > + if (format != 'c') { > + uint64_t value; /* numeric input value */ > + char value_raw[8]; /* numeric input converted to raw data */ > + void *from = &value; > + if (sscanf(data_str, format_str, &value) != 1) { > + monitor_printf(mon, "could not parse search string " > + "\"%s\" as format '%c'.\n", data_str, format); > + return; > + } > +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) > + value = bswap64(value); > +#endif > +#if defined(TARGET_WORDS_BIGENDIAN) > + from += 8 - wsize; > +#endif > + memcpy(value_raw, from, wsize); > + needle = value_raw; > + } > + monitor_printf(mon, "searching memory area "); > + if (is_physical) > + monitor_printf(mon, "[" TARGET_FMT_plx "-" TARGET_FMT_plx "]\n", > + addr, addr + len); > + else > + monitor_printf(mon, "[" TARGET_FMT_lx "-" TARGET_FMT_lx "]\n", > + (target_ulong)addr, (target_ulong)addr + len); > + > + hay_size = len < MONITOR_S_CHUNK_SIZE ? len : MONITOR_S_CHUNK_SIZE; > + hay = g_malloc0(hay_size); > + > + for (pos = 0; pos < len;) { > + char *mark, *match; /* mark new starting position, eventual match */ > + int l, todo; /* total length to be processed in current chunk */ > + l = len - pos; > + if (l > hay_size) { > + l = hay_size; > + } > + if (is_physical) { > + cpu_physical_memory_read(addr, hay, l); > + } else if (cpu_memory_rw_debug(ENV_GET_CPU(mon_get_cpu()), addr, > + (uint8_t *)hay, l, 0) < 0) { > + monitor_printf(mon, " Cannot access memory\n"); > + break; > + } > + for (mark = hay, todo = l; todo >= wsize;) { > + if (!(match = memmem(mark, todo, needle, wsize))) { > + break; > + } > + monitor_print_addr(mon, addr + (match - hay), is_physical); > + mark = match + 1; > + todo = mark - hay; > + } > + if (pos + l < len) { > + /* catch potential matches across chunks. */ > + pos += l - (wsize - 1); > + addr += l - (wsize - 1); > + } else { > + pos += l; > + addr += l; > + } > + } > + g_free(hay); > +} > + > static void memory_dump(Monitor *mon, int count, int format, int wsize, > hwaddr addr, int is_physical) > { > @@ -1332,6 +1449,28 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, > } > } > > +static void hmp_memory_search(Monitor *mon, const QDict *qdict) > +{ > + int count = qdict_get_int(qdict, "count"); > + int format = qdict_get_int(qdict, "format"); > + int size = qdict_get_int(qdict, "size"); > + target_long addr = qdict_get_int(qdict, "addr"); > + const char *data_str = qdict_get_str(qdict, "data"); > + > + memory_search(mon, count, format, size, addr, data_str, false); > +} > + > +static void hmp_physical_memory_search(Monitor *mon, const QDict *qdict) > +{ > + int count = qdict_get_int(qdict, "count"); > + int format = qdict_get_int(qdict, "format"); > + int size = qdict_get_int(qdict, "size"); > + hwaddr addr = qdict_get_int(qdict, "addr"); > + const char *data_str = qdict_get_str(qdict, "data"); > + > + memory_search(mon, count, format, size, addr, data_str, true); > +} > + > static void hmp_memory_dump(Monitor *mon, const QDict *qdict) > { > int count = qdict_get_int(qdict, "count"); >