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


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


Yes.  I found/fixed them + forgot to flush the insn cache + forgot to 
increment myaddr + forgot to write to i of d didn't work, yet it was 
still as broken!  Eventually I found the only real bug :-^

> +         memcpy (buffer + addr_off, myaddr, addr_len);


It should be ``(char*)buffer + addr_off'' :-(

Attatched is a version that appears to work (no regressions).

enjoy,
Andrew


? diffs
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 03:20:14
***************
*** 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,614 ----
  		   struct mem_attrib *attrib ATTRIBUTE_UNUSED,
  		   struct target_ops *target)
  {
+ #if 1
+   CORE_ADDR addr = memaddr;
+   long nr_bytes = len;
+   char *srcdest = myaddr;
+   while (nr_bytes > 0)
+     {
+       PTRACE_XFER_TYPE buffer[1000];
+       long sizeof_buffer;
+       CORE_ADDR bufaddr;
+       long count;
+       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)
+ 		       + nr_bytes
+ 		       + sizeof (PTRACE_XFER_TYPE) - 1);
+       if (sizeof_buffer > sizeof (buffer))
+ 	sizeof_buffer = sizeof (buffer);
+       count = sizeof_buffer / sizeof (PTRACE_XFER_TYPE);
+       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;
+       if (addr_len > nr_bytes)
+ 	addr_len = nr_bytes;
+       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 ((char *) buffer + addr_off, srcdest, addr_len);
+ 	}
+ 
+       /* Transfer COUNT words. */
+       for (i = 0; i < count; i++)
+ 	{
+ 	  CORE_ADDR a = bufaddr + i * sizeof (PTRACE_XFER_TYPE);
+ 	  if (write)
+ 	    {
+ 	      errno = 0;
+ 	      ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+ 		      (PTRACE_ARG3_TYPE) a, buffer[i]);
+ 	      if (errno)
+ 		{
+ 		  /* Using the appropriate one (I or D) is necessary
+ 		     for Gould NP1, at least.  */
+ 		  errno = 0;
+ 		  ptrace (PT_WRITE_I, PIDGET (inferior_ptid), 
+ 			  (PTRACE_ARG3_TYPE) addr, 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 (srcdest, (char *) buffer + addr_off, addr_len);
+ 
+       /* Update all counters.  */
+       addr += addr_len;
+       nr_bytes -= addr_len;
+       srcdest += addr_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
*** 591,596 ****
--- 695,715 ----
  
    if (old_chain != NULL)
      do_cleanups (old_chain);
+ #endif
+ #if 0
+   {
+     int i;
+     static FILE *t;
+     if (!t)
+       t = fopen ("log", "w");
+     fprintf (t, "%c 0x%lx %ld :",
+ 	     write ? 'w' : 'r',
+ 	     (long) memaddr, (long) len);
+     for (i = 0; i < len; i++)
+       fprintf (t, "%02x", myaddr[i] & 0xff);
+     fprintf (t, "\n");
+   }
+ #endif
    return len;
  }
  

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