[2/4] gdb: add "unwinder class" to frame unwinders

Message ID 20240306125135.766567-3-blarsen@redhat.com
State New
Headers
Series Modernize frame unwinders and add disable feature |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Guinevere Larsen March 6, 2024, 12:51 p.m. UTC
  A future patch will add a way to disable certain unwinders based on
different characteristics. This patch aims to make it more convenient
to disable related unwinders in bulk, such as architecture specific
ones, by indentifying all unwinders by which part of the code adds it.
The classes, and explanations, are as follows:

* GDB: An internal unwinder, added by GDB core, such as the unwinder
  for dummy frames;
* EXTENSION: Unwinders added by extension languages;
* DEBUGINFO: Unwinders installed by the debug info reader;
* ARCH: Unwinders installed by the architecture specific code.
---
 gdb/aarch64-tdep.c          |  2 ++
 gdb/alpha-mdebug-tdep.c     |  1 +
 gdb/alpha-tdep.c            |  2 ++
 gdb/amd64-obsd-tdep.c       |  1 +
 gdb/amd64-tdep.c            |  4 ++++
 gdb/amd64-windows-tdep.c    |  1 +
 gdb/amdgpu-tdep.c           |  1 +
 gdb/arc-tdep.c              |  2 ++
 gdb/arm-tdep.c              |  5 +++++
 gdb/avr-tdep.c              |  1 +
 gdb/bfin-tdep.c             |  1 +
 gdb/bpf-tdep.c              |  1 +
 gdb/cris-tdep.c             |  2 ++
 gdb/csky-tdep.c             |  2 ++
 gdb/dummy-frame.c           |  1 +
 gdb/dwarf2/frame-tailcall.c |  1 +
 gdb/dwarf2/frame.c          |  2 ++
 gdb/frame-unwind.c          | 25 ++++++++++++++++++++++++-
 gdb/frame-unwind.h          | 11 +++++++++++
 gdb/frv-linux-tdep.c        |  1 +
 gdb/frv-tdep.c              |  1 +
 gdb/ft32-tdep.c             |  1 +
 gdb/h8300-tdep.c            |  1 +
 gdb/hppa-linux-tdep.c       |  1 +
 gdb/hppa-tdep.c             |  3 +++
 gdb/i386-obsd-tdep.c        |  1 +
 gdb/i386-tdep.c             |  5 +++++
 gdb/ia64-tdep.c             |  4 ++++
 gdb/inline-frame.c          |  1 +
 gdb/iq2000-tdep.c           |  1 +
 gdb/jit.c                   |  1 +
 gdb/lm32-tdep.c             |  1 +
 gdb/loongarch-tdep.c        |  1 +
 gdb/m32c-tdep.c             |  1 +
 gdb/m32r-linux-tdep.c       |  1 +
 gdb/m32r-tdep.c             |  1 +
 gdb/m68hc11-tdep.c          |  1 +
 gdb/m68k-linux-tdep.c       |  1 +
 gdb/m68k-tdep.c             |  1 +
 gdb/mep-tdep.c              |  1 +
 gdb/microblaze-tdep.c       |  1 +
 gdb/mips-sde-tdep.c         |  1 +
 gdb/mips-tdep.c             |  4 ++++
 gdb/mn10300-tdep.c          |  1 +
 gdb/moxie-tdep.c            |  1 +
 gdb/msp430-tdep.c           |  1 +
 gdb/nds32-tdep.c            |  2 ++
 gdb/nios2-tdep.c            |  2 ++
 gdb/or1k-tdep.c             |  1 +
 gdb/ppc-fbsd-tdep.c         |  1 +
 gdb/ppc-obsd-tdep.c         |  1 +
 gdb/python/py-unwind.c      |  1 +
 gdb/record-btrace.c         |  2 ++
 gdb/riscv-tdep.c            |  1 +
 gdb/rl78-tdep.c             |  1 +
 gdb/rs6000-aix-tdep.c       |  1 +
 gdb/rs6000-tdep.c           |  2 ++
 gdb/rx-tdep.c               |  2 ++
 gdb/s12z-tdep.c             |  1 +
 gdb/s390-linux-tdep.c       |  1 +
 gdb/s390-tdep.c             |  2 ++
 gdb/sentinel-frame.c        |  1 +
 gdb/sh-tdep.c               |  2 ++
 gdb/sparc-netbsd-tdep.c     |  1 +
 gdb/sparc-obsd-tdep.c       |  1 +
 gdb/sparc-sol2-tdep.c       |  1 +
 gdb/sparc-tdep.c            |  1 +
 gdb/sparc64-fbsd-tdep.c     |  1 +
 gdb/sparc64-netbsd-tdep.c   |  1 +
 gdb/sparc64-obsd-tdep.c     |  2 ++
 gdb/sparc64-sol2-tdep.c     |  1 +
 gdb/sparc64-tdep.c          |  1 +
 gdb/tic6x-tdep.c            |  2 ++
 gdb/tilegx-tdep.c           |  1 +
 gdb/tramp-frame.c           |  1 +
 gdb/v850-tdep.c             |  1 +
 gdb/vax-tdep.c              |  1 +
 gdb/xstormy16-tdep.c        |  1 +
 gdb/xtensa-tdep.c           |  1 +
 gdb/z80-tdep.c              |  1 +
 80 files changed, 147 insertions(+), 1 deletion(-)
  

Comments

Tom Tromey March 8, 2024, 4:40 p.m. UTC | #1
>>>>> Guinevere Larsen <blarsen@redhat.com> writes:

> A future patch will add a way to disable certain unwinders based on
> different characteristics. This patch aims to make it more convenient
> to disable related unwinders in bulk, such as architecture specific
> ones, by indentifying all unwinders by which part of the code adds it.
> The classes, and explanations, are as follows:

Thanks.

> +/* Conversion list between the enum for frame_unwind_class and
> +   string.  */
> +static std::map<enum frame_unwind_class, std::string> unwind_class_conversion =

This should probably map to const char *.
That would avoid some unnecessary allocations.

 
> +enum frame_unwind_class {
> +  FRAME_UNWIND_GDB,
> +  FRAME_UNWIND_EXTENSION,
> +  FRAME_UNWIND_DEBUGINFO,
> +  FRAME_UNWIND_ARCH,
> +};

This should have a bunch of comments.
Also the "{" should probably be on the next line.

Tom
  

Patch

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index d1d5486f90d..db0cf28d815 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1208,6 +1208,7 @@  static frame_unwind aarch64_prologue_unwind =
 {
   "aarch64 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   aarch64_prologue_frame_unwind_stop_reason,
   aarch64_prologue_this_id,
   aarch64_prologue_prev_register,
@@ -1303,6 +1304,7 @@  static frame_unwind aarch64_stub_unwind =
 {
   "aarch64 stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   aarch64_stub_frame_unwind_stop_reason,
   aarch64_stub_this_id,
   aarch64_prologue_prev_register,
diff --git a/gdb/alpha-mdebug-tdep.c b/gdb/alpha-mdebug-tdep.c
index 7e9312d2aa7..bc7eb8562e9 100644
--- a/gdb/alpha-mdebug-tdep.c
+++ b/gdb/alpha-mdebug-tdep.c
@@ -335,6 +335,7 @@  static const struct frame_unwind alpha_mdebug_frame_unwind =
 {
   "alpha mdebug",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   alpha_mdebug_frame_this_id,
   alpha_mdebug_frame_prev_register,
diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c
index e5e0860fe24..f24312b7cbc 100644
--- a/gdb/alpha-tdep.c
+++ b/gdb/alpha-tdep.c
@@ -1011,6 +1011,7 @@  static const struct frame_unwind alpha_sigtramp_frame_unwind =
 {
   "alpha sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   alpha_sigtramp_frame_this_id,
   alpha_sigtramp_frame_prev_register,
@@ -1430,6 +1431,7 @@  static const struct frame_unwind alpha_heuristic_frame_unwind =
 {
   "alpha prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   alpha_heuristic_frame_this_id,
   alpha_heuristic_frame_prev_register,
diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c
index 6b37e8954ee..0159bdb4049 100644
--- a/gdb/amd64-obsd-tdep.c
+++ b/gdb/amd64-obsd-tdep.c
@@ -409,6 +409,7 @@  static const struct frame_unwind amd64obsd_trapframe_unwind =
      which really is not what we want here.  */
   "amd64 openbsd trap",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   amd64obsd_trapframe_this_id,
   amd64obsd_trapframe_prev_register,
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 60d6b7aa198..bbeeb935192 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2682,6 +2682,7 @@  static const struct frame_unwind amd64_frame_unwind =
 {
   "amd64 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   amd64_frame_unwind_stop_reason,
   amd64_frame_this_id,
   amd64_frame_prev_register,
@@ -2828,6 +2829,7 @@  static const struct frame_unwind amd64_sigtramp_frame_unwind =
 {
   "amd64 sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   amd64_sigtramp_frame_unwind_stop_reason,
   amd64_sigtramp_frame_this_id,
   amd64_sigtramp_frame_prev_register,
@@ -3020,6 +3022,7 @@  static const struct frame_unwind amd64_epilogue_override_frame_unwind =
 {
   "amd64 epilogue override",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   amd64_epilogue_frame_unwind_stop_reason,
   amd64_epilogue_frame_this_id,
   amd64_frame_prev_register,
@@ -3031,6 +3034,7 @@  static const struct frame_unwind amd64_epilogue_frame_unwind =
 {
   "amd64 epilogue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   amd64_epilogue_frame_unwind_stop_reason,
   amd64_epilogue_frame_this_id,
   amd64_frame_prev_register,
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index af17886c080..e4459b4717b 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1185,6 +1185,7 @@  static const struct frame_unwind amd64_windows_frame_unwind =
 {
   "amd64 windows",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   &amd64_windows_frame_this_id,
   &amd64_windows_frame_prev_register,
diff --git a/gdb/amdgpu-tdep.c b/gdb/amdgpu-tdep.c
index ac137d9acc4..8189de8e565 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -895,6 +895,7 @@  amdgpu_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
 static const frame_unwind amdgpu_frame_unwind = {
   "amdgpu",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   amdgpu_frame_this_id,
   amdgpu_frame_prev_register,
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 7dd43cc239f..9e756ad473e 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1913,6 +1913,7 @@  arc_sigtramp_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind arc_frame_unwind = {
   "arc prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   arc_frame_this_id,
   arc_frame_prev_register,
@@ -1929,6 +1930,7 @@  static const struct frame_unwind arc_frame_unwind = {
 static const struct frame_unwind arc_sigtramp_frame_unwind = {
   "arc sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   arc_sigtramp_frame_this_id,
   arc_sigtramp_frame_prev_register,
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 3b4ae15df07..6bec31dead1 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -2472,6 +2472,7 @@  arm_prologue_prev_register (const frame_info_ptr &this_frame,
 static frame_unwind arm_prologue_unwind = {
   "arm prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   arm_prologue_unwind_stop_reason,
   arm_prologue_this_id,
   arm_prologue_prev_register,
@@ -3191,6 +3192,7 @@  arm_exidx_unwind_sniffer (const struct frame_unwind *self,
 struct frame_unwind arm_exidx_unwind = {
   "arm exidx",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   arm_prologue_this_id,
   arm_prologue_prev_register,
@@ -3301,6 +3303,7 @@  static const struct frame_unwind arm_epilogue_frame_unwind =
 {
   "arm epilogue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   arm_epilogue_frame_this_id,
   arm_epilogue_frame_prev_register,
@@ -3430,6 +3433,7 @@  arm_stub_unwind_sniffer (const struct frame_unwind *self,
 struct frame_unwind arm_stub_unwind = {
   "arm stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   arm_stub_this_id,
   arm_prologue_prev_register,
@@ -3956,6 +3960,7 @@  struct frame_unwind arm_m_exception_unwind =
 {
   "arm m exception lockup sec_fnc",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   arm_m_exception_frame_unwind_stop_reason,
   arm_m_exception_this_id,
   arm_m_exception_prev_register,
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index 2d38f41cd7f..0c12a8a1d65 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -1158,6 +1158,7 @@  avr_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind avr_frame_unwind = {
   "avr prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   avr_frame_this_id,
   avr_frame_prev_register,
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index 357866ef953..6c15098fbbc 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -376,6 +376,7 @@  static const struct frame_unwind bfin_frame_unwind =
 {
   "bfin prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   bfin_frame_this_id,
   bfin_frame_prev_register,
diff --git a/gdb/bpf-tdep.c b/gdb/bpf-tdep.c
index 1b3f3e72c5b..15bd08b8f58 100644
--- a/gdb/bpf-tdep.c
+++ b/gdb/bpf-tdep.c
@@ -186,6 +186,7 @@  static const struct frame_unwind bpf_frame_unwind =
 {
   "bpf prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   bpf_frame_unwind_stop_reason,
   bpf_frame_this_id,
   bpf_frame_prev_register,
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 02c35da723d..c1a0e5fe961 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -439,6 +439,7 @@  static const struct frame_unwind cris_sigtramp_frame_unwind =
 {
   "cris sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   cris_sigtramp_frame_this_id,
   cris_sigtramp_frame_prev_register,
@@ -904,6 +905,7 @@  static const struct frame_unwind cris_frame_unwind =
 {
   "cris prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   cris_frame_this_id,
   cris_frame_prev_register,
diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c
index c1ce8a5b02c..d95b0a2f9f2 100644
--- a/gdb/csky-tdep.c
+++ b/gdb/csky-tdep.c
@@ -2162,6 +2162,7 @@  csky_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind csky_unwind_cache = {
   "cski prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   csky_frame_this_id,
   csky_frame_prev_register,
@@ -2296,6 +2297,7 @@  csky_stub_prev_register (const frame_info_ptr &this_frame,
 static frame_unwind csky_stub_unwind = {
   "csky stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   csky_stub_this_id,
   csky_stub_prev_register,
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index 5969ef2cdad..a208e370aac 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -380,6 +380,7 @@  const struct frame_unwind dummy_frame_unwind =
 {
   "dummy",
   DUMMY_FRAME,
+  FRAME_UNWIND_GDB,
   default_frame_unwind_stop_reason,
   dummy_frame_this_id,
   dummy_frame_prev_register,
diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c
index 2f6400d62c3..c4daaf28a01 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -474,6 +474,7 @@  const struct frame_unwind dwarf2_tailcall_frame_unwind =
 {
   "dwarf2 tailcall",
   TAILCALL_FRAME,
+  FRAME_UNWIND_DEBUGINFO,
   default_frame_unwind_stop_reason,
   tailcall_frame_this_id,
   tailcall_frame_prev_register,
diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
index 530513c2684..c1fec57b7c7 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -1344,6 +1344,7 @@  static const struct frame_unwind dwarf2_frame_unwind =
 {
   "dwarf2",
   NORMAL_FRAME,
+  FRAME_UNWIND_DEBUGINFO,
   dwarf2_frame_unwind_stop_reason,
   dwarf2_frame_this_id,
   dwarf2_frame_prev_register,
@@ -1356,6 +1357,7 @@  static const struct frame_unwind dwarf2_signal_frame_unwind =
 {
   "dwarf2 signal",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_DEBUGINFO,
   dwarf2_frame_unwind_stop_reason,
   dwarf2_frame_this_id,
   dwarf2_frame_prev_register,
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index 27d84981d89..5af5085b038 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -31,10 +31,22 @@ 
 #include "cli/cli-cmds.h"
 #include "inferior.h"
 
+#include <map>
+
 /* If an unwinder should be prepended to the list, this is the
    index in which it should be inserted.  */
 static int osabi_start = -1;
 
+/* Conversion list between the enum for frame_unwind_class and
+   string.  */
+static std::map<enum frame_unwind_class, std::string> unwind_class_conversion =
+{
+  {FRAME_UNWIND_GDB, "FRAME_UNWIND_GDB"},
+  {FRAME_UNWIND_ARCH, "FRAME_UNWIND_ARCH"},
+  {FRAME_UNWIND_EXTENSION, "FRAME_UNWIND_EXTENSION"},
+  {FRAME_UNWIND_DEBUGINFO, "FRAME_UNWIND_DEBUGINFO"},
+};
+
 /* Start the table out with a few default sniffers.  OSABI code
    can't override this.  */
 static void
@@ -68,6 +80,14 @@  get_frame_unwind_table (struct gdbarch *gdbarch)
   return table;
 }
 
+static const char *
+frame_unwinder_class_str (frame_unwind_class uclass)
+{
+  auto location = unwind_class_conversion.find (uclass);
+  gdb_assert (location != unwind_class_conversion.end ());
+  return location->second.c_str ();
+}
+
 void
 frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
 				const struct frame_unwind *unwinder)
@@ -324,19 +344,22 @@  maintenance_info_frame_unwinders (const char *args, int from_tty)
   std::vector<const frame_unwind*> table = get_frame_unwind_table (gdbarch);
 
   ui_out *uiout = current_uiout;
-  ui_out_emit_table table_emitter (uiout, 2, -1, "FrameUnwinders");
+  ui_out_emit_table table_emitter (uiout, 3, -1, "FrameUnwinders");
   uiout->table_header (27, ui_left, "name", "Name");
   uiout->table_header (25, ui_left, "type", "Type");
+  uiout->table_header (25, ui_left, "class", "Class");
   uiout->table_body ();
 
   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);
 
       ui_out_emit_list tuple_emitter (uiout, nullptr);
       uiout->field_string ("name", name);
       uiout->field_string ("type", type);
+      uiout->field_string ("class", uclass);
       uiout->text ("\n");
     }
 }
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
index 53fcd6869e9..fd70949df8f 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -156,12 +156,23 @@  typedef void (frame_dealloc_cache_ftype) (frame_info *self,
 typedef gdbarch *(frame_prev_arch_ftype) (const frame_info_ptr &this_frame,
 					  void **this_prologue_cache);
 
+enum frame_unwind_class {
+  FRAME_UNWIND_GDB,
+  FRAME_UNWIND_EXTENSION,
+  FRAME_UNWIND_DEBUGINFO,
+  FRAME_UNWIND_ARCH,
+};
+
 struct frame_unwind
 {
   const char *name;
   /* The frame's type.  Should this instead be a collection of
      predicates that test the frame for various attributes?  */
   enum frame_type type;
+  /* What kind of unwinder is this.  It generally follows from where
+     the unwinder was added or where it looks for information to do the
+     unwinding.  */
+  enum frame_unwind_class unwinder_class;
   /* Should an attribute indicating the frame's address-in-block go
      here?  */
   frame_unwind_stop_reason_ftype *stop_reason;
diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index 5160c3b0c1d..f80e5f0d089 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -336,6 +336,7 @@  static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
 {
   "frv linux sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   frv_linux_sigtramp_frame_this_id,
   frv_linux_sigtramp_frame_prev_register,
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index bcb2c621945..216ccde01b0 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -1408,6 +1408,7 @@  frv_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind frv_frame_unwind = {
   "frv prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   frv_frame_this_id,
   frv_frame_prev_register,
diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c
index 60cd2c974a1..8ec2668906f 100644
--- a/gdb/ft32-tdep.c
+++ b/gdb/ft32-tdep.c
@@ -528,6 +528,7 @@  static const struct frame_unwind ft32_frame_unwind =
 {
   "ft32 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ft32_frame_this_id,
   ft32_frame_prev_register,
diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index 36cbd9d4aa6..3a739c24e79 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -503,6 +503,7 @@  h8300_frame_prev_register (const frame_info_ptr &this_frame, void **this_cache,
 static const struct frame_unwind h8300_frame_unwind = {
   "h8300 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   h8300_frame_this_id,
   h8300_frame_prev_register,
diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index db0c3680131..d44735bc523 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -311,6 +311,7 @@  hppa_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
   "hppa linux sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   hppa_linux_sigtramp_frame_this_id,
   hppa_linux_sigtramp_frame_prev_register,
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 30128bafac4..5a66fe88f45 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -2287,6 +2287,7 @@  static const struct frame_unwind hppa_frame_unwind =
 {
   "hppa unwind table",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   hppa_frame_this_id,
   hppa_frame_prev_register,
@@ -2400,6 +2401,7 @@  static const struct frame_unwind hppa_fallback_frame_unwind =
 {
   "hppa prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   hppa_fallback_frame_this_id,
   hppa_fallback_frame_prev_register,
@@ -2481,6 +2483,7 @@  hppa_stub_unwind_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind hppa_stub_frame_unwind = {
   "hppa stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   hppa_stub_frame_this_id,
   hppa_stub_frame_prev_register,
diff --git a/gdb/i386-obsd-tdep.c b/gdb/i386-obsd-tdep.c
index e1480ec6cc4..1f23c2e7d96 100644
--- a/gdb/i386-obsd-tdep.c
+++ b/gdb/i386-obsd-tdep.c
@@ -396,6 +396,7 @@  static const struct frame_unwind i386obsd_trapframe_unwind = {
      frame, but SIGTRAMP_FRAME would print <signal handler called>,
      which really is not what we want here.  */
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   i386obsd_trapframe_this_id,
   i386obsd_trapframe_prev_register,
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b487a3f7478..ede74a4be70 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -2200,6 +2200,7 @@  static const struct frame_unwind i386_frame_unwind =
 {
   "i386 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   i386_frame_unwind_stop_reason,
   i386_frame_this_id,
   i386_frame_prev_register,
@@ -2355,6 +2356,7 @@  static const struct frame_unwind i386_epilogue_override_frame_unwind =
 {
   "i386 epilogue override",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_epilogue_frame_prev_register,
@@ -2366,6 +2368,7 @@  static const struct frame_unwind i386_epilogue_frame_unwind =
 {
   "i386 epilogue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_epilogue_frame_prev_register,
@@ -2448,6 +2451,7 @@  static const struct frame_unwind i386_stack_tramp_frame_unwind =
 {
   "i386 stack tramp",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_epilogue_frame_prev_register,
@@ -2597,6 +2601,7 @@  static const struct frame_unwind i386_sigtramp_frame_unwind =
 {
   "i386 sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   i386_sigtramp_frame_unwind_stop_reason,
   i386_sigtramp_frame_this_id,
   i386_sigtramp_frame_prev_register,
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 88f67ccf096..a75ac192a25 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2166,6 +2166,7 @@  static const struct frame_unwind ia64_frame_unwind =
 {
   "ia64 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   &ia64_frame_this_id,
   &ia64_frame_prev_register,
@@ -2355,6 +2356,7 @@  static const struct frame_unwind ia64_sigtramp_frame_unwind =
 {
   "ia64 sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ia64_sigtramp_frame_this_id,
   ia64_sigtramp_frame_prev_register,
@@ -3015,6 +3017,7 @@  static const struct frame_unwind ia64_libunwind_frame_unwind =
 {
   "ia64 libunwind",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ia64_libunwind_frame_this_id,
   ia64_libunwind_frame_prev_register,
@@ -3104,6 +3107,7 @@  static const struct frame_unwind ia64_libunwind_sigtramp_frame_unwind =
 {
   "ia64 libunwind sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ia64_libunwind_sigtramp_frame_this_id,
   ia64_libunwind_sigtramp_frame_prev_register,
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index 9f3deef8f03..1a0352a35c1 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -268,6 +268,7 @@  inline_frame_sniffer (const struct frame_unwind *self,
 const struct frame_unwind inline_frame_unwind = {
   "inline",
   INLINE_FRAME,
+  FRAME_UNWIND_GDB,
   default_frame_unwind_stop_reason,
   inline_frame_this_id,
   inline_frame_prev_register,
diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c
index 4177de059c0..698284597d8 100644
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -427,6 +427,7 @@  iq2000_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
 static const struct frame_unwind iq2000_frame_unwind = {
   "iq2000 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   iq2000_frame_this_id,
   iq2000_frame_prev_register,
diff --git a/gdb/jit.c b/gdb/jit.c
index a7fd5c40f9d..16c3111fbc7 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1108,6 +1108,7 @@  static const struct frame_unwind jit_frame_unwind =
 {
   "jit",
   NORMAL_FRAME,
+  FRAME_UNWIND_EXTENSION,
   default_frame_unwind_stop_reason,
   jit_frame_this_id,
   jit_frame_prev_register,
diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c
index b4605e48c6a..9cfc81c429b 100644
--- a/gdb/lm32-tdep.c
+++ b/gdb/lm32-tdep.c
@@ -450,6 +450,7 @@  lm32_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind lm32_frame_unwind = {
   "lm32 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   lm32_frame_this_id,
   lm32_frame_prev_register,
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index 0b38e751d16..e9d3f156125 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -453,6 +453,7 @@  loongarch_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind loongarch_frame_unwind = {
   "loongarch prologue",
   /*.type	   =*/NORMAL_FRAME,
+  /*.unwinder_class=*/FRAME_UNWIND_ARCH,
   /*.stop_reason   =*/default_frame_unwind_stop_reason,
   /*.this_id	   =*/loongarch_frame_this_id,
   /*.prev_register =*/loongarch_frame_prev_register,
diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c
index 0895f7bd0c4..748465256e3 100644
--- a/gdb/m32c-tdep.c
+++ b/gdb/m32c-tdep.c
@@ -1958,6 +1958,7 @@  m32c_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind m32c_unwind = {
   "m32c prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m32c_this_id,
   m32c_prev_register,
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index b74d2f3f161..87dce624a4a 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -304,6 +304,7 @@  m32r_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = {
   "m32r linux sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m32r_linux_sigtramp_frame_this_id,
   m32r_linux_sigtramp_frame_prev_register,
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
index 0bd6b499e6f..9b4af6a7248 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -834,6 +834,7 @@  m32r_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind m32r_frame_unwind = {
   "m32r prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m32r_frame_this_id,
   m32r_frame_prev_register,
diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c
index d80b190f2c0..bcf9861ccd5 100644
--- a/gdb/m68hc11-tdep.c
+++ b/gdb/m68hc11-tdep.c
@@ -939,6 +939,7 @@  m68hc11_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind m68hc11_frame_unwind = {
   "m68hc11 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m68hc11_frame_this_id,
   m68hc11_frame_prev_register,
diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c
index eca4ede099f..86c700dafe6 100644
--- a/gdb/m68k-linux-tdep.c
+++ b/gdb/m68k-linux-tdep.c
@@ -318,6 +318,7 @@  static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
 {
   "m68k linux sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m68k_linux_sigtramp_frame_this_id,
   m68k_linux_sigtramp_frame_prev_register,
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index abfc605aabb..23254dcfac0 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -1011,6 +1011,7 @@  static const struct frame_unwind m68k_frame_unwind =
 {
   "m68k prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   m68k_frame_this_id,
   m68k_frame_prev_register,
diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c
index f455d3eb51d..392c7231535 100644
--- a/gdb/mep-tdep.c
+++ b/gdb/mep-tdep.c
@@ -2064,6 +2064,7 @@  mep_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind mep_frame_unwind = {
   "mep prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mep_frame_this_id,
   mep_frame_prev_register,
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index 07261bd4d22..7dc209c680d 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -482,6 +482,7 @@  static const struct frame_unwind microblaze_frame_unwind =
 {
   "microblaze prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   microblaze_frame_this_id,
   microblaze_frame_prev_register,
diff --git a/gdb/mips-sde-tdep.c b/gdb/mips-sde-tdep.c
index 7b367898f04..9f16d2d8593 100644
--- a/gdb/mips-sde-tdep.c
+++ b/gdb/mips-sde-tdep.c
@@ -165,6 +165,7 @@  static const struct frame_unwind mips_sde_frame_unwind =
 {
   "mips sde sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mips_sde_frame_this_id,
   mips_sde_frame_prev_register,
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 8339d2f1d4c..a8d2cea8cb7 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -2933,6 +2933,7 @@  static const struct frame_unwind mips_insn16_frame_unwind =
 {
   "mips insn16 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mips_insn16_frame_this_id,
   mips_insn16_frame_prev_register,
@@ -3369,6 +3370,7 @@  static const struct frame_unwind mips_micro_frame_unwind =
 {
   "mips micro prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mips_micro_frame_this_id,
   mips_micro_frame_prev_register,
@@ -3748,6 +3750,7 @@  static const struct frame_unwind mips_insn32_frame_unwind =
 {
   "mips insn32 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mips_insn32_frame_this_id,
   mips_insn32_frame_prev_register,
@@ -3865,6 +3868,7 @@  static const struct frame_unwind mips_stub_frame_unwind =
 {
   "mips stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mips_stub_frame_this_id,
   mips_stub_frame_prev_register,
diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c
index f8c5a0906ef..b8b290d1b87 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -1130,6 +1130,7 @@  mn10300_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind mn10300_frame_unwind = {
   "mn10300 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   mn10300_frame_this_id, 
   mn10300_frame_prev_register,
diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c
index 812c92d1e0a..124275de8e2 100644
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -588,6 +588,7 @@  moxie_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind moxie_frame_unwind = {
   "moxie prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   moxie_frame_this_id,
   moxie_frame_prev_register,
diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c
index e07e3cc4be2..05830de63b0 100644
--- a/gdb/msp430-tdep.c
+++ b/gdb/msp430-tdep.c
@@ -545,6 +545,7 @@  msp430_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind msp430_unwind = {
   "msp430 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   msp430_this_id,
   msp430_prev_register,
diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c
index e453cd0f6d9..f2653400ab3 100644
--- a/gdb/nds32-tdep.c
+++ b/gdb/nds32-tdep.c
@@ -992,6 +992,7 @@  static const struct frame_unwind nds32_frame_unwind =
 {
   "nds32 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   nds32_frame_this_id,
   nds32_frame_prev_register,
@@ -1376,6 +1377,7 @@  static const struct frame_unwind nds32_epilogue_frame_unwind =
 {
   "nds32 epilogue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   nds32_epilogue_frame_this_id,
   nds32_epilogue_frame_prev_register,
diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c
index 0a8eeb88bb5..4b5b7239366 100644
--- a/gdb/nios2-tdep.c
+++ b/gdb/nios2-tdep.c
@@ -1981,6 +1981,7 @@  static const struct frame_unwind nios2_frame_unwind =
 {
   "nios2 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   nios2_frame_this_id,
   nios2_frame_prev_register,
@@ -2082,6 +2083,7 @@  static const struct frame_unwind nios2_stub_frame_unwind =
 {
   "nios2 stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   nios2_stub_frame_this_id,
   nios2_stub_frame_prev_register,
diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c
index ffcb50f4bcd..681877fdb18 100644
--- a/gdb/or1k-tdep.c
+++ b/gdb/or1k-tdep.c
@@ -1128,6 +1128,7 @@  or1k_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind or1k_frame_unwind = {
   "or1k prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   or1k_frame_this_id,
   or1k_frame_prev_register,
diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
index 719ddc71d13..a9576231c66 100644
--- a/gdb/ppc-fbsd-tdep.c
+++ b/gdb/ppc-fbsd-tdep.c
@@ -265,6 +265,7 @@  ppcfbsd_sigtramp_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = {
   "ppc freebsd sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ppcfbsd_sigtramp_frame_this_id,
   ppcfbsd_sigtramp_frame_prev_register,
diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c
index b845e67bcaa..c5e08091547 100644
--- a/gdb/ppc-obsd-tdep.c
+++ b/gdb/ppc-obsd-tdep.c
@@ -234,6 +234,7 @@  ppcobsd_sigtramp_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
   "ppc openbsd sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   ppcobsd_sigtramp_frame_this_id,
   ppcobsd_sigtramp_frame_prev_register,
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index 56f925bc57f..6268c475777 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -965,6 +965,7 @@  pyuw_on_new_gdbarch (gdbarch *newarch)
 
       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;
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 6350400c318..b6011c86c85 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1898,6 +1898,7 @@  const struct frame_unwind record_btrace_frame_unwind =
 {
   "record-btrace",
   NORMAL_FRAME,
+  FRAME_UNWIND_GDB,
   record_btrace_frame_unwind_stop_reason,
   record_btrace_frame_this_id,
   record_btrace_frame_prev_register,
@@ -1910,6 +1911,7 @@  const struct frame_unwind record_btrace_tailcall_frame_unwind =
 {
   "record-btrace tailcall",
   TAILCALL_FRAME,
+  FRAME_UNWIND_GDB,
   record_btrace_frame_unwind_stop_reason,
   record_btrace_frame_this_id,
   record_btrace_frame_prev_register,
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 68ef3233e8d..7af747a5161 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3905,6 +3905,7 @@  static const struct frame_unwind riscv_frame_unwind =
 {
   /*.name          =*/ "riscv prologue",
   /*.type          =*/ NORMAL_FRAME,
+  /*.unwinder_class=*/FRAME_UNWIND_ARCH,
   /*.stop_reason   =*/ default_frame_unwind_stop_reason,
   /*.this_id       =*/ riscv_frame_this_id,
   /*.prev_register =*/ riscv_frame_prev_register,
diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c
index 1e439f36356..00fa3ad301e 100644
--- a/gdb/rl78-tdep.c
+++ b/gdb/rl78-tdep.c
@@ -1187,6 +1187,7 @@  static const struct frame_unwind rl78_unwind =
 {
   "rl78 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   rl78_this_id,
   rl78_prev_register,
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index db76af6984b..78d6f5e8a19 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -331,6 +331,7 @@  aix_sighandle_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind aix_sighandle_frame_unwind = {
   "rs6000 aix sighandle",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   aix_sighandle_frame_this_id,
   aix_sighandle_frame_prev_register,
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index c8450345be2..c3551be5248 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -3842,6 +3842,7 @@  static const struct frame_unwind rs6000_frame_unwind =
 {
   "rs6000 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   rs6000_frame_this_id,
   rs6000_frame_prev_register,
@@ -3983,6 +3984,7 @@  static const struct frame_unwind rs6000_epilogue_frame_unwind =
 {
   "rs6000 epilogue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register,
   NULL,
diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c
index 53ad5d5c92b..d959dd1e327 100644
--- a/gdb/rx-tdep.c
+++ b/gdb/rx-tdep.c
@@ -634,6 +634,7 @@  rx_exception_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind rx_frame_unwind = {
   "rx prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   rx_frame_this_id,
   rx_frame_prev_register,
@@ -648,6 +649,7 @@  static const struct frame_unwind rx_exception_unwind = {
   "rx exception",
   /* SIGTRAMP_FRAME could be used here, but backtraces are less informative.  */
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   rx_frame_this_id,
   rx_frame_prev_register,
diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c
index 60cbc26afff..7f7865a8022 100644
--- a/gdb/s12z-tdep.c
+++ b/gdb/s12z-tdep.c
@@ -445,6 +445,7 @@  s12z_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind s12z_frame_unwind = {
   "s12z prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   s12z_frame_this_id,
   s12z_frame_prev_register,
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 945b3c7cee7..8b3df082063 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -545,6 +545,7 @@  s390_sigtramp_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind s390_sigtramp_frame_unwind = {
   "s390 linux sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   s390_sigtramp_frame_this_id,
   s390_sigtramp_frame_prev_register,
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 75983550a5c..d7fa9e11fad 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -2649,6 +2649,7 @@  s390_frame_prev_register (const frame_info_ptr &this_frame,
 static const struct frame_unwind s390_frame_unwind = {
   "s390 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   s390_frame_this_id,
   s390_frame_prev_register,
@@ -2743,6 +2744,7 @@  s390_stub_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind s390_stub_frame_unwind = {
   "s390 stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   s390_stub_frame_this_id,
   s390_stub_frame_prev_register,
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index ca7c28952f3..42e5f66bf2a 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -83,6 +83,7 @@  const struct frame_unwind sentinel_frame_unwind =
 {
   "sentinel",
   SENTINEL_FRAME,
+  FRAME_UNWIND_GDB,
   default_frame_unwind_stop_reason,
   sentinel_frame_this_id,
   sentinel_frame_prev_register,
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 16e513eb405..60e717c73c4 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1932,6 +1932,7 @@  sh_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
 static const struct frame_unwind sh_frame_unwind = {
   "sh prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sh_frame_this_id,
   sh_frame_prev_register,
@@ -1999,6 +2000,7 @@  static const struct frame_unwind sh_stub_unwind =
 {
   "sh stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sh_stub_this_id,
   sh_frame_prev_register,
diff --git a/gdb/sparc-netbsd-tdep.c b/gdb/sparc-netbsd-tdep.c
index d2b1a4bfd14..5861bf7b836 100644
--- a/gdb/sparc-netbsd-tdep.c
+++ b/gdb/sparc-netbsd-tdep.c
@@ -253,6 +253,7 @@  static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
 {
   "sparc32 netbsd sigcontext",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc32nbsd_sigcontext_frame_this_id,
   sparc32nbsd_sigcontext_frame_prev_register,
diff --git a/gdb/sparc-obsd-tdep.c b/gdb/sparc-obsd-tdep.c
index 8cdbc8aae6e..9ffb86fe3dc 100644
--- a/gdb/sparc-obsd-tdep.c
+++ b/gdb/sparc-obsd-tdep.c
@@ -138,6 +138,7 @@  static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
 {
   "sparc32 openbsd sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc32obsd_sigtramp_frame_this_id,
   sparc32obsd_sigtramp_frame_prev_register,
diff --git a/gdb/sparc-sol2-tdep.c b/gdb/sparc-sol2-tdep.c
index 52578440103..2c2f3fb74ee 100644
--- a/gdb/sparc-sol2-tdep.c
+++ b/gdb/sparc-sol2-tdep.c
@@ -184,6 +184,7 @@  static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
 {
   "sparc32 solaris sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc32_sol2_sigtramp_frame_this_id,
   sparc32_sol2_sigtramp_frame_prev_register,
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 5eec3615f53..d26e630b274 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1350,6 +1350,7 @@  static const struct frame_unwind sparc32_frame_unwind =
 {
   "sparc32 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc32_frame_this_id,
   sparc32_frame_prev_register,
diff --git a/gdb/sparc64-fbsd-tdep.c b/gdb/sparc64-fbsd-tdep.c
index c992c8c8f6f..aa5eaf7563e 100644
--- a/gdb/sparc64-fbsd-tdep.c
+++ b/gdb/sparc64-fbsd-tdep.c
@@ -201,6 +201,7 @@  static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
 {
   "sparc64 freebsd sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64fbsd_sigtramp_frame_this_id,
   sparc64fbsd_sigtramp_frame_prev_register,
diff --git a/gdb/sparc64-netbsd-tdep.c b/gdb/sparc64-netbsd-tdep.c
index fe97689ae15..16c5b07fbbb 100644
--- a/gdb/sparc64-netbsd-tdep.c
+++ b/gdb/sparc64-netbsd-tdep.c
@@ -227,6 +227,7 @@  static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
 {
   "sparc64 netbsd sigcontext",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64nbsd_sigcontext_frame_this_id,
   sparc64nbsd_sigcontext_frame_prev_register,
diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c
index 3837074a9fb..50611742726 100644
--- a/gdb/sparc64-obsd-tdep.c
+++ b/gdb/sparc64-obsd-tdep.c
@@ -224,6 +224,7 @@  static const struct frame_unwind sparc64obsd_frame_unwind =
 {
   "sparc64 openbsd sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64obsd_frame_this_id,
   sparc64obsd_frame_prev_register,
@@ -308,6 +309,7 @@  static const struct frame_unwind sparc64obsd_trapframe_unwind =
 {
   "sparc64 openbsd trap",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64obsd_trapframe_this_id,
   sparc64obsd_trapframe_prev_register,
diff --git a/gdb/sparc64-sol2-tdep.c b/gdb/sparc64-sol2-tdep.c
index 7cef98bb681..e2cd7548355 100644
--- a/gdb/sparc64-sol2-tdep.c
+++ b/gdb/sparc64-sol2-tdep.c
@@ -187,6 +187,7 @@  static const struct frame_unwind sparc64_sol2_sigtramp_frame_unwind =
 {
   "sparc64 solaris sigtramp",
   SIGTRAMP_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64_sol2_sigtramp_frame_this_id,
   sparc64_sol2_sigtramp_frame_prev_register,
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 8a90dd00d16..b7036464191 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -1138,6 +1138,7 @@  static const struct frame_unwind sparc64_frame_unwind =
 {
   "sparc64 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   sparc64_frame_this_id,
   sparc64_frame_prev_register,
diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index aa115095df7..7fc58d4fc61 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -456,6 +456,7 @@  static const struct frame_unwind tic6x_frame_unwind =
 {
   "tic6x prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   tic6x_frame_this_id,
   tic6x_frame_prev_register,
@@ -519,6 +520,7 @@  static const struct frame_unwind tic6x_stub_unwind =
 {
   "tic6x stub",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   tic6x_stub_this_id,
   tic6x_frame_prev_register,
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index c25933be558..d0d0de79909 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -903,6 +903,7 @@  tilegx_frame_base_address (const frame_info_ptr &this_frame, void **this_cache)
 static const struct frame_unwind tilegx_frame_unwind = {
   "tilegx prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   tilegx_frame_this_id,
   tilegx_frame_prev_register,
diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c
index 0e730e66b58..fba0c669489 100644
--- a/gdb/tramp-frame.c
+++ b/gdb/tramp-frame.c
@@ -166,6 +166,7 @@  tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
   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;
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index 4c1fd383a84..66cb5004058 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -1323,6 +1323,7 @@  v850_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
 static const struct frame_unwind v850_frame_unwind = {
   "v850 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   v850_frame_this_id,
   v850_frame_prev_register,
diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c
index 125f3423be5..17d36a545fb 100644
--- a/gdb/vax-tdep.c
+++ b/gdb/vax-tdep.c
@@ -390,6 +390,7 @@  static const struct frame_unwind vax_frame_unwind =
 {
   "vax prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   vax_frame_this_id,
   vax_frame_prev_register,
diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c
index 12b16c2d3d3..46412737039 100644
--- a/gdb/xstormy16-tdep.c
+++ b/gdb/xstormy16-tdep.c
@@ -731,6 +731,7 @@  xstormy16_frame_base_address (const frame_info_ptr &this_frame, void **this_cach
 static const struct frame_unwind xstormy16_frame_unwind = {
   "xstormy16 prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   xstormy16_frame_this_id,
   xstormy16_frame_prev_register,
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index d116b34fd81..728774f955a 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -1501,6 +1501,7 @@  xtensa_unwind =
 {
   "xtensa prologue",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   xtensa_frame_this_id,
   xtensa_frame_prev_register,
diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c
index f2d000f5303..4404d4bbd59 100644
--- a/gdb/z80-tdep.c
+++ b/gdb/z80-tdep.c
@@ -1068,6 +1068,7 @@  z80_frame_unwind =
 {
   "z80",
   NORMAL_FRAME,
+  FRAME_UNWIND_ARCH,
   default_frame_unwind_stop_reason,
   z80_frame_this_id,
   z80_frame_prev_register,