[v3,2/5] gdb: add "unwinder class" to frame unwinders

Message ID 20240508145455.2550696-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-aarch64 success Testing passed
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_check--master-aarch64 success Testing passed

Commit Message

Guinevere Larsen May 8, 2024, 2:54 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/NEWS                    |  4 ++++
 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/doc/gdb.texinfo         |  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          | 17 +++++++++++++++++
 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 +
 82 files changed, 158 insertions(+), 2 deletions(-)
  

Comments

Guinevere Larsen May 8, 2024, 7:40 p.m. UTC | #1
On 5/8/24 15:20, Eli Zaretskii wrote:
>> From: Guinevere Larsen <blarsen@redhat.com>
>> Cc: Guinevere Larsen <blarsen@redhat.com>
>> Date: Wed,  8 May 2024 11:54:52 -0300
>>
>> 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.
> Thanks.  I wonder whether some of the above should in the manual as
> well.
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 050f6f96e62..679295f0507 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -32,6 +32,10 @@ maintenance info line-table
>>     if the line is considered the start of the epilgoue, and thus a point at
>>     which the frame can be considered destroyed.
>>   
>> +mainenance info frame-unwinders
>> +  Add a CLASS column to the output.  This class is a somewhat arbitrary
>> +  grouping of unwinders, based on which area of GDB adds the unwinder.
> This part is okay.
>
>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
>> index 61f91ef4ad6..3fc0fafa3cd 100644
>> --- a/gdb/doc/gdb.texinfo
>> +++ b/gdb/doc/gdb.texinfo
>> @@ -42094,7 +42094,7 @@ architecture, then enabling this flag does not cause them to be used.
>>   
>>   @kindex maint info frame-unwinders
>>   @item maint info frame-unwinders
>> -List the frame unwinders currently in effect, starting with the highest priority.
>> +List the frame unwinders currently in effect, starting with the highest priority.  This also lists the unwinder class, which is mostly defined by which area  of @value{GDBN} uses it.
> This is also okay, but please split the long line into a few, so that
> each line is shorter than 79 characters.  And also please consider
> adding the list of currently known classes to the above description.
>
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
>
Thanks for the quick review! I added the following diff to fix the comments:

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index a3226d98ff6..862dd152ab2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -42094,7 +42094,16 @@ architecture, then enabling this flag does not 
cause them to be used.

  @kindex maint info frame-unwinders
  @item maint info frame-unwinders
-List the frame unwinders currently in effect, starting with the highest 
priority.  This also lists the unwinder class, which is mostly defined 
by which area  of @value{GDBN} uses it.
+List the frame unwinders currently in effect, starting with the highest
+priority.  This also lists the unwinder class, which is mostly defined by
+which area  of @value{GDBN} uses it.  The currently available classes are:
+
+@table @samp
+@item GDB: An internal unwinder, added by GDB core;
+@item EXTENSION: Unwinders added by extension languages;
+@item DEBUGINFO: Unwinders installed by debug information readers;
+@item ARCH: Unwinders isntalled by the architecture specific code.
+@end table

  @kindex maint frame-unwinder disable
  @kindex maint frame-unwinder enable
  
Tom Tromey May 9, 2024, 1:55 p.m. UTC | #2
>>>>> "Guinevere" == Guinevere Larsen <blarsen@redhat.com> writes:

Guinevere> +@item ARCH: Unwinders isntalled by the architecture specific code.

I happened to notice that "installed" has a typo here.

Tom
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 050f6f96e62..679295f0507 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -32,6 +32,10 @@  maintenance info line-table
   if the line is considered the start of the epilgoue, and thus a point at
   which the frame can be considered destroyed.
 
+mainenance info frame-unwinders
+  Add a CLASS column to the output.  This class is a somewhat arbitrary
+  grouping of unwinders, based on which area of GDB adds the unwinder.
+
 set unwindonsignal on|off
 show unwindonsignal
   These commands are now aliases for the new set/show unwind-on-signal.
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 8d0553f3d7c..fb431b15334 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 abded2ac192..b087afabae7 100644
--- a/gdb/alpha-mdebug-tdep.c
+++ b/gdb/alpha-mdebug-tdep.c
@@ -334,6 +334,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 fa042b252b0..f55bf2c8661 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 5b1e77b3e86..5359959e3bb 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 df6b882a3fb..d839335d9fa 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 9636201d13a..74bea7370fe 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1186,6 +1186,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 49996aeefc3..679098a778f 100644
--- a/gdb/amdgpu-tdep.c
+++ b/gdb/amdgpu-tdep.c
@@ -894,6 +894,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 9491107ecff..e96d186246f 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 f36ce631a08..5c1f50cd0b8 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 1e39f851bac..569ca94abaa 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 b89b7dfa6d8..739d13ff6c9 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 79a442068b5..1f53d63c982 100644
--- a/gdb/bpf-tdep.c
+++ b/gdb/bpf-tdep.c
@@ -185,6 +185,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 4c8ae77cc86..6af9f52d6af 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 1b6c08eb730..57a07a3c36b 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/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 61f91ef4ad6..3fc0fafa3cd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -42094,7 +42094,7 @@  architecture, then enabling this flag does not cause them to be used.
 
 @kindex maint info frame-unwinders
 @item maint info frame-unwinders
-List the frame unwinders currently in effect, starting with the highest priority.
+List the frame unwinders currently in effect, starting with the highest priority.  This also lists the unwinder class, which is mostly defined by which area  of @value{GDBN} uses it.
 
 @kindex maint set worker-threads
 @kindex maint show worker-threads
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index 9f540d02f1a..e7de15b5c4d 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -379,6 +379,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 bcbe41f7933..45ba3a70262 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -473,6 +473,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 9ebf3ac4ac4..7bbe6cab22d 100644
--- a/gdb/dwarf2/frame.c
+++ b/gdb/dwarf2/frame.c
@@ -1343,6 +1343,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,
@@ -1355,6 +1356,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 0bb47deea3a..d867f0e152d 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, const char *> unwind_class_conversion =
+{
+  {FRAME_UNWIND_GDB, "GDB"},
+  {FRAME_UNWIND_ARCH, "ARCH"},
+  {FRAME_UNWIND_EXTENSION, "EXTENSION"},
+  {FRAME_UNWIND_DEBUGINFO, "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;
+}
+
 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 (9, 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..deab4f7dbfb 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -156,12 +156,29 @@  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);
 
+/* Unwinders are classified by what part of GDB code created it.  */
+enum frame_unwind_class
+{
+  /* This is mostly handled by core GDB code.  */
+  FRAME_UNWIND_GDB,
+  /* This unwinder was added by one of GDB's extension languages.  */
+  FRAME_UNWIND_EXTENSION,
+  /* The unwinder was created and mostly handles debug information.  */
+  FRAME_UNWIND_DEBUGINFO,
+  /* The unwinder was created and handles target dependent things.  */
+  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 46424453ef0..7a7c4904475 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 1b5e15f831b..889397e56cb 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 647c5844151..485253d2baf 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 e91d664ffa3..5b4466ed316 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 8f73f8d2374..2619b60655a 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 c15a9fcc03f..93765060127 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 3539c6599a0..1d2b1a09d16 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 f1f909e1616..3df778d6048 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 6376cf8d069..8c054c304bd 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 f65f39be40d..2da4cad5f9d 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -267,6 +267,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 5776c66f78a..e0db1b0de4e 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 797be95a8da..8f08f75620a 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 98a07281051..4eb5f2ad426 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 af0d6896143..891da6a3b78 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 d9890d0e464..77c109607d7 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 8eea6620df9..11a150a92b8 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 f2f8602f23c..1c1130431d4 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 e58e44b7fd2..909600da2ec 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 7250ce09826..7cca4f86394 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 1b8cc927e0c..329e197a868 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 913889ecfb2..71f37e80680 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 3d768d7e161..94e8b0cee53 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 90988cdfdac..18cb9485639 100644
--- a/gdb/mips-sde-tdep.c
+++ b/gdb/mips-sde-tdep.c
@@ -164,6 +164,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 ae58d7c8720..6b43f08b1dc 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 d44eebfcb17..565300afd3c 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 29ad1f2bb2e..82d3478ed68 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 017ebb432d4..7fb5aee5bbe 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 8ad51d0798b..910a6f7a1d0 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 130c0154a60..5e68764bd6a 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 290f748cc56..6e0466c3408 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 3f0f93f1ac0..12eb396a0e3 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 1bd79b3b3e1..ceb8b5d85db 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 a86ccd2c94e..68da62decec 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -964,6 +964,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 9fec6112755..45f6870bdb6 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 d592d2dc0c4..29b31dcedcc 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3904,6 +3904,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 46a7ee9c3d4..0fcd5f9f1f3 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 3faefe58ceb..3e5c8acff21 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 2edb8234e6b..198703734aa 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 6b12fe0a314..6cb74c23a3c 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 c24c75665ed..7fa73cf6b8c 100644
--- a/gdb/s12z-tdep.c
+++ b/gdb/s12z-tdep.c
@@ -444,6 +444,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 bc1db550d2e..556fad64926 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -544,6 +544,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 6687127d0aa..bbf88dbcab1 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 4eaeae0d254..9fe4036dbbe 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -82,6 +82,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 0dbb905f1db..f87f0aa27c3 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -1953,6 +1953,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,
@@ -2020,6 +2021,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 fc22e66826f..5b3dd067375 100644
--- a/gdb/sparc-netbsd-tdep.c
+++ b/gdb/sparc-netbsd-tdep.c
@@ -252,6 +252,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 3182a7778d3..049c315fa14 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 aea3766d9b5..bb9c8a549b1 100644
--- a/gdb/sparc-sol2-tdep.c
+++ b/gdb/sparc-sol2-tdep.c
@@ -183,6 +183,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 edbc03878dc..30dd061d8c9 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 a30c7c448e5..1d4c075a961 100644
--- a/gdb/sparc64-fbsd-tdep.c
+++ b/gdb/sparc64-fbsd-tdep.c
@@ -200,6 +200,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 b101f4970d9..82eb99f57c1 100644
--- a/gdb/sparc64-netbsd-tdep.c
+++ b/gdb/sparc64-netbsd-tdep.c
@@ -226,6 +226,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 cef6efd3379..e81afa604e7 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 b7ca4ca1f5b..e8d09e2516e 100644
--- a/gdb/sparc64-sol2-tdep.c
+++ b/gdb/sparc64-sol2-tdep.c
@@ -186,6 +186,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 7d44b1e16a0..09774ebcee6 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -1139,6 +1139,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 6732478eb09..bac8ba84ed0 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 92f2be0b208..16cd25f4635 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 4f7c62d11fa..6368f67a2e7 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 531fdb48ab0..9300aeccf6f 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 a42c872feff..25d07c59376 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 766d1d144be..e01da4ecab4 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 840768b65c7..b8b7efb38b0 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 23cdb68e190..fc42d77fa0f 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,