1 /* Register groupings for GDB, the GNU debugger. 2 3 Copyright (C) 2002-2023 Free Software Foundation, Inc. 4 5 Contributed by Red Hat. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 #include "defs.h" 23 #include "arch-utils.h" 24 #include "reggroups.h" 25 #include "gdbtypes.h" 26 #include "regcache.h" 27 #include "command.h" 28 #include "gdbcmd.h" /* For maintenanceprintlist. */ 29 #include "gdbsupport/gdb_obstack.h" 30 31 /* See reggroups.h. */ 32 33 const reggroup * 34 reggroup_new (const char *name, enum reggroup_type type) 35 { 36 return new reggroup (name, type); 37 } 38 39 /* See reggroups.h. */ 40 41 const reggroup * 42 reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name, 43 enum reggroup_type type) 44 { 45 name = gdbarch_obstack_strdup (gdbarch, name); 46 return obstack_new<struct reggroup> (gdbarch_obstack (gdbarch), 47 name, type); 48 } 49 50 /* A container holding all the register groups for a particular 51 architecture. */ 52 53 struct reggroups 54 { 55 reggroups () 56 { 57 /* Add the default groups. */ 58 add (general_reggroup); 59 add (float_reggroup); 60 add (system_reggroup); 61 add (vector_reggroup); 62 add (all_reggroup); 63 add (save_reggroup); 64 add (restore_reggroup); 65 } 66 67 DISABLE_COPY_AND_ASSIGN (reggroups); 68 69 /* Add GROUP to the list of register groups. */ 70 71 void add (const reggroup *group) 72 { 73 gdb_assert (group != nullptr); 74 75 auto find_by_name = [group] (const reggroup *g) 76 { 77 return streq (group->name (), g->name ()); 78 }; 79 gdb_assert (std::find_if (m_groups.begin (), m_groups.end (), find_by_name) 80 == m_groups.end ()); 81 82 m_groups.push_back (group); 83 } 84 85 /* The number of register groups. */ 86 87 std::vector<struct reggroup *>::size_type 88 size () const 89 { 90 return m_groups.size (); 91 } 92 93 /* Return a reference to the list of all groups. */ 94 95 const std::vector<const struct reggroup *> & 96 groups () const 97 { 98 return m_groups; 99 } 100 101 private: 102 /* The register groups. */ 103 std::vector<const struct reggroup *> m_groups; 104 }; 105 106 /* Key used to lookup register group data from a gdbarch. */ 107 108 static const registry<gdbarch>::key<reggroups> reggroups_data; 109 110 /* Get the reggroups for the architecture, creating if necessary. */ 111 112 static reggroups * 113 get_reggroups (struct gdbarch *gdbarch) 114 { 115 struct reggroups *groups = reggroups_data.get (gdbarch); 116 if (groups == nullptr) 117 groups = reggroups_data.emplace (gdbarch); 118 return groups; 119 } 120 121 /* See reggroups.h. */ 122 123 void 124 reggroup_add (struct gdbarch *gdbarch, const reggroup *group) 125 { 126 struct reggroups *groups = get_reggroups (gdbarch); 127 128 gdb_assert (groups != nullptr); 129 gdb_assert (group != nullptr); 130 131 groups->add (group); 132 } 133 134 /* See reggroups.h. */ 135 const std::vector<const reggroup *> & 136 gdbarch_reggroups (struct gdbarch *gdbarch) 137 { 138 struct reggroups *groups = get_reggroups (gdbarch); 139 gdb_assert (groups != nullptr); 140 gdb_assert (groups->size () > 0); 141 return groups->groups (); 142 } 143 144 /* See reggroups.h. */ 145 146 int 147 default_register_reggroup_p (struct gdbarch *gdbarch, int regnum, 148 const struct reggroup *group) 149 { 150 int vector_p; 151 int float_p; 152 int raw_p; 153 154 if (*gdbarch_register_name (gdbarch, regnum) == '\0') 155 return 0; 156 if (group == all_reggroup) 157 return 1; 158 vector_p = register_type (gdbarch, regnum)->is_vector (); 159 float_p = (register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT 160 || (register_type (gdbarch, regnum)->code () 161 == TYPE_CODE_DECFLOAT)); 162 raw_p = regnum < gdbarch_num_regs (gdbarch); 163 if (group == float_reggroup) 164 return float_p; 165 if (group == vector_reggroup) 166 return vector_p; 167 if (group == general_reggroup) 168 return (!vector_p && !float_p); 169 if (group == save_reggroup || group == restore_reggroup) 170 return raw_p; 171 return 0; 172 } 173 174 /* See reggroups.h. */ 175 176 const reggroup * 177 reggroup_find (struct gdbarch *gdbarch, const char *name) 178 { 179 for (const struct reggroup *group : gdbarch_reggroups (gdbarch)) 180 { 181 if (strcmp (name, group->name ()) == 0) 182 return group; 183 } 184 return NULL; 185 } 186 187 /* Dump out a table of register groups for the current architecture. */ 188 189 static void 190 reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file) 191 { 192 static constexpr const char *fmt = " %-10s %-10s\n"; 193 194 gdb_printf (file, fmt, "Group", "Type"); 195 196 for (const struct reggroup *group : gdbarch_reggroups (gdbarch)) 197 { 198 /* Group name. */ 199 const char *name = group->name (); 200 201 /* Group type. */ 202 const char *type; 203 204 switch (group->type ()) 205 { 206 case USER_REGGROUP: 207 type = "user"; 208 break; 209 case INTERNAL_REGGROUP: 210 type = "internal"; 211 break; 212 default: 213 internal_error (_("bad switch")); 214 } 215 216 /* Note: If you change this, be sure to also update the 217 documentation. */ 218 219 gdb_printf (file, fmt, name, type); 220 } 221 } 222 223 /* Implement 'maintenance print reggroups' command. */ 224 225 static void 226 maintenance_print_reggroups (const char *args, int from_tty) 227 { 228 struct gdbarch *gdbarch = get_current_arch (); 229 230 if (args == NULL) 231 reggroups_dump (gdbarch, gdb_stdout); 232 else 233 { 234 stdio_file file; 235 236 if (!file.open (args, "w")) 237 perror_with_name (_("maintenance print reggroups")); 238 reggroups_dump (gdbarch, &file); 239 } 240 } 241 242 /* Pre-defined register groups. */ 243 static const reggroup general_group = { "general", USER_REGGROUP }; 244 static const reggroup float_group = { "float", USER_REGGROUP }; 245 static const reggroup system_group = { "system", USER_REGGROUP }; 246 static const reggroup vector_group = { "vector", USER_REGGROUP }; 247 static const reggroup all_group = { "all", USER_REGGROUP }; 248 static const reggroup save_group = { "save", INTERNAL_REGGROUP }; 249 static const reggroup restore_group = { "restore", INTERNAL_REGGROUP }; 250 251 const reggroup *const general_reggroup = &general_group; 252 const reggroup *const float_reggroup = &float_group; 253 const reggroup *const system_reggroup = &system_group; 254 const reggroup *const vector_reggroup = &vector_group; 255 const reggroup *const all_reggroup = &all_group; 256 const reggroup *const save_reggroup = &save_group; 257 const reggroup *const restore_reggroup = &restore_group; 258 259 void _initialize_reggroup (); 260 void 261 _initialize_reggroup () 262 { 263 add_cmd ("reggroups", class_maintenance, 264 maintenance_print_reggroups, _("\ 265 Print the internal register group names.\n\ 266 Takes an optional file parameter."), 267 &maintenanceprintlist); 268 269 } 270