gdb: Add default frame methods to gdbarch
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 7 Sep 2018 19:04:44 +0000 (20:04 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 19 Dec 2018 20:59:38 +0000 (20:59 +0000)
Supply default gdbarch methods for gdbarch_dummy_id,
gdbarch_unwind_pc, and gdbarch_unwind_sp.  This patch doesn't actually
convert any targets to use these methods, and so, there will be no
user visible changes after this commit.

The implementations for default_dummy_id and default_unwind_sp are
fairly straight forward, these just take on the pattern used by most
targets.  Once these default methods are in place then most targets
will be able to switch over.

The implementation for default_unwind_pc is also fairly straight
forward, but maybe needs some explanation.

This patch has gone through a number of iterations:

  https://sourceware.org/ml/gdb-patches/2018-03/msg00165.html
  https://sourceware.org/ml/gdb-patches/2018-03/msg00306.html
  https://sourceware.org/ml/gdb-patches/2018-06/msg00090.html
  https://sourceware.org/ml/gdb-patches/2018-09/msg00127.html

and the implementation of default_unwind_pc has changed over this
time.  Originally, I took an implementation like this:

    CORE_ADDR
    default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
    {
      int pc_regnum = gdbarch_pc_regnum (gdbarch);
      return frame_unwind_register_unsigned (next_frame, pc_regnum);
    }

This is basically a clone of default_unwind_sp, but using $pc.  It was
pointed out that we could potentially do better, and in version 2 the
implementation became:

    CORE_ADDR
    default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
    {
      struct type *type;
      int pc_regnum;
      CORE_ADDR addr;
      struct value *value;

      pc_regnum = gdbarch_pc_regnum (gdbarch);
      value = frame_unwind_register_value (next_frame, pc_regnum);
      type = builtin_type (gdbarch)->builtin_func_ptr;
      addr = extract_typed_address (value_contents_all (value), type);
      addr = gdbarch_addr_bits_remove (gdbarch, addr);
      release_value (value);
      value_free (value);
      return addr;
    }

The idea was to try split out some of the steps of unwinding the $pc,
steps that are on some (or many) targets no-ops, and so allow targets
that do override these methods, to make use of default_unwind_pc.

This implementation remained in place for version 2, 3, and 4.

However, I realised that I'd made a mistake, most targets simply use
frame_unwind_register_unsigned to unwind the $pc, and this throws an
error if the register value is optimized out or unavailable.  My new
proposed implementation doesn't do this, I was going to end up
breaking many targets.

I considered duplicating the code from frame_unwind_register_unsigned
that throws the errors into my new default_unwind_pc, however, this
felt really overly complex.  So, what I instead went with was to
simply revert back to using frame_unwind_register_unsigned.  Almost
all existing targets already use this. Some of the ones that don't can
be converted to, which means almost all targets could end up using the
default.

One addition I have made over the version 1 implementation is to add a
call to gdbarch_addr_bits_remove.  For most targets this is a no-op,
but for a handful, having this call in place will mean that they can
use the default method.  After all this, the new default_unwind_pc now
looks like this:

    CORE_ADDR
    default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
    {
      int pc_regnum = gdbarch_pc_regnum (gdbarch);
      CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum);
      pc = gdbarch_addr_bits_remove (gdbarch, pc);
      return pc;
    }

gdb/ChangeLog:

* gdb/dummy-frame.c (default_dummy_id): Defined new function.
* gdb/dummy-frame.h (default_dummy_id): Declare new function.
* gdb/frame-unwind.c (default_unwind_pc): Define new function.
(default_unwind_sp): Define new function.
* gdb/frame-unwind.h (default_unwind_pc): Declare new function.
(default_unwind_sp): Declare new function.
* gdb/frame.c (frame_unwind_pc): Assume gdbarch_unwind_pc is
available.
(get_frame_sp): Assume that gdbarch_unwind_sp is available.
* gdb/gdbarch.c: Regenerate.
* gdb/gdbarch.h: Regenerate.
* gdb/gdbarch.sh: Update definition of dummy_id, unwind_pc, and
unwind_sp.  Add additional header files to be included in
generated file.

gdb/ChangeLog
gdb/dummy-frame.c
gdb/dummy-frame.h
gdb/frame-unwind.c
gdb/frame-unwind.h
gdb/frame.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh

index 4283cbb6b17d09ebb48b8921ced19ca5115c60e2..28ab3345032df67cb3539ea7c180000c219ad644 100644 (file)
@@ -1,3 +1,20 @@
+2018-12-19  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb/dummy-frame.c (default_dummy_id): Defined new function.
+       * gdb/dummy-frame.h (default_dummy_id): Declare new function.
+       * gdb/frame-unwind.c (default_unwind_pc): Define new function.
+       (default_unwind_sp): Define new function.
+       * gdb/frame-unwind.h (default_unwind_pc): Declare new function.
+       (default_unwind_sp): Declare new function.
+       * gdb/frame.c (frame_unwind_pc): Assume gdbarch_unwind_pc is
+       available.
+       (get_frame_sp): Assume that gdbarch_unwind_sp is available.
+       * gdb/gdbarch.c: Regenerate.
+       * gdb/gdbarch.h: Regenerate.
+       * gdb/gdbarch.sh: Update definition of dummy_id, unwind_pc, and
+       unwind_sp.  Add additional header files to be included in
+       generated file.
+
 2018-12-19  Dimitar Dimitrov  <dimitar@dinux.eu>
 
        * nat/linux-ptrace.c (linux_ptrace_test_ret_to_nx): Remove
index c6f874a3b19a6e227fb35bfdc673c71727de08f3..8e380ae1c87607a82b4fc5b2030b62c14c599663 100644 (file)
@@ -385,6 +385,18 @@ const struct frame_unwind dummy_frame_unwind =
   dummy_frame_sniffer,
 };
 
+/* See dummy-frame.h.  */
+
+struct frame_id
+default_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  CORE_ADDR sp, pc;
+
+  sp = get_frame_sp (this_frame);
+  pc = get_frame_pc (this_frame);
+  return frame_id_build (sp, pc);
+}
+
 static void
 fprint_dummy_frames (struct ui_file *file)
 {
index 407f398404e21d66ce22b738317f70ce99dfa161..9eaec3492bf293b4a7b2b5b1b17cf46f675725cf 100644 (file)
@@ -73,4 +73,10 @@ extern void register_dummy_frame_dtor (frame_id dummy_id,
 extern int find_dummy_frame_dtor (dummy_frame_dtor_ftype *dtor,
                                  void *dtor_data);
 
+/* Default implementation of gdbarch_dummy_id.  Generate a dummy frame_id
+   for THIS_FRAME assuming that the frame is a dummy frame.  */
+
+extern struct frame_id default_dummy_id (struct gdbarch *gdbarch,
+                                        struct frame_info *this_frame);
+
 #endif /* !defined (DUMMY_FRAME_H)  */
index e6e63539ad79cbd8bbd9a460399a994e5b449101..fb0e5e83213789961e3163db1ceb9affc3a78d4b 100644 (file)
@@ -193,6 +193,26 @@ default_frame_unwind_stop_reason (struct frame_info *this_frame,
     return UNWIND_NO_REASON;
 }
 
+/* See frame-unwind.h.  */
+
+CORE_ADDR
+default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  int pc_regnum = gdbarch_pc_regnum (gdbarch);
+  CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum);
+  pc = gdbarch_addr_bits_remove (gdbarch, pc);
+  return pc;
+}
+
+/* See frame-unwind.h.  */
+
+CORE_ADDR
+default_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  int sp_regnum = gdbarch_sp_regnum (gdbarch);
+  return frame_unwind_register_unsigned (next_frame, sp_regnum);
+}
+
 /* Helper functions for value-based register unwinding.  These return
    a (possibly lazy) value of the appropriate type.  */
 
index af220f72a015cad8dd81bcda4e41cdf66428cfb1..3ca3fdfe727fcf73a4309a1b72f45d5e9438d552 100644 (file)
@@ -70,6 +70,18 @@ enum unwind_stop_reason
   default_frame_unwind_stop_reason (struct frame_info *this_frame,
                                    void **this_cache);
 
+/* A default unwind_pc callback that simply unwinds the register identified
+   by GDBARCH_PC_REGNUM.  */
+
+extern CORE_ADDR default_unwind_pc (struct gdbarch *gdbarch,
+                                   struct frame_info *next_frame);
+
+/* A default unwind_sp callback that simply unwinds the register identified
+   by GDBARCH_SP_REGNUM.  */
+
+extern CORE_ADDR default_unwind_sp (struct gdbarch *gdbarch,
+                                   struct frame_info *next_frame);
+
 /* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
    use THIS frame, and through it the NEXT frame's register unwind
    method, to determine the frame ID of THIS frame.
index 4624eada87b2d761b0f97c8c84eb17f574fa78c7..f98a54a9e0f3577a123d346c8f5a3039c1154f0f 100644 (file)
@@ -872,76 +872,71 @@ frame_unwind_pc (struct frame_info *this_frame)
 {
   if (this_frame->prev_pc.status == CC_UNKNOWN)
     {
-      if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
+      struct gdbarch *prev_gdbarch;
+      CORE_ADDR pc = 0;
+      int pc_p = 0;
+
+      /* The right way.  The `pure' way.  The one true way.  This
+        method depends solely on the register-unwind code to
+        determine the value of registers in THIS frame, and hence
+        the value of this frame's PC (resume address).  A typical
+        implementation is no more than:
+
+        frame_unwind_register (this_frame, ISA_PC_REGNUM, buf);
+        return extract_unsigned_integer (buf, size of ISA_PC_REGNUM);
+
+        Note: this method is very heavily dependent on a correct
+        register-unwind implementation, it pays to fix that
+        method first; this method is frame type agnostic, since
+        it only deals with register values, it works with any
+        frame.  This is all in stark contrast to the old
+        FRAME_SAVED_PC which would try to directly handle all the
+        different ways that a PC could be unwound.  */
+      prev_gdbarch = frame_unwind_arch (this_frame);
+
+      TRY
        {
-         struct gdbarch *prev_gdbarch;
-         CORE_ADDR pc = 0;
-         int pc_p = 0;
-
-         /* The right way.  The `pure' way.  The one true way.  This
-            method depends solely on the register-unwind code to
-            determine the value of registers in THIS frame, and hence
-            the value of this frame's PC (resume address).  A typical
-            implementation is no more than:
-          
-            frame_unwind_register (this_frame, ISA_PC_REGNUM, buf);
-            return extract_unsigned_integer (buf, size of ISA_PC_REGNUM);
-
-            Note: this method is very heavily dependent on a correct
-            register-unwind implementation, it pays to fix that
-            method first; this method is frame type agnostic, since
-            it only deals with register values, it works with any
-            frame.  This is all in stark contrast to the old
-            FRAME_SAVED_PC which would try to directly handle all the
-            different ways that a PC could be unwound.  */
-         prev_gdbarch = frame_unwind_arch (this_frame);
-
-         TRY
+         pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
+         pc_p = 1;
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         if (ex.error == NOT_AVAILABLE_ERROR)
            {
-             pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
-             pc_p = 1;
+             this_frame->prev_pc.status = CC_UNAVAILABLE;
+
+             if (frame_debug)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "{ frame_unwind_pc (this_frame=%d)"
+                                   " -> <unavailable> }\n",
+                                   this_frame->level);
            }
-         CATCH (ex, RETURN_MASK_ERROR)
+         else if (ex.error == OPTIMIZED_OUT_ERROR)
            {
-             if (ex.error == NOT_AVAILABLE_ERROR)
-               {
-                 this_frame->prev_pc.status = CC_UNAVAILABLE;
-
-                 if (frame_debug)
-                   fprintf_unfiltered (gdb_stdlog,
-                                       "{ frame_unwind_pc (this_frame=%d)"
-                                       " -> <unavailable> }\n",
-                                       this_frame->level);
-               }
-             else if (ex.error == OPTIMIZED_OUT_ERROR)
-               {
-                 this_frame->prev_pc.status = CC_NOT_SAVED;
-
-                 if (frame_debug)
-                   fprintf_unfiltered (gdb_stdlog,
-                                       "{ frame_unwind_pc (this_frame=%d)"
-                                       " -> <not saved> }\n",
-                                       this_frame->level);
-               }
-             else
-               throw_exception (ex);
-           }
-         END_CATCH
+             this_frame->prev_pc.status = CC_NOT_SAVED;
 
-         if (pc_p)
-           {
-             this_frame->prev_pc.value = pc;
-             this_frame->prev_pc.status = CC_VALUE;
              if (frame_debug)
                fprintf_unfiltered (gdb_stdlog,
-                                   "{ frame_unwind_pc (this_frame=%d) "
-                                   "-> %s }\n",
-                                   this_frame->level,
-                                   hex_string (this_frame->prev_pc.value));
+                                   "{ frame_unwind_pc (this_frame=%d)"
+                                   " -> <not saved> }\n",
+                                   this_frame->level);
            }
+         else
+           throw_exception (ex);
+       }
+      END_CATCH
+
+      if (pc_p)
+       {
+         this_frame->prev_pc.value = pc;
+         this_frame->prev_pc.status = CC_VALUE;
+         if (frame_debug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "{ frame_unwind_pc (this_frame=%d) "
+                               "-> %s }\n",
+                               this_frame->level,
+                               hex_string (this_frame->prev_pc.value));
        }
-      else
-       internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
     }
 
   if (this_frame->prev_pc.status == CC_VALUE)
@@ -2782,18 +2777,9 @@ get_frame_sp (struct frame_info *this_frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
-  /* Normality - an architecture that provides a way of obtaining any
-     frame inner-most address.  */
-  if (gdbarch_unwind_sp_p (gdbarch))
-    /* NOTE drow/2008-06-28: gdbarch_unwind_sp could be converted to
-       operate on THIS_FRAME now.  */
-    return gdbarch_unwind_sp (gdbarch, this_frame->next);
-  /* Now things are really are grim.  Hope that the value returned by
-     the gdbarch_sp_regnum register is meaningful.  */
-  if (gdbarch_sp_regnum (gdbarch) >= 0)
-    return get_frame_register_unsigned (this_frame,
-                                       gdbarch_sp_regnum (gdbarch));
-  internal_error (__FILE__, __LINE__, _("Missing unwind SP method"));
+  /* NOTE drow/2008-06-28: gdbarch_unwind_sp could be converted to
+     operate on THIS_FRAME now.  */
+  return gdbarch_unwind_sp (gdbarch, this_frame->next);
 }
 
 /* Return the reason why we can't unwind past FRAME.  */
index bc4f786501e3ba62a8538af42de5bfc3e1185fda..193142c3ee90ac2cc01654ca377a40f264013508 100644 (file)
@@ -48,6 +48,8 @@
 #include "regcache.h"
 #include "objfiles.h"
 #include "auxv.h"
+#include "frame-unwind.h"
+#include "dummy-frame.h"
 
 /* Static function declarations */
 
@@ -408,6 +410,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->ecoff_reg_to_regnum = no_op_reg_to_regnum;
   gdbarch->sdb_reg_to_regnum = no_op_reg_to_regnum;
   gdbarch->dwarf2_reg_to_regnum = no_op_reg_to_regnum;
+  gdbarch->dummy_id = default_dummy_id;
   gdbarch->deprecated_fp_regnum = -1;
   gdbarch->call_dummy_location = AT_ENTRY_POINT;
   gdbarch->code_of_frame_writable = default_code_of_frame_writable;
@@ -427,6 +430,8 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint;
   gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
   gdbarch->remote_register_number = default_remote_register_number;
+  gdbarch->unwind_pc = default_unwind_pc;
+  gdbarch->unwind_sp = default_unwind_sp;
   gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
   gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
   gdbarch->addr_bits_remove = core_addr_identity;
@@ -570,7 +575,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if (gdbarch->register_name == 0)
     log.puts ("\n\tregister_name");
   /* Skip verify of register_type, has predicate.  */
-  /* Skip verify of dummy_id, has predicate.  */
+  /* Skip verify of dummy_id, invalid_p == 0 */
   /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
   /* Skip verify of push_dummy_call, has predicate.  */
   /* Skip verify of call_dummy_location, invalid_p == 0 */
@@ -609,8 +614,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of remote_register_number, invalid_p == 0 */
   /* Skip verify of fetch_tls_load_module_address, has predicate.  */
   /* Skip verify of frame_args_skip, invalid_p == 0 */
-  /* Skip verify of unwind_pc, has predicate.  */
-  /* Skip verify of unwind_sp, has predicate.  */
+  /* Skip verify of unwind_pc, invalid_p == 0 */
+  /* Skip verify of unwind_sp, invalid_p == 0 */
   /* Skip verify of frame_num_args, has predicate.  */
   /* Skip verify of frame_align, has predicate.  */
   /* Skip verify of stabs_argument_has_addr, invalid_p == 0 */
@@ -954,9 +959,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: dtrace_probe_is_enabled = <%s>\n",
                       host_address_to_string (gdbarch->dtrace_probe_is_enabled));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_dummy_id_p() = %d\n",
-                      gdbarch_dummy_id_p (gdbarch));
   fprintf_unfiltered (file,
                       "gdbarch_dump: dummy_id = <%s>\n",
                       host_address_to_string (gdbarch->dummy_id));
@@ -1440,15 +1442,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: type_align = <%s>\n",
                       host_address_to_string (gdbarch->type_align));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
-                      gdbarch_unwind_pc_p (gdbarch));
   fprintf_unfiltered (file,
                       "gdbarch_dump: unwind_pc = <%s>\n",
                       host_address_to_string (gdbarch->unwind_pc));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_unwind_sp_p() = %d\n",
-                      gdbarch_unwind_sp_p (gdbarch));
   fprintf_unfiltered (file,
                       "gdbarch_dump: unwind_sp = <%s>\n",
                       host_address_to_string (gdbarch->unwind_sp));
@@ -2307,13 +2303,6 @@ set_gdbarch_register_type (struct gdbarch *gdbarch,
   gdbarch->register_type = register_type;
 }
 
-int
-gdbarch_dummy_id_p (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  return gdbarch->dummy_id != NULL;
-}
-
 struct frame_id
 gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -3046,13 +3035,6 @@ set_gdbarch_frame_args_skip (struct gdbarch *gdbarch,
   gdbarch->frame_args_skip = frame_args_skip;
 }
 
-int
-gdbarch_unwind_pc_p (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  return gdbarch->unwind_pc != NULL;
-}
-
 CORE_ADDR
 gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
@@ -3070,13 +3052,6 @@ set_gdbarch_unwind_pc (struct gdbarch *gdbarch,
   gdbarch->unwind_pc = unwind_pc;
 }
 
-int
-gdbarch_unwind_sp_p (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  return gdbarch->unwind_sp != NULL;
-}
-
 CORE_ADDR
 gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
index e13c4699a607a4be44914fd40224870ea7806eb7..e53f4d4cb277d0d4201f084358c53c548b5666be 100644 (file)
@@ -403,7 +403,14 @@ typedef struct type * (gdbarch_register_type_ftype) (struct gdbarch *gdbarch, in
 extern struct type * gdbarch_register_type (struct gdbarch *gdbarch, int reg_nr);
 extern void set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch_register_type_ftype *register_type);
 
-extern int gdbarch_dummy_id_p (struct gdbarch *gdbarch);
+/* Generate a dummy frame_id for THIS_FRAME assuming that the frame is
+   a dummy frame.  A dummy frame is created before an inferior call,
+   the frame_id returned here must match the frame_id that was built
+   for the inferior call.  Usually this means the returned frame_id's
+   stack address should match the address returned by
+   gdbarch_push_dummy_call, and the returned frame_id's code address
+   should match the address at which the breakpoint was set in the dummy
+   frame. */
 
 typedef struct frame_id (gdbarch_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame);
 extern struct frame_id gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame);
@@ -645,14 +652,10 @@ extern void set_gdbarch_fetch_tls_load_module_address (struct gdbarch *gdbarch,
 extern CORE_ADDR gdbarch_frame_args_skip (struct gdbarch *gdbarch);
 extern void set_gdbarch_frame_args_skip (struct gdbarch *gdbarch, CORE_ADDR frame_args_skip);
 
-extern int gdbarch_unwind_pc_p (struct gdbarch *gdbarch);
-
 typedef CORE_ADDR (gdbarch_unwind_pc_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame);
 extern CORE_ADDR gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame);
 extern void set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch_unwind_pc_ftype *unwind_pc);
 
-extern int gdbarch_unwind_sp_p (struct gdbarch *gdbarch);
-
 typedef CORE_ADDR (gdbarch_unwind_sp_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame);
 extern CORE_ADDR gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame);
 extern void set_gdbarch_unwind_sp (struct gdbarch *gdbarch, gdbarch_unwind_sp_ftype *unwind_sp);
index a876a21555e603a74c2b808d0990ea462ef90b29..16065564ad8ee9f945f1ee9aab75deb7a134ce7d 100755 (executable)
@@ -480,7 +480,15 @@ m;const char *;register_name;int regnr;regnr;;0
 # use "register_type".
 M;struct type *;register_type;int reg_nr;reg_nr
 
-M;struct frame_id;dummy_id;struct frame_info *this_frame;this_frame
+# Generate a dummy frame_id for THIS_FRAME assuming that the frame is
+# a dummy frame.  A dummy frame is created before an inferior call,
+# the frame_id returned here must match the frame_id that was built
+# for the inferior call.  Usually this means the returned frame_id's
+# stack address should match the address returned by
+# gdbarch_push_dummy_call, and the returned frame_id's code address
+# should match the address at which the breakpoint was set in the dummy
+# frame.
+m;struct frame_id;dummy_id;struct frame_info *this_frame;this_frame;;default_dummy_id;;0
 # Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete
 # deprecated_fp_regnum.
 v;int;deprecated_fp_regnum;;;-1;-1;;0
@@ -596,8 +604,8 @@ m;int;remote_register_number;int regno;regno;;default_remote_register_number;;0
 F;CORE_ADDR;fetch_tls_load_module_address;struct objfile *objfile;objfile
 #
 v;CORE_ADDR;frame_args_skip;;;0;;;0
-M;CORE_ADDR;unwind_pc;struct frame_info *next_frame;next_frame
-M;CORE_ADDR;unwind_sp;struct frame_info *next_frame;next_frame
+m;CORE_ADDR;unwind_pc;struct frame_info *next_frame;next_frame;;default_unwind_pc;;0
+m;CORE_ADDR;unwind_sp;struct frame_info *next_frame;next_frame;;default_unwind_sp;;0
 # DEPRECATED_FRAME_LOCALS_ADDRESS as been replaced by the per-frame
 # frame-base.  Enable frame-base before frame-unwind.
 F;int;frame_num_args;struct frame_info *frame;frame
@@ -1690,6 +1698,8 @@ cat <<EOF
 #include "regcache.h"
 #include "objfiles.h"
 #include "auxv.h"
+#include "frame-unwind.h"
+#include "dummy-frame.h"
 
 /* Static function declarations */