MIPS: Make the extracted stack offset signed in the prologue scanner
authorMaciej W. Rozycki <macro@codesourcery.com>
Fri, 2 Jan 2015 23:36:05 +0000 (23:36 +0000)
committerMaciej W. Rozycki <macro@codesourcery.com>
Fri, 2 Jan 2015 23:54:27 +0000 (23:54 +0000)
Make the extracted stack offset signed in the standard MIPS prologue
scanner, to simplify handling and make sure register offsets are correct
in all cases, especially where $fp equals the virtual frame pointer (old
GCC frames) and therefore offsets to save slots are negative.

* mips-tdep.c (mips32_scan_prologue): Make the extracted stack
offset signed.

gdb/ChangeLog
gdb/mips-tdep.c

index 8b016dc4fac7a44a5035dd53e4fa205661c972ad..1d1e32c65ae4da1ffe0cc3d2f614aae59883074d 100644 (file)
@@ -1,3 +1,8 @@
+2015-01-02  Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * mips-tdep.c (mips32_scan_prologue): Keep the extracted stack
+       offset signed.
+
 2015-01-02  Doug Evans  <dje@google.com>
 
        * dwarf2read.c (setup_type_unit_groups): Remove outdated comment.
index 5cd66a1c2f580f8123337c49fb4476d50036f3d2..bd8faef26bd3f0f0e6a537fd66e96d96a74f3ab4 100644 (file)
@@ -3438,7 +3438,8 @@ restart:
   frame_offset = 0;
   for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE)
     {
-      unsigned long inst, high_word, low_word;
+      unsigned long inst, high_word;
+      long offset;
       int reg;
 
       this_non_prologue_insn = 0;
@@ -3450,15 +3451,15 @@ restart:
 
       /* Save some code by pre-extracting some useful fields.  */
       high_word = (inst >> 16) & 0xffff;
-      low_word = inst & 0xffff;
+      offset = ((inst & 0xffff) ^ 0x8000) - 0x8000;
       reg = high_word & 0x1f;
 
       if (high_word == 0x27bd          /* addiu $sp,$sp,-i */
          || high_word == 0x23bd        /* addi $sp,$sp,-i */
          || high_word == 0x67bd)       /* daddiu $sp,$sp,-i */
        {
-         if (low_word & 0x8000)        /* Negative stack adjustment?  */
-            frame_offset += 0x10000 - low_word;
+         if (offset < 0)               /* Negative stack adjustment?  */
+            frame_offset -= offset;
          else
            /* Exit loop if a positive stack adjustment is found, which
               usually means that the stack cleanup code in the function
@@ -3469,19 +3470,19 @@ restart:
       else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
                && !regsize_is_64_bits)
        {
-         set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+         set_reg_offset (gdbarch, this_cache, reg, sp + offset);
        }
       else if (((high_word & 0xFFE0) == 0xffa0)        /* sd reg,offset($sp) */
                && regsize_is_64_bits)
        {
          /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra.  */
-         set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+         set_reg_offset (gdbarch, this_cache, reg, sp + offset);
        }
       else if (high_word == 0x27be)    /* addiu $30,$sp,size */
        {
          /* Old gcc frame, r30 is virtual frame pointer.  */
-         if ((long) low_word != frame_offset)
-           frame_addr = sp + low_word;
+         if (offset != frame_offset)
+           frame_addr = sp + offset;
          else if (this_frame && frame_reg == MIPS_SP_REGNUM)
            {
              unsigned alloca_adjust;
@@ -3491,7 +3492,7 @@ restart:
                (this_frame, gdbarch_num_regs (gdbarch) + 30);
              frame_offset = 0;
 
-             alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
+             alloca_adjust = (unsigned) (frame_addr - (sp + offset));
              if (alloca_adjust > 0)
                {
                   /* FP > SP + frame_size.  This may be because of
@@ -3540,7 +3541,7 @@ restart:
       else if ((high_word & 0xFFE0) == 0xafc0  /* sw reg,offset($30) */
                && !regsize_is_64_bits)
        {
-         set_reg_offset (gdbarch, this_cache, reg, frame_addr + low_word);
+         set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
        }
       else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
                || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */