public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* A patch for ia32 hardware watchpoint.
@ 2000-03-07 13:33 H . J . Lu
  2000-03-07 21:52 ` J.T. Conklin
                   ` (3 more replies)
  0 siblings, 4 replies; 52+ messages in thread
From: H . J . Lu @ 2000-03-07 13:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: GDB

This is a patch for

http://sourceware.cygnus.com/ml/gdb/2000-q1/msg00564.html

I only did it for Linux since it is not a perfect solution.

Thanks.


---
2000-03-07  H.J. Lu  <hjl@gnu.org>

	* breakpoint.c (insert_breakpoints): Also pass b->number to
	target_insert_watchpoint () if NEED_WATCHPOINT_NUMBER is
	defined. Don't return error if errno is EBUSY.
	(remove_breakpoint): Also pass b->number to
	target_remove_watchpoint () if NEED_WATCHPOINT_NUMBER is
	defined.
	(delete_breakpoint): Call target_delete_watchpoint () for
	watchpoint if NEED_WATCHPOINT_NUMBER is defined.

	* breakpoint.c (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT):
	Modified to only take "struct value *".
	(TARGET_REGION_OK_FOR_HW_WATCHPOINT): Likewise.
	(can_use_hardware_watchpoint): Likewise.
	* config/i386/nm-go32.h (TARGET_REGION_OK_FOR_HW_WATCHPOINT):
	Likwise.
	* config/pa/nm-hppah.h (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT):
	Likwise.

	* i386-linux-nat.c (i386_register_u_addr): Copied from
	i386v-nat.c.
	(kernel_u_size): Likewise.
	Copy hardware watchpoint runtines from i386v-nat.c and modify.

	* config/i386/linux.mh (NATDEPFILES): Remove i386v-nat.o.

	* config/i386/nm-linux.h (NEED_WATCHPOINT_NUMBER): Defined.
	(target_insert_watchpoint): Add breakpoint number.
	(target_remove_watchpoint): Likewise.
	(target_delete_watchpoint): New.

	* config/i386/tm-linux.h (TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT):
	Also return 1 for long long, double and long double.

Index: breakpoint.c
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/breakpoint.c,v
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.8 breakpoint.c
--- breakpoint.c	2000/03/07 18:42:09	1.1.1.8
+++ breakpoint.c	2000/03/07 18:44:05
@@ -984,7 +984,12 @@ insert_breakpoints ()
 		    else if (b->type == bp_access_watchpoint)
 		      type = hw_access;
 
+#ifdef NEED_WATCHPOINT_NUMBER
+		    val = target_insert_watchpoint (b->number, addr,
+		    				    len, type);
+#else
 		    val = target_insert_watchpoint (addr, len, type);
+#endif
 		    if (val == -1)
 		      {
 			b->inserted = 0;
@@ -1000,8 +1005,11 @@ insert_breakpoints ()
 		remove_breakpoint (b, mark_uninserted);
 		warning ("Could not insert hardware watchpoint %d.",
 			 b->number);
-		val = -1;
-	      }               
+		/* Don't return an error if we fail to insert
+		   a hardware watchpoint due to the limited number
+		   of hardware watchpoints availabel.  */
+		val = (errno == EBUSY) ? 0 : -1;
+	      }
 	  }
 	else
 	  {
@@ -1337,7 +1345,12 @@ remove_breakpoint (b, is)
 	      else if (b->type == bp_access_watchpoint)
 		type = hw_access;
 
+#ifdef NEED_WATCHPOINT_NUMBER
+	      val = target_remove_watchpoint (b->number, addr, len,
+					      type);
+#else
 	      val = target_remove_watchpoint (addr, len, type);
+#endif
 	      if (val == -1)
 		b->inserted = 1;
 	      val = 0;
@@ -5500,13 +5513,13 @@ watch_command_1 (arg, accessflag, from_t
    in hardware return zero.  */
 
 #if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT)
-#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(BYTE_SIZE) \
-    ((BYTE_SIZE) <= (REGISTER_SIZE))
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(VAL) \
+    (TYPE_LENGTH (VALUE_TYPE (VAL)) <= (REGISTER_SIZE))
 #endif
 
 #if !defined(TARGET_REGION_OK_FOR_HW_WATCHPOINT)
-#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(ADDR,LEN) \
-     TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(LEN)
+#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(VAL) \
+     TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(VAL)
 #endif
 
 static int
@@ -5551,10 +5564,7 @@ can_use_hardware_watchpoint (v)
 	    {
 	      /* Ahh, memory we actually used!  Check if we can cover
                  it with hardware watchpoints.  */
-	      CORE_ADDR vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
-	      int       len   = TYPE_LENGTH (VALUE_TYPE (v));
-
-	      if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
+	      if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (v))
 		return 0;
 	      else
 		found_memory_cnt++;
@@ -6852,6 +6862,11 @@ delete_breakpoint (bpt)
 
   if (bpt->inserted)
     remove_breakpoint (bpt, mark_uninserted);
+
+#ifdef NEED_WATCHPOINT_NUMBER
+  if (bpt->type == bp_hardware_watchpoint)
+    target_delete_watchpoint (bpt->number);
+#endif
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;
Index: i386-linux-nat.c
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/i386-linux-nat.c,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 i386-linux-nat.c
--- i386-linux-nat.c	2000/03/07 18:42:13	1.1.1.5
+++ i386-linux-nat.c	2000/03/07 19:01:36
@@ -35,6 +35,21 @@
 #include <sys/reg.h>
 #endif
 
+/* FIXME: The following used to be just "#include <sys/debugreg.h>", but
+ * the the Linux 2.1.x kernel and glibc 2.0.x are not in sync; including
+ * <sys/debugreg.h> will result in an error.  With luck, these losers
+ * will get their act together and we can trash this hack in the near future.
+ * --jsm 1998-10-21
+ */
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#ifdef HAVE_ASM_DEBUGREG_H
+#include <asm/debugreg.h>
+#else
+#include <sys/debugreg.h>
+#endif
+#endif
+
 /* On Linux, threads are implemented as pseudo-processes, in which
    case we may be tracing more than one process at a time.  In that
    case, inferior_pid will contain the main process ID and the
@@ -1058,3 +1073,300 @@ _initialize_i386_linux_nat ()
 {
   add_core_fns (&linux_elf_core_fns);
 }
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+     int blockend;
+     int regnum;
+{
+  struct user u;
+  int fpstate;
+  int ubase;
+
+  ubase = blockend;
+  /* FIXME:  Should have better way to test floating point range */
+  if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
+    {
+#ifdef KSTKSZ			/* SCO, and others? */
+      ubase += 4 * (SS + 1) - KSTKSZ;
+      fpstate = ubase + ((char *) &u.u_fps.u_fpstate - (char *) &u);
+      return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+#else
+      fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
+      return (fpstate + 10 * (regnum - FP0_REGNUM));
+#endif
+    }
+  else
+    {
+      return (ubase + 4 * regmap[regnum]);
+    }
+
+}
+\f
+int
+kernel_u_size ()
+{
+  return (sizeof (struct user));
+}
+\f
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Record the value of the debug control register.  */
+static int debug_control_mirror;
+
+static struct
+{
+  /* Record which address associates with which register.  */
+  CORE_ADDR address;
+  /* Number assigned to distinguish watchpoints.  */
+  int number;
+} address_lookup [DR_LASTADDR - DR_FIRSTADDR + 1];
+
+static int
+i386_insert_aligned_watchpoint PARAMS ((int, int, CORE_ADDR, CORE_ADDR,
+					int, int));
+
+static int
+i386_insert_nonaligned_watchpoint PARAMS ((int, int, CORE_ADDR,
+					   CORE_ADDR, int, int));
+
+/* Insert a watchpoint.  */
+
+int
+i386_insert_watchpoint (pid, num, addr, len, rw)
+     int pid;
+     int num;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  return i386_insert_aligned_watchpoint (pid, num, addr, addr, len, rw);
+}
+
+static int
+i386_insert_aligned_watchpoint (pid, num, waddr, addr, len, rw)
+     int pid;
+     int num;
+     CORE_ADDR waddr;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  int i;
+  int read_write_bits, len_bits;
+  int free_debug_register;
+  int register_number;
+
+  switch (len)
+    {
+    case 1: case 2: case 4: case 8: case 10: case 12:
+      break;
+
+    default:
+      /* This is a kludge. x86 only has limited number of hardware
+	 waitpoint registers. If LEN is too big, we will check
+
+	1. If we have seen the same watch point number in
+	   address_lookup, we just return 0 to save the hardware
+	   waitpoint registers for others. We fake it to make gdb
+	   happy.
+	2. Otherwise, return -1 and set errno EBUSY.
+      */
+      for (i = 0; i < DR_LASTADDR - DR_FIRSTADDR + 1; i++)
+	if (address_lookup[i].number == num
+	    && address_lookup[i].address != 0)
+	  return 0;
+
+      errno = EBUSY;
+      return -1;
+      break;
+    }
+
+  /* Look for a free debug register.  */
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      if (address_lookup[i - DR_FIRSTADDR].address == 0
+	  || address_lookup[i - DR_FIRSTADDR].address == addr)
+	break;
+    }
+
+  /* No more debug registers!  */
+  if (i > DR_LASTADDR)
+    {
+      errno = EBUSY;
+      return -1;
+    }
+
+  read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
+
+  if (len == 1)
+    len_bits = DR_LEN_1;
+  else if (len == 2)
+    {
+      if (addr % 2)
+	return i386_insert_nonaligned_watchpoint (pid, num, waddr,
+						  addr, len, rw);
+      len_bits = DR_LEN_2;
+    }
+
+  else if (len == 4)
+    {
+      if (addr % 4)
+	return i386_insert_nonaligned_watchpoint (pid, num, waddr,
+						  addr, len, rw);
+      len_bits = DR_LEN_4;
+    }
+  else if (len == 8 || len == 10 || len == 12)
+    {
+      /* It should only happen with long long, double or long double.
+	 All should be updated at the same time. We just watch the
+	 first 4 bytes. */
+      len = 4;
+      if (addr % 4)
+	return i386_insert_nonaligned_watchpoint (pid, num, waddr,
+						  addr, len, rw);
+      len_bits = DR_LEN_4;
+    }
+  else
+    return i386_insert_nonaligned_watchpoint (pid, num, waddr, addr,
+					      len, rw);
+  
+  free_debug_register = i;
+  register_number = free_debug_register - DR_FIRSTADDR;
+  debug_control_mirror |=
+    ((read_write_bits | len_bits)
+     << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+  debug_control_mirror |=
+    (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+  debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+  debug_control_mirror &= ~DR_CONTROL_RESERVED;
+
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+	  debug_control_mirror);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[free_debug_register]),
+	  addr);
+
+  /* Record where we came from.  */
+  address_lookup[register_number].address = addr;
+  address_lookup[register_number].number = num;
+  return 0;
+}
+
+static int
+i386_insert_nonaligned_watchpoint (pid, num, waddr, addr, len, rw)
+     int pid;
+     int num;
+     CORE_ADDR waddr;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  int align;
+  int size;
+  int rv;
+
+  static int size_try_array[16] =
+  {
+    1, 1, 1, 1,			/* trying size one */
+    2, 1, 2, 1,			/* trying size two */
+    2, 1, 2, 1,			/* trying size three */
+    4, 1, 2, 1			/* trying size four */
+  };
+
+  rv = 0;
+  while (len > 0)
+    {
+      align = addr % 4;
+      /* Four is the maximum length for 386.  */
+      size = (len > 4) ? 3 : len - 1;
+      size = size_try_array[size * 4 + align];
+
+      rv = i386_insert_aligned_watchpoint (pid, num, waddr, addr,
+					   size, rw);
+      if (rv)
+	{
+	  i386_remove_watchpoint (pid, num, waddr, size);
+	  return rv;
+	}
+      addr += size;
+      len -= size;
+    }
+  return rv;
+}
+
+/* Remove a watchpoint.  */
+
+int
+i386_remove_watchpoint (pid, num, addr, len)
+     int pid;
+     int num;
+     CORE_ADDR addr;
+     int len;
+{
+  int i;
+  int register_number;
+
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      register_number = i - DR_FIRSTADDR;
+      if (address_lookup[register_number].address == addr)
+	{
+	  debug_control_mirror &=
+	    ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+	  address_lookup[register_number].address = 0;
+	  address_lookup[register_number].number = 0;
+	}
+    }
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+	  debug_control_mirror);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+  return 0;
+}
+
+/* Delete a watchpoint.  */
+
+int
+i386_delete_watchpoint (pid, num)
+     int pid;
+     int num;
+{
+  int i;
+  int retval = -1;
+
+  for (i = 0; i < DR_LASTADDR - DR_FIRSTADDR + 1; i++)
+    if (address_lookup[i].number == num
+	&& address_lookup[i].address != 0)
+      {
+	i386_remove_watchpoint (pid, num, address_lookup[i].address, 0);
+	retval = 0;
+      }
+
+  return retval;
+}
+
+/* Check if stopped by a watchpoint.  */
+CORE_ADDR
+i386_stopped_by_watchpoint (pid)
+     int pid;
+{
+  int i;
+  int status;
+
+  status = ptrace (PT_READ_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+  ptrace (PT_WRITE_U, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+    {
+      if (status & (1 << (i - DR_FIRSTADDR)))
+	return address_lookup[i - DR_FIRSTADDR].address;
+    }
+
+  return 0;
+}
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
Index: config/i386/nm-go32.h
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/config/i386/nm-go32.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nm-go32.h
--- config/i386/nm-go32.h	2000/03/07 18:42:21	1.1.1.2
+++ config/i386/nm-go32.h	2000/03/07 18:53:48
@@ -44,10 +44,10 @@
 #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
 
 /* Returns non-zero if we can use hardware watchpoints to watch a region
-   whose address is ADDR and whose length is LEN.  */
+   which represents VAL.  */
 
-#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(addr,len) \
-	go32_region_ok_for_watchpoint(addr,len)
+#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(val) \
+	go32_region_ok_for_watchpoint((VALUE_ADDRESS (val) + VALUE_OFFSET (val)),TYPE_LENGTH (VALUE_TYPE (val)))
 extern int go32_region_ok_for_watchpoint (CORE_ADDR, int);
 
 /* After a watchpoint trap, the PC points to the instruction after the
Index: config/i386/linux.mh
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/config/i386/linux.mh,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 linux.mh
--- config/i386/linux.mh	2000/01/18 17:07:18	1.1.1.2
+++ config/i386/linux.mh	2000/01/18 17:57:36
@@ -1,10 +1,14 @@
 # Host: Intel 386 running GNU/Linux
 
+# We should use the one in glibc 2.
+REGEX=
+REGEX1=
+
 XM_FILE= xm-linux.h
 XDEPFILES= ser-tcp.o
 
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
-	core-aout.o i386v-nat.o i386-linux-nat.o linux-thread.o lin-thread.o
+	core-aout.o i386-linux-nat.o linux-thread.o lin-thread.o
 
 LOADLIBES = -ldl -rdynamic
Index: config/i386/nm-linux.h
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/config/i386/nm-linux.h,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 nm-linux.h
--- config/i386/nm-linux.h	2000/03/07 18:42:21	1.1.1.4
+++ config/i386/nm-linux.h	2000/03/07 18:44:07
@@ -46,14 +46,19 @@ extern int kernel_u_size PARAMS ((void))
 #define STOPPED_BY_WATCHPOINT(W)  \
   i386_stopped_by_watchpoint (inferior_pid)
 
-/* Use these macros for watchpoint insertion/removal.  */
+#define NEED_WATCHPOINT_NUMBER
 
-#define target_insert_watchpoint(addr, len, type)  \
-  i386_insert_watchpoint (inferior_pid, addr, len, type)
+/* Use these macros for watchpoint insertion/removal/deletion.  */
 
-#define target_remove_watchpoint(addr, len, type)  \
-  i386_remove_watchpoint (inferior_pid, addr, len)
+#define target_insert_watchpoint(num, addr, len, type)  \
+  i386_insert_watchpoint (inferior_pid, num, addr, len, type)
 
+#define target_remove_watchpoint(num, addr, len, type)  \
+  i386_remove_watchpoint (inferior_pid, num, addr, len)
+
+#define target_delete_watchpoint(num) \
+  i386_delete_watchpoint (inferior_pid, num)
+
 /* We define this if link.h is available, because with ELF we use SVR4 style
    shared libraries. */
 
@@ -74,9 +79,11 @@ extern int kernel_u_size PARAMS ((void))
 
 extern CORE_ADDR
   i386_stopped_by_watchpoint PARAMS ((int));
+extern int
+  i386_insert_watchpoint PARAMS ((int pid, int num, CORE_ADDR addr, int len, int rw));
 extern int
-i386_insert_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len, int rw));
+  i386_remove_watchpoint PARAMS ((int pid, int num, CORE_ADDR addr, int len));
 extern int
-i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
+  i386_delete_watchpoint PARAMS ((int pid, int num));
 
 #endif /* #ifndef NM_LINUX_H */
Index: config/i386/tm-linux.h
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/config/i386/tm-linux.h,v
retrieving revision 1.1.1.5
diff -u -p -r1.1.1.5 tm-linux.h
--- config/i386/tm-linux.h	2000/03/07 18:42:21	1.1.1.5
+++ config/i386/tm-linux.h	2000/03/07 18:54:47
@@ -166,4 +166,14 @@ extern CORE_ADDR i386_linux_skip_solib_r
    to be relocated. */
 #define SOFUN_ADDRESS_MAYBE_MISSING
 
+/* Does a value fit in a hardware debug register? Although a long long,
+   double or long double doesn't fit in a register, since x86 has to
+   update all bytes at once, it should be ok to just watch the first
+   few bytes. */
+#undef TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(v) \
+  (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE \
+   || TYPE_CODE (VALUE_TYPE (v)) == TYPE_CODE_INT \
+   || TYPE_CODE (VALUE_TYPE (v)) == TYPE_CODE_FLT)
+
 #endif /* #ifndef TM_LINUX_H */
Index: config/pa/nm-hppah.h
===================================================================
RCS file: /work/cvs/gnu/gdb/gdb/config/pa/nm-hppah.h,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 nm-hppah.h
--- config/pa/nm-hppah.h	2000/01/18 17:07:28	1.1.1.3
+++ config/pa/nm-hppah.h	2000/01/18 17:08:57
@@ -142,7 +142,7 @@ extern int hppa_require_detach PARAMS ((
 /* The PA can also watch memory regions of arbitrary size, since we're using
    a page-protection scheme.  (On some targets, apparently watch registers
    are used, which can only accomodate regions of REGISTER_SIZE.) */
-#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_count) \
+#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(val) \
         (1)
 
 /* However, some addresses may not be profitable to use hardware to watch,

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: breakpoint insert API (was: A patch for ia32 hardware watchpoint.)
@ 2000-03-13  1:50 Stephane.Bihan
  2000-03-14 14:47 ` J.T. Conklin
  2000-04-01  0:00 ` Stephane.Bihan
  0 siblings, 2 replies; 52+ messages in thread
From: Stephane.Bihan @ 2000-03-13  1:50 UTC (permalink / raw)
  To: Todd Whitesel; +Cc: GDB, jtc

> > One issue that I'm not sure how to address is that there are several
> > places breakpoints are inserted where a breakpoint has not been
> > constructed.  Most of these occur in tdep code which implements single
> > step with breakpoints on processors without a trace mode.
>
> Aiee! Such code is evil and must be destroyed.

It seems to me that this single_step function is actually not in use.
I don't know about WindRiver, but here we have two targets: an ISS and a
remote target that use the generic breakpoint functions before stepping.
I don't mind to remove this code.

>
> One important value of the full breakpoint machinery is that it can help
> avoid the same location being patched twice. Any time we patch the same
> instruction twice, we must un-patch it in exactly reverse order or else
> we leave a breakpoint instruction sitting in the code -- Not Good.
>
> So I would have to argue that the singlestep logic must either happen at a
> really low level (this guarantees it will patch last and un-patch first) or
> must go through the real breakpoint logic which can do duplicate detection.
>

----------------------------------------------------------------
Stephane Bihan
ARC Cores Ltd            http://www.arccores.com

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: breakpoint insert API (was: A patch for ia32 hardware watchpoint.)
@ 2000-03-15  4:21 Stephane.Bihan
  2000-03-15  7:51 ` J.T. Conklin
  2000-04-01  0:00 ` Stephane.Bihan
  0 siblings, 2 replies; 52+ messages in thread
From: Stephane.Bihan @ 2000-03-15  4:21 UTC (permalink / raw)
  To: jtc; +Cc: Yuri Karlsbrun, gdb

> >>>>> "Stephane" == Stephane Bihan <Stephane.Bihan@arccores.com> writes:
>
> jtc> One issue that I'm not sure how to address is that there are several
> jtc> places breakpoints are inserted where a breakpoint has not been
> jtc> constructed.  Most of these occur in tdep code which implements single
> jtc> step with breakpoints on processors without a trace mode.
>
> Todd> Aiee! Such code is evil and must be destroyed.
>
> Stephane> It seems to me that this single_step function is actually
> Stephane> not in use.  I don't know about WindRiver, but here we have
> Stephane> two targets: an ISS and a remote target that use the generic
> Stephane> breakpoint functions before stepping.  I don't mind to
> Stephane> remove this code.
>
> I assume you are refering to the ARC port?

yes. But I was actually wrong in my last email, the single step function in
arc-tdep is
used, I was thinking to another function, sorry.
What do you mean by breakpoint without a trace mode?

>
> I see three GDB ports that do single step in software: arc, rs6000,
> and sparc.  The arc and sparc ports, insert breakpoints with target-
> _insert_breakpoint().  The rs6000 port by reading and writing memory
> directly.  Of the two methods, I prefer target_insert_breakpoint().
>
> However, if the breakpoint insert/remove API was changed to require a
> struct breakpoint pointer, we couldn't call target_insert_breakpoint()
> in the foo_single_step() functions without creating a real breakpoint
> object to pass through that first pointer.

I don't know what are the foo_single_step functions.

I also use the breakpoint structure as an extern variable. I needed
it to implement the set_hw_breakpoint routine for the remote protocol.
I think it's not the nicer way to do but ....

> Another reason we might want a real breakpoint for this is that when
> my memory region attribute code is complete we'll be able to say that
> breakpoints in a region should be done with hardware breakpoints.
> A user can debug his/her own code in read-only memory by using hbreak,
> but there is no way to tell GDB to use hardware breakpoints for step,
> next, continue, finish, until, etc.  One thing that surprised me was
> that the single step code used multiple breakpoints.  That would put a
> lot of pressure on hardware breakpoint registers.  I suspect that GDB
> has all the information in order to insert a single breakpoint (by
> evaluating which way a conditional branch will go, etc.).
>

What would be a "real breakpoint"? a pointer to the breakpoint structure?

>
> Since you say you can remove the single step code, I assume that the
> ISS target and remote protocol agents can perform the single step by
> themselves?  If so, it would be advantageous to disable GDB's single
> step support.  GDB would then issue a single "step" command instead of
> "insert breakpoint(s)", "continue", and "remove breakpoint(s)".  The
> latency of a step should be greatly improved.

I will implement this for the remote target only since the hardware supports
single-stepping.
I'm not sure if this feasible in the ISS - Yuri?

If not feasible I won't disable the GDB's single step support (thus enabling a
call to single_step())
but I will implement a single_step call to gdbstub in remote_resume().

Stephane.

----------------------------------------------------------------
Stephane Bihan
ARC Cores Ltd            http://www.arccores.com





^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: breakpoint insert API (was: A patch for ia32 hardware watchpoint.)
@ 2000-03-15  9:07 Stephane.Bihan
  2000-04-01  0:00 ` Stephane.Bihan
  0 siblings, 1 reply; 52+ messages in thread
From: Stephane.Bihan @ 2000-03-15  9:07 UTC (permalink / raw)
  To: jtc; +Cc: gdb

>
> Stephane> I also use the breakpoint structure as an extern variable. I
> Stephane> needed it to implement the set_hw_breakpoint routine for the
> Stephane> remote protocol.  I think it's not the nicer way to do but
> Stephane> ....
>
> Can you explain?  I don't see any use of struct breakpoint in the
> current arc-tdep.c, nor do I see a set_hw_breakpoint function?

The version at FSF is a very old version out of date.
I am currently extending gdb for ARC to support user extensions.

>
> >> Since you say you can remove the single step code, I assume that the
> >> ISS target and remote protocol agents can perform the single step by
> >> themselves?  If so, it would be advantageous to disable GDB's single
> >> step support.  GDB would then issue a single "step" command instead of
> >> "insert breakpoint(s)", "continue", and "remove breakpoint(s)".  The
> >> latency of a step should be greatly improved.
>
> Stephane> I will implement this for the remote target only since the
> Stephane> hardware supports single-stepping.  I'm not sure if this
> Stephane> feasible in the ISS - Yuri?
>
> Stephane> If not feasible I won't disable the GDB's single step
> Stephane> support (thus enabling a call to single_step()) but I will
> Stephane> implement a single_step call to gdbstub in remote_resume().
>
> If your ISS target cannot support single step, but the remote protocol
> can, perhaps the best thing is to make software single step a target
> specific option.

By creating a target specific command?
The single step mechanism is a not a step-over-calls mechanism.

>
> I don't think that the arc is the only processor that would benefit
> from such a change.  For example, the sparclet ROM monitor supports a
> single step command, but I do not know if it is ever issued because
> the SPARC target uses software single step.  Perhaps it inserts the
> trap instructions needed for single step and issues the monitor step
> command?
>
> I do not think it's possible for any change to remote_resume() to be
> the right solution.
>
You're right, I've tried and if does not work.
Thanks for your explanations anyway.

Stephane.

----------------------------------------------------------------
Stephane Bihan
ARC Cores Ltd            http://www.arccores.com

^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2000-04-01  0:00 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-07 13:33 A patch for ia32 hardware watchpoint H . J . Lu
2000-03-07 21:52 ` J.T. Conklin
2000-03-08  0:46   ` Todd Whitesel
2000-03-08  6:04     ` Jim Kingdon
2000-03-08 19:44       ` Todd Whitesel
2000-04-01  0:00         ` Todd Whitesel
2000-03-09  7:06       ` Andrew Cagney
2000-04-01  0:00         ` Andrew Cagney
2000-04-01  0:00       ` Jim Kingdon
2000-03-09  5:28     ` Eli Zaretskii
2000-04-01  0:00       ` Eli Zaretskii
2000-03-09 11:28     ` breakpoint insert API (was: A patch for ia32 hardware watchpoint.) J.T. Conklin
2000-03-09 15:15       ` Jim Kingdon
2000-04-01  0:00         ` Jim Kingdon
2000-03-09 15:33       ` Andrew Cagney
2000-03-09 17:28         ` Todd Whitesel
2000-03-14 15:15           ` J.T. Conklin
2000-03-14 15:31             ` Todd Whitesel
2000-04-01  0:00               ` Todd Whitesel
2000-04-01  0:00             ` J.T. Conklin
2000-04-01  0:00           ` Todd Whitesel
2000-03-14 14:10         ` J.T. Conklin
2000-03-21  2:50           ` Andrew Cagney
2000-04-01  0:00             ` Andrew Cagney
2000-04-01  0:00           ` J.T. Conklin
2000-04-01  0:00         ` Andrew Cagney
2000-03-09 17:33       ` Todd Whitesel
2000-03-14 14:56         ` J.T. Conklin
2000-03-21  3:11           ` Andrew Cagney
2000-03-21  6:10             ` Richard Earnshaw
2000-04-01  0:00               ` Richard Earnshaw
2000-04-01  0:00             ` Andrew Cagney
2000-04-01  0:00           ` J.T. Conklin
2000-04-01  0:00         ` Todd Whitesel
2000-04-01  0:00       ` J.T. Conklin
2000-04-01  0:00     ` A patch for ia32 hardware watchpoint Todd Whitesel
2000-04-01  0:00   ` J.T. Conklin
2000-03-08  2:14 ` Eli Zaretskii
2000-04-01  0:00   ` Eli Zaretskii
2000-03-08  3:32 ` Eli Zaretskii
2000-04-01  0:00   ` Eli Zaretskii
2000-04-01  0:00 ` H . J . Lu
2000-03-13  1:50 breakpoint insert API (was: A patch for ia32 hardware watchpoint.) Stephane.Bihan
2000-03-14 14:47 ` J.T. Conklin
2000-04-01  0:00   ` J.T. Conklin
2000-04-01  0:00 ` Stephane.Bihan
2000-03-15  4:21 Stephane.Bihan
2000-03-15  7:51 ` J.T. Conklin
2000-04-01  0:00   ` J.T. Conklin
2000-04-01  0:00 ` Stephane.Bihan
2000-03-15  9:07 Stephane.Bihan
2000-04-01  0:00 ` Stephane.Bihan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).