15796c8dcSSimon Schubert /* User visible, per-frame registers, for GDB, the GNU debugger.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2002-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert Contributed by Red Hat.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This file is part of GDB.
85796c8dcSSimon Schubert
95796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert (at your option) any later version.
135796c8dcSSimon Schubert
145796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175796c8dcSSimon Schubert GNU General Public License for more details.
185796c8dcSSimon Schubert
195796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
215796c8dcSSimon Schubert
225796c8dcSSimon Schubert #include "defs.h"
235796c8dcSSimon Schubert #include "user-regs.h"
245796c8dcSSimon Schubert #include "gdbtypes.h"
255796c8dcSSimon Schubert #include "gdb_string.h"
265796c8dcSSimon Schubert #include "gdb_assert.h"
275796c8dcSSimon Schubert #include "frame.h"
285796c8dcSSimon Schubert
295796c8dcSSimon Schubert /* A table of user registers.
305796c8dcSSimon Schubert
315796c8dcSSimon Schubert User registers have regnum's that live above of the range [0
325796c8dcSSimon Schubert .. gdbarch_num_regs + gdbarch_num_pseudo_regs)
335796c8dcSSimon Schubert (which is controlled by the target).
345796c8dcSSimon Schubert The target should never see a user register's regnum value.
355796c8dcSSimon Schubert
365796c8dcSSimon Schubert Always append, never delete. By doing this, the relative regnum
375796c8dcSSimon Schubert (offset from gdbarch_num_regs + gdbarch_num_pseudo_regs)
385796c8dcSSimon Schubert assigned to each user register never changes. */
395796c8dcSSimon Schubert
405796c8dcSSimon Schubert struct user_reg
415796c8dcSSimon Schubert {
425796c8dcSSimon Schubert const char *name;
435796c8dcSSimon Schubert struct value *(*read) (struct frame_info * frame, const void *baton);
445796c8dcSSimon Schubert const void *baton;
455796c8dcSSimon Schubert struct user_reg *next;
465796c8dcSSimon Schubert };
475796c8dcSSimon Schubert
485796c8dcSSimon Schubert /* This structure is named gdb_user_regs instead of user_regs to avoid
495796c8dcSSimon Schubert conflicts with any "struct user_regs" in system headers. For instance,
505796c8dcSSimon Schubert on ARM GNU/Linux native builds, nm-linux.h includes <signal.h> includes
515796c8dcSSimon Schubert <sys/ucontext.h> includes <sys/procfs.h> includes <sys/user.h>, which
525796c8dcSSimon Schubert declares "struct user_regs". */
535796c8dcSSimon Schubert
545796c8dcSSimon Schubert struct gdb_user_regs
555796c8dcSSimon Schubert {
565796c8dcSSimon Schubert struct user_reg *first;
575796c8dcSSimon Schubert struct user_reg **last;
585796c8dcSSimon Schubert };
595796c8dcSSimon Schubert
605796c8dcSSimon Schubert static void
append_user_reg(struct gdb_user_regs * regs,const char * name,user_reg_read_ftype * read,const void * baton,struct user_reg * reg)615796c8dcSSimon Schubert append_user_reg (struct gdb_user_regs *regs, const char *name,
625796c8dcSSimon Schubert user_reg_read_ftype *read, const void *baton,
635796c8dcSSimon Schubert struct user_reg *reg)
645796c8dcSSimon Schubert {
655796c8dcSSimon Schubert /* The caller is responsible for allocating memory needed to store
665796c8dcSSimon Schubert the register. By doing this, the function can operate on a
675796c8dcSSimon Schubert register list stored in the common heap or a specific obstack. */
685796c8dcSSimon Schubert gdb_assert (reg != NULL);
695796c8dcSSimon Schubert reg->name = name;
705796c8dcSSimon Schubert reg->read = read;
715796c8dcSSimon Schubert reg->baton = baton;
725796c8dcSSimon Schubert reg->next = NULL;
735796c8dcSSimon Schubert (*regs->last) = reg;
745796c8dcSSimon Schubert regs->last = &(*regs->last)->next;
755796c8dcSSimon Schubert }
765796c8dcSSimon Schubert
775796c8dcSSimon Schubert /* An array of the builtin user registers. */
785796c8dcSSimon Schubert
79c50c785cSJohn Marino static struct gdb_user_regs builtin_user_regs = {
80c50c785cSJohn Marino NULL, &builtin_user_regs.first
81c50c785cSJohn Marino };
825796c8dcSSimon Schubert
835796c8dcSSimon Schubert void
user_reg_add_builtin(const char * name,user_reg_read_ftype * read,const void * baton)845796c8dcSSimon Schubert user_reg_add_builtin (const char *name, user_reg_read_ftype *read,
855796c8dcSSimon Schubert const void *baton)
865796c8dcSSimon Schubert {
875796c8dcSSimon Schubert append_user_reg (&builtin_user_regs, name, read, baton,
885796c8dcSSimon Schubert XMALLOC (struct user_reg));
895796c8dcSSimon Schubert }
905796c8dcSSimon Schubert
915796c8dcSSimon Schubert /* Per-architecture user registers. Start with the builtin user
925796c8dcSSimon Schubert registers and then, again, append. */
935796c8dcSSimon Schubert
945796c8dcSSimon Schubert static struct gdbarch_data *user_regs_data;
955796c8dcSSimon Schubert
965796c8dcSSimon Schubert static void *
user_regs_init(struct gdbarch * gdbarch)975796c8dcSSimon Schubert user_regs_init (struct gdbarch *gdbarch)
985796c8dcSSimon Schubert {
995796c8dcSSimon Schubert struct user_reg *reg;
100cf7f2e2dSJohn Marino struct gdb_user_regs *regs
101cf7f2e2dSJohn Marino = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct gdb_user_regs);
102cf7f2e2dSJohn Marino
1035796c8dcSSimon Schubert regs->last = ®s->first;
1045796c8dcSSimon Schubert for (reg = builtin_user_regs.first; reg != NULL; reg = reg->next)
1055796c8dcSSimon Schubert append_user_reg (regs, reg->name, reg->read, reg->baton,
1065796c8dcSSimon Schubert GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
1075796c8dcSSimon Schubert return regs;
1085796c8dcSSimon Schubert }
1095796c8dcSSimon Schubert
1105796c8dcSSimon Schubert void
user_reg_add(struct gdbarch * gdbarch,const char * name,user_reg_read_ftype * read,const void * baton)1115796c8dcSSimon Schubert user_reg_add (struct gdbarch *gdbarch, const char *name,
1125796c8dcSSimon Schubert user_reg_read_ftype *read, const void *baton)
1135796c8dcSSimon Schubert {
1145796c8dcSSimon Schubert struct gdb_user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
115cf7f2e2dSJohn Marino
1165796c8dcSSimon Schubert if (regs == NULL)
1175796c8dcSSimon Schubert {
1185796c8dcSSimon Schubert /* ULGH, called during architecture initialization. Patch
1195796c8dcSSimon Schubert things up. */
1205796c8dcSSimon Schubert regs = user_regs_init (gdbarch);
1215796c8dcSSimon Schubert deprecated_set_gdbarch_data (gdbarch, user_regs_data, regs);
1225796c8dcSSimon Schubert }
1235796c8dcSSimon Schubert append_user_reg (regs, name, read, baton,
1245796c8dcSSimon Schubert GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
1255796c8dcSSimon Schubert }
1265796c8dcSSimon Schubert
1275796c8dcSSimon Schubert int
user_reg_map_name_to_regnum(struct gdbarch * gdbarch,const char * name,int len)1285796c8dcSSimon Schubert user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
1295796c8dcSSimon Schubert int len)
1305796c8dcSSimon Schubert {
1315796c8dcSSimon Schubert /* Make life easy, set the len to something reasonable. */
1325796c8dcSSimon Schubert if (len < 0)
1335796c8dcSSimon Schubert len = strlen (name);
1345796c8dcSSimon Schubert
1355796c8dcSSimon Schubert /* Search register name space first - always let an architecture
1365796c8dcSSimon Schubert specific register override the user registers. */
1375796c8dcSSimon Schubert {
1385796c8dcSSimon Schubert int i;
1395796c8dcSSimon Schubert int maxregs = (gdbarch_num_regs (gdbarch)
1405796c8dcSSimon Schubert + gdbarch_num_pseudo_regs (gdbarch));
141cf7f2e2dSJohn Marino
1425796c8dcSSimon Schubert for (i = 0; i < maxregs; i++)
1435796c8dcSSimon Schubert {
1445796c8dcSSimon Schubert const char *regname = gdbarch_register_name (gdbarch, i);
145cf7f2e2dSJohn Marino
1465796c8dcSSimon Schubert if (regname != NULL && len == strlen (regname)
1475796c8dcSSimon Schubert && strncmp (regname, name, len) == 0)
1485796c8dcSSimon Schubert {
1495796c8dcSSimon Schubert return i;
1505796c8dcSSimon Schubert }
1515796c8dcSSimon Schubert }
1525796c8dcSSimon Schubert }
1535796c8dcSSimon Schubert
1545796c8dcSSimon Schubert /* Search the user name space. */
1555796c8dcSSimon Schubert {
1565796c8dcSSimon Schubert struct gdb_user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
1575796c8dcSSimon Schubert struct user_reg *reg;
1585796c8dcSSimon Schubert int nr;
159cf7f2e2dSJohn Marino
1605796c8dcSSimon Schubert for (nr = 0, reg = regs->first; reg != NULL; reg = reg->next, nr++)
1615796c8dcSSimon Schubert {
1625796c8dcSSimon Schubert if ((len < 0 && strcmp (reg->name, name))
1635796c8dcSSimon Schubert || (len == strlen (reg->name)
1645796c8dcSSimon Schubert && strncmp (reg->name, name, len) == 0))
1655796c8dcSSimon Schubert return gdbarch_num_regs (gdbarch)
1665796c8dcSSimon Schubert + gdbarch_num_pseudo_regs (gdbarch) + nr;
1675796c8dcSSimon Schubert }
1685796c8dcSSimon Schubert }
1695796c8dcSSimon Schubert
1705796c8dcSSimon Schubert return -1;
1715796c8dcSSimon Schubert }
1725796c8dcSSimon Schubert
1735796c8dcSSimon Schubert static struct user_reg *
usernum_to_user_reg(struct gdbarch * gdbarch,int usernum)1745796c8dcSSimon Schubert usernum_to_user_reg (struct gdbarch *gdbarch, int usernum)
1755796c8dcSSimon Schubert {
1765796c8dcSSimon Schubert struct gdb_user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
1775796c8dcSSimon Schubert struct user_reg *reg;
178cf7f2e2dSJohn Marino
1795796c8dcSSimon Schubert for (reg = regs->first; reg != NULL; reg = reg->next)
1805796c8dcSSimon Schubert {
1815796c8dcSSimon Schubert if (usernum == 0)
1825796c8dcSSimon Schubert return reg;
1835796c8dcSSimon Schubert usernum--;
1845796c8dcSSimon Schubert }
1855796c8dcSSimon Schubert return NULL;
1865796c8dcSSimon Schubert }
1875796c8dcSSimon Schubert
1885796c8dcSSimon Schubert const char *
user_reg_map_regnum_to_name(struct gdbarch * gdbarch,int regnum)1895796c8dcSSimon Schubert user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum)
1905796c8dcSSimon Schubert {
1915796c8dcSSimon Schubert int maxregs = (gdbarch_num_regs (gdbarch)
1925796c8dcSSimon Schubert + gdbarch_num_pseudo_regs (gdbarch));
193cf7f2e2dSJohn Marino
1945796c8dcSSimon Schubert if (regnum < 0)
1955796c8dcSSimon Schubert return NULL;
1965796c8dcSSimon Schubert else if (regnum < maxregs)
1975796c8dcSSimon Schubert return gdbarch_register_name (gdbarch, regnum);
1985796c8dcSSimon Schubert else
1995796c8dcSSimon Schubert {
2005796c8dcSSimon Schubert struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
2015796c8dcSSimon Schubert if (reg == NULL)
2025796c8dcSSimon Schubert return NULL;
2035796c8dcSSimon Schubert else
2045796c8dcSSimon Schubert return reg->name;
2055796c8dcSSimon Schubert }
2065796c8dcSSimon Schubert }
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert struct value *
value_of_user_reg(int regnum,struct frame_info * frame)2095796c8dcSSimon Schubert value_of_user_reg (int regnum, struct frame_info *frame)
2105796c8dcSSimon Schubert {
2115796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
2125796c8dcSSimon Schubert int maxregs = (gdbarch_num_regs (gdbarch)
2135796c8dcSSimon Schubert + gdbarch_num_pseudo_regs (gdbarch));
2145796c8dcSSimon Schubert struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
215cf7f2e2dSJohn Marino
2165796c8dcSSimon Schubert gdb_assert (reg != NULL);
2175796c8dcSSimon Schubert return reg->read (frame, reg->baton);
2185796c8dcSSimon Schubert }
2195796c8dcSSimon Schubert
2205796c8dcSSimon Schubert extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
2215796c8dcSSimon Schubert
2225796c8dcSSimon Schubert void
_initialize_user_regs(void)2235796c8dcSSimon Schubert _initialize_user_regs (void)
2245796c8dcSSimon Schubert {
2255796c8dcSSimon Schubert user_regs_data = gdbarch_data_register_post_init (user_regs_init);
2265796c8dcSSimon Schubert }
227