From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id I9lEH38yiWdARBEAWB0awg (envelope-from ) for ; Thu, 16 Jan 2025 11:23:27 -0500 Authentication-Results: simark.ca; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=B23avN6I; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 6EA4B1E100; Thu, 16 Jan 2025 11:23:27 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.0 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 3F6C31E05C for ; Thu, 16 Jan 2025 11:23:26 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B923D384DEC2 for ; Thu, 16 Jan 2025 16:23:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B923D384DEC2 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=B23avN6I Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 43D71384F03C for ; Thu, 16 Jan 2025 16:22:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 43D71384F03C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 43D71384F03C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1737044525; cv=none; b=FTqEcK2RpWRuHbY7tcg4e14KB9X0HgAG312P3XGcYeALyOQq+MVRlajk2Mpyyk/Trl0CADd5LfjcWYTIJsOEOivIghiF3nScnrdNL72e8K7iZze1tEUpmJErLdbB0t5nYP+f1F0zFWs5ZXKmxCo1PUZPh289le8N1iNSNICZBTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1737044525; c=relaxed/simple; bh=ufK084BR0W9TFljAdTiRXPAB203e7kKrnSGfhjB8tGM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=YPR28UqxM5X00/atjdbe7HcULbpM2fOjrq+5cOu4R6UOdC9EoMAFs5Nqtx7+zIi3yNxGIsTWe6HdX8BYDfv3OxbZmsOsvFC8rAc7D1EsgZlVJJVkyqoADnbnMXDU9JFEH1MAMOYdr8/9kF6z8BncFqK/OsOgSEraqkqL30A7qOY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 43D71384F03C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1737044525; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=dqLXwbutvAWspoABr60l0sF8WdU8sytZoCM63elcbq8=; b=B23avN6IofNltLunnGIX096qV2M5KvfH4Ulr9LaqdcI/2zj5bdpjnx8hb7d8nkbZwaO2H5 GPZAQVaQRF0fBjw8BGxGZu4Y5nptauOEdnPrENKG85SipQI/IBeZQ3oVSYhzundQuE0R/c oz5fqw8yJ7SLUP9KAqpbTZUOdtZVMyw= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-320-YZKZEkUjPPmbbitj9qklCg-1; Thu, 16 Jan 2025 11:22:03 -0500 X-MC-Unique: YZKZEkUjPPmbbitj9qklCg-1 X-Mimecast-MFC-AGG-ID: YZKZEkUjPPmbbitj9qklCg Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-43582d49dacso7417355e9.2 for ; Thu, 16 Jan 2025 08:22:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737044522; x=1737649322; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=9HrkXUZdhNNe1OluKEJN/YB9YTaBQmGRC25Tq/obuIM=; b=K+r0T2eyaX2yWkxK3pZwFosyBvFcUVZw82Rin6UnrAqho6seXv26XrwMlPfnx5xB0j ydekHm0l6mow/N+NrOlcpaVxDg3HqxvUge3bT9aOLn20ze8c9ejvLSw9FlkyUTkNbK92 cW5/cJ7y50CJUfeMv37LgYaaXAnqvKlU/zj7RDkv0aYSlDsY1fgJDS2vubYqy3ZD/KPC esBWFdkXJ2Hz7XXrhr8H32RPiYgcVuZsNjmK2O/QQiL9EqVDyvMfJQWbVxVDRZsc3+f5 5VmKciXWoUHG2QCfeuzDPlgjCd9oVgVhSP8uMcJIMtdUOC0ELsqoYBAPWnRs90NvEC32 NE9A== X-Forwarded-Encrypted: i=1; AJvYcCVZIvnZRid554A5YhZ3yLpgSr9I8BCqis/AGGu+hHei+bkL3jJNE+owjrw1qNspLQWoY/wuM/28rGLL4A==@sourceware.org X-Gm-Message-State: AOJu0YxLwGAtJwry1NF5+Axo/L0K3n+JdDjR4FUFYvtSsTxrkK0PBipi 9grPyZ2xh0E3YK8s4OD07wl1x2GRUVUmiT/RdKcMP1Fbj2je6QeGRlcZCbayBcUGlD1B3dfSmLq kMotHgjrCcZEFXOXS2NAs1TndqzaJ3R8ea/ef6nYn5vQgqw0qPz5Y0OD/BD0= X-Gm-Gg: ASbGncuPuAkfYD12yy3urQJVnb60OLY5NNft3yDsrSGuI4ZqJr1230/dYubmK0Kbf3h ipH/h8Y/sts+bTmXYgBx5zd5suI7eBL6oMLE+oxBaHFsljy2jsk6eTmSsnQMNO8JQTCu6mXhgQZ o1g7kpxJmw3ql1mk0WS83k9F8vBZji6SP+OBw/MnyiovWqC7D2Y1Hd/WfazxrIa2E712sNclAxE y0wp5tl1u0zJSzYGhK5biRGllQOGJQL/A7qb2rTcbCX28P9FzhXKQO0ggdNFk+TKXAOGVRGNT+O 7XoLUw== X-Received: by 2002:a05:600c:1f86:b0:434:fd15:3adc with SMTP id 5b1f17b1804b1-436e2707303mr266105915e9.25.1737044522377; Thu, 16 Jan 2025 08:22:02 -0800 (PST) X-Google-Smtp-Source: AGHT+IFaycCpwCNMUEiKH8OpdNtvulorTr896jsGGB1P7lv0vD90rI4BjowVOJksoaM4BPr1HqVw8Q== X-Received: by 2002:a05:600c:1f86:b0:434:fd15:3adc with SMTP id 5b1f17b1804b1-436e2707303mr266105615e9.25.1737044521834; Thu, 16 Jan 2025 08:22:01 -0800 (PST) Received: from localhost (44.226.159.143.dyn.plus.net. [143.159.226.44]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43890413801sm3882575e9.15.2025.01.16.08.22.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jan 2025 08:22:01 -0800 (PST) From: Andrew Burgess To: Guinevere Larsen , gdb-patches@sourceware.org Cc: Guinevere Larsen , Eli Zaretskii , Thiago Jung Bauermann Subject: Re: [PATCH v8 4/5] gdb: introduce ability to disable frame unwinders In-Reply-To: <20241210195115.3046370-5-guinevere@redhat.com> References: <20241210195115.3046370-1-guinevere@redhat.com> <20241210195115.3046370-5-guinevere@redhat.com> Date: Thu, 16 Jan 2025 16:22:00 +0000 Message-ID: <871px2pw47.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: _Le2zojxKGQh9NUBvOimcfgOtMPX8mPSYGC-yFtQQSI_1737044523 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Guinevere Larsen writes: > Sometimes, in the GDB testsuite, we want to test the ability of specific > unwinders to handle some piece of code. Usually this is done by trying > to outsmart GDB, or by coercing the compiler to remove information that > GDB would rely on. Both approaches have problems as GDB gets smarter > with time, and that compilers might differ in version and behavior, or > simply introduce new useful information. This was requested back in 2003 > in PR backtrace/8434. > > To improve our ability to thoroughly test GDB, this patch introduces a > new maintenance command that allows a user to disable some unwinders, > based on either the name of the unwinder or on its class. With this > change, it will now be possible for GDB to not find any frame unwinders > for a given frame, which would previously cause GDB to assert. GDB will > now check if any frame unwinder has been disabled, and if some has, it > will just error out instead of asserting. > > Unwinders can be disabled or re-enabled in 3 different ways: > * Disabling/enabling all at once (using '-all'). > * By specifying an unwinder class to be disabled (option '-class'). > * By specifying the name of an unwinder (option '-name'). > > If you give no options to the command, GDB assumes the input is an > unwinder class. '-class' would make no difference if used, is just here > for completeness. > > This command is meant to be used once the inferior is already at the > desired location for the test. An example session would be: > > (gdb) start > Temporary breakpoint 1, main () at omp.c:17 > 17 func(); > (gdb) maint frame-unwinder disable ARCH > (gdb) bt > \#0 main () at omp.c:17 > (gdb) maint frame-unwinder enable ARCH > (gdb) cont > Continuing. > > This commit is a more generic version of commit 3c3bb0580be0, > and so, based on the final paragraph of the commit message: > gdb: Add switch to disable DWARF stack unwinders > <...> > If in the future we find ourselves adding more switches to disable > different unwinders, then we should probably move to a more generic > solution, and remove this patch. > this patch also reverts 3c3bb0580be0 > > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=8434 > Reviewed-By: Eli Zaretskii > Reviewed-by: Thiago Jung Bauermann > --- > gdb/NEWS | 17 ++ > gdb/doc/gdb.texinfo | 49 ++-- > gdb/dwarf2/frame-tailcall.c | 3 - > gdb/dwarf2/frame.c | 30 --- > gdb/dwarf2/frame.h | 6 - > gdb/frame-unwind.c | 237 +++++++++++++++++- > gdb/frame-unwind.h | 9 + > .../gdb.base/frame-info-consistent.exp | 8 +- > gdb/testsuite/gdb.base/frame-unwind-disable.c | 22 ++ > .../gdb.base/frame-unwind-disable.exp | 137 ++++++++++ > gdb/testsuite/gdb.base/maint.exp | 4 - > 11 files changed, 437 insertions(+), 85 deletions(-) > create mode 100644 gdb/testsuite/gdb.base/frame-unwind-disable.c > create mode 100644 gdb/testsuite/gdb.base/frame-unwind-disable.exp > > diff --git a/gdb/NEWS b/gdb/NEWS > index 245b355669a..ef3317c11cb 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -125,6 +125,13 @@ maintenance info blocks [ADDRESS] > are listed starting at the inner global block out to the most inner > block. > > +maintenance frame-unwinder disable [-all | -name NAME | [-class] CLASS] > +maintenance frame-unwinder enable [-all | -name NAME | [-class] CLASS] > + Enable or disable frame unwinders. This is only meant to be used when > + testing unwinders themselves, and you want to ensure that a fallback > + algorithm won't obscure a regression. GDB is not expected to behave > + well if you try to execute the inferior with unwinders disabled. > + > info missing-objfile-handlers > List all the registered missing-objfile handlers. > > @@ -167,6 +174,16 @@ maintenance print remote-registers > 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. > + Also add an ENABLED column, that will show if the unwinder is enabled > + or not. > + > +maintenance set dwarf unwinders (on|off) > + This command has been removed because the same functionality can be > + achieved with maint frame-unwinder (enable|disable) DEBUGINFO. > + > +maintenance show dwarf unwinders > + This command has been removed since the functionality can be achieved > + by checking the last column of maint info frame-unwinders. > > show configuration > Now includes the version of GNU Readline library that GDB is using. > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 115c1f46b7f..10e6654a03b 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -42210,31 +42210,6 @@ On hosts without threading, or where worker threads have been disabled > at runtime, this setting has no effect, as DWARF reading is always > done on the main thread, and is therefore always synchronous. > > -@kindex maint set dwarf unwinders > -@kindex maint show dwarf unwinders > -@item maint set dwarf unwinders > -@itemx maint show dwarf unwinders > -Control use of the DWARF frame unwinders. > - > -@cindex DWARF frame unwinders > -Many targets that support DWARF debugging use @value{GDBN}'s DWARF > -frame unwinders to build the backtrace. Many of these targets will > -also have a second mechanism for building the backtrace for use in > -cases where DWARF information is not available, this second mechanism > -is often an analysis of a function's prologue. > - > -In order to extend testing coverage of the second level stack > -unwinding mechanisms it is helpful to be able to disable the DWARF > -stack unwinders, this can be done with this switch. > - > -In normal use of @value{GDBN} disabling the DWARF unwinders is not > -advisable, there are cases that are better handled through DWARF than > -prologue analysis, and the debug experience is likely to be better > -with the DWARF frame unwinders enabled. > - > -If DWARF frame unwinders are not supported for a particular target > -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 > @@ -42252,6 +42227,30 @@ Unwinders installed by debug information readers. > Unwinders installed by the architecture specific code. > @end table > > +@kindex maint frame-unwinder disable > +@kindex maint frame-unwinder enable > +@item maint frame-unwinder disable [@code{-all} | @code{-name} @var{name} | [@code{-class}] @var{class}] > +@item maint frame-unwinder enable [@code{-all} | @code{-name} @var{name} | [@code{-class}] @var{class}] > +Disable or enable frame unwinders. This is meant only as a testing tool, and > +@value{GDBN} is not guaranteed to work properly if it is unable to find > +valid frame unwinders. > + > +The meaning of each of the invocations are as follows: > + > +@table @samp > +@item @code{-all} > +Disable or enable all unwinders. > +@item @code{-name} @var{name} > +@var{name} is the exact name of the unwinder to be disabled or enabled. > +@item [@code{-class}] @var{class} > +@var{class} is the class of frame unwinders to be disabled or enabled. > +The class may include the prefix @code{FRAME_UNWINDER_}, but it is not > +required. > +@end table > + > +@var{name} and @var{class} are always case insensitive. If no option > +starting wth @code{-} is given, @value{GDBN} assumes @code{-class}. > + > @kindex maint set worker-threads > @kindex maint show worker-threads > @item maint set worker-threads > diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c > index 54813d00b03..2d7ab740f62 100644 > --- a/gdb/dwarf2/frame-tailcall.c > +++ b/gdb/dwarf2/frame-tailcall.c > @@ -321,9 +321,6 @@ tailcall_frame_sniffer (const struct frame_unwind *self, > int next_levels; > struct tailcall_cache *cache; > > - if (!dwarf2_frame_unwinders_enabled_p) > - return 0; > - > /* Inner tail call element does not make sense for a sentinel frame. */ > next_frame = get_next_frame (this_frame); > if (next_frame == NULL) > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > index 85e1d59bc09..e0e8eb5dbec 100644 > --- a/gdb/dwarf2/frame.c > +++ b/gdb/dwarf2/frame.c > @@ -183,9 +183,6 @@ static ULONGEST read_encoded_value (struct comp_unit *unit, gdb_byte encoding, > unrelocated_addr func_base); > > > -/* See dwarf2/frame.h. */ > -bool dwarf2_frame_unwinders_enabled_p = true; > - > /* Store the length the expression for the CFA in the `cfa_reg' field, > which is unused in that case. */ > #define cfa_exp_len cfa_reg > @@ -1306,9 +1303,6 @@ static int > dwarf2_frame_sniffer (const struct frame_unwind *self, > const frame_info_ptr &this_frame, void **this_cache) > { > - if (!dwarf2_frame_unwinders_enabled_p) > - return 0; > - > /* Grab an address that is guaranteed to reside somewhere within the > function. get_frame_pc(), with a no-return next function, can > end up returning something past the end of this function's body. > @@ -2253,34 +2247,10 @@ dwarf2_build_frame_info (struct objfile *objfile) > set_comp_unit (objfile, unit.release ()); > } > > -/* Handle 'maintenance show dwarf unwinders'. */ > - > -static void > -show_dwarf_unwinders_enabled_p (struct ui_file *file, int from_tty, > - struct cmd_list_element *c, > - const char *value) > -{ > - gdb_printf (file, > - _("The DWARF stack unwinders are currently %s.\n"), > - value); > -} > - > void _initialize_dwarf2_frame (); > void > _initialize_dwarf2_frame () > { > - add_setshow_boolean_cmd ("unwinders", class_obscure, > - &dwarf2_frame_unwinders_enabled_p , _("\ > -Set whether the DWARF stack frame unwinders are used."), _("\ > -Show whether the DWARF stack frame unwinders are used."), _("\ > -When enabled the DWARF stack frame unwinders can be used for architectures\n\ > -that support the DWARF unwinders. Enabling the DWARF unwinders for an\n\ > -architecture that doesn't support them will have no effect."), > - NULL, > - show_dwarf_unwinders_enabled_p, > - &set_dwarf_cmdlist, > - &show_dwarf_cmdlist); > - > #if GDB_SELF_TEST > selftests::register_test_foreach_arch ("execute_cfa_program", > selftests::execute_cfa_program_test); > diff --git a/gdb/dwarf2/frame.h b/gdb/dwarf2/frame.h > index 2167310fbdf..fe2d669a983 100644 > --- a/gdb/dwarf2/frame.h > +++ b/gdb/dwarf2/frame.h > @@ -198,12 +198,6 @@ struct dwarf2_frame_state > bool armcc_cfa_offsets_reversed = false; > }; > > -/* When this is true the DWARF frame unwinders can be used if they are > - registered with the gdbarch. Not all architectures can or do use the > - DWARF unwinders. Setting this to true on a target that does not > - otherwise support the DWARF unwinders has no effect. */ > -extern bool dwarf2_frame_unwinders_enabled_p; > - > /* Set the architecture-specific register state initialization > function for GDBARCH to INIT_REG. */ > > diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c > index 3ab6af1c4da..968bb846402 100644 > --- a/gdb/frame-unwind.c > +++ b/gdb/frame-unwind.c > @@ -29,6 +29,7 @@ > #include "gdbarch.h" > #include "dwarf2/frame-tailcall.h" > #include "cli/cli-cmds.h" > +#include "cli/cli-option.h" > #include "inferior.h" > > /* Conversion list between the enum for frame_unwind_class and > @@ -89,6 +90,20 @@ frame_unwinder_class_str (frame_unwind_class uclass) > return unwind_class_conversion[uclass]; > } > > +/* Case insensitive search for a frame_unwind_class based on the given > + string. */ > +static enum frame_unwind_class > +str_to_frame_unwind_class (const char *class_str) > +{ > + for (int i = 0; i < UNWIND_CLASS_NUMBER; i++) > + { > + if (strcasecmp (unwind_class_conversion[i], class_str) == 0) > + return (frame_unwind_class) i; > + } > + > + error (_("Unknown frame unwind class: %s"), class_str); > +} > + > void > frame_unwind_prepend_unwinder (struct gdbarch *gdbarch, > const struct frame_unwind *unwinder) > @@ -175,27 +190,46 @@ frame_unwind_find_by_frame (const frame_info_ptr &this_frame, void **this_cache) > FRAME_SCOPED_DEBUG_ENTER_EXIT; > frame_debug_printf ("this_frame=%d", frame_relative_level (this_frame)); > > - const struct frame_unwind *unwinder_from_target; > + /* If we see a disabled unwinder, we assume some test is being run on > + GDB, and we don't want to internal_error at the end of this function. */ > + bool seen_disabled_unwinder = false; > + /* Lambda to factor out the logic of checking if an unwinder is enabled, > + testing it and otherwise recording if we saw a disable unwinder. */ > + auto test_unwinder = [&] (const struct frame_unwind *unwinder) > + { > + if (unwinder == nullptr) > + return false; > + > + if (!unwinder->enabled ()) > + { > + seen_disabled_unwinder = true; > + return false; > + } > + > + return frame_unwind_try_unwinder (this_frame, > + this_cache, > + unwinder); > + }; > > - unwinder_from_target = target_get_unwinder (); > - if (unwinder_from_target != NULL > - && frame_unwind_try_unwinder (this_frame, this_cache, > - unwinder_from_target)) > + if (test_unwinder (target_get_unwinder ())) > return; > > - unwinder_from_target = target_get_tailcall_unwinder (); > - if (unwinder_from_target != NULL > - && frame_unwind_try_unwinder (this_frame, this_cache, > - unwinder_from_target)) > + if (test_unwinder (target_get_tailcall_unwinder ())) > return; > > struct gdbarch *gdbarch = get_frame_arch (this_frame); > std::vector *table = get_frame_unwind_table (gdbarch); > for (auto unwinder : *table) > - if (frame_unwind_try_unwinder (this_frame, this_cache, unwinder)) > - return; > + { > + if (test_unwinder (unwinder)) > + return; > + } > > - internal_error (_("frame_unwind_find_by_frame failed")); > + if (seen_disabled_unwinder) > + error (_("Required frame unwinder may have been disabled" > + ", see 'maint info frame-unwinders'")); > + else > + internal_error (_("frame_unwind_find_by_frame failed")); > } > > /* A default frame sniffer which always accepts the frame. Used by > @@ -394,10 +428,11 @@ maintenance_info_frame_unwinders (const char *args, int from_tty) > std::vector *table = get_frame_unwind_table (gdbarch); > > ui_out *uiout = current_uiout; > - ui_out_emit_table table_emitter (uiout, 3, -1, "FrameUnwinders"); > + ui_out_emit_table table_emitter (uiout, 4, -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_header (8, ui_left, "enabled", "Enabled"); > uiout->table_body (); > > for (auto unwinder : *table) > @@ -407,10 +442,145 @@ maintenance_info_frame_unwinders (const char *args, int from_tty) > uiout->field_string ("type", frame_type_str (unwinder->type ())); > uiout->field_string ("class", frame_unwinder_class_str ( > unwinder->unwinder_class ())); > + uiout->field_string ("enabled", unwinder->enabled () ? "Y" : "N"); > uiout->text ("\n"); > } > } > > +/* Options for disabling frame unwinders. */ > +struct maint_frame_unwind_options > +{ > + std::string unwinder_name; > + const char *unwinder_class = nullptr; > + bool all = false; > +}; > + > +static const gdb::option::option_def maint_frame_unwind_opt_defs[] = { > + > + gdb::option::flag_option_def { > + "all", > + [] (maint_frame_unwind_options *opt) { return &opt->all; }, > + nullptr, > + N_("Change the state of all unwinders") I think for flag_option_def, this should be: gdb::option::flag_option_def { "all", [] (maint_frame_unwind_options *opt) { return &opt->all; }, N_("Change the state of all unwinders") } dropping the 'nullptr'. If/when we use %OPTIONS% this will then print that 'Change the state of all unwinders' text as the description of this option. Thanks, Andrew