From 201e1de37ab9b7d3433b416cb242c2ae49bbca1a Mon Sep 17 00:00:00 2001 From: Alexandra Hájková Date: Dec 13 2021 11:24:38 +0000 Subject: Backport upstream patch "gdb: Have setter and getter callbacks for settings" (RHBZ 2024875, Lancelot SIX). --- diff --git a/_gdb.spec.Patch.include b/_gdb.spec.Patch.include index 8aefee0..33e55a1 100644 --- a/_gdb.spec.Patch.include +++ b/_gdb.spec.Patch.include @@ -363,3 +363,7 @@ Patch087: gdb-rhbz2024875-m_terminal.patch #std::string variable Patch088: gdb-rhbz2024875-use-std_string-variable.patch +#Backport upstream commit from Lancelot SIX +#702991711a9 gdb: Have setter and getter callbacks for settings +Patch089: gdb-rhbz2024875-have-setter-getter-callbacks.patch + diff --git a/_gdb.spec.patch.include b/_gdb.spec.patch.include index b6c1352..dd1a19f 100644 --- a/_gdb.spec.patch.include +++ b/_gdb.spec.patch.include @@ -86,3 +86,4 @@ %patch086 -p1 %patch087 -p1 %patch088 -p1 +%patch089 -p1 diff --git a/_patch_order b/_patch_order index ea19061..c8fbac2 100644 --- a/_patch_order +++ b/_patch_order @@ -86,3 +86,4 @@ gdb-rhbz2024875-add-setter-getter-for-inferior-args.patch gdb-rhbz202487-make_inferior_m_args-an-std_string.patch gdb-rhbz2024875-m_terminal.patch gdb-rhbz2024875-use-std_string-variable.patch +gdb-rhbz2024875-have-setter-getter-callbacks.patch diff --git a/gdb-rhbz2024875-have-setter-getter-callbacks.patch.patch b/gdb-rhbz2024875-have-setter-getter-callbacks.patch.patch new file mode 100644 index 0000000..f43b4b8 --- /dev/null +++ b/gdb-rhbz2024875-have-setter-getter-callbacks.patch.patch @@ -0,0 +1,901 @@ +From b61570593f8ae9f09f59d221612c21af274fd9ea Mon Sep 17 00:00:00 2001 +From: root +Date: Thu, 9 Dec 2021 11:37:09 -0500 +Subject: [PATCH 08/15] gdb-rhbz2024875-have-setter-getter-callbacks.patch + +gdb: Have setter and getter callbacks for settings + +The main motivation behind this improvement is to help the +implementation of a patch Simon Marchi is preparing to fix a bug when +MI or Python try to access parameters that are inferior dependent (see +PR/28085). + +This commit extends the previous ones, which introduces the setting +object to represent a static variable whose value can be set or shown +with the appropriate commands. This patch proposes that a setting can +either contain a pointer to a static variable holding a setting, or +pointers to a pair of setter and getter callback functions. + +The callbacks functions can be used to retrieve or change the value with +custom logic. This is useful when the source of truth for a given +setting is not contained in the variable pointed to by the setting +instance. + +Given that the callback function call is hidden within the setting +abstraction introduced earlier, none of the sites accessing the setting +needs to be updated. The registered getter or setter is used whatever +the way to access it is (through MI, Python, Guile, the "with" command +and the $_gdb_setting / $_gdb_setting_str convenience functions). + +All the add_setshow_*_cmd are given a new overload that will accept the +pair of function pointers (set / get functions) instead of the pointer +to a global variable. + +Tested on GNU/Linux x86_64 with no regression observed. + +Change-Id: Ieb81fef57550632ff66e6aa85f637372a226be8c +Co-authored-by: Simon Marchi +--- + gdb/cli/cli-decode.c | 354 +++++++++++++++++++++++++++++++++++++++---- + gdb/command.h | 194 ++++++++++++++++++++++-- + 2 files changed, 502 insertions(+), 46 deletions(-) + +diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c +index b3bf6276157..3b0830e4c17 100644 +--- a/gdb/cli/cli-decode.c ++++ b/gdb/cli/cli-decode.c +@@ -460,6 +460,10 @@ empty_func (const char *args, int from_tty, cmd_list_element *c) + CLASS is as in add_cmd. + VAR_TYPE is the kind of thing we are setting. + VAR is address of the variable being controlled by this command. ++ SET_SETTING_FUNC is a pointer to an optional function callback used to set ++ the setting value. ++ GET_SETTING_FUNC is a pointer to an optional function callback used to get ++ the setting value. + DOC is the documentation string. */ + + static struct cmd_list_element * +@@ -486,9 +490,11 @@ add_set_or_show_cmd (const char *name, + /* Add element named NAME to both the command SET_LIST and SHOW_LIST. + CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are + setting. VAR is address of the variable being controlled by this +- command. SET_FUNC and SHOW_FUNC are the callback functions (if +- non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation +- strings. ++ command. If nullptr is given as VAR, then both SET_SETTING_FUNC and ++ GET_SETTING_FUNC must be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are ++ callbacks used to access and modify the underlying property, whatever its ++ storage is. SET_FUNC and SHOW_FUNC are the callback functions (if non-NULL). ++ SET_DOC, SHOW_DOC and HELP_DOC are the documentation strings. + + Return the newly created set and show commands. */ + +@@ -544,13 +550,16 @@ add_setshow_cmd_full (const char *name, + var_types var_type, T *var, + const char *set_doc, const char *show_doc, + const char *help_doc, ++ setting_setter_ftype set_setting_func, ++ setting_getter_ftype get_setting_func, + cmd_func_ftype *set_func, + show_value_ftype *show_func, + struct cmd_list_element **set_list, + struct cmd_list_element **show_list) + { + auto erased_args +- = setting::erase_args (var_type, var); ++ = setting::erase_args (var_type, var, ++ set_setting_func, get_setting_func); + + return add_setshow_cmd_full_erased (name, + theclass, +@@ -584,12 +593,36 @@ add_setshow_enum_cmd (const char *name, + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_enum, var, + set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + commands.set->enums = enumlist; + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_enum_cmd (const char *name, command_class theclass, ++ const char *const *enumlist, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_enum, ++ nullptr, set_doc, show_doc, ++ help_doc, set_func, get_func, ++ nullptr, show_func, set_list, ++ show_list); ++ ++ cmds.set->enums = enumlist; ++ ++ return cmds; ++} ++ + /* See cli-decode.h. */ + const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL }; + +@@ -610,17 +643,42 @@ add_setshow_auto_boolean_cmd (const char *name, + struct cmd_list_element **show_list) + { + set_show_commands commands +- = add_setshow_cmd_full (name, theclass, +- var_auto_boolean,var, +- set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ = add_setshow_cmd_full (name, theclass, var_auto_boolean, ++ var, set_doc, show_doc, help_doc, ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + + commands.set->enums = auto_boolean_enums; + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_auto_boolean_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, ++ var_auto_boolean, ++ nullptr, set_doc, ++ show_doc, help_doc, ++ set_func, get_func, ++ nullptr, show_func, ++ set_list, show_list); ++ ++ cmds.set->enums = auto_boolean_enums; ++ ++ return cmds; ++} ++ + /* See cli-decode.h. */ + const char * const boolean_enums[] = { "on", "off", NULL }; + +@@ -642,7 +700,7 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, bool *va + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_boolean, var, + set_doc, show_doc, help_doc, +- set_func, show_func, ++ nullptr, nullptr, set_func, show_func, + set_list, show_list); + + commands.set->enums = boolean_enums; +@@ -650,6 +708,29 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, bool *va + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_boolean_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_boolean, nullptr, ++ set_doc, show_doc, help_doc, ++ set_func, get_func, nullptr, ++ show_func, set_list, show_list); ++ ++ cmds.set->enums = boolean_enums; ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ + +@@ -666,14 +747,38 @@ add_setshow_filename_cmd (const char *name, enum command_class theclass, + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_filename, var, + set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + + set_cmd_completer (commands.set, filename_completer); + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_filename_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_filename, ++ nullptr, set_doc, show_doc, ++ help_doc, set_func, get_func, ++ nullptr, show_func, set_list, ++ show_list); ++ ++ set_cmd_completer (cmds.set, filename_completer); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ + +@@ -689,9 +794,9 @@ add_setshow_string_cmd (const char *name, enum command_class theclass, + { + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_string, var, +- set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ set_doc, show_doc, help_doc, ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + + /* Disable the default symbol completer. */ + set_cmd_completer (commands.set, nullptr); +@@ -699,6 +804,31 @@ add_setshow_string_cmd (const char *name, enum command_class theclass, + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_string_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_string, ++ nullptr, set_doc, show_doc, ++ help_doc, set_func, get_func, ++ nullptr, show_func, set_list, ++ show_list); ++ ++ /* Disable the default symbol completer. */ ++ set_cmd_completer (cmds.set, nullptr); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ + +@@ -715,8 +845,8 @@ add_setshow_string_noescape_cmd (const char *name, enum command_class theclass, + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_string_noescape, + var, set_doc, show_doc, help_doc, +- set_func, show_func, set_list, +- show_list); ++ nullptr, nullptr, set_func, show_func, ++ set_list, show_list); + + /* Disable the default symbol completer. */ + set_cmd_completer (commands.set, nullptr); +@@ -724,6 +854,32 @@ add_setshow_string_noescape_cmd (const char *name, enum command_class theclass, + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_string_noescape_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, ++ var_string_noescape, nullptr, ++ set_doc, show_doc, help_doc, ++ set_func, get_func, ++ nullptr, show_func, set_list, ++ show_list); ++ ++ /* Disable the default symbol completer. */ ++ set_cmd_completer (cmds.set, nullptr); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). */ + +@@ -740,14 +896,38 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_optional_filename, + var, set_doc, show_doc, help_doc, +- set_func, show_func, set_list, +- show_list); ++ nullptr, nullptr, set_func, show_func, ++ set_list, show_list); + + set_cmd_completer (commands.set, filename_completer); + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_optional_filename_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = ++ add_setshow_cmd_full (name, theclass, var_optional_filename, ++ nullptr, set_doc, show_doc, help_doc, ++ set_func, get_func, nullptr, show_func, ++ set_list,show_list); ++ ++ set_cmd_completer (cmds.set, filename_completer); ++ ++ return cmds; ++} ++ + /* Completes on literal "unlimited". Used by integer commands that + support a special "unlimited" value. */ + +@@ -782,15 +962,39 @@ add_setshow_integer_cmd (const char *name, enum command_class theclass, + struct cmd_list_element **show_list) + { + set_show_commands commands +- = add_setshow_cmd_full (name, theclass, var_integer, var, set_doc, +- show_doc, help_doc, set_func, show_func, +- set_list, show_list); ++ = add_setshow_cmd_full (name, theclass, var_integer, var, ++ set_doc, show_doc, help_doc, ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + + set_cmd_completer (commands.set, integer_unlimited_completer); + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_integer_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_integer, nullptr, ++ set_doc, show_doc, help_doc, set_func, ++ get_func, nullptr, show_func, set_list, ++ show_list); ++ ++ set_cmd_completer (cmds.set, integer_unlimited_completer); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the +@@ -809,14 +1013,38 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass, + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_uinteger, var, + set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); + + set_cmd_completer (commands.set, integer_unlimited_completer); + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_uinteger_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds = add_setshow_cmd_full (name, theclass, var_uinteger, ++ nullptr, set_doc, show_doc, ++ help_doc, set_func, get_func, ++ nullptr, show_func, set_list, ++ show_list); ++ ++ set_cmd_completer (cmds.set, integer_unlimited_completer); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the +@@ -834,8 +1062,27 @@ add_setshow_zinteger_cmd (const char *name, enum command_class theclass, + { + return add_setshow_cmd_full (name, theclass, var_zinteger, var, + set_doc, show_doc, help_doc, +- set_func, show_func, +- set_list, show_list); ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); ++} ++ ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_zinteger_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ return add_setshow_cmd_full (name, theclass, var_zinteger, nullptr, ++ set_doc, show_doc, help_doc, set_func, ++ get_func, nullptr, show_func, set_list, ++ show_list); + } + + set_show_commands +@@ -852,14 +1099,39 @@ add_setshow_zuinteger_unlimited_cmd (const char *name, + { + set_show_commands commands + = add_setshow_cmd_full (name, theclass, var_zuinteger_unlimited, var, +- set_doc, show_doc, help_doc, set_func, +- show_func, set_list, show_list); ++ set_doc, show_doc, help_doc, nullptr, ++ nullptr, set_func, show_func, set_list, ++ show_list); + + set_cmd_completer (commands.set, integer_unlimited_completer); + + return commands; + } + ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ auto cmds ++ = add_setshow_cmd_full (name, theclass, var_zuinteger_unlimited, ++ nullptr, set_doc, show_doc, help_doc, set_func, ++ get_func, nullptr, show_func, set_list, ++ show_list); ++ ++ set_cmd_completer (cmds.set, integer_unlimited_completer); ++ ++ return cmds; ++} ++ + /* Add element named NAME to both the set and show command LISTs (the + list for set/show or some sublist thereof). CLASS is as in + add_cmd. VAR is address of the variable which will contain the +@@ -877,7 +1149,27 @@ add_setshow_zuinteger_cmd (const char *name, enum command_class theclass, + { + return add_setshow_cmd_full (name, theclass, var_zuinteger, + var, set_doc, show_doc, help_doc, +- set_func, show_func, set_list, ++ nullptr, nullptr, set_func, ++ show_func, set_list, show_list); ++} ++ ++/* Same as above but using a getter and a setter function instead of a pointer ++ to a global storage buffer. */ ++ ++set_show_commands ++add_setshow_zuinteger_cmd (const char *name, command_class theclass, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, ++ cmd_list_element **set_list, ++ cmd_list_element **show_list) ++{ ++ return add_setshow_cmd_full (name, theclass, var_zuinteger, ++ nullptr, set_doc, show_doc, ++ help_doc, set_func, get_func, ++ nullptr, show_func, set_list, + show_list); + } + +diff --git a/gdb/command.h b/gdb/command.h +index e6e6ec8a5d8..2abfbc497b9 100644 +--- a/gdb/command.h ++++ b/gdb/command.h +@@ -181,6 +181,20 @@ inline bool var_type_uses (var_types t) + return t == var_enum; + } + ++/* Function signature for a callback used to get a value from a setting. */ ++ ++template ++using setting_getter_ftype = const T &(*) (); ++ ++/* Function signature for a callback used to set a value to a setting. */ ++ ++template ++using setting_setter_ftype = void (*) (const T &); ++ ++/* Generic/type-erased function pointer. */ ++ ++using erased_func = void (*) (); ++ + /* Interface for getting and setting a setting's value. + + The underlying data can be of any VAR_TYPES type. */ +@@ -204,14 +218,30 @@ struct setting + struct erased_args + { + void *var; ++ erased_func setter; ++ erased_func getter; + }; + + template +- static erased_args erase_args (var_types var_type, T *var) ++ static erased_args erase_args (var_types var_type, ++ T *var, ++ setting_setter_ftype set_setting_func, ++ setting_getter_ftype get_setting_func) + { + gdb_assert (var_type_uses (var_type)); +- +- return {var}; ++ /* The getter and the setter must be both provided or both omitted. */ ++ gdb_assert ++ ((set_setting_func == nullptr) == (get_setting_func == nullptr)); ++ ++ /* The caller must provide a pointer to a variable or get/set functions, but ++ not both. */ ++ gdb_assert ((set_setting_func == nullptr) != (var == nullptr)); ++ ++ return { ++ var, ++ reinterpret_cast (set_setting_func), ++ reinterpret_cast (get_setting_func) ++ }; + } + + /* Create a setting backed by pre-validated type-erased args. +@@ -219,16 +249,37 @@ struct setting + (see VAR_TYPE_USES). */ + setting (var_types var_type, const erased_args &args) + : m_var_type (var_type), +- m_var (args.var) ++ m_var (args.var), ++ m_getter (args.getter), ++ m_setter (args.setter) + { + } + +- /* Access the type of the current setting. */ +- var_types type () const ++ /* Create a setting backed by setter and getter functions. ++ ++ Type T must match the var type VAR_TYPE (see VAR_TYPE_USES). */ ++ template ++ setting (var_types var_type, ++ setting_setter_ftype setter, ++ setting_getter_ftype getter) ++ : m_var_type (var_type) + { +- return m_var_type; ++ gdb_assert (var_type_uses (var_type)); ++ ++ /* Getters and setters are cast to and from the arbitrary `void (*) ()` ++ function pointer type. Make sure that the two types are really of the ++ same size. */ ++ gdb_static_assert (sizeof (m_getter) == sizeof (getter)); ++ gdb_static_assert (sizeof (m_setter) == sizeof (setter)); ++ ++ m_getter = reinterpret_cast (getter); ++ m_setter = reinterpret_cast (setter); + } + ++ /* Access the type of the current setting. */ ++ var_types type () const ++ { return m_var_type; } ++ + /* Return the current value. + + The template parameter T is the type of the variable used to store the +@@ -239,13 +290,23 @@ struct setting + gdb_assert (var_type_uses (m_var_type)); + gdb_assert (m_var != nullptr); + +- return *static_cast (m_var); ++ if (m_var == nullptr) ++ { ++ gdb_assert (m_getter != nullptr); ++ auto getter = reinterpret_cast> (m_getter); ++ return getter (); ++ } ++ else ++ return *static_cast (m_var); + } + + /* Sets the value of the setting to V. + +- The template parameter T indicates the type of the variable used to +- store the setting. ++ If we have a user-provided setter, use it to set the setting. Otherwise ++ copy the value V to the internally referenced buffer. ++ ++ The template parameter T indicates the type of the variable used to store ++ the setting. + + The var_type of the setting must match T. */ + template +@@ -255,16 +316,32 @@ struct setting + this instantiation. */ + gdb_assert (var_type_uses (m_var_type)); + +- *static_cast (m_var) = v; ++ if (m_var == nullptr) ++ { ++ gdb_assert (m_setter != nullptr); ++ auto setter = reinterpret_cast> (m_setter); ++ setter (v); ++ } ++ else ++ *static_cast (m_var) = v; + } + + private: +- /* The type of the variable M_VAR is pointing to. */ ++ /* The type of the variable M_VAR is pointing to, or that M_GETTER / M_SETTER ++ get or set. */ + var_types m_var_type; + +- /* Pointer to the enclosed variable. The type of the variable is encoded +- in M_VAR_TYPE. */ +- void *m_var; ++ /* Pointer to the enclosed variable ++ ++ Either M_VAR is non-nullptr, or both M_GETTER and M_SETTER are ++ non-nullptr. */ ++ void *m_var = nullptr; ++ ++ /* Pointer to a user provided getter. */ ++ erased_func m_getter = nullptr; ++ ++ /* Pointer to a user provided setter. */ ++ erased_func m_setter = nullptr; + }; + + /* This structure records one command'd definition. */ +@@ -548,72 +625,159 @@ extern set_show_commands add_setshow_enum_cmd + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_enum_cmd ++ (const char *name, command_class theclass, const char *const *enumlist, ++ const char *set_doc, const char *show_doc, ++ const char *help_doc, setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_auto_boolean_cmd + (const char *name, command_class theclass, auto_boolean *var, + const char *set_doc, const char *show_doc, const char *help_doc, + cmd_func_ftype *set_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + ++extern set_show_commands add_setshow_auto_boolean_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, cmd_list_element **set_list, ++ cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_boolean_cmd + (const char *name, command_class theclass, bool *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_boolean_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_filename_cmd + (const char *name, command_class theclass, std::string *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_filename_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_string_cmd + (const char *name, command_class theclass, std::string *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_string_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, cmd_list_element **set_list, ++ cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_string_noescape_cmd + (const char *name, command_class theclass, std::string *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_string_noescape_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_optional_filename_cmd + (const char *name, command_class theclass, std::string *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_optional_filename_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, ++ show_value_ftype *show_func, cmd_list_element **set_list, ++ cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_integer_cmd + (const char *name, command_class theclass, int *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_integer_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_uinteger_cmd + (const char *name, command_class theclass, unsigned int *var, + const char *set_doc, const char *show_doc, const char *help_doc, + cmd_func_ftype *set_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + ++extern set_show_commands add_setshow_uinteger_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_zinteger_cmd + (const char *name, command_class theclass, int *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_zinteger_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_zuinteger_cmd + (const char *name, command_class theclass, unsigned int *var, + const char *set_doc, const char *show_doc, const char *help_doc, + cmd_func_ftype *set_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + ++extern set_show_commands add_setshow_zuinteger_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, ++ setting_getter_ftype get_func, show_value_ftype *show_func, ++ cmd_list_element **set_list, cmd_list_element **show_list); ++ + extern set_show_commands add_setshow_zuinteger_unlimited_cmd + (const char *name, command_class theclass, int *var, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + ++extern set_show_commands add_setshow_zuinteger_unlimited_cmd ++ (const char *name, command_class theclass, const char *set_doc, ++ const char *show_doc, const char *help_doc, ++ setting_setter_ftype set_func, setting_getter_ftype get_func, ++ show_value_ftype *show_func, cmd_list_element **set_list, ++ cmd_list_element **show_list); ++ + /* Do a "show" command for each thing on a command list. */ + + extern void cmd_show_list (struct cmd_list_element *, int); +-- +2.33.1 + diff --git a/gdb.spec b/gdb.spec index fd17bf5..2c90d04 100644 --- a/gdb.spec +++ b/gdb.spec @@ -1144,6 +1144,10 @@ fi %changelog * Fri Nov 10 2021 Alexandra Hájková - 11.1-6 +- Backport upstream patch "gdb: Have setter and getter callbacks for settings" + (RHBZ 2024875, Lancelot SIX). + +* Fri Nov 10 2021 Alexandra Hájková - 11.1-6 - Backport upstream patch "gdb: make string-like set show commands use std::string variable" (RHBZ 2024875, Simon Marchi).