qemu-devel
[Top][All Lists]
Advanced

[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: Luiz Capitulino
Subject: Re: [Qemu-devel] [RFC v3] monitor: add memory search commands s, sp
Date: Tue, 21 Apr 2015 10:35:18 -0400

On Tue, 21 Apr 2015 16:25:12 +0200
Claudio Fontana <address@hidden> wrote:

> 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 honestly don't have an opinion on this, which means I'm willing
to apply if there are no objections.

On the other hand, isn't it possible to just use existing commands?
Like, why can't you just dump this memory to disk and search it
with strings or another tool?

> 
> > 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");
> >>>>
> >>>
> >>>
> >>
> >>
> > 
> 
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]