This is the mail archive of the gdb-patches@sourceware.org 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]

[rfa] Use a different breakpoint instruction for EABI GNU/Linux


Patches have been posted recently for the Linux kernel to use a different
interface for system calls, in which r7 holds the syscall number instead of
embedding it in the SWI.  With old-ABI compatibility mode disabled, the
kernel never looks in the SWI at all.  Which means that using a SWI
to set a breakpoint doesn't work very well.

Since 2003 the kernel has supported these particular undefined instructions
(in the reserved space) as breakpoints.  So if we see an EABI binary, assume
we have a recent vintage of kernel, and use them.

Tested on arm-none-linux-gnueabi.  OK for HEAD and 6.4?

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-11-11  Daniel Jacobowitz  <dan@codesourcery.com>

	* arm-linux-tdep.c (eabi_linux_arm_le_breakpoint)
	(eabi_linux_arm_be_breakpoint): New variables.
	(arm_linux_init_abi): Use them.

2005-11-11  Daniel Jacobowitz  <dan@codesourcery.com>

	* linux-arm-low.c (arm_eabi_breakpoint): New variable.
	(arm_breakpoint_at): Recognize both breakpoints.
	(the_low_target): Use the correct breakpoint instruction.

Index: src/gdb/arm-linux-tdep.c
===================================================================
--- src.orig/gdb/arm-linux-tdep.c	2005-09-01 08:51:23.000000000 -0400
+++ src/gdb/arm-linux-tdep.c	2005-11-08 17:54:18.000000000 -0500
@@ -45,6 +45,19 @@ static const char arm_linux_arm_le_break
 
 static const char arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 };
 
+/* However, the EABI syscall interface (new in Nov. 2005) does not look at
+   the operand of the swi if old-ABI compatibility is disabled.  Therefore,
+   use an undefined instruction instead.  This is supported as of kernel
+   version 2.5.70 (May 2003), so should be a safe assumption for EABI
+   binaries.  */
+
+static const char eabi_linux_arm_le_breakpoint[] = { 0xf0, 0x01, 0xf0, 0xe7 };
+
+static const char eabi_linux_arm_be_breakpoint[] = { 0xe7, 0xf0, 0x01, 0xf0 };
+
+/* All the kernels which support Thumb support using a specific undefined
+   instruction for the Thumb breakpoint.  */
+
 static const char arm_linux_thumb_be_breakpoint[] = {0xde, 0x01};
 
 static const char arm_linux_thumb_le_breakpoint[] = {0x01, 0xde};
@@ -329,12 +342,18 @@ arm_linux_init_abi (struct gdbarch_info 
   tdep->lowest_pc = 0x8000;
   if (info.byte_order == BFD_ENDIAN_BIG)
     {
-      tdep->arm_breakpoint = arm_linux_arm_be_breakpoint;
+      if (tdep->arm_abi == ARM_ABI_AAPCS)
+	tdep->arm_breakpoint = eabi_linux_arm_be_breakpoint;
+      else
+	tdep->arm_breakpoint = arm_linux_arm_be_breakpoint;
       tdep->thumb_breakpoint = arm_linux_thumb_be_breakpoint;
     }
   else
     {
-      tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
+      if (tdep->arm_abi == ARM_ABI_AAPCS)
+	tdep->arm_breakpoint = eabi_linux_arm_le_breakpoint;
+      else
+	tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
       tdep->thumb_breakpoint = arm_linux_thumb_le_breakpoint;
     }
   tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
Index: src/gdb/gdbserver/linux-arm-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-arm-low.c	2005-06-12 21:59:22.000000000 -0400
+++ src/gdb/gdbserver/linux-arm-low.c	2005-11-08 17:54:24.000000000 -0500
@@ -70,6 +70,12 @@ arm_set_pc (CORE_ADDR pc)
 static const unsigned long arm_breakpoint = 0xef9f0001;
 #define arm_breakpoint_len 4
 
+/* For new EABI binaries.  We recognize it regardless of which ABI
+   is used for gdbserver, so single threaded debugging should work
+   OK, but for multi-threaded debugging we only insert the current
+   ABI's breakpoint instruction.  For now at least.  */
+static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
+
 static int
 arm_breakpoint_at (CORE_ADDR where)
 {
@@ -79,8 +85,12 @@ arm_breakpoint_at (CORE_ADDR where)
   if (insn == arm_breakpoint)
     return 1;
 
+  if (insn == arm_eabi_breakpoint)
+    return 1;
+
   /* If necessary, recognize more trap instructions here.  GDB only uses the
-     one.  */
+     two.  */
+
   return 0;
 }
 
@@ -102,7 +112,11 @@ struct linux_target_ops the_low_target =
   arm_cannot_store_register,
   arm_get_pc,
   arm_set_pc,
+#ifndef __ARM_EABI__
   (const unsigned char *) &arm_breakpoint,
+#else
+  (const unsigned char *) &arm_eabi_breakpoint,
+#endif
   arm_breakpoint_len,
   arm_reinsert_addr,
   0,


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