Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: Guinevere Larsen <guinevere@redhat.com>, gdb-patches@sourceware.org
Cc: Guinevere Larsen <guinevere@redhat.com>,
	Thiago Jung Bauermann <thiago.bauermann@linaro.org>,
	Simon Marchi <simon.marchi@efficios.com>
Subject: Re: [PATCH v8 3/5] gdb: Migrate frame unwinders to use C++ classes
Date: Tue, 14 Jan 2025 17:13:38 +0000	[thread overview]
Message-ID: <87zfjtpbct.fsf@redhat.com> (raw)
In-Reply-To: <20241210195115.3046370-4-guinevere@redhat.com>

Guinevere Larsen <guinevere@redhat.com> writes:

> Frame unwinders have historically been a structure populated with
> callback pointers, so that architectures (or other specific unwinders)
> could install their own way to handle the inferior. However, since
> moving to C++, we could use polymorphism to get the same functionality
> in a more readable way. Polymorphism also makes it simpler to add new
> functionality to all frame unwinders, since all that's required is
> adding it to the base class.
>
> As part of the changes to add support to disabling frame unwinders,
> this commit makes the first baby step in  using polymorphism for the
> frame unwinders, by making frame_unwind a virtual class, and adds a
> couple of new classes. The main class added is frame_unwind_legacy,
> which works the same as the previous structs, using function pointers
> as callbacks. This class was added to allow the transition to happen
> piecemeal. New unwinders should instead follow the lead of the other
> classes implemented.
>
> 2 of the others, frame_unwind_python and frame_unwind_trampoline, were added
> because it seemed simpler at the moment to do that instead of reworking
> the dynamic allocation to work with the legacy class, and can be used as
> an example to future implementations.
>
> Finally, the cygwin unwinder was converted to a class since it was most
> of the way there already.
>
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> Approved-By: Simon Marchi <simon.marchi@efficios.com>
> ---
>  gdb/aarch64-tdep.c          |  10 +--
>  gdb/alpha-mdebug-tdep.c     |   5 +-
>  gdb/alpha-tdep.c            |  10 +--
>  gdb/amd64-obsd-tdep.c       |   5 +-
>  gdb/amd64-tdep.c            |  20 ++---
>  gdb/amd64-windows-tdep.c    |   5 +-
>  gdb/amdgpu-tdep.c           |   6 +-
>  gdb/arc-tdep.c              |   8 +-
>  gdb/arm-tdep.c              |  24 +++---
>  gdb/avr-tdep.c              |   4 +-
>  gdb/bfin-tdep.c             |   5 +-
>  gdb/bpf-tdep.c              |   5 +-
>  gdb/cris-tdep.c             |  10 +--
>  gdb/csky-tdep.c             |   8 +-
>  gdb/dummy-frame.c           |   7 +-
>  gdb/dummy-frame.h           |   2 +-
>  gdb/dwarf2/frame-tailcall.c |   5 +-
>  gdb/dwarf2/frame-tailcall.h |   2 +-
>  gdb/dwarf2/frame.c          |  14 ++--
>  gdb/frame-unwind.c          |  68 +++++++++++++++--
>  gdb/frame-unwind.h          | 147 ++++++++++++++++++++++++++++++++----
>  gdb/frame.c                 |  21 ++----
>  gdb/frv-linux-tdep.c        |   5 +-
>  gdb/frv-tdep.c              |   4 +-
>  gdb/ft32-tdep.c             |   5 +-
>  gdb/h8300-tdep.c            |   4 +-
>  gdb/hppa-linux-tdep.c       |   4 +-
>  gdb/hppa-tdep.c             |  14 ++--
>  gdb/i386-obsd-tdep.c        |   4 +-
>  gdb/i386-tdep.c             |  25 +++---
>  gdb/ia64-tdep.c             |  20 ++---
>  gdb/inline-frame.c          |   4 +-
>  gdb/inline-frame.h          |   2 +-
>  gdb/iq2000-tdep.c           |   4 +-
>  gdb/jit.c                   |   5 +-
>  gdb/lm32-tdep.c             |   4 +-
>  gdb/loongarch-tdep.c        |   6 +-
>  gdb/m32c-tdep.c             |   4 +-
>  gdb/m32r-linux-tdep.c       |   4 +-
>  gdb/m32r-tdep.c             |   4 +-
>  gdb/m68hc11-tdep.c          |   4 +-
>  gdb/m68k-linux-tdep.c       |   5 +-
>  gdb/m68k-tdep.c             |   5 +-
>  gdb/mep-tdep.c              |   4 +-
>  gdb/microblaze-tdep.c       |   5 +-
>  gdb/mips-sde-tdep.c         |   5 +-
>  gdb/mips-tdep.c             |  20 ++---
>  gdb/mn10300-tdep.c          |   4 +-
>  gdb/moxie-tdep.c            |   4 +-
>  gdb/msp430-tdep.c           |   4 +-
>  gdb/nds32-tdep.c            |  12 ++-
>  gdb/or1k-tdep.c             |   6 +-
>  gdb/ppc-fbsd-tdep.c         |   4 +-
>  gdb/ppc-obsd-tdep.c         |   4 +-
>  gdb/python/py-unwind.c      |  62 +++++++++------
>  gdb/record-btrace.c         |  10 +--
>  gdb/record.h                |   4 +-
>  gdb/riscv-tdep.c            |   7 +-
>  gdb/rl78-tdep.c             |   5 +-
>  gdb/rs6000-aix-tdep.c       |   4 +-
>  gdb/rs6000-tdep.c           |  10 +--
>  gdb/rx-tdep.c               |   8 +-
>  gdb/s12z-tdep.c             |   6 +-
>  gdb/s390-linux-tdep.c       |   4 +-
>  gdb/s390-tdep.c             |   8 +-
>  gdb/sentinel-frame.c        |   7 +-
>  gdb/sentinel-frame.h        |   2 +-
>  gdb/sh-tdep.c               |   9 +--
>  gdb/sparc-netbsd-tdep.c     |   5 +-
>  gdb/sparc-obsd-tdep.c       |   5 +-
>  gdb/sparc-sol2-tdep.c       |   5 +-
>  gdb/sparc-tdep.c            |   5 +-
>  gdb/sparc64-fbsd-tdep.c     |   5 +-
>  gdb/sparc64-netbsd-tdep.c   |   5 +-
>  gdb/sparc64-obsd-tdep.c     |  10 +--
>  gdb/sparc64-sol2-tdep.c     |   5 +-
>  gdb/sparc64-tdep.c          |   5 +-
>  gdb/tic6x-tdep.c            |  10 +--
>  gdb/tilegx-tdep.c           |   4 +-
>  gdb/tramp-frame.c           |  71 +++++++++++------
>  gdb/v850-tdep.c             |   4 +-
>  gdb/vax-tdep.c              |   5 +-
>  gdb/windows-tdep.c          |  35 ++++-----
>  gdb/windows-tdep.h          |  16 +++-
>  gdb/xstormy16-tdep.c        |   4 +-
>  gdb/xtensa-tdep.c           |   6 +-
>  gdb/z80-tdep.c              |   6 +-
>  87 files changed, 553 insertions(+), 403 deletions(-)
>
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index e5498089ca9..840f9877361 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -1205,8 +1205,7 @@ aarch64_prologue_prev_register (const frame_info_ptr &this_frame,
>  }
>  
>  /* AArch64 prologue unwinder.  */
> -static frame_unwind aarch64_prologue_unwind =
> -{
> +static const frame_unwind_legacy aarch64_prologue_unwind (
>    "aarch64 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1215,7 +1214,7 @@ static frame_unwind aarch64_prologue_unwind =
>    aarch64_prologue_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Allocate and fill in *THIS_CACHE with information about the prologue of
>     *THIS_FRAME.  Do not do this is if *THIS_CACHE was already allocated.
> @@ -1301,8 +1300,7 @@ aarch64_stub_unwind_sniffer (const struct frame_unwind *self,
>  }
>  
>  /* AArch64 stub unwinder.  */
> -static frame_unwind aarch64_stub_unwind =
> -{
> +static const frame_unwind_legacy aarch64_stub_unwind (
>    "aarch64 stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1311,7 +1309,7 @@ static frame_unwind aarch64_stub_unwind =
>    aarch64_prologue_prev_register,
>    NULL,
>    aarch64_stub_unwind_sniffer
> -};
> +);
>  
>  /* Return the frame base address of *THIS_FRAME.  */
>  
> diff --git a/gdb/alpha-mdebug-tdep.c b/gdb/alpha-mdebug-tdep.c
> index b087afabae7..b43849c203d 100644
> --- a/gdb/alpha-mdebug-tdep.c
> +++ b/gdb/alpha-mdebug-tdep.c
> @@ -330,8 +330,7 @@ alpha_mdebug_frame_sniffer (const struct frame_unwind *self,
>    return 1;
>  }
>  
> -static const struct frame_unwind alpha_mdebug_frame_unwind =
> -{
> +static const struct frame_unwind_legacy alpha_mdebug_frame_unwind (
>    "alpha mdebug",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -340,7 +339,7 @@ static const struct frame_unwind alpha_mdebug_frame_unwind =
>    alpha_mdebug_frame_prev_register,
>    NULL,
>    alpha_mdebug_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  alpha_mdebug_frame_base_address (const frame_info_ptr &this_frame,
> diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
> index 4ce45d29ade..7201b724a9e 100644
> --- a/gdb/alpha-tdep.c
> +++ b/gdb/alpha-tdep.c
> @@ -1007,8 +1007,7 @@ alpha_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind alpha_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy alpha_sigtramp_frame_unwind (
>    "alpha sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1017,7 +1016,7 @@ static const struct frame_unwind alpha_sigtramp_frame_unwind =
>    alpha_sigtramp_frame_prev_register,
>    NULL,
>    alpha_sigtramp_frame_sniffer
> -};
> +);
>  
>  \f
>  
> @@ -1427,8 +1426,7 @@ alpha_heuristic_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind alpha_heuristic_frame_unwind =
> -{
> +static const struct frame_unwind_legacy alpha_heuristic_frame_unwind (
>    "alpha prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1437,7 +1435,7 @@ static const struct frame_unwind alpha_heuristic_frame_unwind =
>    alpha_heuristic_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  alpha_heuristic_frame_base_address (const frame_info_ptr &this_frame,
> diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c
> index 5359959e3bb..d1ebb0693e6 100644
> --- a/gdb/amd64-obsd-tdep.c
> +++ b/gdb/amd64-obsd-tdep.c
> @@ -402,8 +402,7 @@ amd64obsd_trapframe_sniffer (const struct frame_unwind *self,
>  		   || (startswith (name, "Xintr"))));
>  }
>  
> -static const struct frame_unwind amd64obsd_trapframe_unwind =
> -{
> +static const struct frame_unwind_legacy amd64obsd_trapframe_unwind (
>    /* FIXME: kettenis/20051219: This really is more like an interrupt
>       frame, but SIGTRAMP_FRAME would print <signal handler called>,
>       which really is not what we want here.  */
> @@ -415,7 +414,7 @@ static const struct frame_unwind amd64obsd_trapframe_unwind =
>    amd64obsd_trapframe_prev_register,
>    NULL,
>    amd64obsd_trapframe_sniffer
> -};
> +);
>  \f
>  
>  static void
> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
> index f1cd1fdef09..3c75f2fa22d 100644
> --- a/gdb/amd64-tdep.c
> +++ b/gdb/amd64-tdep.c
> @@ -2666,8 +2666,7 @@ amd64_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind amd64_frame_unwind =
> -{
> +static const struct frame_unwind_legacy amd64_frame_unwind (
>    "amd64 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2676,7 +2675,7 @@ static const struct frame_unwind amd64_frame_unwind =
>    amd64_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  /* Generate a bytecode expression to get the value of the saved PC.  */
>  
> @@ -2813,8 +2812,7 @@ amd64_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind amd64_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy amd64_sigtramp_frame_unwind (
>    "amd64 sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2823,7 +2821,7 @@ static const struct frame_unwind amd64_sigtramp_frame_unwind =
>    amd64_sigtramp_frame_prev_register,
>    NULL,
>    amd64_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> @@ -3006,8 +3004,7 @@ amd64_epilogue_frame_this_id (const frame_info_ptr &this_frame,
>      (*this_id) = frame_id_build (cache->base + 16, cache->pc);
>  }
>  
> -static const struct frame_unwind amd64_epilogue_override_frame_unwind =
> -{
> +static const struct frame_unwind_legacy amd64_epilogue_override_frame_unwind (
>    "amd64 epilogue override",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3016,10 +3013,9 @@ static const struct frame_unwind amd64_epilogue_override_frame_unwind =
>    amd64_frame_prev_register,
>    NULL,
>    amd64_epilogue_override_frame_sniffer
> -};
> +);
>  
> -static const struct frame_unwind amd64_epilogue_frame_unwind =
> -{
> +static const struct frame_unwind_legacy amd64_epilogue_frame_unwind (
>    "amd64 epilogue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3028,7 +3024,7 @@ static const struct frame_unwind amd64_epilogue_frame_unwind =
>    amd64_frame_prev_register,
>    NULL, 
>    amd64_epilogue_frame_sniffer
> -};
> +);
>  
>  static struct frame_id
>  amd64_dummy_id (struct gdbarch *gdbarch, const frame_info_ptr &this_frame)
> diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
> index ec32a57d7ea..83880afd1cf 100644
> --- a/gdb/amd64-windows-tdep.c
> +++ b/gdb/amd64-windows-tdep.c
> @@ -1184,8 +1184,7 @@ amd64_windows_frame_this_id (const frame_info_ptr &this_frame, void **this_cache
>  
>  /* Windows x64 SEH unwinder.  */
>  
> -static const struct frame_unwind amd64_windows_frame_unwind =
> -{
> +static const struct frame_unwind_legacy amd64_windows_frame_unwind (
>    "amd64 windows",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1194,7 +1193,7 @@ static const struct frame_unwind amd64_windows_frame_unwind =
>    &amd64_windows_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Implement the "skip_prologue" gdbarch method.  */
>  
> diff --git a/gdb/amdgpu-tdep.c b/gdb/amdgpu-tdep.c
> index b8a5fd80fa0..3272d24a820 100644
> --- a/gdb/amdgpu-tdep.c
> +++ b/gdb/amdgpu-tdep.c
> @@ -889,7 +889,7 @@ amdgpu_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const frame_unwind amdgpu_frame_unwind = {
> +static const frame_unwind_legacy amdgpu_frame_unwind (
>    "amdgpu",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -899,8 +899,8 @@ static const frame_unwind amdgpu_frame_unwind = {
>    nullptr,
>    default_frame_sniffer,
>    nullptr,
> -  nullptr,
> -};
> +  nullptr
> +);
>  
>  static int
>  print_insn_amdgpu (bfd_vma memaddr, struct disassemble_info *info)
> diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
> index a4ab78d8ade..d9fafc4d847 100644
> --- a/gdb/arc-tdep.c
> +++ b/gdb/arc-tdep.c
> @@ -1910,7 +1910,7 @@ arc_sigtramp_frame_sniffer (const struct frame_unwind *self,
>     the fallback unwinder, we use the default frame sniffer, which always
>     accepts the frame.  */
>  
> -static const struct frame_unwind arc_frame_unwind = {
> +static const struct frame_unwind_legacy arc_frame_unwind (
>    "arc prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1921,13 +1921,13 @@ static const struct frame_unwind arc_frame_unwind = {
>    default_frame_sniffer,
>    NULL,
>    NULL
> -};
> +);
>  
>  /* Structure defining the ARC signal frame unwind functions.  Custom
>     sniffer is used, because this frame must be accepted only in the right
>     context.  */
>  
> -static const struct frame_unwind arc_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy arc_sigtramp_frame_unwind (
>    "arc sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1938,7 +1938,7 @@ static const struct frame_unwind arc_sigtramp_frame_unwind = {
>    arc_sigtramp_frame_sniffer,
>    NULL,
>    NULL
> -};
> +);
>  
>  
>  static const struct frame_base arc_normal_base = {
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 657ecd57098..b5273c4a049 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -2466,7 +2466,7 @@ arm_prologue_prev_register (const frame_info_ptr &this_frame,
>  				       prev_regnum);
>  }
>  
> -static frame_unwind arm_prologue_unwind = {
> +static const frame_unwind_legacy arm_prologue_unwind (
>    "arm prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2475,7 +2475,7 @@ static frame_unwind arm_prologue_unwind = {
>    arm_prologue_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Maintain a list of ARM exception table entries per objfile, similar to the
>     list of mapping symbols.  We only cache entries for standard ARM-defined
> @@ -3186,7 +3186,7 @@ arm_exidx_unwind_sniffer (const struct frame_unwind *self,
>    return 1;
>  }
>  
> -struct frame_unwind arm_exidx_unwind = {
> +struct frame_unwind_legacy arm_exidx_unwind (
>    "arm exidx",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3195,7 +3195,7 @@ struct frame_unwind arm_exidx_unwind = {
>    arm_prologue_prev_register,
>    NULL,
>    arm_exidx_unwind_sniffer
> -};
> +);
>  
>  static struct arm_prologue_cache *
>  arm_make_epilogue_frame_cache (const frame_info_ptr &this_frame)
> @@ -3296,8 +3296,7 @@ arm_epilogue_frame_sniffer (const struct frame_unwind *self,
>  
>  /* Frame unwinder from epilogue.  */
>  
> -static const struct frame_unwind arm_epilogue_frame_unwind =
> -{
> +static const struct frame_unwind_legacy arm_epilogue_frame_unwind (
>    "arm epilogue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3305,8 +3304,8 @@ static const struct frame_unwind arm_epilogue_frame_unwind =
>    arm_epilogue_frame_this_id,
>    arm_epilogue_frame_prev_register,
>    NULL,
> -  arm_epilogue_frame_sniffer,
> -};
> +  arm_epilogue_frame_sniffer
> +);
>  
>  /* Recognize GCC's trampoline for thumb call-indirect.  If we are in a
>     trampoline, return the target PC.  Otherwise return 0.
> @@ -3427,7 +3426,7 @@ arm_stub_unwind_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -struct frame_unwind arm_stub_unwind = {
> +struct frame_unwind_legacy arm_stub_unwind (
>    "arm stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3436,7 +3435,7 @@ struct frame_unwind arm_stub_unwind = {
>    arm_prologue_prev_register,
>    NULL,
>    arm_stub_unwind_sniffer
> -};
> +);
>  
>  /* Put here the code to store, into CACHE->saved_regs, the addresses
>     of the saved registers of frame described by THIS_FRAME.  CACHE is
> @@ -3953,8 +3952,7 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self,
>  /* Frame unwinder for M-profile exceptions (EXC_RETURN on stack),
>     lockup and secure/nonsecure interstate function calls (FNC_RETURN).  */
>  
> -struct frame_unwind arm_m_exception_unwind =
> -{
> +struct frame_unwind_legacy arm_m_exception_unwind (
>    "arm m exception lockup sec_fnc",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3963,7 +3961,7 @@ struct frame_unwind arm_m_exception_unwind =
>    arm_m_exception_prev_register,
>    NULL,
>    arm_m_exception_unwind_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  arm_normal_frame_base (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
> index 08b3cb146f4..b3fe3fef759 100644
> --- a/gdb/avr-tdep.c
> +++ b/gdb/avr-tdep.c
> @@ -1155,7 +1155,7 @@ avr_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind avr_frame_unwind = {
> +static const struct frame_unwind_legacy avr_frame_unwind (
>    "avr prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1164,7 +1164,7 @@ static const struct frame_unwind avr_frame_unwind = {
>    avr_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  avr_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
> index 60838f0548e..78ade80ad25 100644
> --- a/gdb/bfin-tdep.c
> +++ b/gdb/bfin-tdep.c
> @@ -372,8 +372,7 @@ bfin_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind bfin_frame_unwind =
> -{
> +static const struct frame_unwind_legacy bfin_frame_unwind (
>    "bfin prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -382,7 +381,7 @@ static const struct frame_unwind bfin_frame_unwind =
>    bfin_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Check for "[--SP] = <reg>;" insns.  These are appear in function
>     prologues to save misc registers onto the stack.  */
> diff --git a/gdb/bpf-tdep.c b/gdb/bpf-tdep.c
> index 1f53d63c982..8f3e50d86c1 100644
> --- a/gdb/bpf-tdep.c
> +++ b/gdb/bpf-tdep.c
> @@ -181,8 +181,7 @@ bpf_frame_prev_register (const frame_info_ptr &this_frame,
>  
>  /* Frame unwinder machinery for BPF.  */
>  
> -static const struct frame_unwind bpf_frame_unwind =
> -{
> +static const struct frame_unwind_legacy bpf_frame_unwind (
>    "bpf prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -191,7 +190,7 @@ static const struct frame_unwind bpf_frame_unwind =
>    bpf_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  \f
>  /* Breakpoints.  */
> diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
> index 4db2a234819..f531b4ce1f0 100644
> --- a/gdb/cris-tdep.c
> +++ b/gdb/cris-tdep.c
> @@ -435,8 +435,7 @@ cris_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind cris_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy cris_sigtramp_frame_unwind (
>    "cris sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -445,7 +444,7 @@ static const struct frame_unwind cris_sigtramp_frame_unwind =
>    cris_sigtramp_frame_prev_register,
>    NULL,
>    cris_sigtramp_frame_sniffer
> -};
> +);
>  
>  static int
>  crisv32_single_step_through_delay (struct gdbarch *gdbarch,
> @@ -901,8 +900,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
>    return sp;
>  }
>  
> -static const struct frame_unwind cris_frame_unwind = 
> -{
> +static const struct frame_unwind_legacy cris_frame_unwind (
>    "cris prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -911,7 +909,7 @@ static const struct frame_unwind cris_frame_unwind =
>    cris_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  cris_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c
> index 6e8426fe2d8..4f41a51b576 100644
> --- a/gdb/csky-tdep.c
> +++ b/gdb/csky-tdep.c
> @@ -2159,7 +2159,7 @@ csky_frame_prev_register (const frame_info_ptr &this_frame,
>  /* Data structures for the normal prologue-analysis-based
>     unwinder.  */
>  
> -static const struct frame_unwind csky_unwind_cache = {
> +static const struct frame_unwind_legacy csky_unwind_cache (
>    "cski prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2170,7 +2170,7 @@ static const struct frame_unwind csky_unwind_cache = {
>    default_frame_sniffer,
>    NULL,
>    NULL
> -};
> +);
>  
>  static CORE_ADDR
>  csky_check_long_branch (const frame_info_ptr &frame, CORE_ADDR pc)
> @@ -2294,7 +2294,7 @@ csky_stub_prev_register (const frame_info_ptr &this_frame,
>  				       prev_regnum);
>  }
>  
> -static frame_unwind csky_stub_unwind = {
> +static const frame_unwind_legacy csky_stub_unwind (
>    "csky stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2303,7 +2303,7 @@ static frame_unwind csky_stub_unwind = {
>    csky_stub_prev_register,
>    NULL,
>    csky_stub_unwind_sniffer
> -};
> +);
>  
>  /* Implement the this_base, this_locals, and this_args hooks
>     for the normal unwinder.  */
> diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
> index e7de15b5c4d..697cc11a184 100644
> --- a/gdb/dummy-frame.c
> +++ b/gdb/dummy-frame.c
> @@ -375,8 +375,7 @@ dummy_frame_this_id (const frame_info_ptr &this_frame,
>    (*this_id) = cache->this_id;
>  }
>  
> -const struct frame_unwind dummy_frame_unwind =
> -{
> +const struct frame_unwind_legacy dummy_frame_unwind (
>    "dummy",
>    DUMMY_FRAME,
>    FRAME_UNWIND_GDB,
> @@ -384,8 +383,8 @@ const struct frame_unwind dummy_frame_unwind =
>    dummy_frame_this_id,
>    dummy_frame_prev_register,
>    NULL,
> -  dummy_frame_sniffer,
> -};
> +  dummy_frame_sniffer
> +);
>  
>  /* See dummy-frame.h.  */
>  
> diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h
> index 7d963ad9beb..a1341797acd 100644
> --- a/gdb/dummy-frame.h
> +++ b/gdb/dummy-frame.h
> @@ -54,7 +54,7 @@ extern void dummy_frame_discard (frame_id dummy_id, thread_info *thread);
>  /* If the PC falls in a dummy frame, return a dummy frame
>     unwinder.  */
>  
> -extern const struct frame_unwind dummy_frame_unwind;
> +extern const struct frame_unwind_legacy dummy_frame_unwind;
>  
>  /* Destructor for dummy_frame.  DATA is supplied by registrant.
>     REGISTERS_VALID is 1 for dummy_frame_pop, 0 for dummy_frame_discard.  */
> diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c
> index 50efd4eb5ff..54813d00b03 100644
> --- a/gdb/dwarf2/frame-tailcall.c
> +++ b/gdb/dwarf2/frame-tailcall.c
> @@ -468,8 +468,7 @@ tailcall_frame_prev_arch (const frame_info_ptr &this_frame,
>  /* Virtual tail call frame unwinder if dwarf2_tailcall_sniffer_first finds
>     a chain to create.  */
>  
> -const struct frame_unwind dwarf2_tailcall_frame_unwind =
> -{
> +const struct frame_unwind_legacy dwarf2_tailcall_frame_unwind (
>    "dwarf2 tailcall",
>    TAILCALL_FRAME,
>    FRAME_UNWIND_DEBUGINFO,
> @@ -480,7 +479,7 @@ const struct frame_unwind dwarf2_tailcall_frame_unwind =
>    tailcall_frame_sniffer,
>    tailcall_frame_dealloc_cache,
>    tailcall_frame_prev_arch
> -};
> +);
>  
>  void _initialize_tailcall_frame ();
>  void
> diff --git a/gdb/dwarf2/frame-tailcall.h b/gdb/dwarf2/frame-tailcall.h
> index 3f49487ac2a..3569c7dd3e2 100644
> --- a/gdb/dwarf2/frame-tailcall.h
> +++ b/gdb/dwarf2/frame-tailcall.h
> @@ -34,6 +34,6 @@ extern struct value *
>    dwarf2_tailcall_prev_register_first (const frame_info_ptr &this_frame,
>  				       void **tailcall_cachep, int regnum);
>  
> -extern const struct frame_unwind dwarf2_tailcall_frame_unwind;
> +extern const struct frame_unwind_legacy dwarf2_tailcall_frame_unwind;
>  
>  #endif /* !DWARF2_FRAME_TAILCALL_H */
> diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
> index 492b6928c62..85e1d59bc09 100644
> --- a/gdb/dwarf2/frame.c
> +++ b/gdb/dwarf2/frame.c
> @@ -1329,16 +1329,15 @@ dwarf2_frame_sniffer (const struct frame_unwind *self,
>    if (fde->cie->signal_frame
>        || dwarf2_frame_signal_frame_p (get_frame_arch (this_frame),
>  				      this_frame))
> -    return self->type == SIGTRAMP_FRAME;
> +    return self->type () == SIGTRAMP_FRAME;
>  
> -  if (self->type != NORMAL_FRAME)
> +  if (self->type () != NORMAL_FRAME)
>      return 0;
>  
>    return 1;
>  }
>  
> -static const struct frame_unwind dwarf2_frame_unwind =
> -{
> +static const struct frame_unwind_legacy dwarf2_frame_unwind (
>    "dwarf2",
>    NORMAL_FRAME,
>    FRAME_UNWIND_DEBUGINFO,
> @@ -1348,10 +1347,9 @@ static const struct frame_unwind dwarf2_frame_unwind =
>    NULL,
>    dwarf2_frame_sniffer,
>    dwarf2_frame_dealloc_cache
> -};
> +);
>  
> -static const struct frame_unwind dwarf2_signal_frame_unwind =
> -{
> +static const struct frame_unwind_legacy dwarf2_signal_frame_unwind (
>    "dwarf2 signal",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_DEBUGINFO,
> @@ -1363,7 +1361,7 @@ static const struct frame_unwind dwarf2_signal_frame_unwind =
>  
>    /* TAILCALL_CACHE can never be in such frame to need dealloc_cache.  */
>    NULL
> -};
> +);
>  
>  /* Append the DWARF-2 frame unwinders to GDBARCH's list.  */
>  
> diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
> index d61f06d3305..3ab6af1c4da 100644
> --- a/gdb/frame-unwind.c
> +++ b/gdb/frame-unwind.c
> @@ -121,8 +121,8 @@ frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
>  
>    try
>      {
> -      frame_debug_printf ("trying unwinder \"%s\"", unwinder->name);
> -      res = unwinder->sniffer (unwinder, this_frame, this_cache);
> +      frame_debug_printf ("trying unwinder \"%s\"", unwinder->name ());
> +      res = unwinder->sniff (this_frame, this_cache);
>      }
>    catch (const gdb_exception &ex)
>      {
> @@ -327,6 +327,64 @@ frame_unwind_got_address (const frame_info_ptr &frame, int regnum,
>    return reg_val;
>  }
>  
> +/* See frame-unwind.h.  */
> +
> +enum unwind_stop_reason
> +frame_unwind_legacy::stop_reason (const frame_info_ptr &this_frame,
> +				  void **this_prologue_cache) const
> +{
> +  return m_stop_reason (this_frame, this_prologue_cache);
> +}
> +
> +/* See frame-unwind.h.  */
> +
> +void
> +frame_unwind_legacy::this_id (const frame_info_ptr &this_frame,
> +			      void **this_prologue_cache,
> +			      struct frame_id *id) const
> +{
> +  return m_this_id (this_frame, this_prologue_cache, id);
> +}
> +
> +/* See frame-unwind.h.  */
> +
> +struct value *
> +frame_unwind_legacy::prev_register (const frame_info_ptr &this_frame,
> +				    void **this_prologue_cache,
> +				    int regnum) const
> +{
> +  return m_prev_register (this_frame, this_prologue_cache, regnum);
> +}
> +
> +/* See frame-unwind.h.  */
> +
> +int
> +frame_unwind_legacy::sniff (const frame_info_ptr &this_frame,
> +			    void **this_prologue_cache) const
> +{
> +  return m_sniffer (this, this_frame, this_prologue_cache);
> +}
> +
> +/* See frame-unwind.h.  */
> +
> +void
> +frame_unwind_legacy::dealloc_cache (frame_info *self, void *this_cache) const
> +{
> +  if (m_dealloc_cache != nullptr)
> +    m_dealloc_cache (self, this_cache);
> +}
> +
> +/* See frame-unwind.h.  */
> +
> +struct gdbarch *
> +frame_unwind_legacy::prev_arch (const frame_info_ptr &this_frame,
> +				void **this_prologue_cache) const
> +{
> +  if (m_prev_arch == nullptr)
> +    return frame_unwind::prev_arch (this_frame, this_prologue_cache);
> +  return m_prev_arch (this_frame, this_prologue_cache);
> +}
> +
>  /* Implement "maintenance info frame-unwinders" command.  */
>  
>  static void
> @@ -345,10 +403,10 @@ maintenance_info_frame_unwinders (const char *args, int from_tty)
>    for (auto unwinder : *table)
>      {
>        ui_out_emit_list tuple_emitter (uiout, nullptr);
> -      uiout->field_string ("name", unwinder->name);
> -      uiout->field_string ("type", frame_type_str (unwinder->type));
> +      uiout->field_string ("name", unwinder->name ());
> +      uiout->field_string ("type", frame_type_str (unwinder->type ()));
>        uiout->field_string ("class", frame_unwinder_class_str (
> -					unwinder->unwinder_class));
> +					unwinder->unwinder_class ()));
>        uiout->text ("\n");
>      }
>  }
> diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
> index ef8bbe091b5..13f18618d24 100644
> --- a/gdb/frame-unwind.h
> +++ b/gdb/frame-unwind.h
> @@ -171,25 +171,146 @@ enum frame_unwind_class
>    UNWIND_CLASS_NUMBER,
>  };
>  
> -struct frame_unwind
> +class frame_unwind
>  {
> -  const char *name;
> +public:
> +  frame_unwind (const char *name, frame_type type, frame_unwind_class uclass,
> +		const frame_data *data)
> +    : m_name (name), m_type (type), m_unwinder_class (uclass),
> +      m_unwind_data (data)
> +  { }
> +
> +  const char *name () const
> +  { return m_name; }
> +
> +  frame_type type () const
> +  { return m_type; }
> +
> +  frame_unwind_class unwinder_class () const
> +  { return m_unwinder_class; }
> +
> +  const frame_data *unwind_data () const
> +  { return m_unwind_data; }
> +
> +  /* Default stop_reason implementation.  It reports NO_REASON, unless the
> +     frame is the outermost.  */
> +
> +  virtual unwind_stop_reason stop_reason (const frame_info_ptr &this_frame,
> +					  void **this_prologue_cache) const
> +  {
> +    return default_frame_unwind_stop_reason (this_frame, this_prologue_cache);
> +  }
> +
> +  /* Default frame sniffer.  Will always return that the unwinder
> +     is able to unwind the frame.  */
> +
> +  virtual int sniff (const frame_info_ptr &this_frame,
> +		     void **this_prologue_cache) const
> +  { return 1; }
> +
> +  /* Calculate the ID of the given frame using this unwinder.  */
> +
> +  virtual void this_id (const frame_info_ptr &this_frame,
> +			void **this_prologue_cache,
> +			struct frame_id *id) const = 0;
> +
> +  /* Get the value of a register in a previous frame.  */
> +
> +  virtual struct value *prev_register (const frame_info_ptr &this_frame,
> +				       void **this_prologue_cache,
> +				       int regnum) const = 0;
> +
> +  /* Properly deallocate the cache.  */
> +
> +  virtual void dealloc_cache (frame_info *self, void *this_cache) const
> +  { }
> +
> +  /* Get the previous architecture.  */
> +
> +  virtual gdbarch *prev_arch (const frame_info_ptr &this_frame,
> +			      void **this_prologue_cache) const
> +  { return get_frame_arch (this_frame); }
> +
> +private:
> +
> +  const char *m_name;

This appears to be missing a comment...

> +
>    /* The frame's type.  Should this instead be a collection of
>       predicates that test the frame for various attributes?  */
> -  enum frame_type type;
> +  frame_type m_type;
> +
>    /* What kind of unwinder is this.  It generally follows from where
>       the unwinder was added or where it looks for information to do the
>       unwinding.  */
> -  enum frame_unwind_class unwinder_class;
> -  /* Should an attribute indicating the frame's address-in-block go
> -     here?  */
> -  frame_unwind_stop_reason_ftype *stop_reason;
> -  frame_this_id_ftype *this_id;
> -  frame_prev_register_ftype *prev_register;
> -  const struct frame_data *unwind_data;
> -  frame_sniffer_ftype *sniffer;
> -  frame_dealloc_cache_ftype *dealloc_cache;
> -  frame_prev_arch_ftype *prev_arch;
> +  frame_unwind_class m_unwinder_class;
> +
> +  const frame_data *m_unwind_data;

... as is this.  I know none of this stuff was commented before, but
given we're giving this code a spring clean, it would be nice to comment
the data members.

> +};
> +
> +/* This is a legacy version of the frame unwinder.  The original struct
> +   used function pointers for callbacks, this updated version has a
> +   method that just passes the parameters along to the callback
> +   pointer.
> +   Do not use this class for new unwinders.  Instead, see other classes
> +   that inherit from frame_unwind, such as the python unwinder.  */
> +class frame_unwind_legacy : public frame_unwind
> +{
> +public:

I'd normally use 'struct frame_unwind_legacy : ...' as this removes the
need to immediately add the 'public:' visibility tag.  There seems to be
a mix of the two in GDB, so you don't need to change this.  Just hoping
to make another 'struct' over 'class' convert :)

With the missing comments added, I think this looks great.

Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew

> +  frame_unwind_legacy (const char *name, frame_type type,
> +		       frame_unwind_class uclass,
> +		       frame_unwind_stop_reason_ftype *stop_reason_func,
> +		       frame_this_id_ftype *this_id_func,
> +		       frame_prev_register_ftype *prev_register_func,
> +		       const struct frame_data *data,
> +		       frame_sniffer_ftype *sniffer_func,
> +		       frame_dealloc_cache_ftype *dealloc_cache_func = nullptr,
> +		       frame_prev_arch_ftype *prev_arch_func = nullptr)
> +  : frame_unwind (name, type, uclass, data), m_stop_reason (stop_reason_func),
> +    m_this_id (this_id_func), m_prev_register (prev_register_func),
> +    m_sniffer (sniffer_func), m_dealloc_cache (dealloc_cache_func),
> +    m_prev_arch (prev_arch_func)
> +  { }
> +
> +  /* This method just passes the parameters to the callback pointer.  */
> +
> +  enum unwind_stop_reason stop_reason (const frame_info_ptr &this_frame,
> +				       void **this_prologue_cache) const override;
> +
> +  /* This method just passes the parameters to the callback pointer.  */
> +
> +  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
> +		struct frame_id *id) const override;
> +
> +  /* This method just passes the parameters to the callback pointer.  */
> +
> +  struct value *prev_register (const frame_info_ptr &this_frame,
> +			       void **this_prologue_cache,
> +			       int regnum) const override;
> +
> +  /* This method just passes the parameters to the callback pointer.  */
> +
> +  int sniff (const frame_info_ptr &this_frame,
> +	     void **this_prologue_cache) const override;
> +
> +  /* This method just passes the parameters to the callback pointer.
> +     It is safe to call this method if no callback is installed, it
> +     just turns into a noop.  */
> +
> +  void dealloc_cache (frame_info *self, void *this_cache) const override;
> +
> +  /* This method just passes the parameters to the callback pointer.  */
> +
> +  struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
> +			     void **this_prologue_cache) const override;
> +
> +private:
> +
> +  frame_unwind_stop_reason_ftype *m_stop_reason;
> +  frame_this_id_ftype *m_this_id;
> +  frame_prev_register_ftype *m_prev_register;
> +  frame_sniffer_ftype *m_sniffer;
> +  frame_dealloc_cache_ftype *m_dealloc_cache;
> +  frame_prev_arch_ftype *m_prev_arch;
>  };
>  
>  /* Register a frame unwinder, _prepending_ it to the front of the
> diff --git a/gdb/frame.c b/gdb/frame.c
> index a6900b28072..e930aaf2e1d 100644
> --- a/gdb/frame.c
> +++ b/gdb/frame.c
> @@ -269,12 +269,10 @@ frame_addr_hash_eq (const void *a, const void *b)
>  static void
>  frame_info_del (frame_info *frame)
>  {
> -  if (frame->prologue_cache != nullptr
> -      && frame->unwind->dealloc_cache != nullptr)
> +  if (frame->prologue_cache != nullptr)
>      frame->unwind->dealloc_cache (frame, frame->prologue_cache);
>  
> -  if (frame->base_cache != nullptr
> -      && frame->base->unwind->dealloc_cache != nullptr)
> +  if (frame->base_cache != nullptr)
>      frame->base->unwind->dealloc_cache (frame, frame->base_cache);
>  }
>  
> @@ -487,12 +485,12 @@ frame_info::to_string () const
>    res += string_printf ("{level=%d,", fi->level);
>  
>    if (fi->unwind != NULL)
> -    res += string_printf ("type=%s,", frame_type_str (fi->unwind->type));
> +    res += string_printf ("type=%s,", frame_type_str (fi->unwind->type ()));
>    else
>      res += "type=<unknown>,";
>  
>    if (fi->unwind != NULL)
> -    res += string_printf ("unwinder=\"%s\",", fi->unwind->name);
> +    res += string_printf ("unwinder=\"%s\",", fi->unwind->name ());
>    else
>      res += "unwinder=<unknown>,";
>  
> @@ -2363,7 +2361,7 @@ get_prev_frame_always_1 (const frame_info_ptr &this_frame)
>       This check is valid only if this frame and the next frame are NORMAL.
>       See the comment at frame_id_inner for details.  */
>    if (get_frame_type (this_frame) == NORMAL_FRAME
> -      && this_frame->next->unwind->type == NORMAL_FRAME
> +      && this_frame->next->unwind->type () == NORMAL_FRAME
>        && frame_id_inner (get_frame_arch (frame_info_ptr (this_frame->next)),
>  			 get_frame_id (this_frame),
>  			 get_frame_id (frame_info_ptr (this_frame->next))))
> @@ -2991,7 +2989,7 @@ get_frame_type (const frame_info_ptr &frame)
>      /* Initialize the frame's unwinder because that's what
>         provides the frame's type.  */
>      frame_unwind_find_by_frame (frame, &frame->prologue_cache);
> -  return frame->unwind->type;
> +  return frame->unwind->type ();
>  }
>  
>  struct program_space *
> @@ -3072,11 +3070,8 @@ frame_unwind_arch (const frame_info_ptr &next_frame)
>        if (next_frame->unwind == NULL)
>  	frame_unwind_find_by_frame (next_frame, &next_frame->prologue_cache);
>  
> -      if (next_frame->unwind->prev_arch != NULL)
> -	arch = next_frame->unwind->prev_arch (next_frame,
> -					      &next_frame->prologue_cache);
> -      else
> -	arch = get_frame_arch (next_frame);
> +      arch = next_frame->unwind->prev_arch (next_frame,
> +					    &next_frame->prologue_cache);
>  
>        next_frame->prev_arch.arch = arch;
>        next_frame->prev_arch.p = true;
> diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
> index 7a7c4904475..4941e4a0741 100644
> --- a/gdb/frv-linux-tdep.c
> +++ b/gdb/frv-linux-tdep.c
> @@ -332,8 +332,7 @@ frv_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy frv_linux_sigtramp_frame_unwind (
>    "frv linux sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -342,7 +341,7 @@ static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
>    frv_linux_sigtramp_frame_prev_register,
>    NULL,
>    frv_linux_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  /* The FRV kernel defines ELF_NGREG as 46.  We add 2 in order to include
>     the loadmap addresses in the register set.  (See below for more info.)  */
> diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
> index a1845a25750..b022cc75f85 100644
> --- a/gdb/frv-tdep.c
> +++ b/gdb/frv-tdep.c
> @@ -1404,7 +1404,7 @@ frv_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind frv_frame_unwind = {
> +static const struct frame_unwind_legacy frv_frame_unwind (
>    "frv prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1413,7 +1413,7 @@ static const struct frame_unwind frv_frame_unwind = {
>    frv_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  frv_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c
> index e3827ad96e7..2ef77a271b4 100644
> --- a/gdb/ft32-tdep.c
> +++ b/gdb/ft32-tdep.c
> @@ -525,8 +525,7 @@ ft32_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind ft32_frame_unwind =
> -{
> +static const struct frame_unwind_legacy ft32_frame_unwind (
>    "ft32 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -535,7 +534,7 @@ static const struct frame_unwind ft32_frame_unwind =
>    ft32_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Return the base address of this_frame.  */
>  
> diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
> index 5b4466ed316..a845900d299 100644
> --- a/gdb/h8300-tdep.c
> +++ b/gdb/h8300-tdep.c
> @@ -500,7 +500,7 @@ h8300_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind h8300_frame_unwind = {
> +static const struct frame_unwind_legacy h8300_frame_unwind (
>    "h8300 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -509,7 +509,7 @@ static const struct frame_unwind h8300_frame_unwind = {
>    h8300_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  h8300_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
> index 2619b60655a..f43a5e73856 100644
> --- a/gdb/hppa-linux-tdep.c
> +++ b/gdb/hppa-linux-tdep.c
> @@ -308,7 +308,7 @@ hppa_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy hppa_linux_sigtramp_frame_unwind (
>    "hppa linux sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -317,7 +317,7 @@ static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
>    hppa_linux_sigtramp_frame_prev_register,
>    NULL,
>    hppa_linux_sigtramp_frame_sniffer
> -};
> +);
>  
>  /* Attempt to find (and return) the global pointer for the given
>     function.
> diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
> index 2447b87ebae..1fb68f261c6 100644
> --- a/gdb/hppa-tdep.c
> +++ b/gdb/hppa-tdep.c
> @@ -2282,8 +2282,7 @@ hppa_frame_unwind_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind hppa_frame_unwind =
> -{
> +static const struct frame_unwind_legacy hppa_frame_unwind (
>    "hppa unwind table",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2292,7 +2291,7 @@ static const struct frame_unwind hppa_frame_unwind =
>    hppa_frame_prev_register,
>    NULL,
>    hppa_frame_unwind_sniffer
> -};
> +);
>  
>  /* This is a generic fallback frame unwinder that kicks in if we fail all
>     the other ones.  Normally we would expect the stub and regular unwinder
> @@ -2396,8 +2395,7 @@ hppa_fallback_frame_prev_register (const frame_info_ptr &this_frame,
>  					  info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind hppa_fallback_frame_unwind =
> -{
> +static const struct frame_unwind_legacy hppa_fallback_frame_unwind (
>    "hppa prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2406,7 +2404,7 @@ static const struct frame_unwind hppa_fallback_frame_unwind =
>    hppa_fallback_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Stub frames, used for all kinds of call stubs.  */
>  struct hppa_stub_unwind_cache
> @@ -2479,7 +2477,7 @@ hppa_stub_unwind_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind hppa_stub_frame_unwind = {
> +static const struct frame_unwind_legacy hppa_stub_frame_unwind (
>    "hppa stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2488,7 +2486,7 @@ static const struct frame_unwind hppa_stub_frame_unwind = {
>    hppa_stub_frame_prev_register,
>    NULL,
>    hppa_stub_unwind_sniffer
> -};
> +);
>  
>  CORE_ADDR
>  hppa_unwind_pc (struct gdbarch *gdbarch, const frame_info_ptr &next_frame)
> diff --git a/gdb/i386-obsd-tdep.c b/gdb/i386-obsd-tdep.c
> index 1d2b1a09d16..ea8addce599 100644
> --- a/gdb/i386-obsd-tdep.c
> +++ b/gdb/i386-obsd-tdep.c
> @@ -390,7 +390,7 @@ i386obsd_trapframe_sniffer (const struct frame_unwind *self,
>  		   || startswith (name, "Xsoft")));
>  }
>  
> -static const struct frame_unwind i386obsd_trapframe_unwind = {
> +static const struct frame_unwind_legacy i386obsd_trapframe_unwind (
>    "i386 openbsd trap",
>    /* FIXME: kettenis/20051219: This really is more like an interrupt
>       frame, but SIGTRAMP_FRAME would print <signal handler called>,
> @@ -402,7 +402,7 @@ static const struct frame_unwind i386obsd_trapframe_unwind = {
>    i386obsd_trapframe_prev_register,
>    NULL,
>    i386obsd_trapframe_sniffer
> -};
> +);
>  \f
>  
>  static void 
> diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
> index 6defd225bdb..75d175ad863 100644
> --- a/gdb/i386-tdep.c
> +++ b/gdb/i386-tdep.c
> @@ -2139,8 +2139,7 @@ i386_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind i386_frame_unwind =
> -{
> +static const struct frame_unwind_legacy i386_frame_unwind (
>    "i386 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2149,7 +2148,7 @@ static const struct frame_unwind i386_frame_unwind =
>    i386_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Normal frames, but in a function epilogue.  */
>  
> @@ -2295,8 +2294,7 @@ i386_epilogue_frame_prev_register (const frame_info_ptr &this_frame,
>    return i386_frame_prev_register (this_frame, this_cache, regnum);
>  }
>  
> -static const struct frame_unwind i386_epilogue_override_frame_unwind =
> -{
> +static const struct frame_unwind_legacy i386_epilogue_override_frame_unwind (
>    "i386 epilogue override",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2305,10 +2303,9 @@ static const struct frame_unwind i386_epilogue_override_frame_unwind =
>    i386_epilogue_frame_prev_register,
>    NULL,
>    i386_epilogue_override_frame_sniffer
> -};
> +);
>  
> -static const struct frame_unwind i386_epilogue_frame_unwind =
> -{
> +static const struct frame_unwind_legacy i386_epilogue_frame_unwind (
>    "i386 epilogue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2317,7 +2314,7 @@ static const struct frame_unwind i386_epilogue_frame_unwind =
>    i386_epilogue_frame_prev_register,
>    NULL,
>    i386_epilogue_frame_sniffer
> -};
> +);
>  \f
>  
>  /* Stack-based trampolines.  */
> @@ -2390,8 +2387,7 @@ i386_stack_tramp_frame_sniffer (const struct frame_unwind *self,
>      return 0;
>  }
>  
> -static const struct frame_unwind i386_stack_tramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy i386_stack_tramp_frame_unwind (
>    "i386 stack tramp",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2400,7 +2396,7 @@ static const struct frame_unwind i386_stack_tramp_frame_unwind =
>    i386_epilogue_frame_prev_register,
>    NULL,
>    i386_stack_tramp_frame_sniffer
> -};
> +);
>  \f
>  /* Generate a bytecode expression to get the value of the saved PC.  */
>  
> @@ -2540,8 +2536,7 @@ i386_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind i386_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy i386_sigtramp_frame_unwind (
>    "i386 sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2550,7 +2545,7 @@ static const struct frame_unwind i386_sigtramp_frame_unwind =
>    i386_sigtramp_frame_prev_register,
>    NULL,
>    i386_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
> index b10cc251bf1..11375d5bc69 100644
> --- a/gdb/ia64-tdep.c
> +++ b/gdb/ia64-tdep.c
> @@ -2162,8 +2162,7 @@ ia64_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>      }
>  }
>   
> -static const struct frame_unwind ia64_frame_unwind =
> -{
> +static const struct frame_unwind_legacy ia64_frame_unwind (
>    "ia64 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2172,7 +2171,7 @@ static const struct frame_unwind ia64_frame_unwind =
>    &ia64_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Signal trampolines.  */
>  
> @@ -2352,8 +2351,7 @@ ia64_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind ia64_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy ia64_sigtramp_frame_unwind (
>    "ia64 sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2362,7 +2360,7 @@ static const struct frame_unwind ia64_sigtramp_frame_unwind =
>    ia64_sigtramp_frame_prev_register,
>    NULL,
>    ia64_sigtramp_frame_sniffer
> -};
> +);
>  
>  \f
>  
> @@ -3013,8 +3011,7 @@ ia64_libunwind_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind ia64_libunwind_frame_unwind =
> -{
> +static const struct frame_unwind_legacy ia64_libunwind_frame_unwind (
>    "ia64 libunwind",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3024,7 +3021,7 @@ static const struct frame_unwind ia64_libunwind_frame_unwind =
>    NULL,
>    ia64_libunwind_frame_sniffer,
>    libunwind_frame_dealloc_cache
> -};
> +);
>  
>  static void
>  ia64_libunwind_sigtramp_frame_this_id (const frame_info_ptr &this_frame,
> @@ -3103,8 +3100,7 @@ ia64_libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self,
>      return ia64_sigtramp_frame_sniffer (self, this_frame, this_cache);
>  }
>  
> -static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy ia64_libunwind_sigtramp_frame_unwind (
>    "ia64 libunwind sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3113,7 +3109,7 @@ static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind =
>    ia64_libunwind_sigtramp_frame_prev_register,
>    NULL,
>    ia64_libunwind_sigtramp_frame_sniffer
> -};
> +);
>  
>  /* Set of libunwind callback acccessor functions.  */
>  unw_accessors_t ia64_unw_accessors =
> diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
> index 8b3057159dc..1426ae2faf6 100644
> --- a/gdb/inline-frame.c
> +++ b/gdb/inline-frame.c
> @@ -269,7 +269,7 @@ inline_frame_sniffer (const struct frame_unwind *self,
>    return 1;
>  }
>  
> -const struct frame_unwind inline_frame_unwind = {
> +const struct frame_unwind_legacy inline_frame_unwind (
>    "inline",
>    INLINE_FRAME,
>    FRAME_UNWIND_GDB,
> @@ -278,7 +278,7 @@ const struct frame_unwind inline_frame_unwind = {
>    inline_frame_prev_register,
>    NULL,
>    inline_frame_sniffer
> -};
> +);
>  
>  /* Return non-zero if BLOCK, an inlined function block containing PC,
>     has a group of contiguous instructions starting at PC (but not
> diff --git a/gdb/inline-frame.h b/gdb/inline-frame.h
> index 3ddc9cf2335..96412154f6a 100644
> --- a/gdb/inline-frame.h
> +++ b/gdb/inline-frame.h
> @@ -27,7 +27,7 @@ struct process_stratum_target;
>  
>  /* The inline frame unwinder.  */
>  
> -extern const struct frame_unwind inline_frame_unwind;
> +extern const struct frame_unwind_legacy inline_frame_unwind;
>  
>  /* Skip all inlined functions whose call sites are at the current PC.
>  
> diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c
> index e0db1b0de4e..094f627e37b 100644
> --- a/gdb/iq2000-tdep.c
> +++ b/gdb/iq2000-tdep.c
> @@ -424,7 +424,7 @@ iq2000_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
>    *this_id = frame_id_build (cache->saved_sp, cache->pc);
>  }
>  
> -static const struct frame_unwind iq2000_frame_unwind = {
> +static const struct frame_unwind_legacy iq2000_frame_unwind (
>    "iq2000 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -433,7 +433,7 @@ static const struct frame_unwind iq2000_frame_unwind = {
>    iq2000_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  iq2000_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/jit.c b/gdb/jit.c
> index 33a19d2ba4d..e37f3072470 100644
> --- a/gdb/jit.c
> +++ b/gdb/jit.c
> @@ -1108,8 +1108,7 @@ jit_frame_prev_register (const frame_info_ptr &this_frame, void **cache, int reg
>  /* Relay everything back to the unwinder registered by the JIT debug
>     info reader.*/
>  
> -static const struct frame_unwind jit_frame_unwind =
> -{
> +static const struct frame_unwind_legacy jit_frame_unwind (
>    "jit",
>    NORMAL_FRAME,
>    FRAME_UNWIND_EXTENSION,
> @@ -1119,7 +1118,7 @@ static const struct frame_unwind jit_frame_unwind =
>    NULL,
>    jit_frame_sniffer,
>    jit_dealloc_cache
> -};
> +);
>  
>  
>  /* This is the information that is stored at jit_gdbarch_data for each
> diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c
> index 4eb5f2ad426..c94aef4d839 100644
> --- a/gdb/lm32-tdep.c
> +++ b/gdb/lm32-tdep.c
> @@ -447,7 +447,7 @@ lm32_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind lm32_frame_unwind = {
> +static const struct frame_unwind_legacy lm32_frame_unwind (
>    "lm32 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -456,7 +456,7 @@ static const struct frame_unwind lm32_frame_unwind = {
>    lm32_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  lm32_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
> index 4f00deb677e..1cab29bbecb 100644
> --- a/gdb/loongarch-tdep.c
> +++ b/gdb/loongarch-tdep.c
> @@ -454,7 +454,7 @@ loongarch_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_register (info, this_frame, regnum);
>  }
>  
> -static const struct frame_unwind loongarch_frame_unwind = {
> +static const struct frame_unwind_legacy loongarch_frame_unwind (
>    "loongarch prologue",
>    /*.type	   =*/NORMAL_FRAME,
>    /*.unwinder_class=*/FRAME_UNWIND_ARCH,
> @@ -464,8 +464,8 @@ static const struct frame_unwind loongarch_frame_unwind = {
>    /*.unwind_data   =*/nullptr,
>    /*.sniffer	   =*/default_frame_sniffer,
>    /*.dealloc_cache =*/nullptr,
> -  /*.prev_arch	   =*/nullptr,
> -};
> +  /*.prev_arch	   =*/nullptr
> +);
>  
>  /* Write the contents of buffer VAL into the general-purpose argument
>     register defined by GAR in REGCACHE.  GAR indicates the available
> diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
> index bce12c5fae7..376b3622840 100644
> --- a/gdb/m32c-tdep.c
> +++ b/gdb/m32c-tdep.c
> @@ -1955,7 +1955,7 @@ m32c_prev_register (const frame_info_ptr &this_frame,
>  }
>  
>  
> -static const struct frame_unwind m32c_unwind = {
> +static const struct frame_unwind_legacy m32c_unwind (
>    "m32c prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1964,7 +1964,7 @@ static const struct frame_unwind m32c_unwind = {
>    m32c_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  \f
>  /* Inferior calls.  */
> diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
> index 11a150a92b8..72c18337c4a 100644
> --- a/gdb/m32r-linux-tdep.c
> +++ b/gdb/m32r-linux-tdep.c
> @@ -301,7 +301,7 @@ m32r_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy m32r_linux_sigtramp_frame_unwind (
>    "m32r linux sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -310,7 +310,7 @@ static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = {
>    m32r_linux_sigtramp_frame_prev_register,
>    NULL,
>    m32r_linux_sigtramp_frame_sniffer
> -};
> +);
>  
>  /* Mapping between the registers in `struct pt_regs'
>     format and GDB's register array layout.  */
> diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
> index aadb8c00d86..8300528364e 100644
> --- a/gdb/m32r-tdep.c
> +++ b/gdb/m32r-tdep.c
> @@ -831,7 +831,7 @@ m32r_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind m32r_frame_unwind = {
> +static const struct frame_unwind_legacy m32r_frame_unwind (
>    "m32r prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -840,7 +840,7 @@ static const struct frame_unwind m32r_frame_unwind = {
>    m32r_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  m32r_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
> index e14ac622fda..84a44f525c2 100644
> --- a/gdb/m68hc11-tdep.c
> +++ b/gdb/m68hc11-tdep.c
> @@ -933,7 +933,7 @@ m68hc11_frame_prev_register (const frame_info_ptr &this_frame,
>    return value;
>  }
>  
> -static const struct frame_unwind m68hc11_frame_unwind = {
> +static const struct frame_unwind_legacy m68hc11_frame_unwind (
>    "m68hc11 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -942,7 +942,7 @@ static const struct frame_unwind m68hc11_frame_unwind = {
>    m68hc11_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  m68hc11_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c
> index 7cca4f86394..f7388d952e9 100644
> --- a/gdb/m68k-linux-tdep.c
> +++ b/gdb/m68k-linux-tdep.c
> @@ -314,8 +314,7 @@ m68k_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return m68k_linux_pc_in_sigtramp (this_frame);
>  }
>  
> -static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy m68k_linux_sigtramp_frame_unwind (
>    "m68k linux sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -324,7 +323,7 @@ static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
>    m68k_linux_sigtramp_frame_prev_register,
>    NULL,
>    m68k_linux_sigtramp_frame_sniffer
> -};
> +);
>  
>  /* Register maps for supply/collect regset functions.  */
>  
> diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
> index 2ff507e7816..4318484a5c5 100644
> --- a/gdb/m68k-tdep.c
> +++ b/gdb/m68k-tdep.c
> @@ -1007,8 +1007,7 @@ m68k_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind m68k_frame_unwind =
> -{
> +static const struct frame_unwind_legacy m68k_frame_unwind (
>    "m68k prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1017,7 +1016,7 @@ static const struct frame_unwind m68k_frame_unwind =
>    m68k_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  static CORE_ADDR
>  m68k_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
> index 7dd6371f995..9b6f491c840 100644
> --- a/gdb/mep-tdep.c
> +++ b/gdb/mep-tdep.c
> @@ -2061,7 +2061,7 @@ mep_frame_prev_register (const frame_info_ptr &this_frame,
>  }
>  
>  
> -static const struct frame_unwind mep_frame_unwind = {
> +static const struct frame_unwind_legacy mep_frame_unwind (
>    "mep prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2070,7 +2070,7 @@ static const struct frame_unwind mep_frame_unwind = {
>    mep_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  \f
>  /* Return values.  */
> diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
> index 7a56471a4dd..99c0fc5abc4 100644
> --- a/gdb/microblaze-tdep.c
> +++ b/gdb/microblaze-tdep.c
> @@ -478,8 +478,7 @@ microblaze_frame_prev_register (const frame_info_ptr &this_frame,
>  
>  }
>  
> -static const struct frame_unwind microblaze_frame_unwind =
> -{
> +static const struct frame_unwind_legacy microblaze_frame_unwind (
>    "microblaze prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -488,7 +487,7 @@ static const struct frame_unwind microblaze_frame_unwind =
>    microblaze_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  static CORE_ADDR
>  microblaze_frame_base_address (const frame_info_ptr &next_frame,
> diff --git a/gdb/mips-sde-tdep.c b/gdb/mips-sde-tdep.c
> index 18cb9485639..783e6fd35ab 100644
> --- a/gdb/mips-sde-tdep.c
> +++ b/gdb/mips-sde-tdep.c
> @@ -160,8 +160,7 @@ mips_sde_frame_sniffer (const struct frame_unwind *self,
>  
>  /* Data structure for the SDE frame unwinder.  */
>  
> -static const struct frame_unwind mips_sde_frame_unwind =
> -{
> +static const struct frame_unwind_legacy mips_sde_frame_unwind (
>    "mips sde sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -170,7 +169,7 @@ static const struct frame_unwind mips_sde_frame_unwind =
>    mips_sde_frame_prev_register,
>    NULL,
>    mips_sde_frame_sniffer
> -};
> +);
>  
>  /* Implement the this_base, this_locals, and this_args hooks
>     for the normal unwinder.  */
> diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
> index f5eb2093c8b..4091e5d7a44 100644
> --- a/gdb/mips-tdep.c
> +++ b/gdb/mips-tdep.c
> @@ -2925,8 +2925,7 @@ mips_insn16_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind mips_insn16_frame_unwind =
> -{
> +static const struct frame_unwind_legacy mips_insn16_frame_unwind (
>    "mips insn16 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2935,7 +2934,7 @@ static const struct frame_unwind mips_insn16_frame_unwind =
>    mips_insn16_frame_prev_register,
>    NULL,
>    mips_insn16_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  mips_insn16_frame_base_address (const frame_info_ptr &this_frame,
> @@ -3362,8 +3361,7 @@ mips_micro_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind mips_micro_frame_unwind =
> -{
> +static const struct frame_unwind_legacy mips_micro_frame_unwind (
>    "mips micro prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3372,7 +3370,7 @@ static const struct frame_unwind mips_micro_frame_unwind =
>    mips_micro_frame_prev_register,
>    NULL,
>    mips_micro_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  mips_micro_frame_base_address (const frame_info_ptr &this_frame,
> @@ -3742,8 +3740,7 @@ mips_insn32_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind mips_insn32_frame_unwind =
> -{
> +static const struct frame_unwind_legacy mips_insn32_frame_unwind (
>    "mips insn32 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3752,7 +3749,7 @@ static const struct frame_unwind mips_insn32_frame_unwind =
>    mips_insn32_frame_prev_register,
>    NULL,
>    mips_insn32_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  mips_insn32_frame_base_address (const frame_info_ptr &this_frame,
> @@ -3859,8 +3856,7 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind mips_stub_frame_unwind =
> -{
> +static const struct frame_unwind_legacy mips_stub_frame_unwind (
>    "mips stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3869,7 +3865,7 @@ static const struct frame_unwind mips_stub_frame_unwind =
>    mips_stub_frame_prev_register,
>    NULL,
>    mips_stub_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  mips_stub_frame_base_address (const frame_info_ptr &this_frame,
> diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
> index 565300afd3c..f989bd6c75b 100644
> --- a/gdb/mn10300-tdep.c
> +++ b/gdb/mn10300-tdep.c
> @@ -1127,7 +1127,7 @@ mn10300_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind mn10300_frame_unwind = {
> +static const struct frame_unwind_legacy mn10300_frame_unwind (
>    "mn10300 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1136,7 +1136,7 @@ static const struct frame_unwind mn10300_frame_unwind = {
>    mn10300_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static void
>  mn10300_frame_unwind_init (struct gdbarch *gdbarch)
> diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c
> index 82d3478ed68..f69810f83c3 100644
> --- a/gdb/moxie-tdep.c
> +++ b/gdb/moxie-tdep.c
> @@ -585,7 +585,7 @@ moxie_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind moxie_frame_unwind = {
> +static const struct frame_unwind_legacy moxie_frame_unwind (
>    "moxie prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -594,7 +594,7 @@ static const struct frame_unwind moxie_frame_unwind = {
>    moxie_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Return the base address of this_frame.  */
>  
> diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
> index 6d7fee230c1..17ebddf386a 100644
> --- a/gdb/msp430-tdep.c
> +++ b/gdb/msp430-tdep.c
> @@ -542,7 +542,7 @@ msp430_prev_register (const frame_info_ptr &this_frame,
>      return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind msp430_unwind = {
> +static const struct frame_unwind_legacy msp430_unwind (
>    "msp430 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -551,7 +551,7 @@ static const struct frame_unwind msp430_unwind = {
>    msp430_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Implement the "dwarf2_reg_to_regnum" gdbarch method.  */
>  
> diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
> index 910a6f7a1d0..e08ead24b4f 100644
> --- a/gdb/nds32-tdep.c
> +++ b/gdb/nds32-tdep.c
> @@ -988,8 +988,7 @@ nds32_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind nds32_frame_unwind =
> -{
> +static const struct frame_unwind_legacy nds32_frame_unwind (
>    "nds32 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -997,8 +996,8 @@ static const struct frame_unwind nds32_frame_unwind =
>    nds32_frame_this_id,
>    nds32_frame_prev_register,
>    NULL,
> -  default_frame_sniffer,
> -};
> +  default_frame_sniffer
> +);
>  
>  /* Return the frame base address of *THIS_FRAME.  */
>  
> @@ -1373,8 +1372,7 @@ nds32_epilogue_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind nds32_epilogue_frame_unwind =
> -{
> +static const struct frame_unwind_legacy nds32_epilogue_frame_unwind (
>    "nds32 epilogue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1383,7 +1381,7 @@ static const struct frame_unwind nds32_epilogue_frame_unwind =
>    nds32_epilogue_frame_prev_register,
>    NULL,
>    nds32_epilogue_frame_sniffer
> -};
> +);
>  
>  \f
>  /* Floating type and struct type that has only one floating type member
> diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c
> index 6e0466c3408..bdfad9bfb03 100644
> --- a/gdb/or1k-tdep.c
> +++ b/gdb/or1k-tdep.c
> @@ -1125,7 +1125,7 @@ or1k_frame_prev_register (const frame_info_ptr &this_frame,
>  
>  /* Data structures for the normal prologue-analysis-based unwinder.  */
>  
> -static const struct frame_unwind or1k_frame_unwind = {
> +static const struct frame_unwind_legacy or1k_frame_unwind (
>    "or1k prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1134,8 +1134,8 @@ static const struct frame_unwind or1k_frame_unwind = {
>    or1k_frame_prev_register,
>    NULL,
>    default_frame_sniffer,
> -  NULL,
> -};
> +  NULL
> +);
>  
>  /* Architecture initialization for OpenRISC 1000.  */
>  
> diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
> index 12eb396a0e3..0403b5662b8 100644
> --- a/gdb/ppc-fbsd-tdep.c
> +++ b/gdb/ppc-fbsd-tdep.c
> @@ -262,7 +262,7 @@ ppcfbsd_sigtramp_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_register (cache, this_frame, regnum);
>  }
>  
> -static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy ppcfbsd_sigtramp_frame_unwind (
>    "ppc freebsd sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -271,7 +271,7 @@ static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = {
>    ppcfbsd_sigtramp_frame_prev_register,
>    NULL,
>    ppcfbsd_sigtramp_frame_sniffer
> -};
> +);
>  
>  static enum return_value_convention
>  ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function,
> diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c
> index ceb8b5d85db..37be2d18032 100644
> --- a/gdb/ppc-obsd-tdep.c
> +++ b/gdb/ppc-obsd-tdep.c
> @@ -231,7 +231,7 @@ ppcobsd_sigtramp_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_register (cache, this_frame, regnum);
>  }
>  
> -static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy ppcobsd_sigtramp_frame_unwind (
>    "ppc openbsd sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -240,7 +240,7 @@ static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
>    ppcobsd_sigtramp_frame_prev_register,
>    NULL,
>    ppcobsd_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  
>  static void
> diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
> index ab32f5057f9..e10553c8a93 100644
> --- a/gdb/python/py-unwind.c
> +++ b/gdb/python/py-unwind.c
> @@ -785,11 +785,35 @@ pending_framepy_level (PyObject *self, PyObject *args)
>    return gdb_py_object_from_longest (level).release ();
>  }
>  
> +/* Class for frame unwinders registered by the Python architecture callback.  */
> +class frame_unwind_python : public frame_unwind
> +{
> +public:
> +  frame_unwind_python (const struct frame_data *newarch)
> +    : frame_unwind ("python", NORMAL_FRAME, FRAME_UNWIND_EXTENSION, newarch)
> +  { }
> +
> +  /* No need to override stop_reason, we want the default.  */
> +
> +  int sniff (const frame_info_ptr &this_frame,
> +	     void **this_prologue_cache) const override;
> +
> +  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
> +		struct frame_id *id) const override;
> +
> +  struct value *prev_register (const frame_info_ptr &this_frame,
> +			       void **this_prologue_cache,
> +			       int regnum) const override;
> +
> +  void dealloc_cache (frame_info *self, void *this_cache) const override;
> +};
> +
>  /* frame_unwind.this_id method.  */
>  
> -static void
> -pyuw_this_id (const frame_info_ptr &this_frame, void **cache_ptr,
> -	      struct frame_id *this_id)
> +void
> +frame_unwind_python::this_id (const frame_info_ptr &this_frame,
> +			      void **cache_ptr,
> +			      struct frame_id *this_id) const
>  {
>    *this_id = ((cached_frame_info *) *cache_ptr)->frame_id;
>    pyuw_debug_printf ("frame_id: %s", this_id->to_string ().c_str ());
> @@ -797,9 +821,9 @@ pyuw_this_id (const frame_info_ptr &this_frame, void **cache_ptr,
>  
>  /* frame_unwind.prev_register.  */
>  
> -static struct value *
> -pyuw_prev_register (const frame_info_ptr &this_frame, void **cache_ptr,
> -		    int regnum)
> +struct value *
> +frame_unwind_python::prev_register (const frame_info_ptr &this_frame,
> +				    void **cache_ptr, int regnum) const
>  {
>    PYUW_SCOPED_DEBUG_ENTER_EXIT;
>  
> @@ -820,13 +844,13 @@ pyuw_prev_register (const frame_info_ptr &this_frame, void **cache_ptr,
>  
>  /* Frame sniffer dispatch.  */
>  
> -static int
> -pyuw_sniffer (const struct frame_unwind *self, const frame_info_ptr &this_frame,
> -	      void **cache_ptr)
> +int
> +frame_unwind_python::sniff (const frame_info_ptr &this_frame,
> +			    void **cache_ptr) const
>  {
>    PYUW_SCOPED_DEBUG_ENTER_EXIT;
>  
> -  struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data);
> +  struct gdbarch *gdbarch = (struct gdbarch *) (this->unwind_data ());
>    cached_frame_info *cached_frame;
>  
>    gdbpy_enter enter_py (gdbarch);
> @@ -947,8 +971,8 @@ pyuw_sniffer (const struct frame_unwind *self, const frame_info_ptr &this_frame,
>  
>  /* Frame cache release shim.  */
>  
> -static void
> -pyuw_dealloc_cache (frame_info *this_frame, void *cache)
> +void
> +frame_unwind_python::dealloc_cache (frame_info *this_frame, void *cache) const
>  {
>    PYUW_SCOPED_DEBUG_ENTER_EXIT;
>    cached_frame_info *cached_frame = (cached_frame_info *) cache;
> @@ -980,17 +1004,9 @@ pyuw_on_new_gdbarch (gdbarch *newarch)
>    if (!data->unwinder_registered)
>      {
>        struct frame_unwind *unwinder
> -	  = GDBARCH_OBSTACK_ZALLOC (newarch, struct frame_unwind);
> -
> -      unwinder->name = "python";
> -      unwinder->type = NORMAL_FRAME;
> -      unwinder->unwinder_class = FRAME_UNWIND_EXTENSION;
> -      unwinder->stop_reason = default_frame_unwind_stop_reason;
> -      unwinder->this_id = pyuw_this_id;
> -      unwinder->prev_register = pyuw_prev_register;
> -      unwinder->unwind_data = (const struct frame_data *) newarch;
> -      unwinder->sniffer = pyuw_sniffer;
> -      unwinder->dealloc_cache = pyuw_dealloc_cache;
> +	  = obstack_new<frame_unwind_python>
> +	    (gdbarch_obstack (newarch), (const struct frame_data *) newarch);
> +
>        frame_unwind_prepend_unwinder (newarch, unwinder);
>        data->unwinder_registered = 1;
>      }
> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
> index 47f2a7f6510..a47b34e887c 100644
> --- a/gdb/record-btrace.c
> +++ b/gdb/record-btrace.c
> @@ -1940,8 +1940,7 @@ record_btrace_frame_dealloc_cache (frame_info *self, void *this_cache)
>     Therefore this unwinder reports any possibly unwound registers as
>     <unavailable>.  */
>  
> -const struct frame_unwind record_btrace_frame_unwind =
> -{
> +const struct frame_unwind_legacy record_btrace_frame_unwind (
>    "record-btrace",
>    NORMAL_FRAME,
>    FRAME_UNWIND_GDB,
> @@ -1951,10 +1950,9 @@ const struct frame_unwind record_btrace_frame_unwind =
>    NULL,
>    record_btrace_frame_sniffer,
>    record_btrace_frame_dealloc_cache
> -};
> +);
>  
> -const struct frame_unwind record_btrace_tailcall_frame_unwind =
> -{
> +const struct frame_unwind_legacy record_btrace_tailcall_frame_unwind (
>    "record-btrace tailcall",
>    TAILCALL_FRAME,
>    FRAME_UNWIND_GDB,
> @@ -1964,7 +1962,7 @@ const struct frame_unwind record_btrace_tailcall_frame_unwind =
>    NULL,
>    record_btrace_tailcall_frame_sniffer,
>    record_btrace_frame_dealloc_cache
> -};
> +);
>  
>  /* Implement the get_unwinder method.  */
>  
> diff --git a/gdb/record.h b/gdb/record.h
> index aea6507c947..a5b4082b243 100644
> --- a/gdb/record.h
> +++ b/gdb/record.h
> @@ -36,8 +36,8 @@ extern struct cmd_list_element *show_record_cmdlist;
>  extern struct cmd_list_element *info_record_cmdlist;
>  
>  /* Unwinders for some record targets.  */
> -extern const struct frame_unwind record_btrace_frame_unwind;
> -extern const struct frame_unwind record_btrace_tailcall_frame_unwind;
> +extern const struct frame_unwind_legacy record_btrace_frame_unwind;
> +extern const struct frame_unwind_legacy record_btrace_tailcall_frame_unwind;
>  
>  /* A list of different recording methods.  */
>  enum record_method
> diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
> index 2a292cc4ff8..0801d076a38 100644
> --- a/gdb/riscv-tdep.c
> +++ b/gdb/riscv-tdep.c
> @@ -3900,8 +3900,7 @@ riscv_frame_prev_register (const frame_info_ptr &this_frame,
>     are the fallback unwinder (DWARF unwinder is used first), we use the
>     default frame sniffer, which always accepts the frame.  */
>  
> -static const struct frame_unwind riscv_frame_unwind =
> -{
> +static const struct frame_unwind_legacy riscv_frame_unwind (
>    /*.name          =*/ "riscv prologue",
>    /*.type          =*/ NORMAL_FRAME,
>    /*.unwinder_class=*/FRAME_UNWIND_ARCH,
> @@ -3911,8 +3910,8 @@ static const struct frame_unwind riscv_frame_unwind =
>    /*.unwind_data   =*/ NULL,
>    /*.sniffer       =*/ default_frame_sniffer,
>    /*.dealloc_cache =*/ NULL,
> -  /*.prev_arch     =*/ NULL,
> -};
> +  /*.prev_arch     =*/ NULL
> +);
>  
>  /* Extract a set of required target features out of ABFD.  If ABFD is
>     nullptr then a RISCV_GDBARCH_FEATURES is returned in its default state.  */
> diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
> index 0fcd5f9f1f3..f4aecce055b 100644
> --- a/gdb/rl78-tdep.c
> +++ b/gdb/rl78-tdep.c
> @@ -1183,8 +1183,7 @@ rl78_prev_register (const frame_info_ptr &this_frame,
>      return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind rl78_unwind =
> -{
> +static const struct frame_unwind_legacy rl78_unwind (
>    "rl78 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1193,7 +1192,7 @@ static const struct frame_unwind rl78_unwind =
>    rl78_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Implement the "dwarf_reg_to_regnum" gdbarch method.  */
>  
> diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
> index f1c31ae27ea..e6255b1d3ba 100644
> --- a/gdb/rs6000-aix-tdep.c
> +++ b/gdb/rs6000-aix-tdep.c
> @@ -328,7 +328,7 @@ aix_sighandle_frame_sniffer (const struct frame_unwind *self,
>  
>  /* AIX signal handler frame unwinder */
>  
> -static const struct frame_unwind aix_sighandle_frame_unwind = {
> +static const struct frame_unwind_legacy aix_sighandle_frame_unwind (
>    "rs6000 aix sighandle",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -337,7 +337,7 @@ static const struct frame_unwind aix_sighandle_frame_unwind = {
>    aix_sighandle_frame_prev_register,
>    NULL,
>    aix_sighandle_frame_sniffer
> -};
> +);
>  
>  /* Core file support.  */
>  
> diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
> index e3bffa8f33d..26a78418edb 100644
> --- a/gdb/rs6000-tdep.c
> +++ b/gdb/rs6000-tdep.c
> @@ -3837,8 +3837,7 @@ rs6000_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind rs6000_frame_unwind =
> -{
> +static const struct frame_unwind_legacy rs6000_frame_unwind (
>    "rs6000 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3847,7 +3846,7 @@ static const struct frame_unwind rs6000_frame_unwind =
>    rs6000_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Allocate and initialize a frame cache for an epilogue frame.
>     SP is restored and prev-PC is stored in LR.  */
> @@ -3979,8 +3978,7 @@ rs6000_epilogue_frame_sniffer (const struct frame_unwind *self,
>  /* Frame unwinder for epilogue frame.  This is required for reverse step-over
>     a function without debug information.  */
>  
> -static const struct frame_unwind rs6000_epilogue_frame_unwind =
> -{
> +static const struct frame_unwind_legacy rs6000_epilogue_frame_unwind (
>    "rs6000 epilogue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -3988,7 +3986,7 @@ static const struct frame_unwind rs6000_epilogue_frame_unwind =
>    rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register,
>    NULL,
>    rs6000_epilogue_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
> index 6cb74c23a3c..18d184851cb 100644
> --- a/gdb/rx-tdep.c
> +++ b/gdb/rx-tdep.c
> @@ -631,7 +631,7 @@ rx_exception_sniffer (const struct frame_unwind *self,
>  /* Data structure for normal code using instruction-based prologue
>     analyzer.  */
>  
> -static const struct frame_unwind rx_frame_unwind = {
> +static const struct frame_unwind_legacy rx_frame_unwind (
>    "rx prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -640,12 +640,12 @@ static const struct frame_unwind rx_frame_unwind = {
>    rx_frame_prev_register,
>    NULL,
>    rx_frame_sniffer
> -};
> +);
>  
>  /* Data structure for exception code using instruction-based prologue
>     analyzer.  */
>  
> -static const struct frame_unwind rx_exception_unwind = {
> +static const struct frame_unwind_legacy rx_exception_unwind (
>    "rx exception",
>    /* SIGTRAMP_FRAME could be used here, but backtraces are less informative.  */
>    NORMAL_FRAME,
> @@ -655,7 +655,7 @@ static const struct frame_unwind rx_exception_unwind = {
>    rx_frame_prev_register,
>    NULL,
>    rx_exception_sniffer
> -};
> +);
>  
>  /* Implement the "push_dummy_call" gdbarch method.  */
>  static CORE_ADDR
> diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c
> index 7fa73cf6b8c..faef1a42601 100644
> --- a/gdb/s12z-tdep.c
> +++ b/gdb/s12z-tdep.c
> @@ -441,7 +441,7 @@ s12z_frame_prev_register (const frame_info_ptr &this_frame,
>  }
>  
>  /* Data structures for the normal prologue-analysis-based unwinder.  */
> -static const struct frame_unwind s12z_frame_unwind = {
> +static const struct frame_unwind_legacy s12z_frame_unwind (
>    "s12z prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -450,8 +450,8 @@ static const struct frame_unwind s12z_frame_unwind = {
>    s12z_frame_prev_register,
>    NULL,
>    default_frame_sniffer,
> -  NULL,
> -};
> +  NULL
> +);
>  
>  
>  constexpr gdb_byte s12z_break_insn[] = {0x00};
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index 556fad64926..96d6d446219 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -541,7 +541,7 @@ s390_sigtramp_frame_sniffer (const struct frame_unwind *self,
>  
>  /* S390 sigtramp frame unwinder.  */
>  
> -static const struct frame_unwind s390_sigtramp_frame_unwind = {
> +static const struct frame_unwind_legacy s390_sigtramp_frame_unwind (
>    "s390 linux sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -550,7 +550,7 @@ static const struct frame_unwind s390_sigtramp_frame_unwind = {
>    s390_sigtramp_frame_prev_register,
>    NULL,
>    s390_sigtramp_frame_sniffer
> -};
> +);
>  
>  /* Syscall handling.  */
>  
> diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
> index f0af9a8796d..516546b317d 100644
> --- a/gdb/s390-tdep.c
> +++ b/gdb/s390-tdep.c
> @@ -2646,7 +2646,7 @@ s390_frame_prev_register (const frame_info_ptr &this_frame,
>  
>  /* Default S390 frame unwinder.  */
>  
> -static const struct frame_unwind s390_frame_unwind = {
> +static const struct frame_unwind_legacy s390_frame_unwind (
>    "s390 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2655,7 +2655,7 @@ static const struct frame_unwind s390_frame_unwind = {
>    s390_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  /* Code stubs and their stack frames.  For things like PLTs and NULL
>     function calls (where there is no true frame and the return address
> @@ -2741,7 +2741,7 @@ s390_stub_frame_sniffer (const struct frame_unwind *self,
>  
>  /* S390 stub frame unwinder.  */
>  
> -static const struct frame_unwind s390_stub_frame_unwind = {
> +static const struct frame_unwind_legacy s390_stub_frame_unwind (
>    "s390 stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2750,7 +2750,7 @@ static const struct frame_unwind s390_stub_frame_unwind = {
>    s390_stub_frame_prev_register,
>    NULL,
>    s390_stub_frame_sniffer
> -};
> +);
>  
>  /* Frame base handling.  */
>  
> diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
> index 9fe4036dbbe..c809259920d 100644
> --- a/gdb/sentinel-frame.c
> +++ b/gdb/sentinel-frame.c
> @@ -78,8 +78,7 @@ sentinel_frame_prev_arch (const frame_info_ptr &this_frame,
>    return cache->regcache->arch ();
>  }
>  
> -const struct frame_unwind sentinel_frame_unwind =
> -{
> +const struct frame_unwind_legacy sentinel_frame_unwind (
>    "sentinel",
>    SENTINEL_FRAME,
>    FRAME_UNWIND_GDB,
> @@ -89,5 +88,5 @@ const struct frame_unwind sentinel_frame_unwind =
>    NULL,
>    NULL,
>    NULL,
> -  sentinel_frame_prev_arch,
> -};
> +  sentinel_frame_prev_arch
> +);
> diff --git a/gdb/sentinel-frame.h b/gdb/sentinel-frame.h
> index 1a37ff1f49a..4b498f18940 100644
> --- a/gdb/sentinel-frame.h
> +++ b/gdb/sentinel-frame.h
> @@ -34,6 +34,6 @@ extern void *sentinel_frame_cache (struct regcache *regcache);
>  
>  /* At present there is only one type of sentinel frame.  */
>  
> -extern const struct frame_unwind sentinel_frame_unwind;
> +extern const struct frame_unwind_legacy sentinel_frame_unwind;
>  
>  #endif /* !defined (SENTINEL_FRAME_H)  */
> diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
> index c8809e3018e..375b796bfc8 100644
> --- a/gdb/sh-tdep.c
> +++ b/gdb/sh-tdep.c
> @@ -1950,7 +1950,7 @@ sh_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
>    *this_id = frame_id_build (cache->saved_sp, cache->pc);
>  }
>  
> -static const struct frame_unwind sh_frame_unwind = {
> +static const struct frame_unwind_legacy sh_frame_unwind (
>    "sh prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1959,7 +1959,7 @@ static const struct frame_unwind sh_frame_unwind = {
>    sh_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  sh_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> @@ -2017,8 +2017,7 @@ sh_stub_unwind_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sh_stub_unwind =
> -{
> +static const struct frame_unwind_legacy sh_stub_unwind (
>    "sh stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -2027,7 +2026,7 @@ static const struct frame_unwind sh_stub_unwind =
>    sh_frame_prev_register,
>    NULL,
>    sh_stub_unwind_sniffer
> -};
> +);
>  
>  /* Implement the stack_frame_destroyed_p gdbarch method.
>  
> diff --git a/gdb/sparc-netbsd-tdep.c b/gdb/sparc-netbsd-tdep.c
> index 5b3dd067375..bc058dcbf63 100644
> --- a/gdb/sparc-netbsd-tdep.c
> +++ b/gdb/sparc-netbsd-tdep.c
> @@ -248,8 +248,7 @@ sparc32nbsd_sigcontext_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc32nbsd_sigcontext_frame_unwind (
>    "sparc32 netbsd sigcontext",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -258,7 +257,7 @@ static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
>    sparc32nbsd_sigcontext_frame_prev_register,
>    NULL,
>    sparc32nbsd_sigcontext_frame_sniffer
> -};
> +);
>  \f
>  /* Return the address of a system call's alternative return
>     address.  */
> diff --git a/gdb/sparc-obsd-tdep.c b/gdb/sparc-obsd-tdep.c
> index 049c315fa14..2bc944efca0 100644
> --- a/gdb/sparc-obsd-tdep.c
> +++ b/gdb/sparc-obsd-tdep.c
> @@ -134,8 +134,7 @@ sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
>  
>    return 0;
>  }
> -static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc32obsd_sigtramp_frame_unwind (
>    "sparc32 openbsd sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -144,7 +143,7 @@ static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
>    sparc32obsd_sigtramp_frame_prev_register,
>    NULL,
>    sparc32obsd_sigtramp_frame_sniffer
> -};
> +);
>  
>  \f
>  
> diff --git a/gdb/sparc-sol2-tdep.c b/gdb/sparc-sol2-tdep.c
> index bb9c8a549b1..b6ac8011b7b 100644
> --- a/gdb/sparc-sol2-tdep.c
> +++ b/gdb/sparc-sol2-tdep.c
> @@ -179,8 +179,7 @@ sparc32_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return sol2_sigtramp_p (this_frame);
>  }
>  
> -static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc32_sol2_sigtramp_frame_unwind (
>    "sparc32 solaris sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -189,7 +188,7 @@ static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
>    sparc32_sol2_sigtramp_frame_prev_register,
>    NULL,
>    sparc32_sol2_sigtramp_frame_sniffer
> -};
> +);
>  
>  \f
>  
> diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
> index d69ab87be09..5fab313132b 100644
> --- a/gdb/sparc-tdep.c
> +++ b/gdb/sparc-tdep.c
> @@ -1346,8 +1346,7 @@ sparc32_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind sparc32_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc32_frame_unwind (
>    "sparc32 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1356,7 +1355,7 @@ static const struct frame_unwind sparc32_frame_unwind =
>    sparc32_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> diff --git a/gdb/sparc64-fbsd-tdep.c b/gdb/sparc64-fbsd-tdep.c
> index 1d4c075a961..6630a9b51b0 100644
> --- a/gdb/sparc64-fbsd-tdep.c
> +++ b/gdb/sparc64-fbsd-tdep.c
> @@ -196,8 +196,7 @@ sparc64fbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64fbsd_sigtramp_frame_unwind (
>    "sparc64 freebsd sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -206,7 +205,7 @@ static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
>    sparc64fbsd_sigtramp_frame_prev_register,
>    NULL,
>    sparc64fbsd_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  
>  static const struct regset sparc64fbsd_gregset =
> diff --git a/gdb/sparc64-netbsd-tdep.c b/gdb/sparc64-netbsd-tdep.c
> index 82eb99f57c1..53c49fe1130 100644
> --- a/gdb/sparc64-netbsd-tdep.c
> +++ b/gdb/sparc64-netbsd-tdep.c
> @@ -222,8 +222,7 @@ sparc64nbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64nbsd_sigcontext_frame_unwind (
>    "sparc64 netbsd sigcontext",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -232,7 +231,7 @@ static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
>    sparc64nbsd_sigcontext_frame_prev_register,
>    NULL,
>    sparc64nbsd_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  
>  static const struct regset sparc64nbsd_gregset =
> diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c
> index e81afa604e7..8596d2fa069 100644
> --- a/gdb/sparc64-obsd-tdep.c
> +++ b/gdb/sparc64-obsd-tdep.c
> @@ -220,8 +220,7 @@ sparc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sparc64obsd_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64obsd_frame_unwind (
>    "sparc64 openbsd sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -230,7 +229,7 @@ static const struct frame_unwind sparc64obsd_frame_unwind =
>    sparc64obsd_frame_prev_register,
>    NULL,
>    sparc64obsd_sigtramp_frame_sniffer
> -};
> +);
>  \f
>  /* Kernel debugging support.  */
>  
> @@ -305,8 +304,7 @@ sparc64obsd_trapframe_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind sparc64obsd_trapframe_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64obsd_trapframe_unwind (
>    "sparc64 openbsd trap",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -315,7 +313,7 @@ static const struct frame_unwind sparc64obsd_trapframe_unwind =
>    sparc64obsd_trapframe_prev_register,
>    NULL,
>    sparc64obsd_trapframe_sniffer
> -};
> +);
>  \f
>  
>  /* Threads support.  */
> diff --git a/gdb/sparc64-sol2-tdep.c b/gdb/sparc64-sol2-tdep.c
> index e8d09e2516e..cadbf49788c 100644
> --- a/gdb/sparc64-sol2-tdep.c
> +++ b/gdb/sparc64-sol2-tdep.c
> @@ -182,8 +182,7 @@ sparc64_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self,
>    return sol2_sigtramp_p (this_frame);
>  }
>  
> -static const struct frame_unwind sparc64_sol2_sigtramp_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64_sol2_sigtramp_frame_unwind (
>    "sparc64 solaris sigtramp",
>    SIGTRAMP_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -192,7 +191,7 @@ static const struct frame_unwind sparc64_sol2_sigtramp_frame_unwind =
>    sparc64_sol2_sigtramp_frame_prev_register,
>    NULL,
>    sparc64_sol2_sigtramp_frame_sniffer
> -};
> +);
>  
>  \f
>  
> diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
> index 90b04fc0ff1..7810b81c03b 100644
> --- a/gdb/sparc64-tdep.c
> +++ b/gdb/sparc64-tdep.c
> @@ -1135,8 +1135,7 @@ sparc64_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static const struct frame_unwind sparc64_frame_unwind =
> -{
> +static const struct frame_unwind_legacy sparc64_frame_unwind (
>    "sparc64 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1145,7 +1144,7 @@ static const struct frame_unwind sparc64_frame_unwind =
>    sparc64_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
> index bac8ba84ed0..c7e42b154db 100644
> --- a/gdb/tic6x-tdep.c
> +++ b/gdb/tic6x-tdep.c
> @@ -452,8 +452,7 @@ tic6x_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
>    return info->base;
>  }
>  
> -static const struct frame_unwind tic6x_frame_unwind =
> -{
> +static const struct frame_unwind_legacy tic6x_frame_unwind (
>    "tic6x prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -462,7 +461,7 @@ static const struct frame_unwind tic6x_frame_unwind =
>    tic6x_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static const struct frame_base tic6x_frame_base =
>  {
> @@ -516,8 +515,7 @@ tic6x_stub_unwind_sniffer (const struct frame_unwind *self,
>    return 0;
>  }
>  
> -static const struct frame_unwind tic6x_stub_unwind =
> -{
> +static const struct frame_unwind_legacy tic6x_stub_unwind (
>    "tic6x stub",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -526,7 +524,7 @@ static const struct frame_unwind tic6x_stub_unwind =
>    tic6x_frame_prev_register,
>    NULL,
>    tic6x_stub_unwind_sniffer
> -};
> +);
>  
>  /* Return the instruction on address PC.  */
>  
> diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
> index 16cd25f4635..e2247d769df 100644
> --- a/gdb/tilegx-tdep.c
> +++ b/gdb/tilegx-tdep.c
> @@ -900,7 +900,7 @@ tilegx_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
>    return cache->base;
>  }
>  
> -static const struct frame_unwind tilegx_frame_unwind = {
> +static const struct frame_unwind_legacy tilegx_frame_unwind (
>    "tilegx prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -910,7 +910,7 @@ static const struct frame_unwind tilegx_frame_unwind = {
>    NULL,                        /* const struct frame_data *unwind_data  */
>    default_frame_sniffer,       /* frame_sniffer_ftype *sniffer  */
>    NULL                         /* frame_prev_pc_ftype *prev_pc  */
> -};
> +);
>  
>  static const struct frame_base tilegx_frame_base = {
>    &tilegx_frame_unwind,
> diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c
> index 6368f67a2e7..9353cf605e1 100644
> --- a/gdb/tramp-frame.c
> +++ b/gdb/tramp-frame.c
> @@ -57,10 +57,41 @@ tramp_frame_cache (const frame_info_ptr &this_frame,
>    return tramp_cache->trad_cache;
>  }
>  
> -static void
> -tramp_frame_this_id (const frame_info_ptr &this_frame,
> -		     void **this_cache,
> -		     struct frame_id *this_id)
> +class frame_unwind_trampoline : public frame_unwind
> +{
> +public:
> +  frame_unwind_trampoline (enum frame_type type, const struct frame_data *data,
> +			   frame_prev_arch_ftype *prev_arch_func)
> +    : frame_unwind ("trampoline", type, FRAME_UNWIND_GDB, data),
> +      m_prev_arch (prev_arch_func)
> +  { }
> +
> +  int sniff (const frame_info_ptr &this_frame,
> +	     void **this_prologue_cache) const override;
> +
> +  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
> +		struct frame_id *id) const override;
> +
> +  value *prev_register (const frame_info_ptr &this_frame,
> +			void **this_prologue_cache,
> +			int regnum) const override;
> +
> +  struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
> +			     void **this_prologue_cache) const override
> +  {
> +    if (m_prev_arch == nullptr)
> +      return frame_unwind::prev_arch (this_frame, this_prologue_cache);
> +    return m_prev_arch (this_frame, this_prologue_cache);
> +  }
> +
> +private:
> +  frame_prev_arch_ftype *m_prev_arch;
> +};
> +
> +void
> +frame_unwind_trampoline::this_id (const frame_info_ptr &this_frame,
> +				  void **this_cache,
> +				  struct frame_id *this_id) const
>  {
>    struct trad_frame_cache *trad_cache
>      = tramp_frame_cache (this_frame, this_cache);
> @@ -68,10 +99,10 @@ tramp_frame_this_id (const frame_info_ptr &this_frame,
>    trad_frame_get_id (trad_cache, this_id);
>  }
>  
> -static struct value *
> -tramp_frame_prev_register (const frame_info_ptr &this_frame,
> -			   void **this_cache,
> -			   int prev_regnum)
> +struct value *
> +frame_unwind_trampoline::prev_register (const frame_info_ptr &this_frame,
> +					void **this_cache,
> +					int prev_regnum) const
>  {
>    struct trad_frame_cache *trad_cache
>      = tramp_frame_cache (this_frame, this_cache);
> @@ -119,12 +150,11 @@ tramp_frame_start (const struct tramp_frame *tramp,
>    return 0;
>  }
>  
> -static int
> -tramp_frame_sniffer (const struct frame_unwind *self,
> -		     const frame_info_ptr &this_frame,
> -		     void **this_cache)
> +int
> +frame_unwind_trampoline::sniff (const frame_info_ptr &this_frame,
> +				void **this_cache) const
>  {
> -  const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
> +  const struct tramp_frame *tramp = unwind_data ()->tramp_frame;
>    CORE_ADDR pc = get_frame_pc (this_frame);
>    CORE_ADDR func;
>    struct tramp_frame_cache *tramp_cache;
> @@ -161,16 +191,11 @@ tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
>    gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));
>  
>    data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
> -  unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
> -
>    data->tramp_frame = tramp_frame;
> -  unwinder->type = tramp_frame->frame_type;
> -  unwinder->unwind_data = data;
> -  unwinder->unwinder_class = FRAME_UNWIND_GDB;
> -  unwinder->sniffer = tramp_frame_sniffer;
> -  unwinder->stop_reason = default_frame_unwind_stop_reason;
> -  unwinder->this_id = tramp_frame_this_id;
> -  unwinder->prev_register = tramp_frame_prev_register;
> -  unwinder->prev_arch = tramp_frame->prev_arch;
> +
> +  unwinder = obstack_new <frame_unwind_trampoline> (gdbarch_obstack (gdbarch),
> +						    tramp_frame->frame_type,
> +						    data,
> +						    tramp_frame->prev_arch);
>    frame_unwind_prepend_unwinder (gdbarch, unwinder);
>  }
> diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
> index d3f1af75417..59a29307b14 100644
> --- a/gdb/v850-tdep.c
> +++ b/gdb/v850-tdep.c
> @@ -1320,7 +1320,7 @@ v850_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
>    *this_id = frame_id_build (cache->saved_regs[E_SP_REGNUM].addr (), cache->pc);
>  }
>  
> -static const struct frame_unwind v850_frame_unwind = {
> +static const struct frame_unwind_legacy v850_frame_unwind (
>    "v850 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1329,7 +1329,7 @@ static const struct frame_unwind v850_frame_unwind = {
>    v850_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  v850_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c
> index 25d07c59376..4660979928c 100644
> --- a/gdb/vax-tdep.c
> +++ b/gdb/vax-tdep.c
> @@ -386,8 +386,7 @@ vax_frame_prev_register (const frame_info_ptr &this_frame,
>    return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
>  }
>  
> -static const struct frame_unwind vax_frame_unwind =
> -{
> +static const struct frame_unwind_legacy vax_frame_unwind (
>    "vax prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -396,7 +395,7 @@ static const struct frame_unwind vax_frame_unwind =
>    vax_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  \f
>  
>  static CORE_ADDR
> diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
> index 8a29a33042f..a5243dc8715 100644
> --- a/gdb/windows-tdep.c
> +++ b/gdb/windows-tdep.c
> @@ -1321,10 +1321,9 @@ cygwin_sigwrapper_frame_cache (frame_info_ptr this_frame, void **this_cache)
>    return cache;
>  }
>  
> -static struct value *
> -cygwin_sigwrapper_frame_prev_register (const frame_info_ptr &this_frame,
> -				       void **this_cache,
> -				       int regnum)
> +struct value *
> +cygwin_sigwrapper_frame_unwind::prev_register
> +    (const frame_info_ptr &this_frame, void **this_cache, int regnum) const
>  {
>    struct gdbarch *gdbarch = get_frame_arch (this_frame);
>    struct cygwin_sigwrapper_frame_cache *cache
> @@ -1340,20 +1339,18 @@ cygwin_sigwrapper_frame_prev_register (const frame_info_ptr &this_frame,
>    return frame_unwind_got_register (this_frame, regnum, regnum);
>  }
>  
> -static void
> -cygwin_sigwrapper_frame_this_id (const frame_info_ptr &this_frame,
> -				 void **this_cache,
> -				 struct frame_id *this_id)
> +void
> +cygwin_sigwrapper_frame_unwind::this_id (const frame_info_ptr &this_frame,
> +					 void **this_cache,
> +					 struct frame_id *this_id) const
>  {
>    *this_id = frame_id_build_unavailable_stack (get_frame_func (this_frame));
>  }
>  
> -static int
> -cygwin_sigwrapper_frame_sniffer (const struct frame_unwind *self_,
> -				 const frame_info_ptr &this_frame,
> -				 void **this_cache)
> +int
> +cygwin_sigwrapper_frame_unwind::sniff (const frame_info_ptr &this_frame,
> +					 void **this_cache) const
>  {
> -  const auto *self = (const struct cygwin_sigwrapper_frame_unwind *) self_;
>    struct gdbarch *gdbarch = get_frame_arch (this_frame);
>  
>    CORE_ADDR pc = get_frame_pc (this_frame);
> @@ -1376,7 +1373,7 @@ cygwin_sigwrapper_frame_sniffer (const struct frame_unwind *self_,
>  		      paddress (gdbarch, end));
>  
>    int tlsoffset;
> -  cygwin_sigwrapper_frame_analyze (gdbarch, start, end, self->patterns_list,
> +  cygwin_sigwrapper_frame_analyze (gdbarch, start, end, patterns_list,
>  				   &tlsoffset);
>    if (tlsoffset == 0)
>      return 0;
> @@ -1396,13 +1393,7 @@ cygwin_sigwrapper_frame_sniffer (const struct frame_unwind *self_,
>  
>  cygwin_sigwrapper_frame_unwind::cygwin_sigwrapper_frame_unwind
>    (gdb::array_view<const gdb::array_view<const gdb_byte>> patterns_list)
> -    : frame_unwind (),
> -      patterns_list (patterns_list)
> +    : frame_unwind ("cygwin sigwrapper", NORMAL_FRAME, FRAME_UNWIND_GDB,
> +		    nullptr), patterns_list (patterns_list)
>  {
> -  name = "cygwin sigwrapper";
> -  type = NORMAL_FRAME;
> -  stop_reason = default_frame_unwind_stop_reason;
> -  this_id = cygwin_sigwrapper_frame_this_id;
> -  prev_register = cygwin_sigwrapper_frame_prev_register;
> -  sniffer = cygwin_sigwrapper_frame_sniffer;
>  }
> diff --git a/gdb/windows-tdep.h b/gdb/windows-tdep.h
> index f122f7aaa61..84206fb0c89 100644
> --- a/gdb/windows-tdep.h
> +++ b/gdb/windows-tdep.h
> @@ -60,8 +60,9 @@ extern bool is_linked_with_cygwin_dll (bfd *abfd);
>  /* Cygwin sigwapper unwinder.  Unwinds signal frames over
>     sigbe/sigdelayed.  */
>  
> -struct cygwin_sigwrapper_frame_unwind : public frame_unwind
> +class cygwin_sigwrapper_frame_unwind : public frame_unwind
>  {
> +public:
>    explicit cygwin_sigwrapper_frame_unwind
>      (gdb::array_view<const gdb::array_view<const gdb_byte>> patterns_list);
>  
> @@ -73,6 +74,19 @@ struct cygwin_sigwrapper_frame_unwind : public frame_unwind
>       If any pattern in the list matches, then the frame is assumed to
>       be a sigwrapper frame.  */
>    gdb::array_view<const gdb::array_view<const gdb_byte>> patterns_list;
> +
> +  /* Calculate the frame ID of a cygwin wrapper.  */
> +  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
> +		struct frame_id *id) const override;
> +
> +  /* Sniff the frame to tell if this unwinder should be used.  */
> +  int sniff (const frame_info_ptr &this_frame,
> +	       void **this_prologue_cache) const override;
> +
> +  /* Calculate the value of a given register in the previous frame.  */
> +  struct value *prev_register (const frame_info_ptr &this_frame,
> +			       void **this_cache,
> +			       int regnum) const override;
>  };
>  
>  #endif
> diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c
> index e01da4ecab4..e7f4e6fe600 100644
> --- a/gdb/xstormy16-tdep.c
> +++ b/gdb/xstormy16-tdep.c
> @@ -728,7 +728,7 @@ xstormy16_frame_base_address (const frame_info_ptr &this_frame, void **this_cach
>    return cache->base;
>  }
>  
> -static const struct frame_unwind xstormy16_frame_unwind = {
> +static const struct frame_unwind_legacy xstormy16_frame_unwind (
>    "xstormy16 prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -737,7 +737,7 @@ static const struct frame_unwind xstormy16_frame_unwind = {
>    xstormy16_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static const struct frame_base xstormy16_frame_base = {
>    &xstormy16_frame_unwind,
> diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
> index d12dfdc7347..c87940c1cfc 100644
> --- a/gdb/xtensa-tdep.c
> +++ b/gdb/xtensa-tdep.c
> @@ -1496,9 +1496,7 @@ xtensa_frame_prev_register (const frame_info_ptr &this_frame,
>  }
>  
>  
> -static const struct frame_unwind
> -xtensa_unwind =
> -{
> +static const struct frame_unwind_legacy xtensa_unwind (
>    "xtensa prologue",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1507,7 +1505,7 @@ xtensa_unwind =
>    xtensa_frame_prev_register,
>    NULL,
>    default_frame_sniffer
> -};
> +);
>  
>  static CORE_ADDR
>  xtensa_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
> diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c
> index 66a12cd3be7..c75b6ff3160 100644
> --- a/gdb/z80-tdep.c
> +++ b/gdb/z80-tdep.c
> @@ -1063,9 +1063,7 @@ z80_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
>    return 0;
>  }
>  
> -static const struct frame_unwind
> -z80_frame_unwind =
> -{
> +static const struct frame_unwind_legacy z80_frame_unwind (
>    "z80",
>    NORMAL_FRAME,
>    FRAME_UNWIND_ARCH,
> @@ -1076,7 +1074,7 @@ z80_frame_unwind =
>    default_frame_sniffer
>    /*dealloc_cache*/
>    /*prev_arch*/
> -};
> +);
>  
>  /* Initialize the gdbarch struct for the Z80 arch */
>  static struct gdbarch *
> -- 
> 2.47.0


  reply	other threads:[~2025-01-14 17:14 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-12-10 19:51 [PATCH v8 0/5] Modernize frame unwinders and add disable feature Guinevere Larsen
2024-12-10 19:51 ` [PATCH v8 1/5] gdb: make gdbarch store a vector of frame unwinders Guinevere Larsen
2025-01-14 14:28   ` Andrew Burgess
2025-01-14 20:34     ` Guinevere Larsen
2024-12-10 19:51 ` [PATCH v8 2/5] gdb: add "unwinder class" to " Guinevere Larsen
2025-01-14 15:28   ` Andrew Burgess
2024-12-10 19:51 ` [PATCH v8 3/5] gdb: Migrate frame unwinders to use C++ classes Guinevere Larsen
2025-01-14 17:13   ` Andrew Burgess [this message]
2024-12-10 19:51 ` [PATCH v8 4/5] gdb: introduce ability to disable frame unwinders Guinevere Larsen
2025-01-16 12:06   ` Andrew Burgess
2025-01-17 12:40     ` Guinevere Larsen
2025-01-17 13:55       ` Andrew Burgess
2025-01-17 14:47         ` Guinevere Larsen
2025-01-16 16:22   ` Andrew Burgess
2024-12-10 19:51 ` [PATCH v8 5/5] gdb/testsuite: Test for a backtrace through object without debuginfo Guinevere Larsen
2025-01-16 14:37   ` Andrew Burgess
2025-01-16 18:42     ` Guinevere Larsen
2025-01-17 13:58       ` Andrew Burgess
2025-01-18  8:07     ` Tom de Vries
2025-01-20 12:26       ` [PATCH] gdb/testsuite: Fix file location for gdb.base/backtrace-through-cu-nodebug Guinevere Larsen
2025-01-20 12:46         ` Tom de Vries
2025-01-20 12:48           ` Guinevere Larsen
2025-01-07 12:11 ` [PING][PATCH v8 0/5] Modernize frame unwinders and add disable feature Guinevere Larsen
2025-01-17 14:49 ` [PATCH " Guinevere Larsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87zfjtpbct.fsf@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=guinevere@redhat.com \
    --cc=simon.marchi@efficios.com \
    --cc=thiago.bauermann@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox