OSDN Git Service

* i386-tdep.h (i386bsd_sigcontext_addr): Remove prototype.
authorkettenis <kettenis>
Fri, 30 May 2003 19:24:28 +0000 (19:24 +0000)
committerkettenis <kettenis>
Fri, 30 May 2003 19:24:28 +0000 (19:24 +0000)
(I386_SIZEOF_GREGS, I386_SIZEOF_FREGS, I386_SIZEOF_XREGS): Remove
defenitions.
(IS_FP_REGNUM, IS_SSE_REGNUM): Remove definitions.
* i386-tdep.c: Mark functions that are 64-bit safe as such.
(I386_EAX_REGNUM, I386_EDX_REGNUM, I386_ESP_REGNUM,
I386_EBP_REGNUM, I386_EIP_REGNUM, I386_EFLAGS_REGNUM,
I386_ST0_REGNUM): New defines.
(CODESTREAM_BUFSIZ, codestream_tell, codestream_peek,
codestream_get): Remove define.
(codestream_next_addr, condestream_addr, condestream_buf,
codestream_off, codestream_cnt): Remove variables.
(codestream_fill, codestream_seek, codestream_read): Remove
functions.
(i386_follow_jump): Rewrite to avoid usage of removed codestream
functionality.
(i386_get_frame_setup, i386_frameless_signal_p, i386_frame_chain,
i386_sigtramp_saved_pc, i386_sigtramp_saved_sp,
i386_frame_saved_pc, i386_saved_pc_after_call,
i386_frame_num_args, i386_frame_init_saved_regs,
i386_push_return_address, i386_do_pop_frame, i386_pop_frame,
i386_push_arguments): Remove functions.
(i386_skip_prologue): Rewrite to avoid usage of removed codestream
functionality.  Use i386_analyze_prologue instead of
i386_get_frame_setup.
(I386_NUM_SAVED_REGS): New define.
(struct i386_frame_cache): New structure.
(i386_alloc_frame_cache, i386_analyze_struct_return,
i386_skip_probe, i386_analyze_frame_setup,
i386_analyze_register_saves, i386_analyze_prologue,
i386_unwind_pc, i386_frame_cache, i386_frame_this_id,
i386_frame_prev_register, i386_sigtramp_frame_cache,
i386_sigtramp_frame_this_id, i386_sigtramp_frame_prev_register,
i386_frame_p, i386_sigtramp_frame_p, i386_frame_base_address,
i386_unwind_dummy_id, i386_save_dummy_tos, i386_push_dummy_call):
New functions.
(i386_frame_unwind, i386_sigtramp_frame_unwind, i386_frame_base):
New variables.
(LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM): Define in terms of
I386_EAX_REGNUM and I386_EDX_REGNUM.
(i386_extract_return_value, i386_store_return_value): Use
I386_ST0_REGNUM where appropriate.
(i386_extract_struct_value_address): Rewrite to use extract_address.
(i386_svr4_pc_in_sigtramp): Add comment.
(i386_svr4_sigcontext_addr): Rewrite.
(i386_svr4_init_abi): Adjust TDEP->sc_pc_offset and
TDEP->sc_sp_offset.
(i386_gdbarch_init): Don't set deprecated_init_frame_pc.  Set
sp_regnum, fp_regnum, pc_regnum, ps_regnum and fp0_regnum in terms
of new defines.  Set push_dummy_call, don't set
deprecated_push_arguments, deprecated_push_return_address,
deprecated_pop_frame.  Don't set parm_boundary.  Don't set
deprecated_frame_chain, deprecated_frame_saved_pc,
deprecated_saved_pc_after_call.  Set unwind_dummy_id,
save_dummy_frame_tos, unwind_pc.  Call
frame_unwind_append_predicate and frame_base_set_default.  Don't
set deprecated_dummy_write_pc.  Don't set deprecated_fp_regnum.
Don't set frameless_function_invocation.  Don't set
deprecated_register_bytes, deprecated_register_size,
deprecated_call_dummy_words and deprecated_sizeof_call_dummy.
* i386-linux-tdep.c: Fix formatting in some comments.
(LINUX_SIGTRAMP_INSN0, LINUX_SIGTRAMP_OFFSET0,
LINUX_SIGTRAMP_INSN1, LINUX_SIGTRAMP_OFFSET1,
LINUX_SIGTRAMP_INSN2, LINUX_SIGTRAMP_OFFSET2,
LINUX_RT_SIGTRAMP_INSN0, LINUX_RT_SIGTRAMP_OFFSET0,
LINUX_RT_SIGTRAMP_INSN1, LINUX_RT_SIGTRAMP_OFFSET1): Drop
redundant parentheses.
(I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET): New define.
(i386_linux_sigcontext_addr): Use it.  Rewrite.
(find_minsym_and_objfile): Change name of second argument.
(skip_gnu_resolver): Renamed from skip_hurd_resolver.  All callers
changed.  Use frame_pc_unwind instead of
DEPRECATED_SAVED_PC_AFTER_CALL.
(i386_linux_init_abi): Don't set deprecated_register_bytes.
* i386bsd-tdep.c (i386bsd_sigcontext_addr): Rewrite.
* i386-nto-tdep.c (i386nto_sigcontext_addr): Adapt for new frame
unwinder.
* i386-cygwin-tdep.c: Don't include "gdbcore.h", "frame.h" and
"dummy-frame.h".
(i386_cygwin_frame_chain_valid, i386_cygwin_frame_chain): Removed.
(_initialize_i386_cygwin_tdep): New prototype.
(i386_cygwin_init_abi): Don't set deprecated_frame_chain and
deprecated_frame_chain_valid.
* i386-sol2-tdep.c (i386_sol2_init_abi): Don't set
TDEP->sigcontext_addr, TDEP->sc_pc_offset and TDEP->sc_sp_offset.
Rely on the SVR4 defaults.
* config/i386/i386sol2.mt (TDEPFILES): Remove i386bsd-tdep.o.
* Makefile.in (i386-tdep.o, i386-cygwin-tdep.o): Update dependencies.

gdb/ChangeLog
gdb/Makefile.in
gdb/config/i386/i386sol2.mt
gdb/i386-cygwin-tdep.c
gdb/i386-linux-tdep.c
gdb/i386-nto-tdep.c
gdb/i386-sol2-tdep.c
gdb/i386-tdep.c
gdb/i386-tdep.h
gdb/i386bsd-tdep.c

index 02a4b2d..b31281d 100644 (file)
@@ -1,3 +1,94 @@
+2003-05-30  Mark Kettenis  <kettenis@gnu.org>
+
+       * i386-tdep.h (i386bsd_sigcontext_addr): Remove prototype.
+       (I386_SIZEOF_GREGS, I386_SIZEOF_FREGS, I386_SIZEOF_XREGS): Remove
+       defenitions.
+       (IS_FP_REGNUM, IS_SSE_REGNUM): Remove definitions.
+       * i386-tdep.c: Mark functions that are 64-bit safe as such.
+       (I386_EAX_REGNUM, I386_EDX_REGNUM, I386_ESP_REGNUM,
+       I386_EBP_REGNUM, I386_EIP_REGNUM, I386_EFLAGS_REGNUM,
+       I386_ST0_REGNUM): New defines.
+       (CODESTREAM_BUFSIZ, codestream_tell, codestream_peek,
+       codestream_get): Remove define.
+       (codestream_next_addr, condestream_addr, condestream_buf,
+       codestream_off, codestream_cnt): Remove variables.
+       (codestream_fill, codestream_seek, codestream_read): Remove
+       functions.
+       (i386_follow_jump): Rewrite to avoid usage of removed codestream
+       functionality.
+       (i386_get_frame_setup, i386_frameless_signal_p, i386_frame_chain,
+       i386_sigtramp_saved_pc, i386_sigtramp_saved_sp,
+       i386_frame_saved_pc, i386_saved_pc_after_call,
+       i386_frame_num_args, i386_frame_init_saved_regs,
+       i386_push_return_address, i386_do_pop_frame, i386_pop_frame,
+       i386_push_arguments): Remove functions.
+       (i386_skip_prologue): Rewrite to avoid usage of removed codestream
+       functionality.  Use i386_analyze_prologue instead of
+       i386_get_frame_setup.
+       (I386_NUM_SAVED_REGS): New define.
+       (struct i386_frame_cache): New structure.
+       (i386_alloc_frame_cache, i386_analyze_struct_return,
+       i386_skip_probe, i386_analyze_frame_setup,
+       i386_analyze_register_saves, i386_analyze_prologue,
+       i386_unwind_pc, i386_frame_cache, i386_frame_this_id,
+       i386_frame_prev_register, i386_sigtramp_frame_cache,
+       i386_sigtramp_frame_this_id, i386_sigtramp_frame_prev_register,
+       i386_frame_p, i386_sigtramp_frame_p, i386_frame_base_address,
+       i386_unwind_dummy_id, i386_save_dummy_tos, i386_push_dummy_call):
+       New functions.
+       (i386_frame_unwind, i386_sigtramp_frame_unwind, i386_frame_base):
+       New variables.
+       (LOW_RETURN_REGNUM, HIGH_RETURN_REGNUM): Define in terms of
+       I386_EAX_REGNUM and I386_EDX_REGNUM.
+       (i386_extract_return_value, i386_store_return_value): Use
+       I386_ST0_REGNUM where appropriate.
+       (i386_extract_struct_value_address): Rewrite to use extract_address.
+       (i386_svr4_pc_in_sigtramp): Add comment.
+       (i386_svr4_sigcontext_addr): Rewrite.
+       (i386_svr4_init_abi): Adjust TDEP->sc_pc_offset and
+       TDEP->sc_sp_offset.
+       (i386_gdbarch_init): Don't set deprecated_init_frame_pc.  Set
+       sp_regnum, fp_regnum, pc_regnum, ps_regnum and fp0_regnum in terms
+       of new defines.  Set push_dummy_call, don't set
+       deprecated_push_arguments, deprecated_push_return_address,
+       deprecated_pop_frame.  Don't set parm_boundary.  Don't set
+       deprecated_frame_chain, deprecated_frame_saved_pc,
+       deprecated_saved_pc_after_call.  Set unwind_dummy_id,
+       save_dummy_frame_tos, unwind_pc.  Call
+       frame_unwind_append_predicate and frame_base_set_default.  Don't
+       set deprecated_dummy_write_pc.  Don't set deprecated_fp_regnum.
+       Don't set frameless_function_invocation.  Don't set
+       deprecated_register_bytes, deprecated_register_size,
+       deprecated_call_dummy_words and deprecated_sizeof_call_dummy.
+       * i386-linux-tdep.c: Fix formatting in some comments.
+       (LINUX_SIGTRAMP_INSN0, LINUX_SIGTRAMP_OFFSET0,
+       LINUX_SIGTRAMP_INSN1, LINUX_SIGTRAMP_OFFSET1,
+       LINUX_SIGTRAMP_INSN2, LINUX_SIGTRAMP_OFFSET2,
+       LINUX_RT_SIGTRAMP_INSN0, LINUX_RT_SIGTRAMP_OFFSET0,
+       LINUX_RT_SIGTRAMP_INSN1, LINUX_RT_SIGTRAMP_OFFSET1): Drop
+       redundant parentheses.
+       (I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET): New define.
+       (i386_linux_sigcontext_addr): Use it.  Rewrite.
+       (find_minsym_and_objfile): Change name of second argument.
+       (skip_gnu_resolver): Renamed from skip_hurd_resolver.  All callers
+       changed.  Use frame_pc_unwind instead of
+       DEPRECATED_SAVED_PC_AFTER_CALL.
+       (i386_linux_init_abi): Don't set deprecated_register_bytes.
+       * i386bsd-tdep.c (i386bsd_sigcontext_addr): Rewrite.
+       * i386-nto-tdep.c (i386nto_sigcontext_addr): Adapt for new frame
+       unwinder.
+       * i386-cygwin-tdep.c: Don't include "gdbcore.h", "frame.h" and
+       "dummy-frame.h".
+       (i386_cygwin_frame_chain_valid, i386_cygwin_frame_chain): Removed.
+       (_initialize_i386_cygwin_tdep): New prototype.
+       (i386_cygwin_init_abi): Don't set deprecated_frame_chain and
+       deprecated_frame_chain_valid.
+       * i386-sol2-tdep.c (i386_sol2_init_abi): Don't set
+       TDEP->sigcontext_addr, TDEP->sc_pc_offset and TDEP->sc_sp_offset.
+       Rely on the SVR4 defaults.
+       * config/i386/i386sol2.mt (TDEPFILES): Remove i386bsd-tdep.o.
+       * Makefile.in (i386-tdep.o, i386-cygwin-tdep.o): Update dependencies.
+
 2003-05-30  Andrew Cagney  <cagney@redhat.com>
 
        * infcall.c (call_function_by_hand): Always call
index c52eadc..35125d9 100644 (file)
@@ -1792,11 +1792,12 @@ i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h)
 i386-sol2-tdep.o: i386-sol2-tdep.c $(defs_h) $(value_h) $(i386_tdep_h) \
        $(osabi_h)
 i386-stub.o: i386-stub.c
-i386-tdep.o: i386-tdep.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \
-       $(gdbcore_h) $(objfiles_h) $(target_h) $(floatformat_h) $(symfile_h) \
-       $(symtab_h) $(gdbcmd_h) $(command_h) $(arch_utils_h) $(regcache_h) \
-       $(doublest_h) $(value_h) $(gdb_assert_h) $(i386_tdep_h) \
-       $(i387_tdep_h) $(osabi_h)
+i386-tdep.o: i386-tdep.c $(defs_h) $(arch_utils_h) $(command_h) \
+       $(dummy_frame_h) $(doublest_h) $(floatformat_h) $(frame_h) \
+       $(frame_base_h) $(frame_unwind_h) $(inferior_h) $(gdbcmd_h) \
+       $(gdbcore_h) $(objfiles_h) $(osabi_h) $(regcache_h) $(reggroups_h) \
+       $(symfile_h) $(symtab_h) $(target_h) $(value_h) $(gdb_assert_h) \
+       $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h)
 i386b-nat.o: i386b-nat.c $(defs_h)
 i386bsd-nat.o: i386bsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
        $(gdb_assert_h) $(gregset_h) $(i386_tdep_h) $(i387_tdep_h) \
@@ -1811,7 +1812,7 @@ i386gnu-tdep.o: i386gnu-tdep.c $(defs_h) $(i386_tdep_h) $(osabi_h)
 i386ly-tdep.o: i386ly-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
        $(regcache_h) $(target_h) $(i386_tdep_h) $(osabi_h)
 i386-cygwin-tdep.o: i386-cygwin-tdep.c $(defs_h) $(gdb_string_h) \
-       $(i386_tdep_h) $(osabi_h) $(gdbcore_h) $(frame_h) $(dummy_frame_h)
+       $(i386_tdep_h) $(osabi_h)
 i386nbsd-tdep.o: i386nbsd-tdep.c $(defs_h) $(gdbtypes_h) $(gdbcore_h) \
        $(regcache_h) $(arch_utils_h) $(i386_tdep_h) $(i387_tdep_h) \
        $(nbsd_tdep_h) $(solib_svr4_h) $(osabi_h)
index f8fabd4..93c2d78 100644 (file)
@@ -1,3 +1,3 @@
 # Target: Intel 386 running Solaris 2 (SVR4)
-TDEPFILES= i386-tdep.o i387-tdep.o i386-sol2-tdep.o i386bsd-tdep.o
+TDEPFILES= i386-tdep.o i387-tdep.o i386-sol2-tdep.o
 TM_FILE= tm-i386sol2.h
index 5911ec9..443f8f7 100644 (file)
@@ -1,56 +1,30 @@
 /* Target-dependent code for Cygwin running on i386's, for GDB.
+
    Copyright 2003 Free Software Foundation, Inc.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-
-#include "gdb_string.h"
-#include "gdbcore.h"
-#include "i386-tdep.h"
 #include "osabi.h"
-#include "frame.h"
-#include "dummy-frame.h"
-
-static int
-i386_cygwin_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
-  /* In the context where this is used, we get the saved PC before we've
-     successfully unwound far enough to be sure what we've got (it may
-     be a signal handler caller).  If we're dealing with a signal
-     handler caller, this will return valid, which is fine.  If not,
-     it'll make the correct test.  */
-  return ((get_frame_type (thisframe) == SIGTRAMP_FRAME) || chain != 0);
-}
-/* Return the chain-pointer for FRAME.  In the case of the i386, the
-   frame's nominal address is the address of a 4-byte word containing
-   the calling frame's address.  */
-static CORE_ADDR
-i386_cygwin_frame_chain (struct frame_info *frame)
-{
-  if (pc_in_dummy_frame (get_frame_pc (frame)))
-    return get_frame_base (frame);
 
-  if (get_frame_type (frame) == SIGTRAMP_FRAME
-      || i386_frameless_signal_p (frame))
-    return get_frame_base (frame);
+#include "gdb_string.h"
 
-  return read_memory_unsigned_integer (get_frame_base (frame), 4);
-}
+#include "i386-tdep.h"
 
 static void
 i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -58,8 +32,6 @@ i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   tdep->struct_return = reg_struct_return;
-  set_gdbarch_deprecated_frame_chain (gdbarch, i386_cygwin_frame_chain);
-  set_gdbarch_deprecated_frame_chain_valid (gdbarch, i386_cygwin_frame_chain_valid);
 }
 
 static enum gdb_osabi
@@ -75,6 +47,9 @@ i386_cygwin_osabi_sniffer (bfd * abfd)
   return GDB_OSABI_UNKNOWN;
 }
 
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_i386_cygwin_tdep (void);
+
 void
 _initialize_i386_cygwin_tdep (void)
 {
index afff548..e666610 100644 (file)
@@ -81,7 +81,7 @@ i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 
    The instruction sequence for normal signals is
        pop    %eax
-       mov    $0x77,%eax
+       mov    $0x77, %eax
        int    $0x80
    or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
 
@@ -103,17 +103,17 @@ i386_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
    to the ones used by the kernel.  Therefore, these trampolines are
    supported too.  */
 
-#define LINUX_SIGTRAMP_INSN0 (0x58)    /* pop %eax */
-#define LINUX_SIGTRAMP_OFFSET0 (0)
-#define LINUX_SIGTRAMP_INSN1 (0xb8)    /* mov $NNNN,%eax */
-#define LINUX_SIGTRAMP_OFFSET1 (1)
-#define LINUX_SIGTRAMP_INSN2 (0xcd)    /* int */
-#define LINUX_SIGTRAMP_OFFSET2 (6)
+#define LINUX_SIGTRAMP_INSN0   0x58    /* pop %eax */
+#define LINUX_SIGTRAMP_OFFSET0 0
+#define LINUX_SIGTRAMP_INSN1   0xb8    /* mov $NNNN, %eax */
+#define LINUX_SIGTRAMP_OFFSET1 1
+#define LINUX_SIGTRAMP_INSN2   0xcd    /* int */
+#define LINUX_SIGTRAMP_OFFSET2 6
 
 static const unsigned char linux_sigtramp_code[] =
 {
   LINUX_SIGTRAMP_INSN0,                                        /* pop %eax */
-  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,                /* mov $0x77,%eax */
+  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,                /* mov $0x77, %eax */
   LINUX_SIGTRAMP_INSN2, 0x80                           /* int $0x80 */
 };
 
@@ -167,20 +167,20 @@ i386_linux_sigtramp_start (CORE_ADDR pc)
 
 /* This function does the same for RT signals.  Here the instruction
    sequence is
-       mov    $0xad,%eax
+       mov    $0xad, %eax
        int    $0x80
    or 0xb8 0xad 0x00 0x00 0x00 0xcd 0x80.
 
    The effect is to call the system call rt_sigreturn.  */
 
-#define LINUX_RT_SIGTRAMP_INSN0 (0xb8) /* mov $NNNN,%eax */
-#define LINUX_RT_SIGTRAMP_OFFSET0 (0)
-#define LINUX_RT_SIGTRAMP_INSN1 (0xcd) /* int */
-#define LINUX_RT_SIGTRAMP_OFFSET1 (5)
+#define LINUX_RT_SIGTRAMP_INSN0                0xb8 /* mov $NNNN, %eax */
+#define LINUX_RT_SIGTRAMP_OFFSET0      0
+#define LINUX_RT_SIGTRAMP_INSN1                0xcd /* int */
+#define LINUX_RT_SIGTRAMP_OFFSET1      5
 
 static const unsigned char linux_rt_sigtramp_code[] =
 {
-  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,     /* mov $0xad,%eax */
+  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,     /* mov $0xad, %eax */
   LINUX_RT_SIGTRAMP_INSN1, 0x80                                /* int $0x80 */
 };
 
@@ -239,50 +239,47 @@ i386_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
          || strcmp ("__restore_rt", name) == 0);
 }
 
-/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
-   address of the associated sigcontext structure.  */
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
+#define I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 20
+
+/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
+   routine, return the address of the associated sigcontext structure.  */
 
 static CORE_ADDR
-i386_linux_sigcontext_addr (struct frame_info *frame)
+i386_linux_sigcontext_addr (struct frame_info *next_frame)
 {
   CORE_ADDR pc;
+  CORE_ADDR sp;
+  char buf[4];
+
+  frame_unwind_register (next_frame, SP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4);
 
-  pc = i386_linux_sigtramp_start (get_frame_pc (frame));
+  pc = i386_linux_sigtramp_start (frame_pc_unwind (next_frame));
   if (pc)
     {
-      CORE_ADDR sp;
-
-      if (get_next_frame (frame))
-       /* If this isn't the top frame, the next frame must be for the
-          signal handler itself.  The sigcontext structure lives on
-          the stack, right after the signum argument.  */
-       return get_frame_base (get_next_frame (frame)) + 12;
-
-      /* This is the top frame.  We'll have to find the address of the
-        sigcontext structure by looking at the stack pointer.  Keep
-        in mind that the first instruction of the sigtramp code is
-        "pop %eax".  If the PC is at this instruction, adjust the
-        returned value accordingly.  */
-      sp = read_register (SP_REGNUM);
-      if (pc == get_frame_pc (frame))
+      /* The sigcontext structure lives on the stack, right after
+        the signum argument.  We determine the address of the
+        sigcontext structure by looking at the frame's stack
+        pointer.  Keep in mind that the first instruction of the
+        sigtramp code is "pop %eax".  If the PC is after this
+        instruction, adjust the returned value accordingly.  */
+      if (pc == frame_pc_unwind (next_frame))
        return sp + 4;
       return sp;
     }
 
-  pc = i386_linux_rt_sigtramp_start (get_frame_pc (frame));
+  pc = i386_linux_rt_sigtramp_start (frame_pc_unwind (next_frame));
   if (pc)
     {
-      if (get_next_frame (frame))
-       /* If this isn't the top frame, the next frame must be for the
-          signal handler itself.  The sigcontext structure is part of
-          the user context.  A pointer to the user context is passed
-          as the third argument to the signal handler.  */
-       return read_memory_integer (get_frame_base (get_next_frame (frame))
-                                   + 16, 4) + 20;
-
-      /* This is the top frame.  Again, use the stack pointer to find
-        the address of the sigcontext structure.  */
-      return read_memory_integer (read_register (SP_REGNUM) + 8, 4) + 20;
+      CORE_ADDR ucontext_addr;
+
+      /* The sigcontext structure is part of the user context.  A
+        pointer to the user context is passed as the third argument
+        to the signal handler.  */
+      read_memory (sp + 8, buf, 4);
+      ucontext_addr = extract_unsigned_integer (buf, 4) + 20;
+      return ucontext_addr + I386_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
     }
 
   error ("Couldn't recognize signal trampoline.");
@@ -322,7 +319,7 @@ i386_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
    be considered too special-purpose for general consumption.  */
 
 static struct minimal_symbol *
-find_minsym_and_objfile (char *name, struct objfile **objfile_p)
+find_minsym_and_objfile (char *name, struct objfile **objfilep)
 {
   struct objfile *objfile;
 
@@ -335,7 +332,7 @@ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
          if (SYMBOL_LINKAGE_NAME (msym)
              && strcmp (SYMBOL_LINKAGE_NAME (msym), name) == 0)
            {
-             *objfile_p = objfile;
+             *objfilep = objfile;
              return msym;
            }
        }
@@ -345,9 +342,9 @@ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
 }
 
 static CORE_ADDR
-skip_hurd_resolver (CORE_ADDR pc)
+skip_gnu_resolver (CORE_ADDR pc)
 {
-  /* The HURD dynamic linker is part of the GNU C library, so many
+  /* The GNU dynamic linker is part of the GNU C library, so many
      GNU/Linux distributions use it.  (All ELF versions, as far as I
      know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
      which calls "fixup" to patch the PLT, and then passes control to
@@ -374,7 +371,7 @@ skip_hurd_resolver (CORE_ADDR pc)
        = lookup_minimal_symbol ("fixup", NULL, objfile);
 
       if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
-       return (DEPRECATED_SAVED_PC_AFTER_CALL (get_current_frame ()));
+       return frame_pc_unwind (get_current_frame ()); 
     }
 
   return 0;
@@ -393,7 +390,7 @@ i386_linux_skip_solib_resolver (CORE_ADDR pc)
   CORE_ADDR result;
 
   /* Plug in functions for other kinds of resolvers here.  */
-  result = skip_hurd_resolver (pc);
+  result = skip_gnu_resolver (pc);
   if (result)
     return result;
 
@@ -461,7 +458,6 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS + 1);
   set_gdbarch_register_name (gdbarch, i386_linux_register_name);
   set_gdbarch_register_reggroup_p (gdbarch, i386_linux_register_reggroup_p);
-  set_gdbarch_deprecated_register_bytes (gdbarch, I386_SSE_SIZEOF_REGS + 4);
 
   tdep->jb_pc_offset = 20;     /* From <bits/setjmp.h>.  */
 
index b35dd2a..381119f 100644 (file)
@@ -231,14 +231,20 @@ i386nto_pc_in_sigtramp (CORE_ADDR pc, char *name)
   return name && strcmp ("__signalstub", name) == 0;
 }
 
-#define SIGCONTEXT_OFFSET 136
+#define I386_NTO_SIGCONTEXT_OFFSET 136
+
+/* Assuming NEXT_FRAME is a frame following a QNX Neutrino sigtramp
+   routine, return the address of the associated sigcontext structure.  */
+
 static CORE_ADDR
-i386nto_sigcontext_addr (struct frame_info *frame)
+i386nto_sigcontext_addr (struct frame_info *next_frame)
 {
-  if (get_next_frame (frame))
-    return get_frame_base (get_next_frame (frame)) + SIGCONTEXT_OFFSET;
+  char buf[4];
+
+  frame_unwind_register (next_frame, SP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4);
 
-  return read_register (SP_REGNUM) + SIGCONTEXT_OFFSET;
+  return sp + I386_NTO_SIGCONTEXT_OFFSET;
 }
 
 static void
index a52b188..78487af 100644 (file)
@@ -42,12 +42,8 @@ i386_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Solaris is SVR4-based.  */
   i386_svr4_init_abi (info, gdbarch);
 
-  /* Signal trampolines are different from SVR4, in fact they're
-     rather similar to BSD.  */
+  /* Signal trampolines are slightly different from SVR4.  */
   set_gdbarch_pc_in_sigtramp (gdbarch, i386_sol2_pc_in_sigtramp);
-  tdep->sigcontext_addr = i386bsd_sigcontext_addr;
-  tdep->sc_pc_offset = 36 + 14 * 4;
-  tdep->sc_sp_offset = 36 + 17 * 4;
 }
 \f
 
index 0428c13..6641516 100644 (file)
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include "gdb_string.h"
+#include "arch-utils.h"
+#include "command.h"
+#include "dummy-frame.h"
+#include "doublest.h"
+#include "floatformat.h"
 #include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
 #include "inferior.h"
+#include "gdbcmd.h"
 #include "gdbcore.h"
 #include "objfiles.h"
-#include "target.h"
-#include "floatformat.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "reggroups.h"
 #include "symfile.h"
 #include "symtab.h"
-#include "gdbcmd.h"
-#include "command.h"
-#include "arch-utils.h"
-#include "regcache.h"
-#include "doublest.h"
+#include "target.h"
 #include "value.h"
+
 #include "gdb_assert.h"
-#include "reggroups.h"
-#include "dummy-frame.h"
-#include "osabi.h"
+#include "gdb_string.h"
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
+/* Register numbers of various important registers.  */
+
+#define I386_EAX_REGNUM                0 /* %eax */
+#define I386_EDX_REGNUM                2 /* %edx */
+#define I386_ESP_REGNUM                4 /* %esp */
+#define I386_EBP_REGNUM                5 /* %ebp */
+#define I386_EIP_REGNUM                8 /* %eip */
+#define I386_EFLAGS_REGNUM     9 /* %eflags */
+#define I386_ST0_REGNUM                16 /* %st(0) */
+
 /* Names of the registers.  The first 10 registers match the register
    numbering scheme used by GCC for stabs and DWARF.  */
 
@@ -140,7 +153,7 @@ i386_stab_reg_to_regnum (int reg)
   /* This implements what GCC calls the "default" register map.  */
   if (reg >= 0 && reg <= 7)
     {
-      /* General registers.  */
+      /* General-purpose registers.  */
       return reg;
     }
   else if (reg >= 12 && reg <= 19)
@@ -173,7 +186,7 @@ i386_dwarf_reg_to_regnum (int reg)
      numbers the floating point registers differently.  */
   if (reg >= 0 && reg <= 9)
     {
-      /* General registers.  */
+      /* General-purpose registers.  */
       return reg;
     }
   else if (reg >= 11 && reg <= 18)
@@ -203,412 +216,359 @@ static const char *valid_flavors[] =
   NULL
 };
 static const char *disassembly_flavor = att_flavor;
+\f
 
-/* Stdio style buffering was used to minimize calls to ptrace, but
-   this buffering did not take into account that the code section
-   being accessed may not be an even number of buffers long (even if
-   the buffer is only sizeof(int) long).  In cases where the code
-   section size happened to be a non-integral number of buffers long,
-   attempting to read the last buffer would fail.  Simply using
-   target_read_memory and ignoring errors, rather than read_memory, is
-   not the correct solution, since legitimate access errors would then
-   be totally ignored.  To properly handle this situation and continue
-   to use buffering would require that this code be able to determine
-   the minimum code section size granularity (not the alignment of the
-   section itself, since the actual failing case that pointed out this
-   problem had a section alignment of 4 but was not a multiple of 4
-   bytes long), on a target by target basis, and then adjust it's
-   buffer size accordingly.  This is messy, but potentially feasible.
-   It probably needs the bfd library's help and support.  For now, the
-   buffer size is set to 1.  (FIXME -fnf) */
-
-#define CODESTREAM_BUFSIZ 1    /* Was sizeof(int), see note above.  */
-static CORE_ADDR codestream_next_addr;
-static CORE_ADDR codestream_addr;
-static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
-static int codestream_off;
-static int codestream_cnt;
-
-#define codestream_tell() (codestream_addr + codestream_off)
-#define codestream_peek() \
-  (codestream_cnt == 0 ? \
-   codestream_fill(1) : codestream_buf[codestream_off])
-#define codestream_get() \
-  (codestream_cnt-- == 0 ? \
-   codestream_fill(0) : codestream_buf[codestream_off++])
-
-static unsigned char
-codestream_fill (int peek_flag)
-{
-  codestream_addr = codestream_next_addr;
-  codestream_next_addr += CODESTREAM_BUFSIZ;
-  codestream_off = 0;
-  codestream_cnt = CODESTREAM_BUFSIZ;
-  read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
-
-  if (peek_flag)
-    return (codestream_peek ());
-  else
-    return (codestream_get ());
-}
+/* Use the program counter to determine the contents and size of a
+   breakpoint instruction.  Return a pointer to a string of bytes that
+   encode a breakpoint instruction, store the length of the string in
+   *LEN and optionally adjust *PC to point to the correct memory
+   location for inserting the breakpoint.
 
-static void
-codestream_seek (CORE_ADDR place)
-{
-  codestream_next_addr = place / CODESTREAM_BUFSIZ;
-  codestream_next_addr *= CODESTREAM_BUFSIZ;
-  codestream_cnt = 0;
-  codestream_fill (1);
-  while (codestream_tell () != place)
-    codestream_get ();
-}
+   On the i386 we have a single breakpoint that fits in a single byte
+   and can be inserted anywhere.
 
-static void
-codestream_read (unsigned char *buf, int count)
+   This function is 64-bit safe.  */
+   
+static const unsigned char *
+i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
 {
-  unsigned char *p;
-  int i;
-  p = buf;
-  for (i = 0; i < count; i++)
-    *p++ = codestream_get ();
+  static unsigned char break_insn[] = { 0xcc };        /* int 3 */
+  
+  *len = sizeof (break_insn);
+  return break_insn;
 }
 \f
+#ifdef I386_REGNO_TO_SYMMETRY
+#error "The Sequent Symmetry is no longer supported."
+#endif
 
-/* If the next instruction is a jump, move to its target.  */
+/* According to the System V ABI, the registers %ebp, %ebx, %edi, %esi
+   and %esp "belong" to the calling function.  Therefore these
+   registers should be saved if they're going to be modified.  */
 
-static void
-i386_follow_jump (void)
+/* The maximum number of saved registers.  This should include all
+   registers mentioned above, and %eip.  */
+#define I386_NUM_SAVED_REGS    9
+
+struct i386_frame_cache
 {
-  unsigned char buf[4];
-  long delta;
+  /* Base address.  */
+  CORE_ADDR base;
+  CORE_ADDR sp_offset;
+  CORE_ADDR pc;
+
+  /* Saved registers.  */
+  CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
+  CORE_ADDR saved_sp;
+  int pc_in_eax;
+
+  /* Stack space reserved for local variables.  */
+  long locals;
+};
+
+/* Allocate and initialize a frame cache.  */
+
+static struct i386_frame_cache *
+i386_alloc_frame_cache (void)
+{
+  struct i386_frame_cache *cache;
+  int i;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache);
+
+  /* Base address.  */
+  cache->base = 0;
+  cache->sp_offset = -4;
+  cache->pc = 0;
+
+  /* Saved registers.  We initialize these to -1 since zero is a valid
+     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->pc_in_eax = 0;
+
+  /* Frameless until proven otherwise.  */
+  cache->locals = -1;
+
+  return cache;
+}
 
-  int data16;
-  CORE_ADDR pos;
+/* If the instruction at PC is a jump, return the address of its
+   target.  Otherwise, return PC.  */
 
-  pos = codestream_tell ();
+static CORE_ADDR
+i386_follow_jump (CORE_ADDR pc)
+{
+  unsigned char op;
+  long delta = 0;
+  int data16 = 0;
 
-  data16 = 0;
-  if (codestream_peek () == 0x66)
+  op = read_memory_unsigned_integer (pc, 1);
+  if (op == 0x66)
     {
-      codestream_get ();
       data16 = 1;
+      op = read_memory_unsigned_integer (pc + 1, 1);
     }
 
-  switch (codestream_get ())
+  switch (op)
     {
     case 0xe9:
       /* Relative jump: if data16 == 0, disp32, else disp16.  */
       if (data16)
        {
-         codestream_read (buf, 2);
-         delta = extract_signed_integer (buf, 2);
+         delta = read_memory_integer (pc + 2, 2);
 
          /* Include the size of the jmp instruction (including the
              0x66 prefix).  */
-         pos += delta + 4;
+         delta += 4;
        }
       else
        {
-         codestream_read (buf, 4);
-         delta = extract_signed_integer (buf, 4);
+         delta = read_memory_integer (pc + 1, 4);
 
-         pos += delta + 5;
+         /* Include the size of the jmp instruction.  */
+         delta += 5;
        }
       break;
     case 0xeb:
       /* Relative jump, disp8 (ignore data16).  */
-      codestream_read (buf, 1);
-      /* Sign-extend it.  */
-      delta = extract_signed_integer (buf, 1);
+      delta = read_memory_integer (pc + data16 + 1, 1);
 
-      pos += delta + 2;
+      delta += data16 + 2;
       break;
     }
-  codestream_seek (pos);
-}
 
-/* Find & return the amount a local space allocated, and advance the
-   codestream to the first register push (if any).
+  return pc + delta;
+}
 
-   If the entry sequence doesn't make sense, return -1, and leave
-   codestream pointer at a random spot.  */
+/* Check whether PC points at a prologue for a function returning a
+   structure or union.  If so, it updates CACHE and returns the
+   address of the first instruction after the code sequence that
+   removes the "hidden" argument from the stack or CURRENT_PC,
+   whichever is smaller.  Otherwise, return PC.  */
 
-static long
-i386_get_frame_setup (CORE_ADDR pc)
+static CORE_ADDR
+i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
+                           struct i386_frame_cache *cache)
 {
+  /* Functions that return a structure or union start with:
+
+        popl %eax             0x58
+        xchgl %eax, (%esp)    0x87 0x04 0x24
+     or xchgl %eax, 0(%esp)   0x87 0x44 0x24 0x00
+
+     (the System V compiler puts out the second `xchg' instruction,
+     and the assembler doesn't try to optimize it, so the 'sib' form
+     gets generated).  This sequence is used to get the address of the
+     return buffer for a function that returns a structure.  */
+  static unsigned char proto1[3] = { 0x87, 0x04, 0x24 };
+  static unsigned char proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
+  unsigned char buf[4];
   unsigned char op;
 
-  codestream_seek (pc);
+  if (current_pc <= pc)
+    return pc;
+
+  op = read_memory_unsigned_integer (pc, 1);
 
-  i386_follow_jump ();
+  if (op != 0x58)              /* popl %eax */
+    return pc;
 
-  op = codestream_get ();
+  read_memory (pc + 1, buf, 4);
+  if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
+    return pc;
 
-  if (op == 0x58)              /* popl %eax */
+  if (current_pc == pc)
     {
-      /* This function must start with
-
-           popl %eax             0x58
-            xchgl %eax, (%esp)    0x87 0x04 0x24
-         or xchgl %eax, 0(%esp)   0x87 0x44 0x24 0x00
-
-        (the System V compiler puts out the second `xchg'
-        instruction, and the assembler doesn't try to optimize it, so
-        the 'sib' form gets generated).  This sequence is used to get
-        the address of the return buffer for a function that returns
-        a structure.  */
-      int pos;
-      unsigned char buf[4];
-      static unsigned char proto1[3] = { 0x87, 0x04, 0x24 };
-      static unsigned char proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
-
-      pos = codestream_tell ();
-      codestream_read (buf, 4);
-      if (memcmp (buf, proto1, 3) == 0)
-       pos += 3;
-      else if (memcmp (buf, proto2, 4) == 0)
-       pos += 4;
-
-      codestream_seek (pos);
-      op = codestream_get ();  /* Update next opcode.  */
+      cache->sp_offset += 4;
+      return current_pc;
     }
 
-  if (op == 0x68 || op == 0x6a)
+  if (current_pc == pc + 1)
     {
-      /* This function may start with
+      cache->pc_in_eax = 1;
+      return current_pc;
+    }
+  
+  if (buf[1] == proto1[1])
+    return pc + 4;
+  else
+    return pc + 5;
+}
+
+static CORE_ADDR
+i386_skip_probe (CORE_ADDR pc)
+{
+  /* A function may start with
 
-            pushl constant
-            call _probe
-           addl $4, %esp
+        pushl constant
+        call _probe
+       addl $4, %esp
           
-        followed by
+     followed by
+
+        pushl %ebp
 
-            pushl %ebp
+     etc.  */
+  unsigned char buf[8];
+  unsigned char op;
 
-        etc.  */
-      int pos;
-      unsigned char buf[8];
+  op = read_memory_unsigned_integer (pc, 1);
+
+  if (op == 0x68 || op == 0x6a)
+    {
+      int delta;
 
-      /* Skip past the `pushl' instruction; it has either a one-byte 
-         or a four-byte operand, depending on the opcode.  */
-      pos = codestream_tell ();
+      /* Skip past the `pushl' instruction; it has either a one-byte or a
+        four-byte operand, depending on the opcode.  */
       if (op == 0x68)
-       pos += 4;
+       delta = 5;
       else
-       pos += 1;
-      codestream_seek (pos);
+       delta = 2;
 
-      /* Read the following 8 bytes, which should be "call _probe" (6
-         bytes) followed by "addl $4,%esp" (2 bytes).  */
-      codestream_read (buf, sizeof (buf));
+      /* Read the following 8 bytes, which should be `call _probe' (6
+        bytes) followed by `addl $4,%esp' (2 bytes).  */
+      read_memory (pc + delta, buf, sizeof (buf));
       if (buf[0] == 0xe8 && buf[6] == 0xc4 && buf[7] == 0x4)
-       pos += sizeof (buf);
-      codestream_seek (pos);
-      op = codestream_get ();  /* Update next opcode.  */
+       pc += delta + sizeof (buf);
     }
 
+  return pc;
+}
+
+/* Check whether PC points at a code that sets up a new stack frame.
+   If so, it updates CACHE and returns the address of the first
+   instruction after the sequence that sets removes the "hidden"
+   argument from the stack or CURRENT_PC, whichever is smaller.
+   Otherwise, return PC.  */
+
+static CORE_ADDR
+i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
+                         struct i386_frame_cache *cache)
+{
+  unsigned char op;
+
+  if (current_pc <= pc)
+    return current_pc;
+
+  op = read_memory_unsigned_integer (pc, 1);
+
   if (op == 0x55)              /* pushl %ebp */
     {
-      /* Check for "movl %esp, %ebp" -- can be written in two ways.  */
-      switch (codestream_get ())
+      /* Take into account that we've executed the `pushl %ebp' that
+        starts this instruction sequence.  */
+      cache->saved_regs[I386_EBP_REGNUM] = 0;
+      cache->sp_offset += 4;
+
+      /* If that's all, return now.  */
+      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);
+      switch (op)
        {
        case 0x8b:
-         if (codestream_get () != 0xec)
-           return -1;
+         if (read_memory_unsigned_integer (pc + 2, 1) != 0xec)
+           return pc + 1;
          break;
        case 0x89:
-         if (codestream_get () != 0xe5)
-           return -1;
+         if (read_memory_unsigned_integer (pc + 2, 1) != 0xe5)
+           return pc + 1;
          break;
        default:
-         return -1;
+         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.  */
+      cache->locals = 0;
+
+      /* If that's all, return now.  */
+      if (current_pc <= pc + 3)
+       return current_pc;
+
       /* Check for stack adjustment 
 
-           subl $XXX, %esp
+           subl $XXX, %esp
 
         NOTE: You can't subtract a 16 bit immediate from a 32 bit
         reg, so we don't have to worry about a data16 prefix.  */
-      op = codestream_peek ();
+      op = read_memory_unsigned_integer (pc + 3, 1);
       if (op == 0x83)
        {
          /* `subl' with 8 bit immediate.  */
-         codestream_get ();
-         if (codestream_get () != 0xec)
+         if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
            /* Some instruction starting with 0x83 other than `subl'.  */
-           {
-             codestream_seek (codestream_tell () - 2);
-             return 0;
-           }
-         /* `subl' with signed byte immediate (though it wouldn't
-            make sense to be negative).  */
-         return (codestream_get ());
+           return pc + 3;
+
+         /* `subl' with signed byte immediate (though it wouldn't make
+            sense to be negative).  */
+         cache->locals = read_memory_integer (pc + 5, 1);
+         return pc + 6;
        }
       else if (op == 0x81)
        {
-         char buf[4];
          /* Maybe it is `subl' with a 32 bit immedediate.  */
-         codestream_get ();
-         if (codestream_get () != 0xec)
+         if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
            /* Some instruction starting with 0x81 other than `subl'.  */
-           {
-             codestream_seek (codestream_tell () - 2);
-             return 0;
-           }
+           return pc + 3;
+
          /* It is `subl' with a 32 bit immediate.  */
-         codestream_read ((unsigned char *) buf, 4);
-         return extract_signed_integer (buf, 4);
+         cache->locals = read_memory_integer (pc + 5, 4);
+         return pc + 9;
        }
       else
        {
-         return 0;
+         /* Some instruction other than `subl'.  */
+         return pc + 3;
        }
     }
-  else if (op == 0xc8)
+  else if (op == 0xc8)         /* enter $XXX */
     {
-      char buf[2];
-      /* `enter' with 16 bit unsigned immediate.  */
-      codestream_read ((unsigned char *) buf, 2);
-      codestream_get ();       /* Flush final byte of enter instruction.  */
-      return extract_unsigned_integer (buf, 2);
+      cache->locals = read_memory_unsigned_integer (pc + 1, 2);
+      return pc + 4;
     }
-  return (-1);
-}
-
-/* Signal trampolines don't have a meaningful frame.  The frame
-   pointer value we use is actually the frame pointer of the calling
-   frame -- that is, the frame which was in progress when the signal
-   trampoline was entered.  GDB mostly treats this frame pointer value
-   as a magic cookie.  We detect the case of a signal trampoline by
-   testing for get_frame_type() == SIGTRAMP_FRAME, which is set based
-   on PC_IN_SIGTRAMP.
-
-   When a signal trampoline is invoked from a frameless function, we
-   essentially have two frameless functions in a row.  In this case,
-   we use the same magic cookie for three frames in a row.  We detect
-   this case by seeing whether the next frame is a SIGTRAMP_FRAME,
-   and, if it does, checking whether the current frame is actually
-   frameless.  In this case, we need to get the PC by looking at the
-   SP register value stored in the signal context.
-
-   This should work in most cases except in horrible situations where
-   a signal occurs just as we enter a function but before the frame
-   has been set up.  Incidentally, that's just what happens when we
-   call a function from GDB with a signal pending (there's a test in
-   the testsuite that makes this happen).  Therefore we pretend that
-   we have a frameless function if we're stopped at the start of a
-   function.  */
-
-/* Return non-zero if we're dealing with a frameless signal, that is,
-   a signal trampoline invoked from a frameless function.  */
-
-int
-i386_frameless_signal_p (struct frame_info *frame)
-{
-  return (get_next_frame (frame)
-         && get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME
-         && (frameless_look_for_prologue (frame)
-             || get_frame_pc (frame) == get_frame_func (frame)));
-}
-
-/* Return the chain-pointer for FRAME.  In the case of the i386, the
-   frame's nominal address is the address of a 4-byte word containing
-   the calling frame's address.  */
-
-static CORE_ADDR
-i386_frame_chain (struct frame_info *frame)
-{
-  if (pc_in_dummy_frame (get_frame_pc (frame)))
-    return get_frame_base (frame);
-
-  if (get_frame_type (frame) == SIGTRAMP_FRAME
-      || i386_frameless_signal_p (frame))
-    return get_frame_base (frame);
-
-  if (! inside_entry_file (get_frame_pc (frame)))
-    return read_memory_unsigned_integer (get_frame_base (frame), 4);
-
-  return 0;
-}
-
-/* Determine whether the function invocation represented by FRAME does
-   not have a from on the stack associated with it.  If it does not,
-   return non-zero, otherwise return zero.  */
-
-static int
-i386_frameless_function_invocation (struct frame_info *frame)
-{
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return 0;
-
-  return frameless_look_for_prologue (frame);
-}
-
-/* Assuming FRAME is for a sigtramp routine, return the saved program
-   counter.  */
-
-static CORE_ADDR
-i386_sigtramp_saved_pc (struct frame_info *frame)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  CORE_ADDR addr;
 
-  addr = tdep->sigcontext_addr (frame);
-  return read_memory_unsigned_integer (addr + tdep->sc_pc_offset, 4);
+  return pc;
 }
 
-/* Assuming FRAME is for a sigtramp routine, return the saved stack
-   pointer.  */
+/* 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_sigtramp_saved_sp (struct frame_info *frame)
+i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
+                            struct i386_frame_cache *cache)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  CORE_ADDR addr;
-
-  addr = tdep->sigcontext_addr (frame);
-  return read_memory_unsigned_integer (addr + tdep->sc_sp_offset, 4);
-}
-
-/* Return the saved program counter for FRAME.  */
-
-static CORE_ADDR
-i386_frame_saved_pc (struct frame_info *frame)
-{
-  if (pc_in_dummy_frame (get_frame_pc (frame)))
+  if (cache->locals >= 0)
     {
-      ULONGEST pc;
-
-      frame_unwind_unsigned_register (frame, PC_REGNUM, &pc);
-      return pc;
-    }
+      CORE_ADDR offset;
+      unsigned char op;
+      int i;
 
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return i386_sigtramp_saved_pc (frame);
+      offset = - 4 - cache->locals;
+      for (i = 0; i < 8 && pc < current_pc; i++)
+       {
+         op = read_memory_unsigned_integer (pc, 1);
+         if (op < 0x50 || op > 0x57)
+           break;
 
-  if (i386_frameless_signal_p (frame))
-    {
-      CORE_ADDR sp = i386_sigtramp_saved_sp (get_next_frame (frame));
-      return read_memory_unsigned_integer (sp, 4);
+         cache->saved_regs[op - 0x50] = offset;
+         offset -= 4;
+         pc++;
+       }
     }
 
-  return read_memory_unsigned_integer (get_frame_base (frame) + 4, 4);
+  return pc;
 }
 
-/* Immediately after a function call, return the saved pc.  */
-
-static CORE_ADDR
-i386_saved_pc_after_call (struct frame_info *frame)
-{
-  if (get_frame_type (frame) == SIGTRAMP_FRAME)
-    return i386_sigtramp_saved_pc (frame);
-
-  return read_memory_unsigned_integer (read_register (SP_REGNUM), 4);
-}
+/* 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.
 
-/* Parse the first few instructions the function to see what registers
-   were stored.
-   
    We handle these cases:
 
    The startup sequence can be at the start of the function, or the
@@ -632,79 +592,43 @@ i386_saved_pc_after_call (struct frame_info *frame)
    If the setup sequence is at the end of the function, then the next
    instruction will be a branch back to the start.  */
 
-static void
-i386_frame_init_saved_regs (struct frame_info *fip)
+static CORE_ADDR
+i386_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
+                      struct i386_frame_cache *cache)
 {
-  long locals = -1;
-  unsigned char op;
-  CORE_ADDR addr;
-  CORE_ADDR pc;
-  int i;
-
-  if (get_frame_saved_regs (fip))
-    return;
-
-  frame_saved_regs_zalloc (fip);
-
-  pc = get_frame_func (fip);
-  if (pc != 0)
-    locals = i386_get_frame_setup (pc);
-
-  if (locals >= 0)
-    {
-      addr = get_frame_base (fip) - 4 - locals;
-      for (i = 0; i < 8; i++)
-       {
-         op = codestream_get ();
-         if (op < 0x50 || op > 0x57)
-           break;
-#ifdef I386_REGNO_TO_SYMMETRY
-         /* Dynix uses different internal numbering.  Ick.  */
-         get_frame_saved_regs (fip)[I386_REGNO_TO_SYMMETRY (op - 0x50)] = addr;
-#else
-         get_frame_saved_regs (fip)[op - 0x50] = addr;
-#endif
-         addr -= 4;
-       }
-    }
-
-  get_frame_saved_regs (fip)[PC_REGNUM] = get_frame_base (fip) + 4;
-  get_frame_saved_regs (fip)[DEPRECATED_FP_REGNUM] = get_frame_base (fip);
+  pc = i386_follow_jump (pc);
+  pc = i386_analyze_struct_return (pc, current_pc, cache);
+  pc = i386_skip_probe (pc);
+  pc = i386_analyze_frame_setup (pc, current_pc, cache);
+  return i386_analyze_register_saves (pc, current_pc, cache);
 }
 
 /* Return PC of first real instruction.  */
 
 static CORE_ADDR
-i386_skip_prologue (CORE_ADDR pc)
+i386_skip_prologue (CORE_ADDR start_pc)
 {
-  unsigned char op;
-  int i;
   static unsigned char pic_pat[6] =
-  { 0xe8, 0, 0, 0, 0,          /* call   0x0 */
-    0x5b,                      /* popl   %ebx */
+  {
+    0xe8, 0, 0, 0, 0,          /* call 0x0 */
+    0x5b,                      /* popl %ebx */
   };
-  CORE_ADDR pos;
-
-  if (i386_get_frame_setup (pc) < 0)
-    return (pc);
+  struct i386_frame_cache cache;
+  CORE_ADDR pc;
+  unsigned char op;
+  int i;
 
-  /* Found valid frame setup -- codestream now points to start of push
-     instructions for saving registers.  */
+  cache.locals = -1;
+  pc = i386_analyze_prologue (start_pc, 0xffffffff, &cache);
+  if (cache.locals < 0)
+    return start_pc;
 
-  /* Skip over register saves.  */
-  for (i = 0; i < 8; i++)
-    {
-      op = codestream_peek ();
-      /* Break if not `pushl' instrunction.  */
-      if (op < 0x50 || op > 0x57)
-       break;
-      codestream_get ();
-    }
+  /* Found valid frame setup.  */
 
   /* The native cc on SVR4 in -K PIC mode inserts the following code
      to get the address of the global offset table (GOT) into register
-     %ebx
-     
+     %ebx:
+
         call   0x0
        popl    %ebx
         movl    %ebx,x(%ebp)    (optional)
@@ -714,110 +638,335 @@ i386_skip_prologue (CORE_ADDR pc)
      function), so we have to skip it to get to the first real
      instruction at the start of the function.  */
 
-  pos = codestream_tell ();
   for (i = 0; i < 6; i++)
     {
-      op = codestream_get ();
+      op = read_memory_unsigned_integer (pc + i, 1);
       if (pic_pat[i] != op)
        break;
     }
   if (i == 6)
     {
-      unsigned char buf[4];
-      long delta = 6;
+      int delta = 6;
+
+      op = read_memory_unsigned_integer (pc + delta, 1);
 
-      op = codestream_get ();
       if (op == 0x89)          /* movl %ebx, x(%ebp) */
        {
-         op = codestream_get ();
+         op = read_memory_unsigned_integer (pc + delta + 1, 1);
+
          if (op == 0x5d)       /* One byte offset from %ebp.  */
-           {
-             delta += 3;
-             codestream_read (buf, 1);
-           }
+           delta += 3;
          else if (op == 0x9d)  /* Four byte offset from %ebp.  */
-           {
-             delta += 6;
-             codestream_read (buf, 4);
-           }
+           delta += 6;
          else                  /* Unexpected instruction.  */
-           delta = -1;
-         op = codestream_get ();
+           delta = 0;
+
+         op = read_memory_unsigned_integer (pc + delta, 1);
        }
+
       /* addl y,%ebx */
-      if (delta > 0 && op == 0x81 && codestream_get () == 0xc3)
+      if (delta > 0 && op == 0x81
+         && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3);
        {
-         pos += delta + 6;
+         pc += delta + 6;
        }
     }
-  codestream_seek (pos);
-
-  i386_follow_jump ();
 
-  return (codestream_tell ());
+  return i386_follow_jump (pc);
 }
 
-/* Use the program counter to determine the contents and size of a
-   breakpoint instruction.  Return a pointer to a string of bytes that
-   encode a breakpoint instruction, store the length of the string in
-   *LEN and optionally adjust *PC to point to the correct memory
-   location for inserting the breakpoint.
+/* This function is 64-bit safe.  */
 
-   On the i386 we have a single breakpoint that fits in a single byte
-   and can be inserted anywhere.  */
-   
-static const unsigned char *
-i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
+static CORE_ADDR
+i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  static unsigned char break_insn[] = { 0xcc };        /* int 3 */
-  
-  *len = sizeof (break_insn);
-  return break_insn;
+  char buf[8];
+
+  frame_unwind_register (next_frame, PC_REGNUM, buf);
+  return extract_typed_address (buf, builtin_type_void_func_ptr);
 }
+\f
 
-/* Push the return address (pointing to the call dummy) onto the stack
-   and return the new value for the stack pointer.  */
+/* Normal frames.  */
 
-static CORE_ADDR
-i386_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
+static struct i386_frame_cache *
+i386_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
+  struct i386_frame_cache *cache;
   char buf[4];
+  int i;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = i386_alloc_frame_cache ();
+  *this_cache = cache;
+
+  /* In principle, for normal frames, %ebp holds the frame pointer,
+     which holds the base address for the current stack frame.
+     However, for functions that don't need it, the frame pointer is
+     optional.  For these "frameless" functions the frame pointer is
+     actually the frame pointer of the calling frame.  Signal
+     trampolines are just a special case of a "frameless" function.
+     They (usually) share their frame pointer with the frame that was
+     in progress when the signal occurred.  */
+
+  frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
+  cache->base = extract_unsigned_integer (buf, 4);
+  if (cache->base == 0)
+    return cache;
+
+  /* For normal frames, %eip is stored at 4(%ebp).  */
+  cache->saved_regs[I386_EIP_REGNUM] = 4;
+
+  cache->pc = frame_func_unwind (next_frame);
+  if (cache->pc != 0)
+    i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
+
+  if (cache->locals < 0)
+    {
+      /* We didn't find a valid frame, which means that CACHE->base
+        currently holds the frame pointer for our calling frame.  If
+        we're at the start of a function, or somewhere half-way its
+        prologue, the function's frame probably hasn't been fully
+        setup yet.  Try to reconstruct the base address for the stack
+        frame by looking at the stack pointer.  For truly "frameless"
+        functions this might work too.  */
+
+      frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+      cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+    }
+
+  /* Now that we have the base address for the stack frame we can
+     calculate the value of %esp in the calling frame.  */
+  cache->saved_sp = cache->base + 8;
 
-  store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ());
-  write_memory (sp - 4, buf, 4);
-  return sp - 4;
+  /* Adjust all the saved registers such that they contain addresses
+     instead of offsets.  */
+  for (i = 0; i < I386_NUM_SAVED_REGS; i++)
+    if (cache->saved_regs[i] != -1)
+      cache->saved_regs[i] += cache->base;
+
+  return cache;
 }
 
 static void
-i386_do_pop_frame (struct frame_info *frame)
+i386_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                   struct frame_id *this_id)
 {
-  CORE_ADDR fp;
-  int regnum;
-  char regbuf[I386_MAX_REGISTER_SIZE];
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return;
+
+  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
+}
+
+static void
+i386_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+                         int regnum, int *optimizedp,
+                         enum lval_type *lvalp, CORE_ADDR *addrp,
+                         int *realnump, void *valuep)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
+
+  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 == I386_EFLAGS_REGNUM)
+    {
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
+       {
+         ULONGEST val;
 
-  fp = get_frame_base (frame);
-  i386_frame_init_saved_regs (frame);
+         /* Clear the direction flag.  */
+         frame_unwind_unsigned_register (next_frame, PS_REGNUM, &val);
+         val &= ~(1 << 10);
+         store_unsigned_integer (valuep, 4, val);
+       }
+
+      return;
+    }
 
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
+  if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
     {
-      CORE_ADDR addr;
-      addr = get_frame_saved_regs (frame)[regnum];
-      if (addr)
+      frame_register_unwind (next_frame, I386_EAX_REGNUM,
+                            optimizedp, lvalp, addrp, realnump, valuep);
+      return;
+    }
+
+  if (regnum == I386_ESP_REGNUM && cache->saved_sp)
+    {
+      *optimizedp = 0;
+      *lvalp = not_lval;
+      *addrp = 0;
+      *realnump = -1;
+      if (valuep)
        {
-         read_memory (addr, regbuf, REGISTER_RAW_SIZE (regnum));
-         deprecated_write_register_gen (regnum, regbuf);
+         /* Store the value.  */
+         store_unsigned_integer (valuep, 4, cache->saved_sp);
        }
+      return;
     }
-  write_register (DEPRECATED_FP_REGNUM, read_memory_integer (fp, 4));
-  write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
-  write_register (SP_REGNUM, fp + 8);
-  flush_cached_frames ();
+
+  if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
+    {
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = cache->saved_regs[regnum];
+      *realnump = -1;
+      if (valuep)
+       {
+         /* Read the value in from memory.  */
+         read_memory (*addrp, valuep,
+                      register_size (current_gdbarch, regnum));
+       }
+      return;
+    }
+
+  frame_register_unwind (next_frame, regnum,
+                        optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind i386_frame_unwind =
+{
+  NORMAL_FRAME,
+  i386_frame_this_id,
+  i386_frame_prev_register
+};
+
+static const struct frame_unwind *
+i386_frame_p (CORE_ADDR pc)
+{
+  return &i386_frame_unwind;
+}
+\f
+
+/* Signal trampolines.  */
+
+static struct i386_frame_cache *
+i386_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct i386_frame_cache *cache;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  CORE_ADDR addr;
+  char buf[4];
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = i386_alloc_frame_cache ();
+
+  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+  cache->base = extract_unsigned_integer (buf, 4) - 4;
+
+  addr = tdep->sigcontext_addr (next_frame);
+  cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
+  cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+
+  *this_cache = cache;
+  return cache;
+}
+
+static void
+i386_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                            struct frame_id *this_id)
+{
+  struct i386_frame_cache *cache =
+    i386_sigtramp_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base + 8, frame_pc_unwind (next_frame));
+}
+
+static void
+i386_sigtramp_frame_prev_register (struct frame_info *next_frame,
+                                  void **this_cache,
+                                  int regnum, int *optimizedp,
+                                  enum lval_type *lvalp, CORE_ADDR *addrp,
+                                  int *realnump, void *valuep)
+{
+  /* Make sure we've initialized the cache.  */
+  i386_sigtramp_frame_cache (next_frame, this_cache);
+
+  i386_frame_prev_register (next_frame, this_cache, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
 }
 
+static const struct frame_unwind i386_sigtramp_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  i386_sigtramp_frame_this_id,
+  i386_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+i386_sigtramp_frame_p (CORE_ADDR pc)
+{
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (PC_IN_SIGTRAMP (pc, name))
+    return &i386_sigtramp_frame_unwind;
+
+  return NULL;
+}
+\f
+
+static CORE_ADDR
+i386_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
+
+  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
+};
+
 static void
-i386_pop_frame (void)
+i386_save_dummy_frame_tos (CORE_ADDR sp)
 {
-  generic_pop_current_frame (i386_do_pop_frame);
+  generic_save_dummy_frame_tos (sp + 8);
+}
+
+static struct frame_id
+i386_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  char buf[4];
+  CORE_ADDR fp;
+
+  frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
+  fp = extract_unsigned_integer (buf, 4);
+
+  return frame_id_build (fp + 8, frame_pc_unwind (next_frame));
 }
 \f
 
@@ -825,7 +974,9 @@ i386_pop_frame (void)
    stack.  We expect the first arg to be a pointer to the jmp_buf
    structure from which we extract the address that we will land at.
    This address is copied into PC.  This routine returns non-zero on
-   success.  */
+   success.
+
+   This function is 64-bit safe.  */
 
 static int
 i386_get_longjmp_target (CORE_ADDR *pc)
@@ -854,28 +1005,57 @@ i386_get_longjmp_target (CORE_ADDR *pc)
 \f
 
 static CORE_ADDR
-i386_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
-                    int struct_return, CORE_ADDR struct_addr)
+i386_push_dummy_call (struct gdbarch *gdbarch, struct regcache *regcache,
+                     CORE_ADDR dummy_addr, int nargs, struct value **args,
+                     CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
 {
-  sp = legacy_push_arguments (nargs, args, sp, struct_return, struct_addr);
-  
-  if (struct_return)
+  char buf[4];
+  int i;
+
+  /* Push arguments in reverse order.  */
+  for (i = nargs - 1; i >= 0; i--)
     {
-      char buf[4];
+      int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+
+      /* The System V ABI says that:
+
+        "An argument's size is increased, if necessary, to make it a
+        multiple of [32-bit] words.  This may require tail padding,
+        depending on the size of the argument."
+
+        This makes sure the stack says word-aligned.  */
+      sp -= (len + 3) & ~3;
+      write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len);
+    }
 
+  /* Push value address.  */
+  if (struct_return)
+    {
       sp -= 4;
       store_unsigned_integer (buf, 4, struct_addr);
       write_memory (sp, buf, 4);
     }
 
+  /* Store return address.  */
+  sp -= 4;
+  store_unsigned_integer (buf, 4, dummy_addr);
+  write_memory (sp, buf, 4);
+
+  /* Finally, update the stack pointer...  */
+  store_unsigned_integer (buf, 4, sp);
+  regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);
+
+  /* ...and fake a frame pointer.  */
+  regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);
+
   return sp;
 }
 
 /* These registers are used for returning integers (and on some
    targets also for returning `struct' and `union' values when their
    size and alignment match an integer type).  */
-#define LOW_RETURN_REGNUM 0    /* %eax */
-#define HIGH_RETURN_REGNUM 2   /* %edx */
+#define LOW_RETURN_REGNUM      I386_EAX_REGNUM /* %eax */
+#define HIGH_RETURN_REGNUM     I386_EDX_REGNUM /* %edx */
 
 /* Extract from an array REGBUF containing the (raw) register state, a
    function return value of TYPE, and copy that, in virtual format,
@@ -909,7 +1089,7 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
         its contents to the desired type.  This is probably not
         exactly how it would happen on the target itself, but it is
         the best we can do.  */
-      regcache_raw_read (regcache, FP0_REGNUM, buf);
+      regcache_raw_read (regcache, I386_ST0_REGNUM, buf);
       convert_typed_floating (buf, builtin_type_i387_ext, valbuf, type);
     }
   else
@@ -971,7 +1151,7 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
         not exactly how it would happen on the target itself, but
         it is the best we can do.  */
       convert_typed_floating (valbuf, type, buf, builtin_type_i387_ext);
-      regcache_raw_write (regcache, FP0_REGNUM, buf);
+      regcache_raw_write (regcache, I386_ST0_REGNUM, buf);
 
       /* Set the top of the floating-point register stack to 7.  The
          actual value doesn't really matter, but 7 is what a normal
@@ -1012,10 +1192,10 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
 static CORE_ADDR
 i386_extract_struct_value_address (struct regcache *regcache)
 {
-  ULONGEST addr;
+  char buf[4];
 
-  regcache_raw_read_unsigned (regcache, LOW_RETURN_REGNUM, &addr);
-  return addr;
+  regcache_cooked_read (regcache, I386_EAX_REGNUM, buf);
+  return extract_unsigned_integer (buf, 4);
 }
 \f
 
@@ -1057,7 +1237,8 @@ i386_use_struct_convention (int gcc_p, struct type *type)
 static struct type *
 i386_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  if (regnum == PC_REGNUM || regnum == DEPRECATED_FP_REGNUM || regnum == SP_REGNUM)
+  if (regnum == I386_EIP_REGNUM
+      || regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
     return lookup_pointer_type (builtin_type_void);
 
   if (i386_fp_regnum_p (regnum))
@@ -1073,7 +1254,7 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
 }
 
 /* Map a cooked register onto a raw register or memory.  For the i386,
-   the MMX registers need to be mapped onto floating-point registers.  */
+   the MMX registers need to be mapped onto floating point registers.  */
 
 static int
 i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
@@ -1274,36 +1455,27 @@ i386_print_insn (bfd_vma pc, disassemble_info *info)
 static int
 i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
 {
+  /* UnixWare uses _sigacthandler.  The origin of the other symbols is
+     currently unknown.  */
   return (name && (strcmp ("_sigreturn", name) == 0
                   || strcmp ("_sigacthandler", name) == 0
                   || strcmp ("sigvechandler", name) == 0));
 }
 
-/* Get address of the pushed ucontext (sigcontext) on the stack for
-   all three variants of SVR4 sigtramps.  */
+/* Assuming NEXT_FRAME is for a frame following a SVR4 sigtramp
+   routine, return the address of the associated sigcontext (ucontext)
+   structure.  */
 
 static CORE_ADDR
-i386_svr4_sigcontext_addr (struct frame_info *frame)
+i386_svr4_sigcontext_addr (struct frame_info *next_frame)
 {
-  int sigcontext_offset = -1;
-  char *name = NULL;
-
-  find_pc_partial_function (get_frame_pc (frame), &name, NULL, NULL);
-  if (name)
-    {
-      if (strcmp (name, "_sigreturn") == 0)
-       sigcontext_offset = 132;
-      else if (strcmp (name, "_sigacthandler") == 0)
-       sigcontext_offset = 80;
-      else if (strcmp (name, "sigvechandler") == 0)
-       sigcontext_offset = 120;
-    }
+  char buf[4];
+  CORE_ADDR sp;
 
-  gdb_assert (sigcontext_offset != -1);
+  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4);
 
-  if (get_next_frame (frame))
-    return get_frame_base (get_next_frame (frame)) + sigcontext_offset;
-  return read_register (SP_REGNUM) + sigcontext_offset;
+  return read_memory_unsigned_integer (sp + 8, 4);
 }
 \f
 
@@ -1342,8 +1514,8 @@ i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
   tdep->sigcontext_addr = i386_svr4_sigcontext_addr;
-  tdep->sc_pc_offset = 14 * 4;
-  tdep->sc_sp_offset = 7 * 4;
+  tdep->sc_pc_offset = 36 + 14 * 4;
+  tdep->sc_sp_offset = 36 + 17 * 4;
 
   tdep->jb_pc_offset = 20;
 }
@@ -1407,6 +1579,7 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   int fp_regnum_p = (i386_fp_regnum_p (regnum)
                     || i386_fpc_regnum_p (regnum));
   int mmx_regnum_p = (i386_mmx_regnum_p (regnum));
+
   if (group == i386_mmx_reggroup)
     return mmx_regnum_p;
   if (group == i386_sse_reggroup)
@@ -1417,10 +1590,11 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return fp_regnum_p;
   if (group == general_reggroup)
     return (!fp_regnum_p && !mmx_regnum_p && !sse_regnum_p);
+
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
-
 \f
+
 static struct gdbarch *
 i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -1436,10 +1610,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep = XMALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
-  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
-     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
-  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
-
   /* The i386 default settings don't include the SSE registers.
      FIXME: kettenis/20020614: They do include the FPU registers for
      now, which probably is not quite right.  */
@@ -1464,15 +1634,17 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      alignment.  */
   set_gdbarch_long_double_bit (gdbarch, 96);
 
-  /* NOTE: tm-i386aix.h, tm-i386bsd.h, tm-i386os9k.h, tm-ptx.h,
-     tm-symmetry.h currently override this.  Sigh.  */
+  /* The default ABI includes general-purpose registers and
+     floating-point registers.  */
   set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS);
+  set_gdbarch_register_name (gdbarch, i386_register_name);
+  set_gdbarch_register_type (gdbarch, i386_register_type);
 
-  set_gdbarch_sp_regnum (gdbarch, 4); /* %esp */
-  set_gdbarch_deprecated_fp_regnum (gdbarch, 5); /* %ebp */
-  set_gdbarch_pc_regnum (gdbarch, 8); /* %eip */
-  set_gdbarch_ps_regnum (gdbarch, 9); /* %eflags */
-  set_gdbarch_fp0_regnum (gdbarch, 16);        /* %st(0) */
+  /* Register numbers of various important registers.  */
+  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
+  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
+  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
+  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
 
   /* Use the "default" register numbering scheme for stabs and COFF.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
@@ -1485,39 +1657,24 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to
      be in use on any of the supported i386 targets.  */
 
-  set_gdbarch_register_name (gdbarch, i386_register_name);
-  set_gdbarch_deprecated_register_size (gdbarch, 4);
-  set_gdbarch_deprecated_register_bytes (gdbarch, I386_SIZEOF_GREGS + I386_SIZEOF_FREGS);
-  set_gdbarch_register_type (gdbarch, i386_register_type);
-
   set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
 
   set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
 
   /* Call dummy code.  */
-  set_gdbarch_deprecated_call_dummy_words (gdbarch, NULL);
-  set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, 0);
+  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
 
   set_gdbarch_register_convertible (gdbarch, i386_register_convertible);
   set_gdbarch_register_convert_to_virtual (gdbarch,
                                           i386_register_convert_to_virtual);
   set_gdbarch_register_convert_to_raw (gdbarch, i386_register_convert_to_raw);
 
-  /* "An argument's size is increased, if necessary, to make it a
-     multiple of [32-bit] words.  This may require tail padding,
-     depending on the size of the argument" -- from the x86 ABI.  */
-  set_gdbarch_parm_boundary (gdbarch, 32);
-
   set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
-  set_gdbarch_deprecated_push_arguments (gdbarch, i386_push_arguments);
-  set_gdbarch_deprecated_push_return_address (gdbarch, i386_push_return_address);
-  set_gdbarch_deprecated_pop_frame (gdbarch, i386_pop_frame);
   set_gdbarch_store_return_value (gdbarch, i386_store_return_value);
   set_gdbarch_extract_struct_value_address (gdbarch,
                                            i386_extract_struct_value_address);
   set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
 
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, i386_frame_init_saved_regs);
   set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
 
   /* Stack grows downward.  */
@@ -1527,17 +1684,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_decr_pc_after_break (gdbarch, 1);
   set_gdbarch_function_start_offset (gdbarch, 0);
 
-  /* The following redefines make backtracing through sigtramp work.
-     They manufacture a fake sigtramp frame and obtain the saved pc in
-     sigtramp from the sigcontext structure which is pushed by the
-     kernel on the user stack, along with a pointer to it.  */
-
   set_gdbarch_frame_args_skip (gdbarch, 8);
-  set_gdbarch_frameless_function_invocation (gdbarch,
-                                           i386_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_chain (gdbarch, i386_frame_chain);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, i386_frame_saved_pc);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, i386_saved_pc_after_call);
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
 
@@ -1548,16 +1695,23 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_print_insn (gdbarch, i386_print_insn);
 
+  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);
 
-  /* Should be using push_dummy_call.  */
-  set_gdbarch_deprecated_dummy_write_sp (gdbarch, generic_target_write_sp);
+  frame_base_set_default (gdbarch, &i386_frame_base);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  frame_unwind_append_predicate (gdbarch, i386_sigtramp_frame_p);
+  frame_unwind_append_predicate (gdbarch, i386_frame_p);
+
   return gdbarch;
 }
 
index 1b569d9..b2c2dff 100644 (file)
@@ -136,8 +136,6 @@ extern int i386_mxcsr_regnum_p (int regnum);
 #define FCOFF_REGNUM FIOFF_REGNUM
 #define FDS_REGNUM FOSEG_REGNUM
 #define FDOFF_REGNUM FOOFF_REGNUM
-#define IS_FP_REGNUM(n) i386_fp_regnum_p (n)
-#define IS_SSE_REGNUM(n) i386_sse_regnum_p (n)
 
 #define I386_NUM_GREGS 16
 #define I386_NUM_FREGS 16
@@ -146,16 +144,6 @@ extern int i386_mxcsr_regnum_p (int regnum);
 #define I386_SSE_NUM_REGS      (I386_NUM_GREGS + I386_NUM_FREGS \
                                 + I386_NUM_XREGS)
 
-/* Sizes of individual register sets.  These cover the entire register
-   file, so summing up the sizes of those portions actually present
-   yields DEPRECATED_REGISTER_BYTES.  */
-#define I386_SIZEOF_GREGS      (I386_NUM_GREGS * 4)
-#define I386_SIZEOF_FREGS      (8 * 10 + 8 * 4)
-#define I386_SIZEOF_XREGS      (8 * 16 + 4)
-
-#define I386_SSE_SIZEOF_REGS   (I386_SIZEOF_GREGS + I386_SIZEOF_FREGS \
-                                + I386_SIZEOF_XREGS)
-
 /* Size of the largest register.  */
 #define I386_MAX_REGISTER_SIZE 16
 
@@ -178,7 +166,6 @@ extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *);
 
 /* Functions exported from i386bsd-tdep.c.  */
 
-extern CORE_ADDR i386bsd_sigcontext_addr (struct frame_info *frame);
 extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *);
 
 #endif /* i386-tdep.h */
index c0c544d..d91be26 100644 (file)
@@ -41,26 +41,19 @@ i386bsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
   return (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end);
 }
 
-/* Assuming FRAME is for a BSD sigtramp routine, return the address of
-   the associated sigcontext structure.
+/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
+   routine, return the address of the associated sigcontext structure.  */
 
-   Note: This function is used for Solaris 2 too, so don't make it
-   static.  */
-
-CORE_ADDR
-i386bsd_sigcontext_addr (struct frame_info *frame)
+static CORE_ADDR
+i386bsd_sigcontext_addr (struct frame_info *next_frame)
 {
-  struct frame_info *next_frame = get_next_frame (frame);
+  char buf[4];
+  CORE_ADDR sp;
 
-  if (next_frame)
-    /* If this isn't the top frame, the next frame must be for the
-       signal handler itself.  A pointer to the sigcontext structure
-       is passed as the third argument to the signal handler.  */
-    return read_memory_unsigned_integer (get_frame_base (next_frame) + 16, 4);
+  frame_unwind_register (next_frame, SP_REGNUM, buf);
+  sp = extract_unsigned_integer (buf, 4);
 
-  /* This is the top frame.  We'll have to find the address of the
-     sigcontext structure by looking at the stack pointer.  */
-  return read_memory_unsigned_integer (read_register (SP_REGNUM) + 8, 4);
+  return read_memory_unsigned_integer (sp + 8, 4);
 }
 
 /* Return the start address of the sigtramp routine.  */