qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] gdbstub: Implement Xfer:auxv:read


From: Peter Maydell
Subject: Re: [Qemu-devel] [PATCH v2] gdbstub: Implement Xfer:auxv:read
Date: Tue, 28 Jul 2015 12:24:13 +0100

On 28 July 2015 at 11:58, Bhushan Attarde <address@hidden> wrote:
> Implementation of "Xfer:auxv:read" to provide auxiliary vector information
> to clients which relies on it.
>
> For example: AT_ENTRY in auxiliary vector provides the entry point 
> information.
> Client can use this information to compare it with entry point mentioned in
> executable to calculate load offset and then update the load addresses
> accordingly.
>
> Signed-off-by: Bhushan Attarde <address@hidden>
> ---
>
> Notes:
>     Changes for v2:
>         - Xfer:auxv:read and Xfer:features:read now shares the code for 
> parsing out arguments rather than duplicating it.
>
>  gdbstub.c | 71 
> ++++++++++++++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 54 insertions(+), 17 deletions(-)
>
> diff --git a/gdbstub.c b/gdbstub.c
> index 92b2f81..a6a79dc 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1150,42 +1150,73 @@ static int gdb_handle_packet(GDBState *s, const char 
> *line_buf)
>              if (cc->gdb_core_xml_file != NULL) {
>                  pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
>              }
> +#ifdef CONFIG_USER_ONLY
> +            pstrcat(buf, sizeof(buf), ";qXfer:auxv:read+");
> +#endif
>              put_packet(s, buf);
>              break;
>          }
> -        if (strncmp(p, "Xfer:features:read:", 19) == 0) {
> +        if (strncmp(p, "Xfer:", 5) == 0) {
> +#ifdef CONFIG_USER_ONLY
> +            target_ulong auxv = 0;
> +#endif
> +            target_ulong total_len = 0;
> +            char *ptr = NULL;
>              const char *xml;
> -            target_ulong total_len;
>
> -            cc = CPU_GET_CLASS(first_cpu);
> -            if (cc->gdb_core_xml_file == NULL) {
> +            if (strncmp(p + 5, "features:read:", 14) == 0) {
> +                cc = CPU_GET_CLASS(first_cpu);
> +                if (cc->gdb_core_xml_file == NULL) {
> +                    goto unknown_command;
> +                }
> +                gdb_has_xml = true;
> +                p += 19;
> +                xml = get_feature_xml(p, &p, cc);
> +                if (!xml) {
> +                    snprintf(buf, sizeof(buf), "E00");
> +                    put_packet(s, buf);
> +                    break;
> +                }
> +                total_len = strlen(xml);
> +            }
> +#ifdef CONFIG_USER_ONLY
> +            else if (strncmp(p + 5, "auxv:read:", 10) == 0) {
> +                TaskState *ts = s->c_cpu->opaque;
> +                auxv = ts->info->saved_auxv;
> +                total_len = ts->info->auxv_len;
> +                p += 15;
> +                ptr = lock_user(VERIFY_READ, auxv, total_len, 0);
> +                if (ptr == NULL) {
> +                    break;
> +                }
> +                xml = (char *) ptr;
> +            }
> +#endif
> +            else {
>                  goto unknown_command;
>              }
>
> -            gdb_has_xml = true;
> -            p += 19;
> -            xml = get_feature_xml(p, &p, cc);
> -            if (!xml) {
> -                snprintf(buf, sizeof(buf), "E00");
> -                put_packet(s, buf);
> -                break;
> +            while (*p && *p != ':') {
> +                p++;
>              }
> +            p++;
>
> -            if (*p == ':')
> -                p++;
>              addr = strtoul(p, (char **)&p, 16);
> -            if (*p == ',')
> +            if (*p == ',') {
>                  p++;
> +            }
>              len = strtoul(p, (char **)&p, 16);
>
> -            total_len = strlen(xml);
> -            if (addr > total_len) {
> +            if ((ptr != NULL && addr > len)
> +                || (ptr == NULL && addr > total_len)) {

This if is rather confusing. Why should ptr == or != NULL
make a difference? What is ptr == NULL actually encoding?

>                  snprintf(buf, sizeof(buf), "E00");
>                  put_packet(s, buf);
>                  break;
>              }
> -            if (len > (MAX_PACKET_LENGTH - 5) / 2)
> +
> +            if (len > (MAX_PACKET_LENGTH - 5) / 2) {
>                  len = (MAX_PACKET_LENGTH - 5) / 2;
> +            }
>              if (len < total_len - addr) {
>                  buf[0] = 'm';
>                  len = memtox(buf + 1, xml + addr, len);

> @@ -1194,6 +1225,12 @@ static int gdb_handle_packet(GDBState *s, const char 
> *line_buf)
>                  len = memtox(buf + 1, xml + addr, total_len - addr);
>              }
>              put_packet_binary(s, buf, len + 1);
> +
> +#ifdef CONFIG_USER_ONLY
> +            if (ptr != NULL) {
> +                unlock_user(ptr, auxv, len);
> +            }
> +#endif

This hunk is pretty ugly and rather subtle too since "ptr" is a
very generic variable name. This is implicitly placing requirements
on the code further up to behave in a particular way (use ptr
and only ptr as locked-memory in user mode). Isn't there some
way to write this that abstracts stuff out into separate functions
or a 'register an Xfer read handler' pattern somehow?

-- PMM



reply via email to

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