This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] Crasher bug in infptrace.c


Andrew Cagney wrote:
> 
> > Anyway, looking at the code, I'm wondering if it would actually be
> >> better to just eliminate that bounce buffer and, instead just transfer
> >> the data directly.  This might leave the buffer in an undefined state, I
> >> think, however, that is ok.
> >
> >
> > I spent an hour thinking about how to do that (without significantly
> > uglifying the code), and decided it was more trouble than I wanted to
> > go to.  I agree with you -- the function doesn't require a buffer
> > at all.  Anyone who wants to rewrite the function to that extent
> > is more than welcome to by me.  ;-)
> 
> How does the attached work-in-progress look as a starting point?  Ran it
> against the testsuite and that came up with a few regressions .....
> However, it isn't totally broken.

Close to how I envisioned it, but see comments below.

> One thing I didn't realize is that I can't trust the alignment of the
> hosts buffer and consequently I can't actually avoid the double buffering.

That's right...  ;-)   That's one reason why I bailed on it.

>   ------------------------------------------------------------------------
> Index: infptrace.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/infptrace.c,v
> retrieving revision 1.20
> diff -p -r1.20 infptrace.c
> *** infptrace.c 2002/01/08 00:59:29     1.20
> --- infptrace.c 2002/01/14 01:40:42
> ***************
> *** 26,31 ****
> --- 26,32 ----
>   #include "target.h"
>   #include "gdb_string.h"
>   #include "regcache.h"
> + #include "gdb_assert.h"
> 
>   #include "gdb_wait.h"
> 
> *************** child_xfer_memory (CORE_ADDR memaddr, ch
> *** 505,510 ****
> --- 506,603 ----
>                    struct mem_attrib *attrib ATTRIBUTE_UNUSED,
>                    struct target_ops *target)
>   {
> + #if 1
> +   CORE_ADDR addr = memaddr;
> +   long nr_bytes = len;
> +   PTRACE_XFER_TYPE buffer[1000];
> +   while (nr_bytes > 0)
> +     {
> +       CORE_ADDR bufaddr;
> +       long count;
> +       long sizeof_buffer;
> +       long addr_off;
> +       long addr_len;
> +       long addr_pad;
> +       long i;
> +
> +       /* Round starting address down to longword boundary to pick up
> +          all of the first byte.  */
> +       bufaddr = addr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
> +
> +       /* Round ending address up to ensure that all of the last word
> +          is copied up and then adjust that to fit in BUFFER.  */
> +       sizeof_buffer = (addr - bufaddr) + len + sizeof (PTRACE_XFER_TYPE) - 1;
> +       if (sizeof_buffer > sizeof (buffer))
> +       sizeof_buffer = sizeof (buffer);

Now you've thrown away your rounding on the ending address.

> +       count = sizeof_buffer / sizeof (PTRACE_XFER_TYPE);

Now count will never be greater than 250, so all writes of
greater than 1000 bytes will lose.

> +       sizeof_buffer = count * sizeof (PTRACE_XFER_TYPE); /* adjust */
> +
> +       /* Break the buffer down into three byte regions: ADDR_OFF
> +        specifies the offset into BUFFER that ADDR starts;
> +        ADDR_LEN specifies the number of ADDR bytes actually in
> +        the buffer; and ADDR_PAD is the number of left over bytes
> +        in the buffer.  Either/or ADDR_OFF and ADDR_PAD can be
> +        zero.  */
> +       addr_off = addr - bufaddr;
> +       addr_len = sizeof_buffer - addr_off;

OK, except that sizeof_buffer has been truncated to 1000, 
therefore addr_len is forced to be less than or equal to that.

> +       if (addr_len > len)

And this can't evaluate to true if len > 1000.

> +       {
> +         addr_len = len;
> +       }
> +       addr_pad = sizeof_buffer - (addr_len + addr_off);
> +       gdb_assert (addr_off + addr_len + addr_pad == sizeof_buffer);
> +
> +       /* For writes, pre-fill the buffer with data that has to go out.  */
> +       if (write)
> +       {
> +         /* If the start is misaligned, a read - modify - write is
> +              needed.  */
> +         if (addr_off > 0)
> +           buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
> +                               (PTRACE_ARG3_TYPE) bufaddr, 0);
> +         /* If the end is misaligned, a read - modify - write is
> +              needed.  */
> +         if (addr_pad > 0 && count > 1)
> +           {
> +             buffer[count - 1] =
> +               ptrace (PT_READ_I, PIDGET (inferior_ptid),
> +                       ((PTRACE_ARG3_TYPE)
> +                        (bufaddr + (count - 1) * sizeof (PTRACE_XFER_TYPE))), 0);
> +           }
> +         /* Fill in LEN bytes in the middle. */
> +         memcpy (buffer + addr_off, myaddr, addr_len);
> +       }
> +
> +       /* Transfer COUNT words. */
> +       for (i = 0; i < count; i++)
> +       {
> +         CORE_ADDR a = bufaddr + i * sizeof (PTRACE_XFER_TYPE);
> +         if (write)
> +           {
> +             ptrace (PT_WRITE_D, PIDGET (inferior_ptid),
> +                     (PTRACE_ARG3_TYPE) a, buffer[i]);
> +           }
> +         else
> +           {
> +             buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
> +                                 (PTRACE_ARG3_TYPE) a, 0);
> +           }
> +       }
> +
> +       /* Copy any read data into MYADDR.  */
> +       if (!write)
> +       memcpy (myaddr, buffer + addr_off, addr_len);
> +
> +       /* Update all counters.  */
> +       addr += addr_len;
> +       nr_bytes -= addr_len;
> +     }
> +   return len;
> + #ifdef CLEAR_INSN_CACHE
> +   if (write)
> +     CLEAR_INSN_CACHE ();
> + #endif
> + #else
>     int i;
>     /* Round starting address down to longword boundary.  */
>     CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
> *************** child_xfer_memory (CORE_ADDR memaddr, ch
> *** 592,597 ****
> --- 685,691 ----
>     if (old_chain != NULL)
>       do_cleanups (old_chain);
>     return len;
> + #endif
>   }
> 
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]