public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* Cortex-M CPSR thumb bit fix
@ 2010-07-08 19:26 Jonathan Larmour
  2010-07-08 21:37 ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Larmour @ 2010-07-08 19:26 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1255 bytes --]

I posted a patch in 2008 here:
http://sourceware.org/ml/gdb-patches/2008-10/msg00462.html but
unfortunately it wasn't applied. Without it, GDB cannot debug Cortex-M
processors as the thumb bit is in a different place in the CPSR register.

I have updated it for GDB 7.1, as per the attached mail and updated
ChangeLog below.

I do have a copyright assignment, as well as the ability to commit.

Can someone review please?

Jifl

2010-07-08  Jonathan Larmour <jifl@eCosCentric.com>

	* arm-tdep.h (CPSR_T): define as function-like macro, checking
	for M-profile, which affects T_bit position, e.g. for Cortex-M.
	(struct gdbarch_tdep): add arm_eabi_cpu_arch and
	arm_eabi_cpu_arch_profile members.
	* arm-tdep.c (arm_frame_is_thumb, arm_prologue_prev_register,
	arm_dwarf2_prev_register, displaced_in_arm_mode, bx_write_pc,
	arm_write_pc): Get tdep and use with updated CPSR_T macro.
	(arm_gdbarch_init): If EABI, extract architecture and profile
	attributes and store in tdep.



-- 
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine

[-- Attachment #2: arm.patch --]
[-- Type: text/plain, Size: 7451 bytes --]

--- gdb-7.1.clean/gdb/arm-tdep.c	2010-02-26 20:45:33.000000000 +0000
+++ gdb-7.1/gdb/arm-tdep.c	2010-06-23 04:17:50.000000000 +0100
@@ -256,6 +256,7 @@ static int
 arm_frame_is_thumb (struct frame_info *frame)
 {
   CORE_ADDR cpsr;
+  struct gdbarch_tdep *tdep = gdbarch_tdep(get_frame_arch(frame));
 
   /* Every ARM frame unwinder can unwind the T bit of the CPSR, either
      directly (from a signal frame or dummy frame) or by interpreting
@@ -263,7 +264,7 @@ arm_frame_is_thumb (struct frame_info *f
      trust the unwinders.  */
   cpsr = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
 
-  return (cpsr & CPSR_T) != 0;
+  return (cpsr & CPSR_T(tdep)) != 0;
 }
 
 /* Callback for VEC_lower_bound.  */
@@ -1113,6 +1114,7 @@ arm_prologue_prev_register (struct frame
 			    int prev_regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep(gdbarch);
   struct arm_prologue_cache *cache;
 
   if (*this_cache == NULL)
@@ -1154,9 +1156,9 @@ arm_prologue_prev_register (struct frame
       cpsr = get_frame_register_unsigned (this_frame, prev_regnum);
       lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
       if (IS_THUMB_ADDR (lr))
-	cpsr |= CPSR_T;
+	cpsr |= CPSR_T(tdep);
       else
-	cpsr &= ~CPSR_T;
+	cpsr &= ~CPSR_T(tdep);
       return frame_unwind_got_constant (this_frame, prev_regnum, cpsr);
     }
 
@@ -1283,6 +1285,7 @@ arm_dwarf2_prev_register (struct frame_i
 {
   struct gdbarch * gdbarch = get_frame_arch (this_frame);
   CORE_ADDR lr, cpsr;
+  struct gdbarch_tdep *tdep = gdbarch_tdep(gdbarch);
 
   switch (regnum)
     {
@@ -1300,9 +1303,9 @@ arm_dwarf2_prev_register (struct frame_i
       cpsr = get_frame_register_unsigned (this_frame, regnum);
       lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
       if (IS_THUMB_ADDR (lr))
-	cpsr |= CPSR_T;
+        cpsr |= CPSR_T(tdep);
       else
-	cpsr &= ~CPSR_T;
+        cpsr &= ~CPSR_T(tdep);
       return frame_unwind_got_constant (this_frame, regnum, cpsr);
 
     default:
@@ -3185,11 +3188,12 @@ displaced_read_reg (struct regcache *reg
 static int
 displaced_in_arm_mode (struct regcache *regs)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep(get_regcache_arch(regs));
   ULONGEST ps;
 
   regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &ps);
 
-  return (ps & CPSR_T) == 0;
+  return (ps & CPSR_T(tdep)) == 0;
 }
 
 /* Write to the PC as from a branch instruction.  */
@@ -3210,19 +3214,20 @@ branch_write_pc (struct regcache *regs, 
 static void
 bx_write_pc (struct regcache *regs, ULONGEST val)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep(get_regcache_arch(regs));
   ULONGEST ps;
 
   regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &ps);
 
   if ((val & 1) == 1)
     {
-      regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps | CPSR_T);
+      regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps | CPSR_T(tdep));
       regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val & 0xfffffffe);
     }
   else if ((val & 2) == 0)
     {
       regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM,
-				      ps & ~(ULONGEST) CPSR_T);
+				      ps & ~(ULONGEST) CPSR_T(tdep));
       regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val);
     }
   else
@@ -3231,7 +3236,7 @@ bx_write_pc (struct regcache *regs, ULON
 	  mode, align dest to 4 bytes).  */
       warning (_("Single-stepping BX to non-word-aligned ARM instruction."));
       regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM,
-				      ps & ~(ULONGEST) CPSR_T);
+				      ps & ~(ULONGEST) CPSR_T(tdep));
       regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val & 0xfffffffc);
     }
 }
@@ -5862,6 +5867,8 @@ arm_record_special_symbol (struct gdbarc
 static void
 arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep(get_regcache_arch(regcache));
+
   regcache_cooked_write_unsigned (regcache, ARM_PC_REGNUM, pc);
 
   /* If necessary, set the T bit.  */
@@ -5870,10 +5877,10 @@ arm_write_pc (struct regcache *regcache,
       ULONGEST val;
       regcache_cooked_read_unsigned (regcache, ARM_PS_REGNUM, &val);
       if (arm_pc_is_thumb (pc))
-	regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM, val | CPSR_T);
+        regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM, val | CPSR_T(tdep));
       else
 	regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM,
-					val & ~(ULONGEST) CPSR_T);
+					val & ~(ULONGEST) CPSR_T(tdep));
     }
 }
 
@@ -6058,6 +6065,8 @@ arm_gdbarch_init (struct gdbarch_info in
   int have_vfp_registers = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
   int have_neon = 0;
   int have_fpa_registers = 1;
+  int arm_eabi_cpu_arch = -1;
+  int arm_eabi_cpu_arch_profile = -1;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -6248,6 +6257,7 @@ arm_gdbarch_init (struct gdbarch_info in
 	  else if (ei_osabi == ELFOSABI_NONE)
 	    {
 	      int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
+              int attr;
 
 	      switch (eabi_ver)
 		{
@@ -6305,8 +6315,24 @@ arm_gdbarch_init (struct gdbarch_info in
 		  warning (_("unknown ARM EABI version 0x%x"), eabi_ver);
 		  break;
 		}
-	    }
 
+              /* Cortex-M has different CPSR layout. Use object tags to determine
+               * if this was generated for the Microcontroller (M) profile.
+               * Cortex-A has a CPSR like previous ARM cores.
+               * Cortex-R is unknown.
+               */
+              
+              attr = bfd_elf_get_obj_attr_int(info.abfd, OBJ_ATTR_PROC, Tag_CPU_arch);
+              if (attr > 0)
+                arm_eabi_cpu_arch = attr;
+              if (arm_eabi_cpu_arch >= TAG_CPU_ARCH_V7) /* Profile n/a before V7 */
+                {
+                  attr = bfd_elf_get_obj_attr_int(info.abfd, OBJ_ATTR_PROC, Tag_CPU_arch_profile);
+                  if (attr > 0)
+                      arm_eabi_cpu_arch_profile = attr;
+                }
+              
+	    }
 	  if (fp_model == ARM_FLOAT_AUTO)
 	    {
 	      int e_flags = elf_elfheader (info.abfd)->e_flags;
@@ -6383,6 +6409,8 @@ arm_gdbarch_init (struct gdbarch_info in
   tdep->have_vfp_pseudos = have_vfp_pseudos;
   tdep->have_neon_pseudos = have_neon_pseudos;
   tdep->have_neon = have_neon;
+  tdep->arm_eabi_cpu_arch = arm_eabi_cpu_arch;
+  tdep->arm_eabi_cpu_arch_profile = arm_eabi_cpu_arch_profile;
 
   /* Breakpoints.  */
   switch (info.byte_order_for_code)
--- gdb-7.1.clean/gdb/arm-tdep.h	2010-02-01 16:13:15.000000000 +0000
+++ gdb-7.1/gdb/arm-tdep.h	2010-06-23 03:34:34.000000000 +0100
@@ -105,7 +105,8 @@ enum gdb_regnum {
 #define FLAG_C		0x20000000
 #define FLAG_V		0x10000000
 
-#define CPSR_T		0x20
+/* CPSR T-bit for Architecture v7+ Microcontroller Profile is different from others */
+#define CPSR_T(tdep)	((tdep)->arm_eabi_cpu_arch_profile==(int)'M' ? 0x01000000 : 0x20)
 
 /* Type of floating-point code in use by inferior.  There are really 3 models
    that are traditionally supported (plus the endianness issue), but gcc can
@@ -192,6 +193,9 @@ struct gdbarch_tdep
   struct type *arm_ext_type;
   struct type *neon_double_type;
   struct type *neon_quad_type;
+
+  int arm_eabi_cpu_arch;         /* Arch version from EABI attribute (-1 == unknown) */
+  int arm_eabi_cpu_arch_profile; /* Arch profile from EABI attribute (-1 == unknown) */
 };
 
 /* Structures used for displaced stepping.  */

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

end of thread, other threads:[~2010-07-09  3:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-08 19:26 Cortex-M CPSR thumb bit fix Jonathan Larmour
2010-07-08 21:37 ` Daniel Jacobowitz
2010-07-09  3:43   ` Jonathan Larmour
2010-07-09  3:51     ` Daniel Jacobowitz

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