This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: gdb, insight, and tcltk


Charles Wilson wrote:
> (patch vs. "regular" gdb-6.8 attached).

Oops.

diff -urN old/insight-6.8/gdb/i386-tdep.c new/insight-6.8/gdb/i386-tdep.c
--- old/insight-6.8/gdb/i386-tdep.c	2008-03-04 14:49:39.000000000 -0500
+++ new/insight-6.8/gdb/i386-tdep.c	2008-03-22 18:24:36.000000000 -0400
@@ -296,6 +296,24 @@
    registers mentioned above, and %eip.  */
 #define I386_NUM_SAVED_REGS	I386_NUM_GREGS
 
+/* The standard stack frame according to the System V ABI:
+
+      Position  |         Contents         |   Frame
+     -----------+--------------------------+-----------
+     4n+8(%ebp) |      argument word n     |
+                |      ...                 |  Previous
+     8(%ebp)    |      argument word 0     |
+     -----------+--------------------------+-----------
+     4(%ebp)    |      return address      |
+                +--------------------------+
+     0(%ebp)    | previous %ebp (optional) |
+                +--------------------------+  Current
+    -4(%ebp)    |       unspecified        |
+                |           ...            |
+     0(%esp)    |      variable size       |
+     -----------+--------------------------+-----------
+*/
+
 struct i386_frame_cache
 {
   /* Base address.  */
@@ -305,8 +323,17 @@
 
   /* Saved registers.  */
   CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
-  CORE_ADDR saved_sp;
+
+  /* The value of %esp in the calling frame.  */
+  CORE_ADDR prev_frame_sp;
+
+  /* Non-zero if this frame has enforced stack alignment.  */
   int stack_align;
+
+  /* If STACK_ALIGN, which register holds %esp of the calling frame,
+     else undefined.  */
+  int saved_sp_regnum;
+
   int pc_in_eax;
 
   /* Stack space reserved for local variables.  */
@@ -332,7 +359,7 @@
      offset (that's where %ebp is supposed to be stored).  */
   for (i = 0; i < I386_NUM_SAVED_REGS; i++)
     cache->saved_regs[i] = -1;
-  cache->saved_sp = 0;
+  cache->prev_frame_sp = 0;
   cache->stack_align = 0;
   cache->pc_in_eax = 0;
 
@@ -515,15 +542,25 @@
     0xff, 0x70, 0xfc		/* pushl -4(%eax) */
   };
   gdb_byte buf[10];
+  int regnum;
 
-  if (target_read_memory (pc, buf, sizeof buf)
-      || (memcmp (buf, insns_ecx, sizeof buf) != 0
-          && memcmp (buf, insns_edx, sizeof buf) != 0
-          && memcmp (buf, insns_eax, sizeof buf) != 0))
+  if (target_read_memory (pc, buf, sizeof buf))
+    return pc;
+
+  if (memcmp (buf, insns_ecx, sizeof buf) == 0)
+    regnum = I386_ECX_REGNUM;
+  else if (memcmp (buf, insns_edx, sizeof buf) == 0)
+    regnum = I386_EDX_REGNUM;
+  else if (memcmp (buf, insns_eax, sizeof buf) == 0)
+    regnum = I386_EAX_REGNUM;
+  else
     return pc;
 
   if (current_pc > pc + 4)
-    cache->stack_align = 1;
+    {
+      cache->stack_align = 1;
+      cache->saved_sp_regnum = regnum;
+    }
 
   return min (pc + 10, current_pc);
 }
@@ -577,6 +614,36 @@
   return NULL;
 }
 
+/* Check whether PC points at code that saves registers on the stack.
+   If so, it updates CACHE and returns the address of the first
+   instruction after the register saves or CURRENT_PC, whichever is
+   smaller.  Otherwise, return PC.  */
+
+static CORE_ADDR
+i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
+			     struct i386_frame_cache *cache)
+{
+  CORE_ADDR offset = 0;
+  gdb_byte op;
+  int i;
+
+  if (cache->locals > 0)
+    offset -= cache->locals;
+  for (i = 0; i < 8 && pc < current_pc; i++)
+    {
+      read_memory_nobpt (pc, &op, 1);
+      if (op < 0x50 || op > 0x57)
+	break;
+
+      offset -= 4;
+      cache->saved_regs[op - 0x50] = offset;
+      cache->sp_offset += 4;
+      pc++;
+    }
+
+  return pc;
+}
+
 /* Some special instructions that might be migrated by GCC into the
    part of the prologue that sets up the new stack frame.  Because the
    stack frame hasn't been setup yet, no registers have been saved
@@ -756,7 +823,11 @@
       if (limit <= pc)
 	return limit;
 
-      /* Check for stack adjustment 
+      /* There may be registers saves before the stack is grown for
+	 locals.  */
+      pc = i386_analyze_register_saves (pc, limit, cache);
+
+      /* Check for stack adjustment
 
 	    subl $XXX, %esp
 
@@ -801,36 +872,6 @@
   return pc;
 }
 
-/* Check whether PC points at code that saves registers on the stack.
-   If so, it updates CACHE and returns the address of the first
-   instruction after the register saves or CURRENT_PC, whichever is
-   smaller.  Otherwise, return PC.  */
-
-static CORE_ADDR
-i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
-			     struct i386_frame_cache *cache)
-{
-  CORE_ADDR offset = 0;
-  gdb_byte op;
-  int i;
-
-  if (cache->locals > 0)
-    offset -= cache->locals;
-  for (i = 0; i < 8 && pc < current_pc; i++)
-    {
-      read_memory_nobpt (pc, &op, 1);
-      if (op < 0x50 || op > 0x57)
-	break;
-
-      offset -= 4;
-      cache->saved_regs[op - 0x50] = offset;
-      cache->sp_offset += 4;
-      pc++;
-    }
-
-  return pc;
-}
-
 /* Do a full analysis of the prologue at PC and update CACHE
    accordingly.  Bail out early if CURRENT_PC is reached.  Return the
    address where the analysis stopped.
@@ -854,7 +895,7 @@
    %ebx (and sometimes a harmless bug causes it to also save but not
    restore %eax); however, the code below is willing to see the pushes
    in any order, and will handle up to 8 of them.
- 
+
    If the setup sequence is at the end of the function, then the next
    instruction will be a branch back to the start.  */
 
@@ -969,6 +1010,7 @@
   struct i386_frame_cache *cache;
   gdb_byte buf[4];
   int i;
+  CORE_ADDR saved_sp = 0;
 
   if (*this_cache)
     return *this_cache;
@@ -999,9 +1041,23 @@
 
   if (cache->stack_align)
     {
-      /* Saved stack pointer has been saved in %ecx.  */
-      frame_unwind_register (next_frame, I386_ECX_REGNUM, buf);
-      cache->saved_sp = extract_unsigned_integer(buf, 4);
+      /* The previous frame stack pointer has been saved in %ecx, %edx
+	 or %eax at the beginning of the frame setup.  Since the
+	 storing register may have been clobbered by the time we're
+	 analyzing this frame, we prefer reading it from the stack if
+	 we've seen it being pushed.  */
+      if (cache->saved_regs[cache->saved_sp_regnum] != -1)
+	{
+	  /* We can only see it being pushed if we found a valid
+	     frame, so we can safely access cache->base here.  */
+	  CORE_ADDR reg
+	    = cache->base + cache->saved_regs[cache->saved_sp_regnum];
+	  read_memory (reg, buf, 4);
+	}
+      else
+	frame_unwind_register (next_frame, cache->saved_sp_regnum, buf);
+
+      saved_sp = extract_unsigned_integer (buf, 4);
     }
 
   if (cache->locals < 0)
@@ -1017,8 +1073,8 @@
       if (cache->stack_align)
 	{
 	  /* We're halfway aligning the stack.  */
-	  cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
-	  cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
+	  cache->base = ((saved_sp - 4) & 0xfffffff0) - 4;
+	  cache->saved_regs[I386_EIP_REGNUM] = saved_sp - 4;
 
 	  /* This will be added back below.  */
 	  cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
@@ -1032,8 +1088,11 @@
 
   /* Now that we have the base address for the stack frame we can
      calculate the value of %esp in the calling frame.  */
-  if (cache->saved_sp == 0)
-    cache->saved_sp = cache->base + 8;
+
+  if (cache->stack_align)
+    cache->prev_frame_sp = saved_sp;
+  else
+    cache->prev_frame_sp = cache->base + 8;
 
   /* Adjust all the saved registers such that they contain addresses
      instead of offsets.  */
@@ -1118,7 +1177,7 @@
       return;
     }
 
-  if (regnum == I386_ESP_REGNUM && cache->saved_sp)
+  if (regnum == I386_ESP_REGNUM && cache->prev_frame_sp)
     {
       *optimizedp = 0;
       *lvalp = not_lval;
@@ -1127,7 +1186,7 @@
       if (valuep)
 	{
 	  /* Store the value.  */
-	  store_unsigned_integer (valuep, 4, cache->saved_sp);
+	  store_unsigned_integer (valuep, 4, cache->prev_frame_sp);
 	}
       return;
     }
@@ -1277,12 +1336,28 @@
   return cache->base;
 }
 
+static CORE_ADDR
+i386_frame_args_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
+
+  if (cache->stack_align)
+    /* For `main', the values of LOC_ARG variables are offsets
+       relative to the arglist address, while for other functions the
+       offsets are relative to the frame base.  */
+    return cache->prev_frame_sp;
+
+  /* Arguments are found at 8(%ebp), but STABS parameter values are
+     offsets from %ebp.  */
+  return cache->base;
+}
+
 static const struct frame_base i386_frame_base =
 {
   &i386_frame_unwind,
-  i386_frame_base_address,
-  i386_frame_base_address,
-  i386_frame_base_address
+  i386_frame_base_address, /* base */
+  i386_frame_base_address, /* locals */
+  i386_frame_args_address  /* args */
 };
 
 static struct frame_id
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]