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: Bhushan Attarde
Subject: Re: [Qemu-devel] [PATCH v2] gdbstub: Implement Xfer:auxv:read
Date: Thu, 30 Jul 2015 05:36:37 +0000

Hi Peter,

Thanks for the review.

>> 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?

I think it is enough just to check if (addr > total_len) where,
"addr" is the offset (specified in packet) into target data area we are 
reading, and "total_len" is the byte size of that data area.
Checking if (addr > len) seems incorrect to me. I will change this in v3.

>> +#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).

Yes, "ptr" seems a very generic variable name, so we can use some 
unique/meaningful name for variable that represents locked-memory in user mode.
The same is applicable for 2nd argument of unlock_user (it represents guest 
address pointer).

Thanks,
Bhushan


-----Original Message-----
From: Peter Maydell [mailto:address@hidden 
Sent: 28 July 2015 16:54
To: Bhushan Attarde
Cc: QEMU Developers; Yongbok Kim; Jaydeep Patil
Subject: Re: [PATCH v2] gdbstub: Implement Xfer:auxv:read

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]