On Fri, 27 Mar 2015 17:19:30 +0100 Claudio Fontana <claudio.font...@huawei.com> wrote:
> Just a respectful ping on this one.. > Luiz do you think you can integrate this into the monitor? Would be nice to get a Reviewed-by from someone and, I'm getting a build error: /home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c: In function ‘memory_search’: /home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c:1307:19: error: ‘needle’ may be used uninitialized in this function [-Werror=maybe-uninitialized] match = memmem(mark, todo, needle, wsize); ^ cc1: all warnings being treated as errors > > I have given it quite some testing for the LE host case, > I don't have a BE host to test with at the moment, maybe someone can advise > about how to test that scenario? > I was trying to do some qemu under qemu self-emulation but didn't quite get > there.. > > Thanks, > > Claudio > > On 18.03.2015 14:30, Claudio Fontana wrote: > > Tested with kvm on aarch64 LE host with aarch64 LE guest, > > tested with tcg on aarch64 LE host with aarch64 LE/sparc BE/x86 LE guests. > > Would be interesting to test this also on a big endian host with different > > guest combinations.. > > > > Claudio > > > > On 16.03.2015 11:31, 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> > >> --- > >> hmp-commands.hx | 28 ++++++++++++ > >> monitor.c | 140 > >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > >> 2 files changed, 168 insertions(+) > >> > >> Hello, looking for some comments on whether the addition of this > >> command is welcome, and whether the syntax chosen is acceptable, > >> or how it can made better. > >> > >> Thanks! > >> > >> Claudio > >> > >> changes from v2: > >> move value_raw array outside of the inner block. > >> Hopefully this will also make patchew tool happy. > >> Weird that I didn't get that warning/error. > >> > >> 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..7495d7e 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; /* 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"); > >> > > > > > >