On 11 March 2015 at 12:27, Gonglei <arei.gong...@huawei.com> wrote: > On 2015/3/11 19:03, 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 | 139 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 167 insertions(+) >> > Hi, Claudio > checkpatch.pl reports some warnings.
Right, I'll get rid of those -tx Claudio > > 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"); >> > >