Based on a patch from Michael Elizabeth Chastain (mec@shout.net):
authorMark Kettenis <kettenis@gnu.org>
Sun, 10 Aug 2003 12:15:16 +0000 (12:15 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sun, 10 Aug 2003 12:15:16 +0000 (12:15 +0000)
* i386-tdep.c (i386_analyze_frame_setup): Recognize more
instructions that GCC likes to mingle into the prologue.  Fixes
gdb/1253 and gdb/1255.

gdb/ChangeLog
gdb/i386-tdep.c

index 59a57390d5a7c0d67fea92e23bca8612851ab834..9ee048b526c3b9e8f4296f70d4d1240ed4d31f69 100644 (file)
@@ -1,3 +1,10 @@
+2003-08-10  Mark Kettenis  <kettenis@gnu.org>
+
+       Based on a patch from Michael Elizabeth Chastain (mec@shout.net):
+       * i386-tdep.c (i386_analyze_frame_setup): Recognize more
+       instructions that GCC likes to mingle into the prologue.  Fixes
+       gdb/1253 and gdb/1255.
+
 2003-08-09  Andrew Cagney  <cagney@redhat.com>
 
        Fix GDB PR cli/926.
index 328dff29f3a8d8f0bcf1e357887128af1751d153..6a54be5478549de2fe30b12d3fc5e1c0879dc294 100644 (file)
@@ -439,6 +439,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
                          struct i386_frame_cache *cache)
 {
   unsigned char op;
+  int skip = 0;
 
   if (current_pc <= pc)
     return current_pc;
@@ -456,25 +457,61 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
       if (current_pc <= pc + 1)
        return current_pc;
 
-      /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
       op = read_memory_unsigned_integer (pc + 1, 1);
+
+      /* Check for some special instructions that might be migrated
+        by GCC into the prologue.  We check for
+
+           xorl %ebx, %ebx
+           xorl %ecx, %ecx
+           xorl %edx, %edx
+
+        and the equivalent
+
+           subl %ebx, %ebx
+           subl %ecx, %ecx
+           subl %edx, %edx
+
+        Make sure we only skip these instructions if we later see the
+        `movl %esp, %ebp' that actually sets up the frame.  */
+      while (op == 0x29 || op == 0x31)
+       {
+         op = read_memory_unsigned_integer (pc + skip + 2, 1);
+         switch (op)
+           {
+           case 0xdb:  /* %ebx */
+           case 0xc9:  /* %ecx */
+           case 0xd2:  /* %edx */
+             skip += 2;
+             break;
+           default:
+             return pc + 1;
+           }
+
+         op = read_memory_unsigned_integer (pc + skip + 1, 1);
+       }
+
+      /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
       switch (op)
        {
        case 0x8b:
-         if (read_memory_unsigned_integer (pc + 2, 1) != 0xec)
+         if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xec)
            return pc + 1;
          break;
        case 0x89:
-         if (read_memory_unsigned_integer (pc + 2, 1) != 0xe5)
+         if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xe5)
            return pc + 1;
          break;
        default:
          return pc + 1;
        }
 
-      /* OK, we actually have a frame.  We just don't know how large it is
-        yet.  Set its size to zero.  We'll adjust it if necessary.  */
+      /* OK, we actually have a frame.  We just don't know how large
+        it is yet.  Set its size to zero.  We'll adjust it if
+        necessary.  We also now commit to skipping the special
+        instructions mentioned before.  */
       cache->locals = 0;
+      pc += skip;
 
       /* If that's all, return now.  */
       if (current_pc <= pc + 3)