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 | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) 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..f35d949 100644 --- a/monitor.c +++ b/monitor.c @@ -1208,6 +1208,125 @@ 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;) { + 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 +1451,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"); -- 1.8.5.3