]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* i386-tdep.c (regcache_cooked_write_unsigned): Remove define.
authorMark Kettenis <kettenis@gnu.org>
Sun, 16 Mar 2003 17:33:08 +0000 (17:33 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sun, 16 Mar 2003 17:33:08 +0000 (17:33 +0000)
(i386_frame_cache): Cache PC.
(i386_frame_pop, i386_frame_pc_unwind): Remove.
(i386_unwind_pc): New function.
(i386_frame_id_unwind): Initialize cache if necessary.  Remove
related assertion.
(i386_frame_register_unwind): Remove FIXME and related assertion.
Add code that fakes a saved processor state with the direction
flag cleared.  Fix unwinding the stack register.
(struct i386_frame_unwind): Remove i386_frame_pop and
i386_frame_pc_unwind.
(i386_gdbarch_init): Set unwind_pc.

gdb/ChangeLog
gdb/i386-tdep.c

index 17fe75158e5ee7d53cae57a3046cf40c63494837..93bded96c5c807f7c4782ae48f7ef7f5b198ffad 100644 (file)
@@ -1,3 +1,18 @@
+2003-03-16  Mark Kettenis  <kettenis@gnu.org>
+
+       * i386-tdep.c (regcache_cooked_write_unsigned): Remove define.
+       (i386_frame_cache): Cache PC.
+       (i386_frame_pop, i386_frame_pc_unwind): Remove.
+       (i386_unwind_pc): New function.
+       (i386_frame_id_unwind): Initialize cache if necessary.  Remove
+       related assertion.
+       (i386_frame_register_unwind): Remove FIXME and related assertion.
+       Add code that fakes a saved processor state with the direction
+       flag cleared.  Fix unwinding the stack register.
+       (struct i386_frame_unwind): Remove i386_frame_pop and
+       i386_frame_pc_unwind.
+       (i386_gdbarch_init): Set unwind_pc.
+
 2003-03-16  Mark Kettenis  <kettenis@gnu.org>
 
        Merge with mainline.  Tag is kettenis-i386newframe-20030316-mergepoint.
index 3e0314a621f7af6d4c1a8315ec372e24985d1546..9859a7f0918781f78a4240e9c06363c33e04fe42 100644 (file)
@@ -686,8 +686,6 @@ i386_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
 \f
 #include "frame-unwind.h"
 
-#define regcache_cooked_write_unsigned regcache_raw_write_unsigned
-
 #ifdef I386_REGNO_TO_SYMMETRY
 #error "The Sequent Symmetry is no longer supported."
 #endif
@@ -806,67 +804,33 @@ i386_frame_cache (struct frame_info *frame, void **cachep)
        }
     }
 
-  *cachep = cache;
-  return cache;
-}
-
-static void
-i386_frame_pop (struct frame_info *frame, void **cachep,
-               struct regcache *regcache)
-{
-  CORE_ADDR fp = get_frame_base (frame);
-  int regnum;
-  char buf[4];
-  ULONGEST val;
-
-  gdb_assert (get_frame_type (frame) != DUMMY_FRAME);
-
-  for (regnum = 0; regnum < I386_NUM_SAVED_REGISTERS; regnum++)
+  if (cache->saved_regs[PC_REGNUM])
     {
-      frame_unwind_register (frame, regnum, buf);
-      regcache_cooked_write (regcache, regnum, buf);
-    }
-
-  /* Reset the direction flag.  */
-  regcache_cooked_read_unsigned (regcache, PS_REGNUM, &val);
-  val &= ~(1 << 10);
-  regcache_cooked_write_unsigned (regcache, PS_REGNUM, val);
+      char buf[4];
 
-  /* The following sequence restores %ebp, %eip and %esp.  */
-  read_memory (fp, buf, 4);
-  regcache_cooked_write (regcache, FP_REGNUM, buf);
-  read_memory (fp + 4, buf, 4);
-  regcache_cooked_write (regcache, PC_REGNUM, buf);
-  regcache_cooked_write_unsigned (regcache, SP_REGNUM, fp + 8);
+      read_memory (cache->saved_regs[PC_REGNUM], buf, 4);
+      cache->return_pc = extract_address (buf, 4);
+    }
 
-  flush_cached_frames ();
+  *cachep = cache;
+  return cache;
 }
 
 static CORE_ADDR
-i386_frame_pc_unwind (struct frame_info *frame, void **cachep)
+i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  struct i386_frame_cache *cache = i386_frame_cache (frame, cachep);
-
-  gdb_assert (get_frame_type (frame) != DUMMY_FRAME);
-
-  if (cache->return_pc == 0)
-    {
-      char buf[4];
-
-      frame_unwind_register (frame, PC_REGNUM, buf);
-      cache->return_pc = extract_address (buf, 4);
-    }
+  char buf[4];
 
-  return cache->return_pc;
+  frame_unwind_register (next_frame, PC_REGNUM, buf);
+  return extract_address (buf, 4);
 }
 
 static void
 i386_frame_id_unwind (struct frame_info *frame, void **cachep,
                      struct frame_id *id)
 {
-  struct i386_frame_cache *cache = *cachep;
+  struct i386_frame_cache *cache = i386_frame_cache (frame, cachep);
 
-  gdb_assert (cache);
   gdb_assert (get_frame_type (frame) != DUMMY_FRAME);
 
   /* Start with a NULL frame ID.  */
@@ -897,14 +861,49 @@ i386_frame_register_unwind (struct frame_info *frame, void **cachep,
                            enum lval_type *lvalp, CORE_ADDR *addrp,
                            int *realnump, void *valuep)
 {
-  /* FIXME: kettenis/20030302: I don't understand why the cache isn't
-     already initialized.  */
   struct i386_frame_cache *cache = i386_frame_cache (frame, cachep);
 
-  gdb_assert (cache);
   gdb_assert (get_frame_type (frame) != DUMMY_FRAME);
   gdb_assert (regnum >= 0);
 
+  /* The System V ABI says that:
+
+     "The flags register contains the system flags, such as the
+     direction flag and the carry flag.  The direction flag must be
+     set to the forward (that is, zero) direction before entry and
+     upon exit from a function.  Other user flags have no specified
+     role in the standard calling sequence and are not preserved.
+
+     To guarantee the "upon exit" part of that statement we fake a
+     saved flags register that has its direction flag cleared.
+
+     Note that GCC doesn't seem to rely on the fact that the direction
+     flag is cleared after a function return; it always explicitly
+     clears the flag before operations where it matters.
+
+     FIXME: kettenis/20030316: I'm not quite sure whether this is the
+     right thing to do.  The way we fake the flags register here makes
+     it impossible to change it.  */
+
+  if (regnum == PS_REGNUM)
+    {
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+       {
+         ULONGEST val;
+
+         /* Clear the direction flag.  */
+         frame_read_unsigned_register (frame, PS_REGNUM, &val);
+         val &= ~(1 << 10);
+         store_unsigned_integer (valuep, 4, val);
+       }
+
+      return;
+    }
+
   if (regnum == SP_REGNUM && cache->saved_sp)
     {
       *optimizedp = 0;
@@ -914,7 +913,7 @@ i386_frame_register_unwind (struct frame_info *frame, void **cachep,
       if (valuep)
        {
          /* Store the value.  */
-         store_address (valuep, 4, cache->saved_regs[SP_REGNUM]);
+         store_address (valuep, 4, cache->saved_sp);
        }
       return;
     }
@@ -938,8 +937,6 @@ i386_frame_register_unwind (struct frame_info *frame, void **cachep,
 }
 
 static struct frame_unwind i386_frame_unwind = {
-  i386_frame_pop,
-  i386_frame_pc_unwind,
   i386_frame_id_unwind,
   i386_frame_register_unwind
 };
@@ -1705,6 +1702,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_unwind_dummy_id (gdbarch, i386_unwind_dummy_id);
   set_gdbarch_save_dummy_frame_tos (gdbarch, i386_save_dummy_frame_tos);
 
+  set_gdbarch_unwind_pc (gdbarch, i386_unwind_pc);
+
   /* Add the i386 register groups.  */
   i386_add_reggroups (gdbarch);
   set_gdbarch_register_reggroup_p (gdbarch, i386_register_reggroup_p);