binutils-gdb/gdb/reggroups.c
Andrew Burgess e7d69e72bf gdb: always add the default register groups
There's a set of 7 default register groups.  If we don't add any
gdbarch specific register groups during gdbarch initialisation, then
when we iterate over the register groups using reggroup_next and
reggroup_prev we will make use of these 7 default groups.  See the use
of default_groups in gdb/reggroups.c for details on this.

However, if the gdbarch adds its own groups during gdbarch
initialisation, then these groups will be used in preference to the
default groups.

A problem arises though if the particular architecture makes use of
the target description mechanism.  If the default target
description(s) (i.e. those internal to GDB that are used when the user
doesn't provide their own) don't mention any additional register
groups then the default register groups will be used.

But if the target description does mention additional groups then the
default groups are not used, and instead, the groups from the target
description are used.

The problem with this is that what usually happens is that the target
description will mention additional groups, e.g. groups for special
registers.  Most architectures that use target descriptions work
around this by adding all (or most) of the default register groups in
all cases.  See i386_add_reggroups, aarch64_add_reggroups,
riscv_add_reggroups, xtensa_add_reggroups, and others.

In this patch, my suggestion is that we should just add the default
register groups for every architecture, always.  This change is in
gdb/reggroups.c.

All the remaining changes are me updating the various architectures to
not add the default groups themselves.

So, where will this change be visible to the user?  I think the
following commands will possibly change:

* info registers / info all-registers:

  The user can provide a register group to these commands.  For example,
  on csky, we previously never added the 'vector' group.  Now, as a
  default group, this will be available, but (presumably) will not
  contain any registers.  I don't think this is necessarily a bad
  thing, there's something to be said for having some consistent
  defaults available.  There are other architectures that didn't add
  all 7 of the defaults, which will now have gained additional groups.

* maint print reggroups

  This prints the set of all available groups.  As a maintenance
  command I'm less concerned with the output changing here.
  Obviously, for the architectures that didn't previously add all the
  defaults, this list just got bigger.

* maint print register-groups

  This prints all the registers, and the groups they are in.  If the
  defaults were not previously being added then a register (obviously)
  can't appear in one of the default groups.  Now the groups are
  available then registers might be in more groups than previously.
  However, this is again a maintenance command, so I'm less concerned
  about this changing.
2022-04-07 16:01:18 +01:00

355 lines
8.9 KiB
C

/* Register groupings for GDB, the GNU debugger.
Copyright (C) 2002-2022 Free Software Foundation, Inc.
Contributed by Red Hat.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
#include "reggroups.h"
#include "gdbtypes.h"
#include "regcache.h"
#include "command.h"
#include "gdbcmd.h" /* For maintenanceprintlist. */
#include "gdbsupport/gdb_obstack.h"
/* Individual register groups. */
struct reggroup
{
const char *name;
enum reggroup_type type;
};
struct reggroup *
reggroup_new (const char *name, enum reggroup_type type)
{
struct reggroup *group = XNEW (struct reggroup);
group->name = name;
group->type = type;
return group;
}
/* See reggroups.h. */
struct reggroup *
reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name,
enum reggroup_type type)
{
struct reggroup *group = GDBARCH_OBSTACK_ZALLOC (gdbarch,
struct reggroup);
group->name = gdbarch_obstack_strdup (gdbarch, name);
group->type = type;
return group;
}
/* Register group attributes. */
const char *
reggroup_name (const struct reggroup *group)
{
return group->name;
}
enum reggroup_type
reggroup_type (const struct reggroup *group)
{
return group->type;
}
/* A linked list of groups for the given architecture. */
struct reggroup_el
{
struct reggroup *group;
struct reggroup_el *next;
};
struct reggroups
{
struct reggroup_el *first;
struct reggroup_el **last;
};
static struct gdbarch_data *reggroups_data;
/* Add a register group (with attribute values) to the pre-defined
list. */
static void
add_group (struct reggroups *groups, struct reggroup *group,
struct reggroup_el *el)
{
gdb_assert (group != NULL);
el->group = group;
el->next = NULL;
(*groups->last) = el;
groups->last = &el->next;
}
void
reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
{
struct reggroups *groups
= (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
/* The same reggroup should not be added multiple times. */
gdb_assert (groups != nullptr);
for (struct reggroup_el *el = groups->first; el != nullptr; el = el->next)
gdb_assert (group != el->group);
add_group (groups, group,
GDBARCH_OBSTACK_ZALLOC (gdbarch, struct reggroup_el));
}
/* Called to initialize the per-gdbarch register group information. */
static void *
reggroups_init (struct obstack *obstack)
{
struct reggroups *groups = OBSTACK_ZALLOC (obstack, struct reggroups);
groups->last = &groups->first;
/* Add the default groups. */
add_group (groups, general_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, float_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, system_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, vector_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, all_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, save_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
add_group (groups, restore_reggroup,
OBSTACK_ZALLOC (obstack, struct reggroup_el));
return groups;
}
/* A register group iterator. */
struct reggroup *
reggroup_next (struct gdbarch *gdbarch, const struct reggroup *last)
{
struct reggroups *groups;
struct reggroup_el *el;
/* Don't allow this function to be called during architecture
creation. If there are no groups, use the default groups list. */
groups = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
gdb_assert (groups != NULL);
gdb_assert (groups->first != NULL);
/* Return the first/next reggroup. */
if (last == NULL)
return groups->first->group;
for (el = groups->first; el != NULL; el = el->next)
{
if (el->group == last)
{
if (el->next != NULL)
return el->next->group;
else
return NULL;
}
}
return NULL;
}
/* See reggroups.h. */
struct reggroup *
reggroup_prev (struct gdbarch *gdbarch, const struct reggroup *curr)
{
struct reggroups *groups;
struct reggroup_el *el;
struct reggroup *prev;
/* Don't allow this function to be called during architecture
creation. If there are no groups, use the default groups list. */
groups = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
gdb_assert (groups != NULL);
gdb_assert (groups->first != NULL);
prev = NULL;
for (el = groups->first; el != NULL; el = el->next)
{
gdb_assert (el->group != NULL);
if (el->group == curr)
return prev;
prev = el->group;
}
if (curr == NULL)
return prev;
return NULL;
}
/* Is REGNUM a member of REGGROUP? */
int
default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
const struct reggroup *group)
{
int vector_p;
int float_p;
int raw_p;
if (gdbarch_register_name (gdbarch, regnum) == NULL
|| *gdbarch_register_name (gdbarch, regnum) == '\0')
return 0;
if (group == all_reggroup)
return 1;
vector_p = register_type (gdbarch, regnum)->is_vector ();
float_p = (register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT
|| (register_type (gdbarch, regnum)->code ()
== TYPE_CODE_DECFLOAT));
raw_p = regnum < gdbarch_num_regs (gdbarch);
if (group == float_reggroup)
return float_p;
if (group == vector_reggroup)
return vector_p;
if (group == general_reggroup)
return (!vector_p && !float_p);
if (group == save_reggroup || group == restore_reggroup)
return raw_p;
return 0;
}
/* See reggroups.h. */
const reggroup *
reggroup_find (struct gdbarch *gdbarch, const char *name)
{
struct reggroup *group;
for (group = reggroup_next (gdbarch, NULL);
group != NULL;
group = reggroup_next (gdbarch, group))
{
if (strcmp (name, reggroup_name (group)) == 0)
return group;
}
return NULL;
}
/* Dump out a table of register groups for the current architecture. */
static void
reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
{
struct reggroup *group = NULL;
do
{
/* Group name. */
{
const char *name;
if (group == NULL)
name = "Group";
else
name = reggroup_name (group);
gdb_printf (file, " %-10s", name);
}
/* Group type. */
{
const char *type;
if (group == NULL)
type = "Type";
else
{
switch (reggroup_type (group))
{
case USER_REGGROUP:
type = "user";
break;
case INTERNAL_REGGROUP:
type = "internal";
break;
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
}
gdb_printf (file, " %-10s", type);
}
/* Note: If you change this, be sure to also update the
documentation. */
gdb_printf (file, "\n");
group = reggroup_next (gdbarch, group);
}
while (group != NULL);
}
static void
maintenance_print_reggroups (const char *args, int from_tty)
{
struct gdbarch *gdbarch = get_current_arch ();
if (args == NULL)
reggroups_dump (gdbarch, gdb_stdout);
else
{
stdio_file file;
if (!file.open (args, "w"))
perror_with_name (_("maintenance print reggroups"));
reggroups_dump (gdbarch, &file);
}
}
/* Pre-defined register groups. */
static struct reggroup general_group = { "general", USER_REGGROUP };
static struct reggroup float_group = { "float", USER_REGGROUP };
static struct reggroup system_group = { "system", USER_REGGROUP };
static struct reggroup vector_group = { "vector", USER_REGGROUP };
static struct reggroup all_group = { "all", USER_REGGROUP };
static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
struct reggroup *const general_reggroup = &general_group;
struct reggroup *const float_reggroup = &float_group;
struct reggroup *const system_reggroup = &system_group;
struct reggroup *const vector_reggroup = &vector_group;
struct reggroup *const all_reggroup = &all_group;
struct reggroup *const save_reggroup = &save_group;
struct reggroup *const restore_reggroup = &restore_group;
void _initialize_reggroup ();
void
_initialize_reggroup ()
{
reggroups_data = gdbarch_data_register_pre_init (reggroups_init);
add_cmd ("reggroups", class_maintenance,
maintenance_print_reggroups, _("\
Print the internal register group names.\n\
Takes an optional file parameter."),
&maintenanceprintlist);
}