diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 4c22d3705f5..c1a9ad67193 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1203,8 +1203,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,
@@ -1213,7 +1212,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.
@@ -1299,8 +1298,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,
@@ -1309,7 +1307,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 dd3556d6ae0..4f7526e5b19 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -1006,8 +1006,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,
@@ -1016,7 +1015,7 @@ static const struct frame_unwind alpha_sigtramp_frame_unwind =
   alpha_sigtramp_frame_prev_register,
   NULL,
   alpha_sigtramp_frame_sniffer
-};
+);
 
 
 
@@ -1426,8 +1425,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,
@@ -1436,7 +1434,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 059628cd7f0..b4ff53eeab4 100644
--- a/gdb/amd64-obsd-tdep.c
+++ b/gdb/amd64-obsd-tdep.c
@@ -401,8 +401,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.  */
@@ -414,7 +413,7 @@ static const struct frame_unwind amd64obsd_trapframe_unwind =
   amd64obsd_trapframe_prev_register,
   NULL,
   amd64obsd_trapframe_sniffer
-};
+);
 
 
 static void
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index b3be7dbed82..1b18b67c9ee 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2677,8 +2677,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,
@@ -2687,7 +2686,7 @@ static const struct frame_unwind amd64_frame_unwind =
   amd64_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 /* Generate a bytecode expression to get the value of the saved PC.  */
 
@@ -2824,8 +2823,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,
@@ -2834,7 +2832,7 @@ static const struct frame_unwind amd64_sigtramp_frame_unwind =
   amd64_sigtramp_frame_prev_register,
   NULL,
   amd64_sigtramp_frame_sniffer
-};
+);
 
 
 static CORE_ADDR
@@ -3017,8 +3015,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,
@@ -3027,10 +3024,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,
@@ -3039,7 +3035,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 d395e3a73f2..fecce06fefa 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1180,8 +1180,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,
@@ -1190,7 +1189,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 679098a778f..4f02a7efd63 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -891,7 +891,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,
@@ -901,8 +901,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 373c392f700..d25c577b62d 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1909,7 +1909,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,
@@ -1920,13 +1920,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,
@@ -1937,7 +1937,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 acee2d5b95f..a2785ae3358 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -2468,7 +2468,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,
@@ -2477,7 +2477,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
@@ -3188,7 +3188,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,
@@ -3197,7 +3197,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)
@@ -3298,8 +3298,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,
@@ -3307,8 +3306,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.
@@ -3429,7 +3428,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,
@@ -3438,7 +3437,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
@@ -3955,8 +3954,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,
@@ -3965,7 +3963,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 d3b6f949843..82ce125f1e9 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -1154,7 +1154,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,
@@ -1163,7 +1163,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 5400857a929..3849002c40e 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -371,8 +371,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,
@@ -381,7 +380,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 83bee2bf676..6f1ae050225 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
-};
+);
 
 
 /* Breakpoints.  */
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 7345dd2d668..c91d3a6019d 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -434,8 +434,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,
@@ -444,7 +443,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,
@@ -900,8 +899,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,
@@ -910,7 +908,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 fc13865e22f..3313803c19a 100644
--- a/gdb/csky-tdep.c
+++ b/gdb/csky-tdep.c
@@ -2158,7 +2158,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,
@@ -2169,7 +2169,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)
@@ -2293,7 +2293,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,
@@ -2302,7 +2302,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 09513ea4aad..045c2e44872 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 45ba3a70262..20a98f436aa 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -469,8 +469,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,
@@ -481,7 +480,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 7bbe6cab22d..6386ac20899 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -1331,16 +1331,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,
@@ -1350,10 +1349,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,
@@ -1365,7 +1363,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 fa0ea1cba4c..fd3d3b378ab 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -128,7 +128,7 @@ frame_unwind_try_unwinder (const frame_info_ptr &this_frame, void **this_cache,
 
   try
     {
-      frame_debug_printf ("trying unwinder \"%s\"", unwinder->name);
+      frame_debug_printf ("trying unwinder \"%s\"", unwinder->name ());
       res = unwinder->sniffer (unwinder, this_frame, this_cache);
     }
   catch (const gdb_exception &ex)
@@ -334,6 +334,59 @@ frame_unwind_got_address (const frame_info_ptr &frame, int regnum,
   return reg_val;
 }
 
+/* This method just passes the parameters to the callback pointer.  */
+enum unwind_stop_reason
+frame_unwind_legacy::stop_reason (const frame_info_ptr &this_frame,
+				  void **this_prologue_cache) const
+{
+  return stop_reason_p (this_frame, this_prologue_cache);
+}
+
+/* This method just passes the parameters to the callback pointer.  */
+void
+frame_unwind_legacy::this_id (const frame_info_ptr &this_frame,
+			      void **this_prologue_cache,
+			      struct frame_id *id) const
+{
+  return this_id_p (this_frame, this_prologue_cache, id);
+}
+
+/* This method just passes the parameters to the callback pointer.  */
+struct value *
+frame_unwind_legacy::prev_register (const frame_info_ptr &this_frame,
+				    void **this_prologue_cache,
+				    int regnum) const
+{
+  return prev_register_p (this_frame, this_prologue_cache, regnum);
+}
+
+/* This method just passes the parameters to the callback pointer.  */
+int
+frame_unwind_legacy::sniffer (const struct frame_unwind *self,
+			      const frame_info_ptr &this_frame,
+			      void **this_prologue_cache) const
+{
+  return sniffer_p (self, this_frame, this_prologue_cache);
+}
+
+/* This method just passes the parameters to the callback pointer.  */
+void
+frame_unwind_legacy::dealloc_cache (frame_info *self, void *this_cache) const
+{
+  if (dealloc_cache_p != nullptr)
+    dealloc_cache_p (self, this_cache);
+}
+
+/* This method just passes the parameters to the callback pointer.  */
+struct gdbarch *
+frame_unwind_legacy::prev_arch (const frame_info_ptr &this_frame,
+				void **this_prologue_cache) const
+{
+  if (prev_arch_p == nullptr)
+    error (_("No prev_arch callback installed"));
+  return prev_arch_p (this_frame, this_prologue_cache);
+}
+
 /* Implement "maintenance info frame-unwinders" command.  */
 
 static void
@@ -351,9 +404,9 @@ maintenance_info_frame_unwinders (const char *args, int from_tty)
 
   for (const struct frame_unwind* unwinder: table)
     {
-      const char *name = unwinder->name;
-      const char *type = frame_type_str (unwinder->type);
-      const char *uclass = frame_unwinder_class_str (unwinder->unwinder_class);
+      const char *name = unwinder->name ();
+      const char *type = frame_type_str (unwinder->type ());
+      const char *uclass = frame_unwinder_class_str (unwinder->unwinder_class ());
 
       ui_out_emit_list tuple_emitter (uiout, nullptr);
       uiout->field_string ("name", name);
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
index deab4f7dbfb..62da34b6ee8 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -169,25 +169,153 @@ enum frame_unwind_class
   FRAME_UNWIND_ARCH,
 };
 
-struct frame_unwind
+class frame_unwind
 {
-  const char *name;
+  const char *m_name;
   /* The frame's type.  Should this instead be a collection of
      predicates that test the frame for various attributes?  */
-  enum frame_type type;
+  enum 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;
+  enum frame_unwind_class m_unwinder_class;
+  const struct frame_data *m_unwind_data;
+public:
+  frame_unwind (const char *name, frame_type type, frame_unwind_class uclass,
+		       const struct frame_data *data)
+    : m_name (name), m_type (type), m_unwinder_class (uclass),
+      m_unwind_data (data)
+    { }
+
+  const char *name () const
+  {
+    return m_name;
+  }
+
+  enum frame_type type () const
+  {
+    return m_type;
+  }
+
+  enum frame_unwind_class unwinder_class () const
+  {
+    return m_unwinder_class;
+  }
+
+  const struct frame_data *unwind_data () const
+  {
+    return m_unwind_data;
+  }
+
+  /* Default stop_reason function.  It reports NO_REASON, unless the
+     frame is the outermost.  */
+  virtual enum 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 sniffer (const frame_unwind *self,
+		       const frame_info_ptr &this_frame,
+		       void **this_prologue_cache) const
+  {
+    return 1;
+  }
+
+  /* The following methods are here mostly for interface functionality.  They
+     all throw an error when called, as a safe way to check if an unwinder has
+     implemented the desired functionality.  */
+
+  /* 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
+  {
+    error (_("No method this_id implemented for unwinder %s"), m_name);
+  }
+
+  /* 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
+  {
+    error (_("No method prev_register implemented for unwinder %s"), m_name);
+  }
+
+  /* Properly deallocate the cache.  */
+  virtual void dealloc_cache (frame_info *self, void *this_cache) const
+  {
+    error (_("No method dealloc_cache implemented for unwinder %s"), m_name);
+  }
+
+  /* Get the previous architecture.  */
+  virtual struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
+				     void **this_prologue_cache) const
+  {
+    error (_("No method prev_arch implemented for unwinder %s"), m_name);
+  }
+};
+
+/* 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
+{
+private:
   /* 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_stop_reason_ftype *stop_reason_p;
+  frame_this_id_ftype *this_id_p;
+  frame_prev_register_ftype *prev_register_p;
+  frame_sniffer_ftype *sniffer_p;
+  frame_dealloc_cache_ftype *dealloc_cache_p;
+  frame_prev_arch_ftype *prev_arch_p;
+public:
+  frame_unwind_legacy (const char *n, frame_type t, frame_unwind_class c,
+		       frame_unwind_stop_reason_ftype *sr,
+		       frame_this_id_ftype *ti,
+		       frame_prev_register_ftype *pr,
+		       const struct frame_data *ud,
+		       frame_sniffer_ftype *s,
+		       frame_dealloc_cache_ftype *dc = nullptr,
+		       frame_prev_arch_ftype *pa = nullptr)
+  : frame_unwind (n, t, c, ud), stop_reason_p (sr),
+    this_id_p (ti), prev_register_p (pr), sniffer_p (s),
+    dealloc_cache_p (dc), prev_arch_p (pa) { }
+
+  /* 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 sniffer (const frame_unwind *self,
+		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.
+     If this function is called with no installed callback, this method
+     will error out.  Wrap calls in try-catch blocks.  */
+  struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
+			      void **this_prologue_cache) const override;
 };
 
 /* Register a frame unwinder, _prepending_ it to the front of the
diff --git a/gdb/frame.c b/gdb/frame.c
index f042bbb2ec2..b20a8f5668d 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -267,12 +267,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);
 }
 
@@ -485,12 +483,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>,";
 
@@ -2361,7 +2359,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))))
@@ -2989,7 +2987,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 *
@@ -3070,11 +3068,15 @@ 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);
+      try
+	{
+	  arch = next_frame->unwind->prev_arch (next_frame,
+						&next_frame->prologue_cache);
+	}
+      catch (gdb_exception &e)
+	{
+	  arch = get_frame_arch (next_frame);
+	}
 
       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 874e2b02e8d..5251e7bd0c9 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -331,8 +331,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,
@@ -341,7 +340,7 @@ static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
   frv_linux_sigtramp_frame_prev_register,
   NULL,
   frv_linux_sigtramp_frame_sniffer
-};
+);
 
 /* 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 e443fe22b76..bc18ea126ca 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 42102bdbb66..ec8ea67eabd 100644
--- a/gdb/ft32-tdep.c
+++ b/gdb/ft32-tdep.c
@@ -523,8 +523,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,
@@ -533,7 +532,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 017be737796..3a8fc9d1821 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -499,7 +499,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,
@@ -508,7 +508,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 6cd7de08308..13229bf3e87 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -307,7 +307,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,
@@ -316,7 +316,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 838cc42ec77..deb7e5f7b4e 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 e262528506c..1d2bef770bc 100644
--- a/gdb/i386-obsd-tdep.c
+++ b/gdb/i386-obsd-tdep.c
@@ -389,7 +389,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>,
@@ -401,7 +401,7 @@ static const struct frame_unwind i386obsd_trapframe_unwind = {
   i386obsd_trapframe_prev_register,
   NULL,
   i386obsd_trapframe_sniffer
-};
+);
 
 
 static void 
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 57c0253e1de..e98e7caffd8 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2195,8 +2195,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,
@@ -2205,7 +2204,7 @@ static const struct frame_unwind i386_frame_unwind =
   i386_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 /* Normal frames, but in a function epilogue.  */
 
@@ -2351,8 +2350,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,
@@ -2361,10 +2359,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,
@@ -2373,7 +2370,7 @@ static const struct frame_unwind i386_epilogue_frame_unwind =
   i386_epilogue_frame_prev_register,
   NULL,
   i386_epilogue_frame_sniffer
-};
+);
 
 
 /* Stack-based trampolines.  */
@@ -2446,8 +2443,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,
@@ -2456,7 +2452,7 @@ static const struct frame_unwind i386_stack_tramp_frame_unwind =
   i386_epilogue_frame_prev_register,
   NULL,
   i386_stack_tramp_frame_sniffer
-};
+);
 
 /* Generate a bytecode expression to get the value of the saved PC.  */
 
@@ -2596,8 +2592,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,
@@ -2606,7 +2601,7 @@ static const struct frame_unwind i386_sigtramp_frame_unwind =
   i386_sigtramp_frame_prev_register,
   NULL,
   i386_sigtramp_frame_sniffer
-};
+);
 
 
 static CORE_ADDR
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index e214d963f5f..f4ff03c2df8 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2161,8 +2161,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,
@@ -2171,7 +2170,7 @@ static const struct frame_unwind ia64_frame_unwind =
   &ia64_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 /* Signal trampolines.  */
 
@@ -2351,8 +2350,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,
@@ -2361,7 +2359,7 @@ static const struct frame_unwind ia64_sigtramp_frame_unwind =
   ia64_sigtramp_frame_prev_register,
   NULL,
   ia64_sigtramp_frame_sniffer
-};
+);
 
 
 
@@ -3012,8 +3010,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,
@@ -3023,7 +3020,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,
@@ -3102,8 +3099,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,
@@ -3112,7 +3108,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 2da4cad5f9d..b274ab23125 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -264,7 +264,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,
@@ -273,7 +273,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 bbe617c7c5b..a8bd9b07414 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 ea249060e6b..48e0ab18094 100644
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -423,7 +423,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,
@@ -432,7 +432,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 db1b64d0b0b..efb65167a08 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1103,8 +1103,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,
@@ -1114,7 +1113,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 7fbf403dd28..02bd1a8762a 100644
--- a/gdb/lm32-tdep.c
+++ b/gdb/lm32-tdep.c
@@ -446,7 +446,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,
@@ -455,7 +455,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 c86a2f9ea9c..5b2293911ea 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -449,7 +449,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,
@@ -459,8 +459,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 0f74cf1458e..fca328eda73 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -1954,7 +1954,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,
@@ -1963,7 +1963,7 @@ static const struct frame_unwind m32c_unwind = {
   m32c_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 
 /* Inferior calls.  */
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index ae8e364d794..01e47ed67ec 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -300,7 +300,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,
@@ -309,7 +309,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 1743884ba3c..c58c82e3fa6 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -830,7 +830,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,
@@ -839,7 +839,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 44a032157af..7c00061bd09 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -935,7 +935,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,
@@ -944,7 +944,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 e1d2f51522a..5b3ad72074b 100644
--- a/gdb/m68k-linux-tdep.c
+++ b/gdb/m68k-linux-tdep.c
@@ -313,8 +313,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,
@@ -323,7 +322,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 0fcd340eee7..a051e514245 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -1006,8 +1006,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,
@@ -1016,7 +1015,7 @@ static const struct frame_unwind m68k_frame_unwind =
   m68k_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 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 004a9f44dca..1648f3fee85 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -2060,7 +2060,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,
@@ -2069,7 +2069,7 @@ static const struct frame_unwind mep_frame_unwind = {
   mep_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 
 /* Return values.  */
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index 8d53d193dd4..05fedf6c9d6 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -477,8 +477,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,
@@ -487,7 +486,7 @@ static const struct frame_unwind microblaze_frame_unwind =
   microblaze_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 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 92630f329d8..b33df4e3461 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2928,8 +2928,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,
@@ -2938,7 +2937,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,
@@ -3365,8 +3364,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,
@@ -3375,7 +3373,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,
@@ -3745,8 +3743,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,
@@ -3755,7 +3752,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,
@@ -3863,8 +3860,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,
@@ -3873,7 +3869,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 63fc62c734f..19dd3b2bac0 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -1126,7 +1126,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,
@@ -1135,7 +1135,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 d4684a0d3c3..22c74d28920 100644
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -584,7 +584,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,
@@ -593,7 +593,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 765b15b87e7..ce82a0cee34 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -541,7 +541,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,
@@ -550,7 +550,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 6fd5c3c7a28..6aca27ee96a 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -987,8 +987,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,
@@ -996,8 +995,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.  */
 
@@ -1372,8 +1371,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,
@@ -1382,7 +1380,7 @@ static const struct frame_unwind nds32_epilogue_frame_unwind =
   nds32_epilogue_frame_prev_register,
   NULL,
   nds32_epilogue_frame_sniffer
-};
+);
 
 
 /* Floating type and struct type that has only one floating type member
diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c
index 179c3d72a49..709b86742e3 100644
--- a/gdb/nios2-tdep.c
+++ b/gdb/nios2-tdep.c
@@ -1976,8 +1976,7 @@ nios2_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
 /* Data structures for the normal prologue-analysis-based
    unwinder.  */
 
-static const struct frame_unwind nios2_frame_unwind =
-{
+static const struct frame_unwind_legacy nios2_frame_unwind (
   "nios2 prologue",
   NORMAL_FRAME,
   FRAME_UNWIND_ARCH,
@@ -1986,7 +1985,7 @@ static const struct frame_unwind nios2_frame_unwind =
   nios2_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 static const struct frame_base nios2_frame_base =
 {
@@ -2078,8 +2077,7 @@ nios2_stub_frame_sniffer (const struct frame_unwind *self,
 
 /* Define the data structures for the stub unwinder.  */
 
-static const struct frame_unwind nios2_stub_frame_unwind =
-{
+static const struct frame_unwind_legacy nios2_stub_frame_unwind (
   "nios2 stub",
   NORMAL_FRAME,
   FRAME_UNWIND_ARCH,
@@ -2088,7 +2086,7 @@ static const struct frame_unwind nios2_stub_frame_unwind =
   nios2_stub_frame_prev_register,
   NULL,
   nios2_stub_frame_sniffer
-};
+);
 
 
 
diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c
index b1d7911de98..e36e4ce9dd1 100644
--- a/gdb/or1k-tdep.c
+++ b/gdb/or1k-tdep.c
@@ -1124,7 +1124,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,
@@ -1133,8 +1133,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 f7f99660e29..d8c76f77fd8 100644
--- a/gdb/ppc-fbsd-tdep.c
+++ b/gdb/ppc-fbsd-tdep.c
@@ -261,7 +261,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,
@@ -270,7 +270,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 f7e642ee05c..68edd54dd96 100644
--- a/gdb/ppc-obsd-tdep.c
+++ b/gdb/ppc-obsd-tdep.c
@@ -230,7 +230,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,
@@ -239,7 +239,7 @@ static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
   ppcobsd_sigtramp_frame_prev_register,
   NULL,
   ppcobsd_sigtramp_frame_sniffer
-};
+);
 
 
 static void
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 668835e0444..91c9fbf2274 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -806,7 +806,7 @@ pyuw_sniffer (const struct frame_unwind *self, const frame_info_ptr &this_frame,
 {
   PYUW_SCOPED_DEBUG_ENTER_EXIT;
 
-  struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data);
+  struct gdbarch *gdbarch = (struct gdbarch *) (self->unwind_data ());
   cached_frame_info *cached_frame;
 
   gdbpy_enter enter_py (gdbarch);
@@ -947,6 +947,41 @@ struct pyuw_gdbarch_data_type
 
 static const registry<gdbarch>::key<pyuw_gdbarch_data_type> pyuw_gdbarch_data;
 
+/* 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 sniffer (const frame_unwind *self, const frame_info_ptr &this_frame,
+		void **this_prologue_cache) const override
+  {
+    return pyuw_sniffer (self, this_frame, this_prologue_cache);
+  }
+
+  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
+		struct frame_id *id) const override
+  {
+    pyuw_this_id (this_frame, this_prologue_cache, id);
+  }
+
+  struct value *prev_register (const frame_info_ptr &this_frame,
+			       void **this_prologue_cache,
+			       int regnum) const override
+  {
+      return pyuw_prev_register (this_frame, this_prologue_cache, regnum);
+  }
+
+  void dealloc_cache (frame_info *self, void *this_cache) const override
+  {
+      pyuw_dealloc_cache (self, this_cache);
+  }
+};
+
 /* New inferior architecture callback: register the Python unwinders
    intermediary.  */
 
@@ -960,17 +995,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 2bf3e214446..c069850d4bd 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1893,8 +1893,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,
@@ -1904,10 +1903,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,
@@ -1917,7 +1915,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 f44b3952943..44918ef4242 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 860a895bc06..b9391d0845b 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3899,8 +3899,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,
@@ -3910,8 +3909,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 4af93c37df1..62098d9f85a 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -1182,8 +1182,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,
@@ -1192,7 +1191,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 ea44765c7fa..4cf539507ac 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -327,7 +327,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,
@@ -336,7 +336,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 5d1fde07145..c4f015de4b3 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
-};
+);
 
 
 static CORE_ADDR
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index b35d477204e..ebdb324945d 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -630,7 +630,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,
@@ -639,12 +639,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,
@@ -654,7 +654,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 bb0c8bef327..6a377709eff 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 065c52e6442..4d429ba0301 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -2645,7 +2645,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,
@@ -2654,7 +2654,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
@@ -2740,7 +2740,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,
@@ -2749,7 +2749,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 8491adbb5c1..d3cb50fe352 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1928,7 +1928,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,
@@ -1937,7 +1937,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)
@@ -1995,8 +1995,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,
@@ -2005,7 +2004,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
-};
+);
 
 /* 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 5d42e4e6515..fe6a73909ae 100644
--- a/gdb/sparc-obsd-tdep.c
+++ b/gdb/sparc-obsd-tdep.c
@@ -133,8 +133,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,
@@ -143,7 +142,7 @@ static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
   sparc32obsd_sigtramp_frame_prev_register,
   NULL,
   sparc32obsd_sigtramp_frame_sniffer
-};
+);
 
 
 
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
-};
+);
 
 
 
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index a40570d6894..e951e0b57a1 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1345,8 +1345,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,
@@ -1355,7 +1354,7 @@ static const struct frame_unwind sparc32_frame_unwind =
   sparc32_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 
 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
-};
+);
 
 
 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
-};
+);
 
 
 static const struct regset sparc64nbsd_gregset =
diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c
index ad69476dac4..92c7f311a0d 100644
--- a/gdb/sparc64-obsd-tdep.c
+++ b/gdb/sparc64-obsd-tdep.c
@@ -219,8 +219,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,
@@ -229,7 +228,7 @@ static const struct frame_unwind sparc64obsd_frame_unwind =
   sparc64obsd_frame_prev_register,
   NULL,
   sparc64obsd_sigtramp_frame_sniffer
-};
+);
 
 /* Kernel debugging support.  */
 
@@ -304,8 +303,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,
@@ -314,7 +312,7 @@ static const struct frame_unwind sparc64obsd_trapframe_unwind =
   sparc64obsd_trapframe_prev_register,
   NULL,
   sparc64obsd_trapframe_sniffer
-};
+);
 
 
 /* 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
-};
+);
 
 
 
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 30ee241c5b6..43427ad1aba 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -1133,8 +1133,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,
@@ -1143,7 +1142,7 @@ static const struct frame_unwind sparc64_frame_unwind =
   sparc64_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 
 static CORE_ADDR
diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index bc0465b4635..00192caf386 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -451,8 +451,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,
@@ -461,7 +460,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 =
 {
@@ -515,8 +514,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,
@@ -525,7 +523,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 fc1c01c7ea4..18cb722b4a8 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -899,7 +899,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,
@@ -909,7 +909,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 2fcc3814e59..7fee4d5c71d 100644
--- a/gdb/tramp-frame.c
+++ b/gdb/tramp-frame.c
@@ -123,7 +123,7 @@ tramp_frame_sniffer (const struct frame_unwind *self,
 		     const frame_info_ptr &this_frame,
 		     void **this_cache)
 {
-  const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
+  const struct tramp_frame *tramp = self->unwind_data ()->tramp_frame;
   CORE_ADDR pc = get_frame_pc (this_frame);
   CORE_ADDR func;
   struct tramp_frame_cache *tramp_cache;
@@ -142,6 +142,46 @@ tramp_frame_sniffer (const struct frame_unwind *self,
   return 1;
 }
 
+class frame_unwind_trampoline : public frame_unwind
+{
+private:
+  frame_prev_arch_ftype *prev_arch_p;
+public:
+  frame_unwind_trampoline (enum frame_type t, const struct frame_data *d,
+			   frame_prev_arch_ftype *pa)
+    : frame_unwind ("trampoline", t, FRAME_UNWIND_GDB, d), prev_arch_p (pa)
+  { }
+
+  int sniffer(const frame_unwind *self, const frame_info_ptr &this_frame,
+	      void **this_prologue_cache) const override
+  {
+    return tramp_frame_sniffer (self, this_frame, this_prologue_cache);
+  }
+  void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache,
+		struct frame_id *id) const override
+  {
+    tramp_frame_this_id (this_frame, this_prologue_cache, id);
+  }
+  struct value *prev_register (const frame_info_ptr &this_frame,
+			       void **this_prologue_cache,
+			       int regnum) const override
+  {
+    return tramp_frame_prev_register (this_frame, this_prologue_cache, regnum);
+  }
+
+  struct gdbarch *prev_arch (const frame_info_ptr &this_frame,
+			     void **this_prologue_cache) const override
+  {
+    return prev_arch_p (this_frame, this_prologue_cache);
+  }
+
+  /* FIXME: This should have a proper algorithm to deallocate the cache,
+     otherwise memory is leaked.  This method is empty here just so the
+     migration to c++ classes doesn't add regressions.  */
+  void dealloc_cache (frame_info *self, void *this_cache) const override
+  { }
+};
+
 void
 tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
 			      const struct tramp_frame *tramp_frame)
@@ -160,16 +200,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 f875a351ac7..733e1985fa8 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -1319,7 +1319,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,
@@ -1328,7 +1328,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 460a6058d0a..fea24fcf599 100644
--- a/gdb/vax-tdep.c
+++ b/gdb/vax-tdep.c
@@ -385,8 +385,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,
@@ -395,7 +394,7 @@ static const struct frame_unwind vax_frame_unwind =
   vax_frame_prev_register,
   NULL,
   default_frame_sniffer
-};
+);
 
 
 static CORE_ADDR
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index f9585adf8fa..07b1e9b1e2c 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -1320,10 +1320,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
@@ -1339,18 +1338,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::sniffer (const struct frame_unwind *self_,
+					 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);
@@ -1395,13 +1394,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..bdab0962ede 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 sniffer (const frame_unwind *self, 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 73fa6ed9c0d..750c94a5701 100644
--- a/gdb/xstormy16-tdep.c
+++ b/gdb/xstormy16-tdep.c
@@ -727,7 +727,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,
@@ -736,7 +736,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 a0801466c42..1425b6029f3 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -1495,9 +1495,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,
@@ -1506,7 +1504,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 ea78a01cbfc..7b3d7f6b6b5 100644
--- a/gdb/z80-tdep.c
+++ b/gdb/z80-tdep.c
@@ -1062,9 +1062,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,
@@ -1075,7 +1073,7 @@ z80_frame_unwind =
   default_frame_sniffer
   /*dealloc_cache*/
   /*prev_arch*/
-};
+);
 
 /* Initialize the gdbarch struct for the Z80 arch */
 static struct gdbarch *
