diff options
author | Mark Kettenis <kettenis@gnu.org> | 2003-03-16 17:33:08 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2003-03-16 17:33:08 +0000 |
commit | 8d1f4677f6c438bb59d62a3aab04b50489464446 (patch) | |
tree | 7c7ba1e7f59d211de49931f1fa1fc6fe44c3fb93 | |
parent | 71a22da70674c5f17bfd18d860ed3f1c858fbd21 (diff) | |
download | gdb-8d1f4677f6c438bb59d62a3aab04b50489464446.tar.gz |
* 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.
-rw-r--r-- | gdb/ChangeLog | 15 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 107 |
2 files changed, 68 insertions, 54 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 17fe75158e5..93bded96c5c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,20 @@ 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. 2003-03-08 Mark Kettenis <kettenis@gnu.org> diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 3e0314a621f..9859a7f0918 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -686,8 +686,6 @@ i386_push_return_address (CORE_ADDR pc, CORE_ADDR sp) #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); |