[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC v3] monitor: add memory search commands s, sp
From: |
Claudio Fontana |
Subject: |
Re: [Qemu-devel] [RFC v3] monitor: add memory search commands s, sp |
Date: |
Tue, 21 Apr 2015 16:25:12 +0200 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Thunderbird/24.0.1 |
Hello Luiz,
On 21.04.2015 00:01, Luiz Capitulino wrote:
> On Fri, 27 Mar 2015 17:19:30 +0100
> Claudio Fontana <address@hidden> 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,
gladly, I am definitely looking for Review, first I wanted to check if the idea
itself was acceptable.
> 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
right, this has been pointed out to me before also, I tried to move things
around but that did not help apparently.
I seem not to get this warning with the compiler version I am currently using,
and after checking the code I could not find out why with some compilers would
emit such a warning.
It is difficult for me to debug this issue since I do not get this..
I am using a slightly older compiler from Linaro for AArch64 (4.8.3 based)
Thanks,
Claudio
>
>>
>> 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, address@hidden wrote:
>>>> From: Claudio Fontana <address@hidden>
>>>>
>>>> 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 <address@hidden>
>>>> ---
>>>> 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
>>>> address@hidden s/fmt @var{addr} @var{data}
>>>> address@hidden 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
>>>> address@hidden sp/fmt @var{addr} @var{data}
>>>> address@hidden 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");
>>>>
>>>
>>>
>>
>>
>
--
Claudio Fontana
Server Virtualization Architect
Huawei Technologies Duesseldorf GmbH
Riesstraße 25 - 80992 München
office: +49 89 158834 4135
mobile: +49 15253060158