Remove arm_insert_single_step_breakpoint
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 01f53d6095ce32c799103887b7bba51bca2853a5..a3bea97b34e98c2d13fdbf556875a0a0afc7f73c 100644 (file)
 
 #include "record.h"
 #include "record-full.h"
+#include <algorithm>
 
-#include "features/arm-with-m.c"
-#include "features/arm-with-m-fpa-layout.c"
-#include "features/arm-with-m-vfp-d16.c"
-#include "features/arm-with-iwmmxt.c"
-#include "features/arm-with-vfpv2.c"
-#include "features/arm-with-vfpv3.c"
-#include "features/arm-with-neon.c"
+#include "features/arm/arm-with-m.c"
+#include "features/arm/arm-with-m-fpa-layout.c"
+#include "features/arm/arm-with-m-vfp-d16.c"
+#include "features/arm/arm-with-iwmmxt.c"
+#include "features/arm/arm-with-vfpv2.c"
+#include "features/arm/arm-with-vfpv3.c"
+#include "features/arm/arm-with-neon.c"
 
 static int arm_debug;
 
@@ -143,13 +144,6 @@ static const char *const arm_mode_strings[] =
 static const char *arm_fallback_mode_string = "auto";
 static const char *arm_force_mode_string = "auto";
 
-/* Internal override of the execution mode.  -1 means no override,
-   0 means override to ARM mode, 1 means override to Thumb mode.
-   The effect is the same as if arm_force_mode has been set by the
-   user (except the internal override has precedence over a user's
-   arm_force_mode override).  */
-static int arm_override_mode = -1;
-
 /* Number of different reg name sets (options).  */
 static int num_disassembly_options;
 
@@ -422,10 +416,6 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
   if (IS_THUMB_ADDR (memaddr))
     return 1;
 
-  /* Respect internal mode override if active.  */
-  if (arm_override_mode != -1)
-    return arm_override_mode;
-
   /* If the user wants to override the symbol table, let him.  */
   if (strcmp (arm_force_mode_string, "arm") == 0)
     return 0;
@@ -464,6 +454,62 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
   return 0;
 }
 
+/* Determine if the address specified equals any of these magic return
+   values, called EXC_RETURN, defined by the ARM v6-M and v7-M
+   architectures.
+
+   From ARMv6-M Reference Manual B1.5.8
+   Table B1-5 Exception return behavior
+
+   EXC_RETURN    Return To        Return Stack
+   0xFFFFFFF1    Handler mode     Main
+   0xFFFFFFF9    Thread mode      Main
+   0xFFFFFFFD    Thread mode      Process
+
+   From ARMv7-M Reference Manual B1.5.8
+   Table B1-8 EXC_RETURN definition of exception return behavior, no FP
+
+   EXC_RETURN    Return To        Return Stack
+   0xFFFFFFF1    Handler mode     Main
+   0xFFFFFFF9    Thread mode      Main
+   0xFFFFFFFD    Thread mode      Process
+
+   Table B1-9 EXC_RETURN definition of exception return behavior, with
+   FP
+
+   EXC_RETURN    Return To        Return Stack    Frame Type
+   0xFFFFFFE1    Handler mode     Main            Extended
+   0xFFFFFFE9    Thread mode      Main            Extended
+   0xFFFFFFED    Thread mode      Process         Extended
+   0xFFFFFFF1    Handler mode     Main            Basic
+   0xFFFFFFF9    Thread mode      Main            Basic
+   0xFFFFFFFD    Thread mode      Process         Basic
+
+   For more details see "B1.5.8 Exception return behavior"
+   in both ARMv6-M and ARMv7-M Architecture Reference Manuals.  */
+
+static int
+arm_m_addr_is_magic (CORE_ADDR addr)
+{
+  switch (addr)
+    {
+      /* Values from Tables in B1.5.8 the EXC_RETURN definitions of
+        the exception return behavior.  */
+      case 0xffffffe1:
+      case 0xffffffe9:
+      case 0xffffffed:
+      case 0xfffffff1:
+      case 0xfffffff9:
+      case 0xfffffffd:
+       /* Address is magic.  */
+       return 1;
+
+      default:
+       /* Address is not magic.  */
+       return 0;
+    }
+}
+
 /* Remove useless bits from addresses in a running program.  */
 static CORE_ADDR
 arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
@@ -471,7 +517,7 @@ arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
   /* On M-profile devices, do not strip the low bit from EXC_RETURN
      (the magic exception return address).  */
   if (gdbarch_tdep (gdbarch)->is_m
-      && (val & 0xfffffff0) == 0xfffffff0)
+      && arm_m_addr_is_magic (val))
     return val;
 
   if (arm_apcs_32)
@@ -1393,7 +1439,7 @@ thumb_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR prev_pc,
        function is.  */
     return;
 
-  prologue_end = min (prologue_end, prev_pc);
+  prologue_end = std::min (prologue_end, prev_pc);
 
   thumb_analyze_prologue (gdbarch, prologue_start, prologue_end, cache);
 }
@@ -2673,7 +2719,6 @@ static struct arm_prologue_cache *
 arm_make_epilogue_frame_cache (struct frame_info *this_frame)
 {
   struct arm_prologue_cache *cache;
-  CORE_ADDR sp;
   int reg;
 
   cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
@@ -2714,7 +2759,7 @@ arm_epilogue_frame_this_id (struct frame_info *this_frame,
      fall back to just using the current PC.  */
   pc = get_frame_pc (this_frame);
   func = get_frame_func (this_frame);
-  if (func == NULL)
+  if (func == 0)
     func = pc;
 
   (*this_id) = frame_id_build (cache->prev_sp, pc);
@@ -2727,11 +2772,8 @@ static struct value *
 arm_epilogue_frame_prev_register (struct frame_info *this_frame,
                                  void **this_cache, int regnum)
 {
-  struct arm_prologue_cache *cache;
-
   if (*this_cache == NULL)
     *this_cache = arm_make_epilogue_frame_cache (this_frame);
-  cache = (struct arm_prologue_cache *) *this_cache;
 
   return arm_prologue_prev_register (this_frame, this_cache, regnum);
 }
@@ -2994,14 +3036,8 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self,
   /* No need to check is_m; this sniffer is only registered for
      M-profile architectures.  */
 
-  /* Exception frames return to one of these magic PCs.  Other values
-     are not defined as of v7-M.  See details in "B1.5.8 Exception
-     return behavior" in "ARMv7-M Architecture Reference Manual".  */
-  if (this_pc == 0xfffffff1 || this_pc == 0xfffffff9
-      || this_pc == 0xfffffffd)
-    return 1;
-
-  return 0;
+  /* Check if exception frame returns to a magic PC value.  */
+  return arm_m_addr_is_magic (this_pc);
 }
 
 /* Frame unwinder for M-profile exceptions.  */
@@ -3558,8 +3594,11 @@ arm_vfp_cprc_sub_candidate (struct type *t,
        int i;
        for (i = 0; i < TYPE_NFIELDS (t); i++)
          {
-           int sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
-                                                       base_type);
+           int sub_count = 0;
+
+           if (!field_is_static (&TYPE_FIELD (t, i)))
+             sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
+                                                     base_type);
            if (sub_count == -1)
              return -1;
            count += sub_count;
@@ -4196,26 +4235,6 @@ convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr,
                               &d, dbl);
 }
 
-/* Like insert_single_step_breakpoint, but make sure we use a breakpoint
-   of the appropriate mode (as encoded in the PC value), even if this
-   differs from what would be expected according to the symbol tables.  */
-
-void
-arm_insert_single_step_breakpoint (struct gdbarch *gdbarch,
-                                  struct address_space *aspace,
-                                  CORE_ADDR pc)
-{
-  struct cleanup *old_chain
-    = make_cleanup_restore_integer (&arm_override_mode);
-
-  arm_override_mode = IS_THUMB_ADDR (pc);
-  pc = gdbarch_addr_bits_remove (gdbarch, pc);
-
-  insert_single_step_breakpoint (gdbarch, aspace, pc);
-
-  do_cleanups (old_chain);
-}
-
 /* Given BUF, which is OLD_LEN bytes ending at ENDADDR, expand
    the buffer to be NEW_LEN bytes ending at ENDADDR.  Return
    NULL if an error occurs.  BUF is freed.  */
@@ -4288,7 +4307,7 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
      footwork to distinguish a real IT instruction from the second
      half of a 32-bit instruction, but there is no need for that if
      there's no candidate.  */
-  buf_len = min (bpaddr - boundary, MAX_IT_BLOCK_PREFIX);
+  buf_len = std::min (bpaddr - boundary, (CORE_ADDR) MAX_IT_BLOCK_PREFIX);
   if (buf_len == 0)
     /* No room for an IT instruction.  */
     return bpaddr;
@@ -6289,7 +6308,10 @@ arm_software_single_step (struct frame_info *frame)
   next_pcs = arm_get_next_pcs (&next_pcs_ctx);
 
   for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
-    arm_insert_single_step_breakpoint (gdbarch, aspace, pc);
+    {
+      pc = gdbarch_addr_bits_remove (gdbarch, pc);
+      insert_single_step_breakpoint (gdbarch, aspace, pc);
+    }
 
   do_cleanups (old_chain);
 
@@ -7796,16 +7818,10 @@ static const gdb_byte arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
 static const gdb_byte arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT;
 static const gdb_byte arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
 
-/* Determine the type and size of breakpoint to insert at PCPTR.  Uses
-   the program counter value to determine whether a 16-bit or 32-bit
-   breakpoint should be used.  It returns a pointer to a string of
-   bytes that encode a breakpoint instruction, stores the length of
-   the string to *lenptr, and adjusts the program counter (if
-   necessary) to point to the actual memory location where the
-   breakpoint should be inserted.  */
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
 
-static const unsigned char *
-arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+static int
+arm_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
@@ -7819,38 +7835,98 @@ arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
       if (tdep->thumb2_breakpoint != NULL)
        {
          gdb_byte buf[2];
+
          if (target_read_memory (*pcptr, buf, 2) == 0)
            {
              unsigned short inst1;
+
              inst1 = extract_unsigned_integer (buf, 2, byte_order_for_code);
              if (thumb_insn_size (inst1) == 4)
-               {
-                 *lenptr = tdep->thumb2_breakpoint_size;
-                 return tdep->thumb2_breakpoint;
-               }
+               return ARM_BP_KIND_THUMB2;
            }
        }
 
-      *lenptr = tdep->thumb_breakpoint_size;
-      return tdep->thumb_breakpoint;
+      return ARM_BP_KIND_THUMB;
     }
   else
+    return ARM_BP_KIND_ARM;
+
+}
+
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
+
+static const gdb_byte *
+arm_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  switch (kind)
     {
-      *lenptr = tdep->arm_breakpoint_size;
+    case ARM_BP_KIND_ARM:
+      *size = tdep->arm_breakpoint_size;
       return tdep->arm_breakpoint;
+    case ARM_BP_KIND_THUMB:
+      *size = tdep->thumb_breakpoint_size;
+      return tdep->thumb_breakpoint;
+    case ARM_BP_KIND_THUMB2:
+      *size = tdep->thumb2_breakpoint_size;
+      return tdep->thumb2_breakpoint;
+    default:
+      gdb_assert_not_reached ("unexpected arm breakpoint kind");
     }
 }
 
-static void
-arm_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-                              int *kindptr)
+/* Implement the breakpoint_kind_from_current_state gdbarch method.  */
+
+static int
+arm_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+                                       struct regcache *regcache,
+                                       CORE_ADDR *pcptr)
 {
-  arm_breakpoint_from_pc (gdbarch, pcptr, kindptr);
+  gdb_byte buf[4];
+
+  /* Check the memory pointed by PC is readable.  */
+  if (target_read_memory (regcache_read_pc (regcache), buf, 4) == 0)
+    {
+      struct arm_get_next_pcs next_pcs_ctx;
+      CORE_ADDR pc;
+      int i;
+      VEC (CORE_ADDR) *next_pcs = NULL;
+      struct cleanup *old_chain
+       = make_cleanup (VEC_cleanup (CORE_ADDR), &next_pcs);
+
+      arm_get_next_pcs_ctor (&next_pcs_ctx,
+                            &arm_get_next_pcs_ops,
+                            gdbarch_byte_order (gdbarch),
+                            gdbarch_byte_order_for_code (gdbarch),
+                            0,
+                            regcache);
 
-  if (arm_pc_is_thumb (gdbarch, *pcptr) && *kindptr == 4)
-    /* The documented magic value for a 32-bit Thumb-2 breakpoint, so
-       that this is not confused with a 32-bit ARM breakpoint.  */
-    *kindptr = 3;
+      next_pcs = arm_get_next_pcs (&next_pcs_ctx);
+
+      /* If MEMADDR is the next instruction of current pc, do the
+        software single step computation, and get the thumb mode by
+        the destination address.  */
+      for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
+       {
+         if (UNMAKE_THUMB_ADDR (pc) == *pcptr)
+           {
+             do_cleanups (old_chain);
+
+             if (IS_THUMB_ADDR (pc))
+               {
+                 *pcptr = MAKE_THUMB_ADDR (*pcptr);
+                 return arm_breakpoint_kind_from_pc (gdbarch, pcptr);
+               }
+             else
+               return ARM_BP_KIND_ARM;
+           }
+       }
+
+      do_cleanups (old_chain);
+    }
+
+  return arm_breakpoint_kind_from_pc (gdbarch, pcptr);
 }
 
 /* Extract from an array REGBUF containing the (raw) register state a
@@ -8542,7 +8618,9 @@ coff_sym_is_thumb (int val)
 static void
 arm_elf_make_msymbol_special(asymbol *sym, struct minimal_symbol *msym)
 {
-  if (ARM_SYM_BRANCH_TYPE (&((elf_symbol_type *)sym)->internal_elf_sym)
+  elf_symbol_type *elfsym = (elf_symbol_type *) sym;
+
+  if (ARM_GET_SYM_BRANCH_TYPE (elfsym->internal_elf_sym.st_target_internal)
       == ST_BRANCH_TO_THUMB)
     MSYMBOL_SET_SPECIAL (msym);
 }
@@ -8864,6 +8942,22 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch)
   /* Otherwise we don't have a useful guess.  */
 }
 
+/* Implement the code_of_frame_writable gdbarch method.  */
+
+static int
+arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame)
+{
+  if (gdbarch_tdep (gdbarch)->is_m
+      && get_frame_type (frame) == SIGTRAMP_FRAME)
+    {
+      /* M-profile exception frames return to some magic PCs, where
+        isn't writable at all.  */
+      return 0;
+    }
+  else
+    return 1;
+}
+
 \f
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
@@ -9314,6 +9408,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, arm_frame_align);
 
+  if (is_m)
+    set_gdbarch_code_of_frame_writable (gdbarch, arm_code_of_frame_writable);
+
   set_gdbarch_write_pc (gdbarch, arm_write_pc);
 
   /* Frame handling.  */
@@ -9339,9 +9436,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   /* Breakpoint manipulation.  */
-  set_gdbarch_breakpoint_from_pc (gdbarch, arm_breakpoint_from_pc);
-  set_gdbarch_remote_breakpoint_from_pc (gdbarch,
-                                        arm_remote_breakpoint_from_pc);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch, arm_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch, arm_sw_breakpoint_from_kind);
+  set_gdbarch_breakpoint_kind_from_current_state (gdbarch,
+                                                 arm_breakpoint_kind_from_current_state);
 
   /* Information about registers, etc.  */
   set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
@@ -10979,7 +11077,6 @@ arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r)
   uint32_t bits_a, bit_c, bit_l, reg_t, reg_v;
   uint32_t record_buf[4];
 
-  const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch);
   reg_t = bits (arm_insn_r->arm_insn, 12, 15);
   reg_v = bits (arm_insn_r->arm_insn, 21, 23);
   bits_a = bits (arm_insn_r->arm_insn, 21, 23);
@@ -11069,7 +11166,6 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r)
   ULONGEST u_regval = 0;
 
   struct regcache *reg_cache = arm_insn_r->regcache;
-  const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch);
 
   opcode = bits (arm_insn_r->arm_insn, 20, 24);
   single_reg = !bit (arm_insn_r->arm_insn, 8);
This page took 0.029658 seconds and 4 git commands to generate.