[commit] Improve gdbserver behavior for Thumb

Daniel Jacobowitz drow@false.org
Wed Jun 4 19:55:00 GMT 2008


ARM binaries can have several different breakpoint instructions.
Pre-EABI binaries have one, EABI binaries have another, and Thumb mode
code has a third.

What gdbserver thinks of as a breakpoint is not too important, since
I recently (November 2007) made gdbserver capable of working without
inserting any breakpoints.  That should cover anything on a 2.6
kernel.  This is quite fortunate, as gdbserver does not have any handy
way to decide whether to insert an ARM or Thumb mode breakpoint.

gdbserver still needs to recognize breakpoints inserted by GDB,
though.  So if the T bit is set, this patch makes gdbserver recognize
a Thumb breakpoint at the current PC.  This should improve behavior
for multi-threaded programs in which more than one thread hits a
breakpoint simultaneously.

Tested on arm-linux-gnueabi and committed.

-- 
Daniel Jacobowitz
CodeSourcery

2008-06-03  Daniel Jacobowitz  <dan@codesourcery.com>

	* linux-arm-low.c (thumb_breakpoint, thumb_breakpoint_len): New.
	(arm_breakpoint_at): Handle Thumb.
	(the_low_target): Add comment.

--- src/gdb/gdbserver/linux-arm-low.c	27 Feb 2008 03:27:40 -0000	1.16
+++ src/gdb/gdbserver/linux-arm-low.c	3 Jun 2008 17:39:31 -0000
@@ -136,9 +136,11 @@ arm_set_pc (CORE_ADDR pc)
   supply_register_by_name ("pc", &newpc);
 }
 
-/* Correct in either endianness.  We do not support Thumb yet.  */
+/* Correct in either endianness.  */
 static const unsigned long arm_breakpoint = 0xef9f0001;
 #define arm_breakpoint_len 4
+static const unsigned short thumb_breakpoint = 0xde01;
+#define thumb_breakpoint_len 2
 
 /* For new EABI binaries.  We recognize it regardless of which ABI
    is used for gdbserver, so single threaded debugging should work
@@ -149,17 +151,31 @@ static const unsigned long arm_eabi_brea
 static int
 arm_breakpoint_at (CORE_ADDR where)
 {
-  unsigned long insn;
+  unsigned long cpsr;
 
-  (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
-  if (insn == arm_breakpoint)
-    return 1;
+  collect_register_by_name ("cpsr", &cpsr);
 
-  if (insn == arm_eabi_breakpoint)
-    return 1;
-
-  /* If necessary, recognize more trap instructions here.  GDB only uses the
-     two.  */
+  if (cpsr & 0x20)
+    {
+      /* Thumb mode.  */
+      unsigned short insn;
+
+      (*the_target->read_memory) (where, (unsigned char *) &insn, 2);
+      if (insn == thumb_breakpoint)
+	return 1;
+    }
+  else
+    {
+      /* ARM mode.  */
+      unsigned long insn;
+
+      (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
+      if (insn == arm_breakpoint)
+	return 1;
+
+      if (insn == arm_eabi_breakpoint)
+	return 1;
+    }
 
   return 0;
 }
@@ -216,6 +232,12 @@ struct linux_target_ops the_low_target =
   arm_cannot_store_register,
   arm_get_pc,
   arm_set_pc,
+
+  /* Define an ARM-mode breakpoint; we only set breakpoints in the C
+     library, which is most likely to be ARM.  If the kernel supports
+     clone events, we will never insert a breakpoint, so even a Thumb
+     C library will work; so will mixing EABI/non-EABI gdbserver and
+     application.  */
 #ifndef __ARM_EABI__
   (const unsigned char *) &arm_breakpoint,
 #else



More information about the Gdb-patches mailing list