On Fri, 24 Apr 2015 14:39:48 +0200 hw.clau...@gmail.com wrote: > From: Claudio Fontana <claudio.font...@huawei.com> > > 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 <claudio.font...@huawei.com>
Applied to the qmp branch, thanks. > --- > hmp-commands.hx | 28 ++++++++++++ > monitor.c | 140 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 168 insertions(+) > > changes from v3: > initialize pointer variable to NULL to finally get rid of spurious warning > > changes from v2: > move code to try to address spurious warning > > changes from v1: > make checkpatch happy by adding braces here and there. > > 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..b648dd2 100644 > --- a/monitor.c > +++ b/monitor.c > @@ -1208,6 +1208,124 @@ 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 = NULL; /* needle to search in the haystack */ > + const char *format_str; /* numeric input format string */ > + char value_raw[8]; /* numeric input converted to raw data */ > +#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 */ > + 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;) { > + match = memmem(mark, todo, needle, wsize); > + if (!match) { > + 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 +1450,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");