[v5,1/5] gdb: make gdbarch store a vector of frame unwinders
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
From: Guinevere Larsen <blarsen@redhat.com>
Before this commit, all frame unwinders would be stored in the obstack
of a gdbarch and accessed by using the registry system. This made for
unwieldy code, and unnecessarily complex logic in the frame_unwinder
implementation, along with making frame_unwind structs be unable to have
non-trivial destructors.
Seeing as a future patch of this series wants to refactor the
frame_unwind struct to use inheritance, and we'd like to not restrict
the future derived classes on what destructors are allowed. In
preparation for that change, this commit adds an std::vector to gdbarch
to store the unwinders in.
There should be no user-visible changes.
---
gdb/arch-utils.c | 8 ++++
gdb/frame-unwind.c | 113 +++++++++++++++++----------------------------
gdb/gdbarch-gen.c | 6 +++
gdb/gdbarch.h | 5 ++
gdb/gdbarch.py | 6 +++
5 files changed, 67 insertions(+), 71 deletions(-)
Comments
Hello Guinevere,
Just a couple of nits. Regardless:
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Guinevere Larsen <guinevere@redhat.com> writes:
> diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
> index e5f108d3257..b69ae8596a2 100644
> --- a/gdb/frame-unwind.c
> +++ b/gdb/frame-unwind.c
> @@ -31,62 +31,46 @@
> #include "cli/cli-cmds.h"
> #include "inferior.h"
>
> -struct frame_unwind_table_entry
> +/* Default sniffers, that must always be the first in the unwinder list,
> + no matter the architecture. */
> +static constexpr auto standard_unwinders =
> {
> - const struct frame_unwind *unwinder;
> - struct frame_unwind_table_entry *next;
> -};
> + &dummy_frame_unwind,
> + /* The DWARF tailcall sniffer must come before the inline sniffer.
> + Otherwise, we can end up in a situation where a DWARF frame finds
> + tailcall information, but then the inline sniffer claims a frame
> + before the tailcall sniffer, resulting in confusion. This is
> + safe to do always because the tailcall sniffer can only ever be
> + activated if the newer frame was created using the DWARF
> + unwinder, and it also found tailcall information. */
> + &dwarf2_tailcall_frame_unwind,
> + &inline_frame_unwind,
>
Nit: this empty line should be removed.
> -struct frame_unwind_table
> -{
> - struct frame_unwind_table_entry *list = nullptr;
> - /* The head of the OSABI part of the search list. */
> - struct frame_unwind_table_entry **osabi_head = nullptr;
> };
> @@ -355,11 +327,10 @@ maintenance_info_frame_unwinders (const char *args, int from_tty)
> uiout->table_header (25, ui_left, "type", "Type");
> uiout->table_body ();
>
> - for (struct frame_unwind_table_entry *entry = table->list; entry != NULL;
> - entry = entry->next)
> + for (auto unwinder : table)
> {
> - const char *name = entry->unwinder->name;
> - const char *type = frame_type_str (entry->unwinder->type);
> + const char *name = unwinder->name;
> + const char *type = frame_type_str (unwinder->type);
Did you try getting rid of the local vars here, as Simon suggested?
I agree with him that seem unnecessary.
> ui_out_emit_list tuple_emitter (uiout, nullptr);
> uiout->field_string ("name", name);
On 10/1/24 2:42 PM, Guinevere Larsen wrote:
> From: Guinevere Larsen <blarsen@redhat.com>
>
> Before this commit, all frame unwinders would be stored in the obstack
> of a gdbarch and accessed by using the registry system. This made for
> unwieldy code, and unnecessarily complex logic in the frame_unwinder
> implementation, along with making frame_unwind structs be unable to have
> non-trivial destructors.
>
> Seeing as a future patch of this series wants to refactor the
> frame_unwind struct to use inheritance, and we'd like to not restrict
> the future derived classes on what destructors are allowed. In
> preparation for that change, this commit adds an std::vector to gdbarch
> to store the unwinders in.
>
> There should be no user-visible changes.
Just some nits, but with those addressed:
Approved-By: Simon Marchi <simon.marchi@efficios.com>
> ---
> gdb/arch-utils.c | 8 ++++
> gdb/frame-unwind.c | 113 +++++++++++++++++----------------------------
> gdb/gdbarch-gen.c | 6 +++
> gdb/gdbarch.h | 5 ++
> gdb/gdbarch.py | 6 +++
> 5 files changed, 67 insertions(+), 71 deletions(-)
>
> diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
> index 6ffa4109765..5a4ed097321 100644
> --- a/gdb/arch-utils.c
> +++ b/gdb/arch-utils.c
> @@ -1225,6 +1225,14 @@ obstack *gdbarch_obstack (gdbarch *arch)
>
> /* See gdbarch.h. */
>
> +std::vector<const frame_unwind *> &
> +gdbarch_unwinder_list (struct gdbarch *arch)
> +{
> + return arch->unwinders;
> +}
> +
> +/* See gdbarch.h. */
> +
> char *
> gdbarch_obstack_strdup (struct gdbarch *arch, const char *string)
> {
> diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
> index e5f108d3257..b69ae8596a2 100644
> --- a/gdb/frame-unwind.c
> +++ b/gdb/frame-unwind.c
> @@ -31,62 +31,46 @@
> #include "cli/cli-cmds.h"
> #include "inferior.h"
>
> -struct frame_unwind_table_entry
> +/* Default sniffers, that must always be the first in the unwinder list,
> + no matter the architecture. */
> +static constexpr auto standard_unwinders =
> {
> - const struct frame_unwind *unwinder;
> - struct frame_unwind_table_entry *next;
> -};
> + &dummy_frame_unwind,
> + /* The DWARF tailcall sniffer must come before the inline sniffer.
> + Otherwise, we can end up in a situation where a DWARF frame finds
> + tailcall information, but then the inline sniffer claims a frame
> + before the tailcall sniffer, resulting in confusion. This is
> + safe to do always because the tailcall sniffer can only ever be
> + activated if the newer frame was created using the DWARF
> + unwinder, and it also found tailcall information. */
> + &dwarf2_tailcall_frame_unwind,
> + &inline_frame_unwind,
>
> -struct frame_unwind_table
> -{
> - struct frame_unwind_table_entry *list = nullptr;
> - /* The head of the OSABI part of the search list. */
> - struct frame_unwind_table_entry **osabi_head = nullptr;
> };
>
> -static const registry<gdbarch>::key<struct frame_unwind_table>
> - frame_unwind_data;
> +/* If an unwinder should be prepended to the list, this is the
> + index in which it should be inserted. */
> +static constexpr int prepend_unwinder_index = standard_unwinders.size ();
>
> -/* A helper function to add an unwinder to a list. LINK says where to
> - install the new unwinder. The new link is returned. */
> -
> -static struct frame_unwind_table_entry **
> -add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder,
> - struct frame_unwind_table_entry **link)
> +/* Start the table out with a few default sniffers. OSABI code
> + can't override this. */
> +static void
> +initialize_frame_unwind_table (std::vector<const frame_unwind *>& table)
> {
> - *link = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
> - (*link)->unwinder = unwinder;
> - return &(*link)->next;
> + gdb_assert (table.empty ());
> +
> + table.insert(table.begin (), standard_unwinders.begin (), standard_unwinders.end ());
Line a bit too long and missing space.
> }
>
> -static struct frame_unwind_table *
> +/* This function call retrieves the list of frame unwinders available in
> + GDBARCH. If this list is empty, it is initialized before being
> + returned. */
For brevity, I think you should remove "This function call", just start
with "Retrieve" or "Retrieves", depending of which school you are.
> +static std::vector<const frame_unwind *> &
> get_frame_unwind_table (struct gdbarch *gdbarch)
> {
> - struct frame_unwind_table *table = frame_unwind_data.get (gdbarch);
> - if (table != nullptr)
> - return table;
> -
> - table = new frame_unwind_table;
> -
> - /* Start the table out with a few default sniffers. OSABI code
> - can't override this. */
> - struct frame_unwind_table_entry **link = &table->list;
> -
> - struct obstack *obstack = gdbarch_obstack (gdbarch);
> - link = add_unwinder (obstack, &dummy_frame_unwind, link);
> - /* The DWARF tailcall sniffer must come before the inline sniffer.
> - Otherwise, we can end up in a situation where a DWARF frame finds
> - tailcall information, but then the inline sniffer claims a frame
> - before the tailcall sniffer, resulting in confusion. This is
> - safe to do always because the tailcall sniffer can only ever be
> - activated if the newer frame was created using the DWARF
> - unwinder, and it also found tailcall information. */
> - link = add_unwinder (obstack, &dwarf2_tailcall_frame_unwind, link);
> - link = add_unwinder (obstack, &inline_frame_unwind, link);
> -
> - /* The insertion point for OSABI sniffers. */
> - table->osabi_head = link;
> - frame_unwind_data.set (gdbarch, table);
> + std::vector<const frame_unwind *> &table = gdbarch_unwinder_list (gdbarch);
> + if (table.size () == 0)
table.empty ()
Simon
>>>>> "Guinevere" == Guinevere Larsen <guinevere@redhat.com> writes:
Guinevere> Seeing as a future patch of this series wants to refactor the
Guinevere> frame_unwind struct to use inheritance, and we'd like to not restrict
Guinevere> the future derived classes on what destructors are allowed. In
Guinevere> preparation for that change, this commit adds an std::vector to gdbarch
Guinevere> to store the unwinders in.
Using a vector is fine, but I still think that this approach
makes gdbarch mildly less opaque. That is, now code anywhere can modify
the unwinder list in any way; whereas currently this is constrained to
the interface provided by frame-unwind.c.
Tom
Thanks for the review!
On 10/2/24 6:49 PM, Thiago Jung Bauermann wrote:
>> @@ -355,11 +327,10 @@ maintenance_info_frame_unwinders (const char *args, int from_tty)
>> uiout->table_header (25, ui_left, "type", "Type");
>> uiout->table_body ();
>>
>> - for (struct frame_unwind_table_entry *entry = table->list; entry != NULL;
>> - entry = entry->next)
>> + for (auto unwinder : table)
>> {
>> - const char *name = entry->unwinder->name;
>> - const char *type = frame_type_str (entry->unwinder->type);
>> + const char *name = unwinder->name;
>> + const char *type = frame_type_str (unwinder->type);
> Did you try getting rid of the local vars here, as Simon suggested?
> I agree with him that seem unnecessary.
I must have overlooked Simon's original suggestion. Considering he has
approved with minor nits fixed, I'll send a follow up patch removing
these, once this is merged.
Hello,
Tom Tromey <tom@tromey.com> writes:
>>>>>> "Guinevere" == Guinevere Larsen <guinevere@redhat.com> writes:
>
> Guinevere> Seeing as a future patch of this series wants to refactor the
> Guinevere> frame_unwind struct to use inheritance, and we'd like to not restrict
> Guinevere> the future derived classes on what destructors are allowed. In
> Guinevere> preparation for that change, this commit adds an std::vector to gdbarch
> Guinevere> to store the unwinders in.
>
> Using a vector is fine, but I still think that this approach
> makes gdbarch mildly less opaque. That is, now code anywhere can modify
> the unwinder list in any way; whereas currently this is constrained to
> the interface provided by frame-unwind.c.
Do you think it would be better if the vector was kept in a registry,
like the current frame_unwind_table is? I.e, changing:
static const registry<gdbarch>::key<struct frame_unwind_table>
frame_unwind_data;
to:
static const registry<gdbarch>::key<std::vector<const frame_unwind *>>
frame_unwind_data;
?
On 10/11/24 10:34 PM, Thiago Jung Bauermann wrote:
> Hello,
>
> Tom Tromey <tom@tromey.com> writes:
>
>>>>>>> "Guinevere" == Guinevere Larsen <guinevere@redhat.com> writes:
>> Guinevere> Seeing as a future patch of this series wants to refactor the
>> Guinevere> frame_unwind struct to use inheritance, and we'd like to not restrict
>> Guinevere> the future derived classes on what destructors are allowed. In
>> Guinevere> preparation for that change, this commit adds an std::vector to gdbarch
>> Guinevere> to store the unwinders in.
>>
>> Using a vector is fine, but I still think that this approach
>> makes gdbarch mildly less opaque. That is, now code anywhere can modify
>> the unwinder list in any way; whereas currently this is constrained to
>> the interface provided by frame-unwind.c.
> Do you think it would be better if the vector was kept in a registry,
> like the current frame_unwind_table is? I.e, changing:
>
> static const registry<gdbarch>::key<struct frame_unwind_table>
> frame_unwind_data;
>
> to:
>
> static const registry<gdbarch>::key<std::vector<const frame_unwind *>>
> frame_unwind_data;
>
> ?
>
I am not a big fan of the registry subsystem, so I would prefer to keep
it as a simple vector. However, if you are concerned about the
opaqueness change, Tromey, I can try to make it more opaque. I just
personally find that registry tends to make the code too opaque for
programmers as well as the program itself :-)
So if you want more separation, I would personally prefer to look into
only receiving a copy of the unwinder list, and gdbarch is responsible
for adding and removing things. Just let me know and I can give it a shot
Guinevere> I am not a big fan of the registry subsystem, so I would prefer to
Guinevere> keep it as a simple vector. However, if you are concerned about the
Guinevere> opaqueness change, Tromey, I can try to make it more opaque. I just
Guinevere> personally find that registry tends to make the code too opaque for
Guinevere> programmers as well as the program itself :-)
I think gdbarch is exposed to a lot of tdep code, and this code in
particular to do questionable things. So, preserving some opacity makes
sense to me.
Guinevere> So if you want more separation, I would personally prefer to look into
Guinevere> only receiving a copy of the unwinder list, and gdbarch is responsible
Guinevere> for adding and removing things. Just let me know and I can give it a
Guinevere> shot
I think it would be more worthwhile to understand your objections to the
registry. It seems to me that switching back to using it is just a
couple of lines of code, so it makes me think there must be some pretty
strong reason.
Tom
>>>>> "Thiago" == Thiago Jung Bauermann <thiago.bauermann@linaro.org> writes:
Sorry, didn't see this until now.
Thiago> Do you think it would be better if the vector was kept in a registry,
Thiago> like the current frame_unwind_table is? I.e, changing:
Thiago> static const registry<gdbarch>::key<struct frame_unwind_table>
Thiago> frame_unwind_data;
Thiago> to:
Thiago> static const registry<gdbarch>::key<std::vector<const frame_unwind *>>
Thiago> frame_unwind_data;
Thiago> ?
I tend to think so yes.
Tom
On 10/17/24 7:53 PM, Tom Tromey wrote:
> Guinevere> I am not a big fan of the registry subsystem, so I would prefer to
> Guinevere> keep it as a simple vector. However, if you are concerned about the
> Guinevere> opaqueness change, Tromey, I can try to make it more opaque. I just
> Guinevere> personally find that registry tends to make the code too opaque for
> Guinevere> programmers as well as the program itself :-)
>
> I think gdbarch is exposed to a lot of tdep code, and this code in
> particular to do questionable things. So, preserving some opacity makes
> sense to me.
Understandable. It didn't sound like you were that worried about it
previously, apologies for seemingly ignoring this feedback
>
> Guinevere> So if you want more separation, I would personally prefer to look into
> Guinevere> only receiving a copy of the unwinder list, and gdbarch is responsible
> Guinevere> for adding and removing things. Just let me know and I can give it a
> Guinevere> shot
>
> I think it would be more worthwhile to understand your objections to the
> registry. It seems to me that switching back to using it is just a
> couple of lines of code, so it makes me think there must be some pretty
> strong reason.
My main objection is in the form of "this feels like the type of magic
you don't want on the project". It feels like some very complicated
arcane code that causes things to seem much more complicated for new
contributors. I understand it is important in some cases, but in here it
seemed to me like making a registry that stores a standard library class
was just obfuscating the code for little gain.
I would propose that instead, the getter for the vector returns a const
reference (asserts if it is called before initialization). gdbarch would
then provide a "initialize_unwinders" method and a "add_unwinder"
method, but those should only be called by frame-unwind.c (and that
would be explicitly called out in the comments of those functions). This
follows a bit more the traditional object orientation route for handling
opaqueness, I believe, which would make it slightly easier to have new
contributors up to speed.
I know this isn't the strongets, so I understand if you want me to keep
the registry stuff.
@@ -1225,6 +1225,14 @@ obstack *gdbarch_obstack (gdbarch *arch)
/* See gdbarch.h. */
+std::vector<const frame_unwind *> &
+gdbarch_unwinder_list (struct gdbarch *arch)
+{
+ return arch->unwinders;
+}
+
+/* See gdbarch.h. */
+
char *
gdbarch_obstack_strdup (struct gdbarch *arch, const char *string)
{
@@ -31,62 +31,46 @@
#include "cli/cli-cmds.h"
#include "inferior.h"
-struct frame_unwind_table_entry
+/* Default sniffers, that must always be the first in the unwinder list,
+ no matter the architecture. */
+static constexpr auto standard_unwinders =
{
- const struct frame_unwind *unwinder;
- struct frame_unwind_table_entry *next;
-};
+ &dummy_frame_unwind,
+ /* The DWARF tailcall sniffer must come before the inline sniffer.
+ Otherwise, we can end up in a situation where a DWARF frame finds
+ tailcall information, but then the inline sniffer claims a frame
+ before the tailcall sniffer, resulting in confusion. This is
+ safe to do always because the tailcall sniffer can only ever be
+ activated if the newer frame was created using the DWARF
+ unwinder, and it also found tailcall information. */
+ &dwarf2_tailcall_frame_unwind,
+ &inline_frame_unwind,
-struct frame_unwind_table
-{
- struct frame_unwind_table_entry *list = nullptr;
- /* The head of the OSABI part of the search list. */
- struct frame_unwind_table_entry **osabi_head = nullptr;
};
-static const registry<gdbarch>::key<struct frame_unwind_table>
- frame_unwind_data;
+/* If an unwinder should be prepended to the list, this is the
+ index in which it should be inserted. */
+static constexpr int prepend_unwinder_index = standard_unwinders.size ();
-/* A helper function to add an unwinder to a list. LINK says where to
- install the new unwinder. The new link is returned. */
-
-static struct frame_unwind_table_entry **
-add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder,
- struct frame_unwind_table_entry **link)
+/* Start the table out with a few default sniffers. OSABI code
+ can't override this. */
+static void
+initialize_frame_unwind_table (std::vector<const frame_unwind *>& table)
{
- *link = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
- (*link)->unwinder = unwinder;
- return &(*link)->next;
+ gdb_assert (table.empty ());
+
+ table.insert(table.begin (), standard_unwinders.begin (), standard_unwinders.end ());
}
-static struct frame_unwind_table *
+/* This function call retrieves the list of frame unwinders available in
+ GDBARCH. If this list is empty, it is initialized before being
+ returned. */
+static std::vector<const frame_unwind *> &
get_frame_unwind_table (struct gdbarch *gdbarch)
{
- struct frame_unwind_table *table = frame_unwind_data.get (gdbarch);
- if (table != nullptr)
- return table;
-
- table = new frame_unwind_table;
-
- /* Start the table out with a few default sniffers. OSABI code
- can't override this. */
- struct frame_unwind_table_entry **link = &table->list;
-
- struct obstack *obstack = gdbarch_obstack (gdbarch);
- link = add_unwinder (obstack, &dummy_frame_unwind, link);
- /* The DWARF tailcall sniffer must come before the inline sniffer.
- Otherwise, we can end up in a situation where a DWARF frame finds
- tailcall information, but then the inline sniffer claims a frame
- before the tailcall sniffer, resulting in confusion. This is
- safe to do always because the tailcall sniffer can only ever be
- activated if the newer frame was created using the DWARF
- unwinder, and it also found tailcall information. */
- link = add_unwinder (obstack, &dwarf2_tailcall_frame_unwind, link);
- link = add_unwinder (obstack, &inline_frame_unwind, link);
-
- /* The insertion point for OSABI sniffers. */
- table->osabi_head = link;
- frame_unwind_data.set (gdbarch, table);
+ std::vector<const frame_unwind *> &table = gdbarch_unwinder_list (gdbarch);
+ if (table.size () == 0)
+ initialize_frame_unwind_table (table);
return table;
}
@@ -95,27 +79,16 @@ void
frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
const struct frame_unwind *unwinder)
{
- struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
- struct frame_unwind_table_entry *entry;
-
- /* Insert the new entry at the start of the list. */
- entry = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
- entry->unwinder = unwinder;
- entry->next = (*table->osabi_head);
- (*table->osabi_head) = entry;
+ std::vector<const frame_unwind *> &table = get_frame_unwind_table (gdbarch);
+
+ table.insert (table.begin () + prepend_unwinder_index, unwinder);
}
void
frame_unwind_append_unwinder (struct gdbarch *gdbarch,
const struct frame_unwind *unwinder)
{
- struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
- struct frame_unwind_table_entry **ip;
-
- /* Find the end of the list and insert the new entry there. */
- for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next);
- (*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
- (*ip)->unwinder = unwinder;
+ get_frame_unwind_table (gdbarch).push_back (unwinder);
}
/* Call SNIFFER from UNWINDER. If it succeeded set UNWINDER for
@@ -188,9 +161,6 @@ 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));
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
- struct frame_unwind_table_entry *entry;
const struct frame_unwind *unwinder_from_target;
unwinder_from_target = target_get_unwinder ();
@@ -205,8 +175,10 @@ frame_unwind_find_by_frame (const frame_info_ptr &this_frame, void **this_cache)
unwinder_from_target))
return;
- for (entry = table->list; entry != NULL; entry = entry->next)
- if (frame_unwind_try_unwinder (this_frame, this_cache, entry->unwinder))
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ std::vector<const frame_unwind *> &table = get_frame_unwind_table (gdbarch);
+ for (auto unwinder : table)
+ if (frame_unwind_try_unwinder (this_frame, this_cache, unwinder))
return;
internal_error (_("frame_unwind_find_by_frame failed"));
@@ -347,7 +319,7 @@ static void
maintenance_info_frame_unwinders (const char *args, int from_tty)
{
gdbarch *gdbarch = current_inferior ()->arch ();
- struct frame_unwind_table *table = get_frame_unwind_table (gdbarch);
+ 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");
@@ -355,11 +327,10 @@ maintenance_info_frame_unwinders (const char *args, int from_tty)
uiout->table_header (25, ui_left, "type", "Type");
uiout->table_body ();
- for (struct frame_unwind_table_entry *entry = table->list; entry != NULL;
- entry = entry->next)
+ for (auto unwinder : table)
{
- const char *name = entry->unwinder->name;
- const char *type = frame_type_str (entry->unwinder->type);
+ const char *name = unwinder->name;
+ const char *type = frame_type_str (unwinder->type);
ui_out_emit_list tuple_emitter (uiout, nullptr);
uiout->field_string ("name", name);
@@ -27,6 +27,8 @@
/* Maintain the struct gdbarch object. */
+#include <vector>
+
struct gdbarch
{
/* Has this architecture been fully initialized? */
@@ -34,9 +36,13 @@ struct gdbarch
/* An obstack bound to the lifetime of the architecture. */
auto_obstack obstack;
+
/* Registry. */
registry<gdbarch> registry_fields;
+ /* List of frame unwinders. */
+ std::vector<const frame_unwind *> unwinders;
+
/* basic architectural information. */
const struct bfd_arch_info * bfd_arch_info;
enum bfd_endian byte_order;
@@ -30,6 +30,7 @@
#include "displaced-stepping.h"
#include "gdbsupport/gdb-checked-static-cast.h"
#include "registry.h"
+#include "frame-unwind.h"
struct floatformat;
struct ui_file;
@@ -310,6 +311,10 @@ extern obstack *gdbarch_obstack (gdbarch *arch);
#define GDBARCH_OBSTACK_ZALLOC(GDBARCH, TYPE) obstack_zalloc<TYPE> (gdbarch_obstack ((GDBARCH)))
+/* Return the vector of unwinders stored in a gdbarch object. */
+
+std::vector<const frame_unwind*> &gdbarch_unwinder_list (struct gdbarch *arch);
+
/* Duplicate STRING, returning an equivalent string that's allocated on the
obstack associated with GDBARCH. The string is freed when the corresponding
architecture is also freed. */
@@ -125,6 +125,8 @@ with open("gdbarch-gen.c", "w") as f:
print(file=f)
print("/* Maintain the struct gdbarch object. */", file=f)
print(file=f)
+ print("#include <vector>", file=f)
+ print(file=f)
#
# The struct definition body.
#
@@ -135,9 +137,13 @@ with open("gdbarch-gen.c", "w") as f:
print(file=f)
print(" /* An obstack bound to the lifetime of the architecture. */", file=f)
print(" auto_obstack obstack;", file=f)
+ print(file=f)
print(" /* Registry. */", file=f)
print(" registry<gdbarch> registry_fields;", file=f)
print(file=f)
+ print(" /* List of frame unwinders. */", file=f)
+ print(" std::vector<const frame_unwind *> unwinders;", file=f)
+ print(file=f)
print(" /* basic architectural information. */", file=f)
for c in filter(info, components):
print(f" {c.type} {c.name};", file=f)