Patchwork gdb: Add a default_unwind_pc method for gdbarch

login
register
mail settings
Submitter Andrew Burgess
Date March 7, 2018, 10:04 p.m.
Message ID <20180307220420.23307-1-andrew.burgess@embecosm.com>
Download mbox | patch
Permalink /patch/26236/
State New
Headers show

Comments

Andrew Burgess - March 7, 2018, 10:04 p.m.
As requested / suggested by Yao in this mail:

   https://sourceware.org/ml/gdb-patches/2018-03/msg00133.html

this patch provides a default implementation of unwind_pc and switches
over targets that I believe are "obviously" using the default strategy.

I've been pretty conservative about switching targets over, so targets
like arc that have some logging in place, but otherwise do the
standard thing, are left with their own unwind_pc method.

In frame.c I've removed the gdbarch_unwind_pc_p check (the predicate
is gone now) as it's assumed that all targets will have an
implementation either the default, or their own.  This function is
reindented, so it looks like a bigger change than it really is.

The problem with this patch is testing, there's been very little.  I
tested that every target I could build GDB for before still builds
after this patch, which covers all of the targets I touched, however,
I've done no functionality testing on the built GDBs.

Is there any interest in merging this patch?  I'm happy to run any
additional testing if I can be pointed to some instructions / hints
for what to do.

Thanks,
Andrew

--

Many architectures gdbarch unwind_pc method follow the same pattern.
Provide a default method and convert targets to use it where possible.

gdb/ChangeLog:

	* gdb/alpha-tdep.c (alpha_unwind_pc): Deleted.
	(alpha_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/bfin-tdep.c (bfin_unwind_pc): Deleted.
	(bfin_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/cris-tdep.c (cris_unwind_pc): Deleted.
	(cris_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* frame-unwind.c (default_unwind_pc): New function.
	* frame-unwind.h (default_unwind_pc): Declare new function.
	* frame.c: Remove use of gdbarch_unwind_pc_p and reindent.
	* gdb/frv-tdep.c (frv_unwind_pc): Deleted.
	(frv_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/ft32-tdep.c (ft32_unwind_pc): Deleted.
	(ft32_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh: Update unwind_pc spec, and add new header file to be
	included.
	* gdb/h8300-tdep.c (h8300_unwind_pc): Deleted.
	(h8300_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/iq2000-tdep.c (iq2000_unwind_pc): Deleted.
	(iq2000_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/lm32-tdep.c (lm32_unwind_pc): Deleted.
	(lm32_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/m32r-tdep.c (m32r_unwind_pc): Deleted.
	(m32r_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/m68hc11-tdep.c (m68hc11_unwind_pc): Deleted.
	(m68hc11_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/mep-tdep.c (mep_unwind_pc): Deleted.
	(mep_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/mn10300-tdep.c (mn10300_unwind_pc): Deleted.
	(mn10300_frame_unwind_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/moxie-tdep.c (moxie_unwind_pc): Deleted.
	(moxie_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/msp430-tdep.c (msp430_unwind_pc): Deleted.
	(msp430_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/nds32-tdep.c (nds32_unwind_pc): Deleted.
	(nds32_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/riscv-tdep.c (riscv_unwind_pc): Deleted.
	(riscv_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/rs6000-tdep.c (rs6000_unwind_pc): Deleted.
	(rs6000_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/rx-tdep.c (rx_unwind_pc): Deleted.
	(rx_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/score-tdep.c (score_unwind_pc): Deleted.
	(score_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/sh-tdep.c (sh_unwind_pc): Deleted.
	(sh_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/sh64-tdep.c (sh64_unwind_pc): Deleted.
	(sh64_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/tilegx-tdep.c (tilegx_unwind_pc): Deleted.
	(tilegx_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/v850-tdep.c (v850_unwind_pc): Deleted.
	(v850_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/vax-tdep.c (vax_unwind_pc): Deleted.
	(vax_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
	* gdb/xstormy16-tdep.c (xstormy16_unwind_pc): Deleted.
	(xstormy16_gdbarch_init): Delete use of set_gdbarch_unwind_pc.
---
 gdb/ChangeLog        |  60 ++++++++++++++++++++++++++
 gdb/alpha-tdep.c     |  11 -----
 gdb/bfin-tdep.c      |   7 ---
 gdb/cris-tdep.c      |  13 ------
 gdb/frame-unwind.c   |   9 ++++
 gdb/frame-unwind.h   |   6 +++
 gdb/frame.c          | 117 ++++++++++++++++++++++++---------------------------
 gdb/frv-tdep.c       |   7 ---
 gdb/ft32-tdep.c      |  10 -----
 gdb/gdbarch.c        |  14 ++----
 gdb/gdbarch.h        |   2 -
 gdb/gdbarch.sh       |   3 +-
 gdb/h8300-tdep.c     |   7 ---
 gdb/iq2000-tdep.c    |   7 ---
 gdb/lm32-tdep.c      |   7 ---
 gdb/m32r-tdep.c      |  11 -----
 gdb/m68hc11-tdep.c   |  14 ------
 gdb/mep-tdep.c       |   9 ----
 gdb/mn10300-tdep.c   |  10 -----
 gdb/moxie-tdep.c     |  10 -----
 gdb/msp430-tdep.c    |   9 ----
 gdb/nds32-tdep.c     |   9 ----
 gdb/riscv-tdep.c     |   9 ----
 gdb/rs6000-tdep.c    |   9 ----
 gdb/rx-tdep.c        |  11 -----
 gdb/score-tdep.c     |   7 ---
 gdb/sh-tdep.c        |   8 ----
 gdb/sh64-tdep.c      |   8 ----
 gdb/tilegx-tdep.c    |   7 ---
 gdb/v850-tdep.c      |   8 ----
 gdb/vax-tdep.c       |   8 ----
 gdb/xstormy16-tdep.c |   7 ---
 32 files changed, 136 insertions(+), 298 deletions(-)
Simon Marchi - March 8, 2018, 10:32 p.m.
On 2018-03-07 05:04 PM, Andrew Burgess wrote:
> As requested / suggested by Yao in this mail:
> 
>    https://sourceware.org/ml/gdb-patches/2018-03/msg00133.html
> 
> this patch provides a default implementation of unwind_pc and switches
> over targets that I believe are "obviously" using the default strategy.
> 
> I've been pretty conservative about switching targets over, so targets
> like arc that have some logging in place, but otherwise do the
> standard thing, are left with their own unwind_pc method.
> 
> In frame.c I've removed the gdbarch_unwind_pc_p check (the predicate
> is gone now) as it's assumed that all targets will have an
> implementation either the default, or their own.  This function is
> reindented, so it looks like a bigger change than it really is.
> 
> The problem with this patch is testing, there's been very little.  I
> tested that every target I could build GDB for before still builds
> after this patch, which covers all of the targets I touched, however,
> I've done no functionality testing on the built GDBs.
> 
> Is there any interest in merging this patch?  I'm happy to run any
> additional testing if I can be pointed to some instructions / hints
> for what to do.
> 
> Thanks,
> Andrew
> 
> --
> 
> Many architectures gdbarch unwind_pc method follow the same pattern.
> Provide a default method and convert targets to use it where possible.

Hi Andrew,

Patches that reduce duplication are always welcome :)

Do you have access to the buildbot to at least test your patch there?  It
only covers a fraction of the arches supported by GDB, but it's better than
nothing.  We can't expect a contributor to test on all supported arches.

Things that I think could be added to this patch:

- aarch64 seems like it could be converted too
- sparc too.  It passes tdep->pc_regnum, but from what I can tell
  gdbarch_pc_regnum is set to the same value, so it should be equivalent.

And maybe for a future patch, I wonder if we could generalize even more the
default method by applying in order:

  1. frame_unwind_register (next_frame, gdbarch_pc_regnum (gdbarch), buf);
  2. extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
  3. gdbarch_addr_bits_remove (gdbarch, addr)

That would allow removing a bunch of other implementations.  If an architecture
doesn't specify a custom pointer_to_address gdbarch method, extract_typed_address
will end up calling extract_unsigned_integer, which is similar to the current
behavior (just a different path to get there).  Arches that don't specify a custom
addr_bits_remove method use core_addr_identity, which is a no-op.

And for another future patch, could we apply the same treatment to *_unwind_sp?
Even *_dummy_id seem like it's always the same pattern.

Simon
Yao Qi - March 9, 2018, 3:54 p.m.
Simon Marchi <simon.marchi@ericsson.com> writes:

> Things that I think could be added to this patch:
>
> - aarch64 seems like it could be converted too
> - sparc too.  It passes tdep->pc_regnum, but from what I can tell
>   gdbarch_pc_regnum is set to the same value, so it should be equivalent.

Agreed.  FWIW, the patch is good to me.
Andrew Burgess - March 15, 2018, 9:51 p.m.
This revision follows up on Simon's feedback.

Patch #1 has been extended to cover aarch64 and sparc.

Patch #2 rewrites default_unwind_pc as suggested, and allows even more
targets to use the default.

Patch #3 adds a default_dummy_id.

Patch #4 adds a default_unwind_sp.

For testing I've built a wide range of targets, I believe that most of
the targets I've touched have been built.

I've tested on x86-64 GNU/Linux (though that target hasn't changed),
and I've also run this patch through buildbot without issue.

Is there any additional testing I should run?

All feedback appreciated.

Thanks,
Andrew

---

Andrew Burgess (4):
  gdb: Add a default_unwind_pc method for gdbarch
  gdb: Remove more targets unwind_pc methods
  gdb: Supply a default for gdbarch_dummy_id
  gdb: Supply default gdbarch_unwind_sp and use where possible

 gdb/ChangeLog        | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/aarch64-tdep.c   |  38 ---------
 gdb/alpha-tdep.c     |  29 -------
 gdb/arc-tdep.c       |  14 ----
 gdb/arm-tdep.c       |  37 ---------
 gdb/bfin-tdep.c      |  18 -----
 gdb/cris-tdep.c      |  40 ----------
 gdb/dummy-frame.c    |  16 ++++
 gdb/dummy-frame.h    |   6 ++
 gdb/frame-unwind.c   |  32 ++++++++
 gdb/frame-unwind.h   |  12 +++
 gdb/frame.c          | 132 ++++++++++++++----------------
 gdb/frv-tdep.c       |  27 -------
 gdb/ft32-tdep.c      |  33 --------
 gdb/gdbarch.c        |  41 ++--------
 gdb/gdbarch.h        |   6 --
 gdb/gdbarch.sh       |   8 +-
 gdb/h8300-tdep.c     |  22 -----
 gdb/hppa-tdep.c      |   9 ---
 gdb/i386-tdep.c      |  13 ---
 gdb/iq2000-tdep.c    |  22 -----
 gdb/lm32-tdep.c      |  23 ------
 gdb/m32r-tdep.c      |  37 ---------
 gdb/m68hc11-tdep.c   |  24 ------
 gdb/m68k-tdep.c      |  10 ---
 gdb/m88k-tdep.c      |  21 -----
 gdb/mep-tdep.c       |  30 -------
 gdb/mn10300-tdep.c   |  32 +-------
 gdb/moxie-tdep.c     |  33 --------
 gdb/msp430-tdep.c    |  31 --------
 gdb/nds32-tdep.c     |  29 -------
 gdb/nios2-tdep.c     |  35 +-------
 gdb/or1k-tdep.c      |  10 ---
 gdb/riscv-tdep.c     |  30 -------
 gdb/rl78-tdep.c      |  20 -----
 gdb/rs6000-tdep.c    |  19 -----
 gdb/rx-tdep.c        |  33 --------
 gdb/s390-tdep.c      |  12 ---
 gdb/score-tdep.c     |  23 ------
 gdb/sh-tdep.c        |  25 ------
 gdb/sh64-tdep.c      |  25 ------
 gdb/sparc-tdep.c     |   9 ---
 gdb/tic6x-tdep.c     |  35 --------
 gdb/tilegx-tdep.c    |  26 ------
 gdb/v850-tdep.c      |  25 ------
 gdb/vax-tdep.c       |   8 --
 gdb/xstormy16-tdep.c |  23 ------
 47 files changed, 361 insertions(+), 1043 deletions(-)
Andrew Burgess - April 10, 2018, 10:13 a.m.
Ping.

Thanks,
Andrew

* Andrew Burgess <andrew.burgess@embecosm.com> [2018-03-15 21:51:20 +0000]:

> This revision follows up on Simon's feedback.
> 
> Patch #1 has been extended to cover aarch64 and sparc.
> 
> Patch #2 rewrites default_unwind_pc as suggested, and allows even more
> targets to use the default.
> 
> Patch #3 adds a default_dummy_id.
> 
> Patch #4 adds a default_unwind_sp.
> 
> For testing I've built a wide range of targets, I believe that most of
> the targets I've touched have been built.
> 
> I've tested on x86-64 GNU/Linux (though that target hasn't changed),
> and I've also run this patch through buildbot without issue.
> 
> Is there any additional testing I should run?
> 
> All feedback appreciated.
> 
> Thanks,
> Andrew
> 
> ---
> 
> Andrew Burgess (4):
>   gdb: Add a default_unwind_pc method for gdbarch
>   gdb: Remove more targets unwind_pc methods
>   gdb: Supply a default for gdbarch_dummy_id
>   gdb: Supply default gdbarch_unwind_sp and use where possible
> 
>  gdb/ChangeLog        | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/aarch64-tdep.c   |  38 ---------
>  gdb/alpha-tdep.c     |  29 -------
>  gdb/arc-tdep.c       |  14 ----
>  gdb/arm-tdep.c       |  37 ---------
>  gdb/bfin-tdep.c      |  18 -----
>  gdb/cris-tdep.c      |  40 ----------
>  gdb/dummy-frame.c    |  16 ++++
>  gdb/dummy-frame.h    |   6 ++
>  gdb/frame-unwind.c   |  32 ++++++++
>  gdb/frame-unwind.h   |  12 +++
>  gdb/frame.c          | 132 ++++++++++++++----------------
>  gdb/frv-tdep.c       |  27 -------
>  gdb/ft32-tdep.c      |  33 --------
>  gdb/gdbarch.c        |  41 ++--------
>  gdb/gdbarch.h        |   6 --
>  gdb/gdbarch.sh       |   8 +-
>  gdb/h8300-tdep.c     |  22 -----
>  gdb/hppa-tdep.c      |   9 ---
>  gdb/i386-tdep.c      |  13 ---
>  gdb/iq2000-tdep.c    |  22 -----
>  gdb/lm32-tdep.c      |  23 ------
>  gdb/m32r-tdep.c      |  37 ---------
>  gdb/m68hc11-tdep.c   |  24 ------
>  gdb/m68k-tdep.c      |  10 ---
>  gdb/m88k-tdep.c      |  21 -----
>  gdb/mep-tdep.c       |  30 -------
>  gdb/mn10300-tdep.c   |  32 +-------
>  gdb/moxie-tdep.c     |  33 --------
>  gdb/msp430-tdep.c    |  31 --------
>  gdb/nds32-tdep.c     |  29 -------
>  gdb/nios2-tdep.c     |  35 +-------
>  gdb/or1k-tdep.c      |  10 ---
>  gdb/riscv-tdep.c     |  30 -------
>  gdb/rl78-tdep.c      |  20 -----
>  gdb/rs6000-tdep.c    |  19 -----
>  gdb/rx-tdep.c        |  33 --------
>  gdb/s390-tdep.c      |  12 ---
>  gdb/score-tdep.c     |  23 ------
>  gdb/sh-tdep.c        |  25 ------
>  gdb/sh64-tdep.c      |  25 ------
>  gdb/sparc-tdep.c     |   9 ---
>  gdb/tic6x-tdep.c     |  35 --------
>  gdb/tilegx-tdep.c    |  26 ------
>  gdb/v850-tdep.c      |  25 ------
>  gdb/vax-tdep.c       |   8 --
>  gdb/xstormy16-tdep.c |  23 ------
>  47 files changed, 361 insertions(+), 1043 deletions(-)
> 
> -- 
> 2.14.3
>
Andrew Burgess - June 5, 2018, 2:34 p.m.
Ping!

Patch rebased and retested on current HEAD.

Thanks,
Andrew

---

Andrew Burgess (4):
  gdb: Add a default_unwind_pc method for gdbarch
  gdb: Remove more targets unwind_pc methods
  gdb: Supply a default for gdbarch_dummy_id
  gdb: Supply default gdbarch_unwind_sp and use where possible

 gdb/ChangeLog        | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/aarch64-tdep.c   |  38 ----------
 gdb/alpha-tdep.c     |  29 -------
 gdb/arc-tdep.c       |  14 ----
 gdb/arm-tdep.c       |  37 ---------
 gdb/bfin-tdep.c      |  18 -----
 gdb/cris-tdep.c      |  40 ----------
 gdb/dummy-frame.c    |  16 ++++
 gdb/dummy-frame.h    |   6 ++
 gdb/frame-unwind.c   |  31 ++++++++
 gdb/frame-unwind.h   |  12 +++
 gdb/frame.c          | 132 ++++++++++++++------------------
 gdb/frv-tdep.c       |  27 -------
 gdb/ft32-tdep.c      |  33 --------
 gdb/gdbarch.c        |  41 ++--------
 gdb/gdbarch.h        |   6 --
 gdb/gdbarch.sh       |   8 +-
 gdb/h8300-tdep.c     |  22 ------
 gdb/hppa-tdep.c      |   9 ---
 gdb/i386-tdep.c      |  13 ----
 gdb/iq2000-tdep.c    |  22 ------
 gdb/lm32-tdep.c      |  23 ------
 gdb/m32r-tdep.c      |  37 ---------
 gdb/m68hc11-tdep.c   |  24 ------
 gdb/m68k-tdep.c      |  10 ---
 gdb/mep-tdep.c       |  30 --------
 gdb/mn10300-tdep.c   |  32 +-------
 gdb/moxie-tdep.c     |  33 --------
 gdb/msp430-tdep.c    |  31 --------
 gdb/nds32-tdep.c     |  29 -------
 gdb/nios2-tdep.c     |  35 +--------
 gdb/or1k-tdep.c      |  10 ---
 gdb/riscv-tdep.c     |  30 --------
 gdb/rl78-tdep.c      |  20 -----
 gdb/rs6000-tdep.c    |  19 -----
 gdb/rx-tdep.c        |  33 --------
 gdb/s390-tdep.c      |  12 ---
 gdb/score-tdep.c     |  23 ------
 gdb/sh-tdep.c        |  25 ------
 gdb/sparc-tdep.c     |   9 ---
 gdb/tic6x-tdep.c     |  35 ---------
 gdb/tilegx-tdep.c    |  26 -------
 gdb/v850-tdep.c      |  25 ------
 gdb/vax-tdep.c       |   8 --
 gdb/xstormy16-tdep.c |  23 ------
 45 files changed, 350 insertions(+), 997 deletions(-)

Patch

diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index 52a46d96eaf..81ee43c9fa4 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -1479,14 +1479,6 @@  alpha_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
   return frame_id_build (base, get_frame_pc (this_frame));
 }
 
-static CORE_ADDR
-alpha_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  ULONGEST pc;
-  pc = frame_unwind_register_unsigned (next_frame, ALPHA_PC_REGNUM);
-  return pc;
-}
-
 
 /* Helper routines for alpha*-nat.c files to move register sets to and
    from core files.  The UNIQUE pointer is allowed to be NULL, as most
@@ -1813,9 +1805,6 @@  alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Methods for saving / extracting a dummy frame's ID.  */
   set_gdbarch_dummy_id (gdbarch, alpha_dummy_id);
 
-  /* Return the unwound PC value.  */
-  set_gdbarch_unwind_pc (gdbarch, alpha_unwind_pc);
-
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
 
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index 63fbf6209e2..696786dc1b0 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -766,12 +766,6 @@  bfin_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
   return frame_id_build (sp, get_frame_pc (this_frame));
 }
 
-static CORE_ADDR
-bfin_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, BFIN_PC_REGNUM);
-}
-
 static CORE_ADDR
 bfin_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
 {
@@ -836,7 +830,6 @@  bfin_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, bfin_sw_breakpoint_from_kind);
   set_gdbarch_decr_pc_after_break (gdbarch, 2);
   set_gdbarch_frame_args_skip (gdbarch, 8);
-  set_gdbarch_unwind_pc (gdbarch, bfin_unwind_pc);
   set_gdbarch_frame_align (gdbarch, bfin_frame_align);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 5fa79ef2cfa..74368b7b0a4 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -651,9 +651,6 @@  static CORE_ADDR crisv32_scan_prologue (CORE_ADDR pc,
 					struct frame_info *this_frame,
 					struct cris_unwind_cache *info);
 
-static CORE_ADDR cris_unwind_pc (struct gdbarch *gdbarch, 
-				 struct frame_info *next_frame);
-
 static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch, 
 				 struct frame_info *next_frame);
 
@@ -1373,15 +1370,6 @@  cris_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return pc_after_prologue;
 }
 
-static CORE_ADDR
-cris_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  ULONGEST pc;
-  pc = frame_unwind_register_unsigned (next_frame,
-				       gdbarch_pc_regnum (gdbarch));
-  return pc;
-}
-
 static CORE_ADDR
 cris_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
@@ -4096,7 +4084,6 @@  cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_breakpoint_kind_from_pc (gdbarch, cris_breakpoint_kind_from_pc);
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, cris_sw_breakpoint_from_kind);
   
-  set_gdbarch_unwind_pc (gdbarch, cris_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp);
   set_gdbarch_dummy_id (gdbarch, cris_dummy_id);
 
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index e6e63539ad7..0eed572ebbb 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -193,6 +193,15 @@  default_frame_unwind_stop_reason (struct frame_info *this_frame,
     return UNWIND_NO_REASON;
 }
 
+/* Default unwind of the PC.  */
+
+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);
+}
+
 /* Helper functions for value-based register unwinding.  These return
    a (possibly lazy) value of the appropriate type.  */
 
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
index af220f72a01..4dfc7bedcc6 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -70,6 +70,12 @@  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);
+
 /* 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.
diff --git a/gdb/frame.c b/gdb/frame.c
index 0b04a4ebacb..340dc99d5af 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -856,76 +856,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)
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index 2f9a8d27c46..38f996d2e5c 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -1366,12 +1366,6 @@  frv_return_value (struct gdbarch *gdbarch, struct value *function,
     return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-static CORE_ADDR
-frv_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, pc_regnum);
-}
-
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
@@ -1539,7 +1533,6 @@  frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_return_value (gdbarch, frv_return_value);
 
   /* Frame stuff.  */
-  set_gdbarch_unwind_pc (gdbarch, frv_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, frv_unwind_sp);
   set_gdbarch_frame_align (gdbarch, frv_frame_align);
   frame_base_set_default (gdbarch, &frv_frame_base);
diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c
index 7198b84aca0..5c0a3384dbd 100644
--- a/gdb/ft32-tdep.c
+++ b/gdb/ft32-tdep.c
@@ -492,14 +492,6 @@  ft32_frame_cache (struct frame_info *this_frame, void **this_cache)
   return cache;
 }
 
-/* Implement the "unwind_pc" gdbarch method.  */
-
-static CORE_ADDR
-ft32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, FT32_PC_REGNUM);
-}
-
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
@@ -627,8 +619,6 @@  ft32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
   set_gdbarch_dummy_id (gdbarch, ft32_dummy_id);
 
-  set_gdbarch_unwind_pc (gdbarch, ft32_unwind_pc);
-
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index b8703e5a556..884b7b24f86 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -48,6 +48,7 @@ 
 #include "regcache.h"
 #include "objfiles.h"
 #include "auxv.h"
+#include "frame-unwind.h"
 
 /* Static function declarations */
 
@@ -426,6 +427,7 @@  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->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;
@@ -612,7 +614,7 @@  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_pc, invalid_p == 0 */
   /* Skip verify of unwind_sp, has predicate.  */
   /* Skip verify of frame_num_args, has predicate.  */
   /* Skip verify of frame_align, has predicate.  */
@@ -1435,9 +1437,6 @@  gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: target_desc = %s\n",
                       host_address_to_string (gdbarch->target_desc));
-  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));
@@ -3058,13 +3057,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)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 5cb131de1d2..2ac229cda3a 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -625,8 +625,6 @@  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);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 33dfa6b349d..9eab0b30321 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -599,7 +599,7 @@  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_pc;struct frame_info *next_frame;next_frame;;default_unwind_pc;;0
 M;CORE_ADDR;unwind_sp;struct frame_info *next_frame;next_frame
 # DEPRECATED_FRAME_LOCALS_ADDRESS as been replaced by the per-frame
 # frame-base.  Enable frame-base before frame-unwind.
@@ -1648,6 +1648,7 @@  cat <<EOF
 #include "regcache.h"
 #include "objfiles.h"
 #include "auxv.h"
+#include "frame-unwind.h"
 
 /* Static function declarations */
 
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index 55e77b6bb6e..b7670ea2cec 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -92,12 +92,6 @@  static int is_h8300_normal_mode (struct gdbarch *gdbarch);
 		  && !is_h8300_normal_mode (gdbarch)) \
 		 ? h8300h_reg_size : h8300_reg_size)
 
-static CORE_ADDR
-h8300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
-}
-
 static CORE_ADDR
 h8300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
@@ -1353,7 +1347,6 @@  h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_prologue (gdbarch, h8300_skip_prologue);
 
   /* Frame unwinder.  */
-  set_gdbarch_unwind_pc (gdbarch, h8300_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, h8300_unwind_sp);
   set_gdbarch_dummy_id (gdbarch, h8300_dummy_id);
   frame_base_set_default (gdbarch, &h8300_frame_base);
diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c
index f8e2f234e02..9316bbb852f 100644
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -440,12 +440,6 @@  iq2000_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
 }   
 
-static CORE_ADDR
-iq2000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
-}
-
 static struct frame_id
 iq2000_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -841,7 +835,6 @@  iq2000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_type (gdbarch, iq2000_register_type);
   set_gdbarch_frame_align (gdbarch, iq2000_frame_align);
   set_gdbarch_unwind_sp (gdbarch, iq2000_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, iq2000_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, iq2000_dummy_id);
   frame_base_set_default (gdbarch, &iq2000_frame_base);
   set_gdbarch_push_dummy_call (gdbarch, iq2000_push_dummy_call);
diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c
index 942852140d7..26f2faee365 100644
--- a/gdb/lm32-tdep.c
+++ b/gdb/lm32-tdep.c
@@ -382,12 +382,6 @@  lm32_return_value (struct gdbarch *gdbarch, struct value *function,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-static CORE_ADDR
-lm32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, SIM_LM32_PC_REGNUM);
-}
-
 static CORE_ADDR
 lm32_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
@@ -551,7 +545,6 @@  lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Frame unwinding.  */
   set_gdbarch_frame_align (gdbarch, lm32_frame_align);
   frame_base_set_default (gdbarch, &lm32_frame_base);
-  set_gdbarch_unwind_pc (gdbarch, lm32_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, lm32_unwind_sp);
   set_gdbarch_dummy_id (gdbarch, lm32_dummy_id);
   frame_unwind_append_unwinder (gdbarch, &lm32_frame_unwind);
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
index fd79f3f4cde..9bfff6b0675 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -798,14 +798,6 @@  m32r_return_value (struct gdbarch *gdbarch, struct value *function,
     }
 }
 
-
-
-static CORE_ADDR
-m32r_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, M32R_PC_REGNUM);
-}
-
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
@@ -933,9 +925,6 @@  m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
   set_gdbarch_dummy_id (gdbarch, m32r_dummy_id);
 
-  /* Return the unwound PC value.  */
-  set_gdbarch_unwind_pc (gdbarch, m32r_unwind_pc);
-
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index 58ef4a32927..9855c023d4d 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -757,16 +757,6 @@  m68hc11_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return pc;
 }
 
-static CORE_ADDR
-m68hc11_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  ULONGEST pc;
-
-  pc = frame_unwind_register_unsigned (next_frame,
-				       gdbarch_pc_regnum (gdbarch));
-  return pc;
-}
-
 /* Put here the code to store, into fi->saved_regs, the addresses of
    the saved registers of frame described by FRAME_INFO.  This
    includes special registers such as pc and fp saved in special ways
@@ -1494,7 +1484,6 @@  m68hc11_gdbarch_init (struct gdbarch_info info,
   /* Characters are unsigned.  */
   set_gdbarch_char_signed (gdbarch, 0);
 
-  set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, m68hc11_unwind_sp);
 
   /* Set register info.  */
@@ -1531,9 +1520,6 @@  m68hc11_gdbarch_init (struct gdbarch_info info,
      PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
   set_gdbarch_dummy_id (gdbarch, m68hc11_dummy_id);
 
-  /* Return the unwound PC value.  */
-  set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
-
   /* Minsymbol frobbing.  */
   set_gdbarch_elf_make_msymbol_special (gdbarch,
                                         m68hc11_elf_make_msymbol_special);
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index 1cda2b35af9..af921a86c0c 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -2066,14 +2066,6 @@  static const struct frame_unwind mep_frame_unwind = {
 };
 
 
-/* Our general unwinding function can handle unwinding the PC.  */
-static CORE_ADDR
-mep_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, MEP_PC_REGNUM);
-}
-
-
 /* Our general unwinding function can handle unwinding the SP.  */
 static CORE_ADDR
 mep_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
@@ -2468,7 +2460,6 @@  mep_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Frames and frame unwinding.  */
   frame_unwind_append_unwinder (gdbarch, &mep_frame_unwind);
-  set_gdbarch_unwind_pc (gdbarch, mep_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, mep_unwind_sp);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_frame_args_skip (gdbarch, 0);
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index e12e01df030..0222b3192d1 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -1150,15 +1150,6 @@  static const struct frame_unwind mn10300_frame_unwind = {
   default_frame_sniffer
 };
 
-static CORE_ADDR
-mn10300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  ULONGEST pc;
-
-  pc = frame_unwind_register_unsigned (this_frame, E_PC_REGNUM);
-  return pc;
-}
-
 static CORE_ADDR
 mn10300_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -1174,7 +1165,6 @@  mn10300_frame_unwind_init (struct gdbarch *gdbarch)
   dwarf2_append_unwinders (gdbarch);
   frame_unwind_append_unwinder (gdbarch, &mn10300_frame_unwind);
   set_gdbarch_dummy_id (gdbarch, mn10300_dummy_id);
-  set_gdbarch_unwind_pc (gdbarch, mn10300_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, mn10300_unwind_sp);
 }
 
diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c
index 50cacfef972..2ef1b753109 100644
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -557,14 +557,6 @@  moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
   return cache;
 }
 
-/* Implement the "unwind_pc" gdbarch method.  */
-
-static CORE_ADDR
-moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
-}
-
 /* Given a GDB frame, determine the address of the calling function's
    frame.  This will be used to create a new GDB frame struct.  */
 
@@ -1115,8 +1107,6 @@  moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
   set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
 
-  set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
-
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index 169b7e95058..008a178e993 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -447,14 +447,6 @@  msp430_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return p.prologue_end;
 }
 
-/* Implement the "unwind_pc" gdbarch method.  */
-
-static CORE_ADDR
-msp430_unwind_pc (struct gdbarch *arch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, MSP430_PC_REGNUM);
-}
-
 /* Implement the "unwind_sp" gdbarch method.  */
 
 static CORE_ADDR
@@ -995,7 +987,6 @@  msp430_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Frames, prologues, etc.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_skip_prologue (gdbarch, msp430_skip_prologue);
-  set_gdbarch_unwind_pc (gdbarch, msp430_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, msp430_unwind_sp);
   set_gdbarch_frame_align (gdbarch, msp430_frame_align);
   dwarf2_append_unwinders (gdbarch);
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
index 8cc9d5bc84c..9fe4f6916e3 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -1398,14 +1398,6 @@  nds32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
   return frame_id_build (sp, get_frame_pc (this_frame));
 }
 
-/* Implement the "unwind_pc" gdbarch method.  */
-
-static CORE_ADDR
-nds32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, NDS32_PC_REGNUM);
-}
-
 /* Implement the "unwind_sp" gdbarch method.  */
 
 static CORE_ADDR
@@ -2141,7 +2133,6 @@  nds32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_sp_regnum (gdbarch, NDS32_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, NDS32_PC_REGNUM);
   set_gdbarch_unwind_sp (gdbarch, nds32_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, nds32_unwind_pc);
   set_gdbarch_stack_frame_destroyed_p (gdbarch, nds32_stack_frame_destroyed_p);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, nds32_dwarf2_reg_to_regnum);
 
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 11b12279321..923ed74cdf7 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -2326,14 +2326,6 @@  riscv_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
   return align_down (addr, 16);
 }
 
-/* Implement the unwind_pc gdbarch method.  */
-
-static CORE_ADDR
-riscv_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, RISCV_PC_REGNUM);
-}
-
 /* Implement the unwind_sp gdbarch method.  */
 
 static CORE_ADDR
@@ -2548,7 +2540,6 @@  riscv_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_frame_align (gdbarch, riscv_frame_align);
 
   /* Functions to access frame data.  */
-  set_gdbarch_unwind_pc (gdbarch, riscv_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, riscv_unwind_sp);
 
   /* Functions handling dummy frames.  */
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index a5b70917b7e..66c88d452f5 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -3255,13 +3255,6 @@  find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
 }
 
 
-static CORE_ADDR
-rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-					 gdbarch_pc_regnum (gdbarch));
-}
-
 static struct frame_id
 rs6000_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -6578,7 +6571,6 @@  rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     case GDB_OSABI_LINUX:
     case GDB_OSABI_NETBSD:
     case GDB_OSABI_UNKNOWN:
-      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
       frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
       frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
       set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
@@ -6587,7 +6579,6 @@  rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     default:
       set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
-      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
       frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
       frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
       set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index 94d57913a31..3d982795db4 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -751,16 +751,6 @@  static const struct frame_unwind rx_exception_unwind = {
   rx_exception_sniffer
 };
 
-/* Implement the "unwind_pc" gdbarch method.  */
-static CORE_ADDR
-rx_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  ULONGEST pc;
-
-  pc = frame_unwind_register_unsigned (this_frame, RX_PC_REGNUM);
-  return pc;
-}
-
 /* Implement the "unwind_sp" gdbarch method.  */
 static CORE_ADDR
 rx_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
@@ -1110,7 +1100,6 @@  rx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, rx_breakpoint::bp_from_kind);
   set_gdbarch_skip_prologue (gdbarch, rx_skip_prologue);
 
-  set_gdbarch_unwind_pc (gdbarch, rx_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, rx_unwind_sp);
 
   /* Target builtin data types.  */
diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c
index a1679323273..c0f1291ed52 100644
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -70,12 +70,6 @@  score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM);
 }
 
-static CORE_ADDR
-score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM);
-}
-
 static const char *
 score7_register_name (struct gdbarch *gdbarch, int regnum)
 {
@@ -1481,7 +1475,6 @@  score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_frame_align (gdbarch, score_frame_align);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_unwind_sp (gdbarch, score_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, score_unwind_pc);
 
   switch (target_mach)
     {
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 75ea673b82a..2f022909d6d 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1983,13 +1983,6 @@  sh_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 					 gdbarch_sp_regnum (gdbarch));
 }
 
-static CORE_ADDR
-sh_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-					 gdbarch_pc_regnum (gdbarch));
-}
-
 static struct frame_id
 sh_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -2311,7 +2304,6 @@  sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_frame_align (gdbarch, sh_frame_align);
   set_gdbarch_unwind_sp (gdbarch, sh_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, sh_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, sh_dummy_id);
   frame_base_set_default (gdbarch, &sh_frame_base);
 
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index 8eb88eb3adf..9066c7cd9fe 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -2319,13 +2319,6 @@  sh64_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 					 gdbarch_sp_regnum (gdbarch));
 }
 
-static CORE_ADDR
-sh64_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-					 gdbarch_pc_regnum (gdbarch));
-}
-
 static struct frame_id
 sh64_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -2421,7 +2414,6 @@  sh64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_frame_align (gdbarch, sh64_frame_align);
   set_gdbarch_unwind_sp (gdbarch, sh64_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, sh64_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, sh64_dummy_id);
   frame_base_set_default (gdbarch, &sh64_frame_base);
 
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 8f688b16cf0..2ed32e3dfa8 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -936,12 +936,6 @@  tilegx_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_unwind_register_unsigned (next_frame, TILEGX_SP_REGNUM);
 }
 
-static CORE_ADDR
-tilegx_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, TILEGX_PC_REGNUM);
-}
-
 static struct frame_id
 tilegx_unwind_dummy_id (struct gdbarch *gdbarch,
 			struct frame_info *this_frame)
@@ -1028,7 +1022,6 @@  tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Frame Info.  */
   set_gdbarch_unwind_sp (gdbarch, tilegx_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, tilegx_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, tilegx_unwind_dummy_id);
   set_gdbarch_frame_align (gdbarch, tilegx_frame_align);
   frame_base_set_default (gdbarch, &tilegx_frame_base);
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index ac7d6aa4240..ce8b400fcdb 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -1333,13 +1333,6 @@  v850_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 					 gdbarch_sp_regnum (gdbarch));
 } 
 
-static CORE_ADDR
-v850_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame,
-					 gdbarch_pc_regnum (gdbarch));
-}
-
 static struct frame_id
 v850_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -1465,7 +1458,6 @@  v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_frame_align (gdbarch, v850_frame_align);
   set_gdbarch_unwind_sp (gdbarch, v850_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, v850_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, v850_dummy_id);
   frame_base_set_default (gdbarch, &v850_frame_base);
 
diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c
index 4c1ab2e73e6..a8c2b31dbdc 100644
--- a/gdb/vax-tdep.c
+++ b/gdb/vax-tdep.c
@@ -435,12 +435,6 @@  vax_frame_num_args (struct frame_info *frame)
   args = get_frame_register_unsigned (frame, VAX_AP_REGNUM);
   return get_frame_memory_unsigned (frame, args, 1);
 }
-
-static CORE_ADDR
-vax_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, VAX_PC_REGNUM);
-}
 
 
 /* Initialize the current architecture based on INFO.  If possible, re-use an
@@ -501,8 +495,6 @@  vax_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_deprecated_function_start_offset (gdbarch, 2);
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
-  set_gdbarch_unwind_pc (gdbarch, vax_unwind_pc);
-
   frame_base_set_default (gdbarch, &vax_frame_base);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c
index 31650ac3a95..4d5c50e0755 100644
--- a/gdb/xstormy16-tdep.c
+++ b/gdb/xstormy16-tdep.c
@@ -757,12 +757,6 @@  xstormy16_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
 }
 
-static CORE_ADDR
-xstormy16_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
-  return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
-}
-
 static struct frame_id
 xstormy16_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
@@ -825,7 +819,6 @@  xstormy16_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
    * Frame Info
    */
   set_gdbarch_unwind_sp (gdbarch, xstormy16_unwind_sp);
-  set_gdbarch_unwind_pc (gdbarch, xstormy16_unwind_pc);
   set_gdbarch_dummy_id (gdbarch, xstormy16_dummy_id);
   set_gdbarch_frame_align (gdbarch, xstormy16_frame_align);
   frame_base_set_default (gdbarch, &xstormy16_frame_base);