aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/gdbserver/ChangeLog6
-rw-r--r--gdb/gdbserver/linux-arm-low.c40
2 files changed, 37 insertions, 9 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 7a7afcc..72d8575 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,9 @@
+2008-06-04 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.
+
2008-05-29 Ulrich Weigand <uweigand@de.ibm.com>
* linux-ppc-low.c (ppc_collect_ptrace_register): Clear buffer.
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index d47ecbc..8aba59e 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -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_breakpoint = 0xe7f001f0;
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 (cpsr & 0x20)
+ {
+ /* Thumb mode. */
+ unsigned short insn;
- /* If necessary, recognize more trap instructions here. GDB only uses the
- two. */
+ (*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