From: Mark Kettenis Date: Wed, 13 Aug 2003 22:03:21 +0000 (+0000) Subject: Based on a patch from Michael Elizabeth Chastain (mec@shout.net): X-Git-Tag: gdb_6_0-2003-10-04-release~113 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa6c146b3a8b9e95055f72ab5b18ff7c15ecb712;p=thirdparty%2Fbinutils-gdb.git 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0a6279cfc24..64a36406acb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2003-08-10 Mark Kettenis + + 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-13 Jeff Johnston From 2003-07-24 Jeff Johnston diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 1a3d072f740..8017cfcc07a 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -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)