Don't allow non-stack memory writes in the prologue for nios2.
[deliverable/binutils-gdb.git] / gdb / nios2-tdep.c
index 08f20346e79a79fc3eb376edc89fb2738a17fc13..12056b51a54cdfd0d4f0b785e13567c9109f54e7 100644 (file)
@@ -658,10 +658,10 @@ nios2_in_epilogue_p (struct gdbarch *gdbarch,
   return 0;
 }
 
-/* Implement the in_function_epilogue_p gdbarch method.  */
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
 
 static int
-nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+nios2_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr;
 
@@ -697,22 +697,29 @@ nios2_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
          stw    sp, constant(rx)
          mov    sp, rx
 
-     5) A frame pointer save, which can be either a MOV or ADDI.
+     4) A frame pointer save, which can be either a MOV or ADDI.
 
-     6) A further stack pointer adjustment.  This is normally included
-        adjustment in step 4 unless the total adjustment is too large
+     5) A further stack pointer adjustment.  This is normally included
+        adjustment in step 3 unless the total adjustment is too large
        to be done in one step.
 
      7) A stack overflow check, which can take either of these forms:
          bgeu   sp, rx, +8
-         break  3
+         trap  3
        or
          bltu   sp, rx, .Lstack_overflow
          ...
        .Lstack_overflow:
-         break  3
-        If present, this is inserted after the stack pointer adjustments
-       for steps 3, 4, and 6.
+         trap  3
+         
+       Older versions of GCC emitted "break 3" instead of "trap 3" here,
+       so we check for both cases.
+
+       Older GCC versions emitted stack overflow checks after the SP
+       adjustments in both steps 3 and 4.  Starting with GCC 6, there is
+       at most one overflow check, which is placed before the first
+       stack adjustment for R2 CDX and after the first stack adjustment
+       otherwise.
 
     The prologue instructions may be combined or interleaved with other
     instructions.
@@ -928,9 +935,7 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
          if (orig > 0
              && (value[rb].offset == 0
                  || (orig == NIOS2_EA_REGNUM && value[rb].offset == -4))
-             && ((value[ra].reg == NIOS2_SP_REGNUM
-                  && cache->reg_saved[orig].basereg != NIOS2_SP_REGNUM)
-                 || cache->reg_saved[orig].basereg == -1))
+             && value[ra].reg == NIOS2_SP_REGNUM)
            {
              if (pc < current_pc)
                {
@@ -995,14 +1000,15 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
          else if (cond == branch_geu)
            {
              /* BGEU sp, rx, +8
-                BREAK 3
+                TRAP 3  (or BREAK 3)
                 This instruction sequence is used in stack checking;
                 we can ignore it.  */
              unsigned int next_insn;
              const struct nios2_opcode *next_op
                = nios2_fetch_insn (gdbarch, pc, &next_insn);
              if (next_op != NULL
-                 && nios2_match_break (next_insn, op, mach, &uimm))
+                 && (nios2_match_trap (next_insn, op, mach, &uimm)
+                     || nios2_match_break (next_insn, op, mach, &uimm)))
                pc += next_op->size;
              else
                break;
@@ -1010,13 +1016,14 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
          else if (cond == branch_ltu)
            {
              /* BLTU sp, rx, .Lstackoverflow
-                If the location branched to holds a BREAK 3 instruction
-                then this is also stack overflow detection.  */
+                If the location branched to holds a TRAP or BREAK
+                instruction then this is also stack overflow detection.  */
              unsigned int next_insn;
              const struct nios2_opcode *next_op
                = nios2_fetch_insn (gdbarch, pc + imm, &next_insn);
              if (next_op != NULL
-                 && nios2_match_break (next_insn, op, mach, &uimm))
+                 && (nios2_match_trap (next_insn, op, mach, &uimm)
+                     || nios2_match_break (next_insn, op, mach, &uimm)))
                ;
              else
                break;
@@ -1025,11 +1032,13 @@ nios2_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
            break;
        }
 
-      /* All other calls or jumps (including returns) terminate 
+      /* All other calls, jumps, returns, TRAPs, or BREAKs terminate
         the prologue.  */
       else if (nios2_match_callr (insn, op, mach, &ra)
               || nios2_match_jmpr (insn, op, mach, &ra)
-              || nios2_match_jmpi (insn, op, mach, &uimm))
+              || nios2_match_jmpi (insn, op, mach, &uimm)
+              || nios2_match_trap (insn, op, mach, &uimm)
+              || nios2_match_break (insn, op, mach, &uimm))
        break;
     }
 
@@ -1189,7 +1198,15 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   return nios2_analyze_prologue (gdbarch, start_pc, start_pc, &cache, NULL);
 }
 
-/* Implement the breakpoint_from_pc gdbarch hook.  */
+/* Implement the breakpoint_from_pc gdbarch hook.
+
+   The Nios II ABI for Linux says: "Userspace programs should not use
+   the break instruction and userspace debuggers should not insert
+   one." and "Userspace breakpoints are accomplished using the trap
+   instruction with immediate operand 31 (all ones)."
+
+   So, we use "trap 31" consistently as the breakpoint on bare-metal
+   as well as Linux targets.  */
 
 static const gdb_byte*
 nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
@@ -1198,11 +1215,11 @@ nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
 
-  /* R1 break encoding:
-     ((0x1e << 17) | (0x34 << 11) | (0x1f << 6) | (0x3a << 0))
-     0x003da7fa */
-  static const gdb_byte r1_breakpoint_le[] = {0xfa, 0xa7, 0x3d, 0x0};
-  static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3d, 0xa7, 0xfa};
+  /* R1 trap encoding:
+     ((0x1d << 17) | (0x2d << 11) | (0x1f << 6) | (0x3a << 0))
+     0x003b6ffa */
+  static const gdb_byte r1_breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
+  static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
   *bp_size = NIOS2_OPCODE_SIZE;
   if (byte_order_for_code == BFD_ENDIAN_BIG)
     return r1_breakpoint_be;
@@ -1767,7 +1784,7 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_return_value (gdbarch, nios2_return_value);
 
   set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
-  set_gdbarch_in_function_epilogue_p (gdbarch, nios2_in_function_epilogue_p);
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, nios2_stack_frame_destroyed_p);
   set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
 
   set_gdbarch_dummy_id (gdbarch, nios2_dummy_id);
This page took 0.026208 seconds and 4 git commands to generate.