2003-07-07 Andrew Cagney <cagney@redhat.com>

* expprint.c: Include "user-regs.h" instead of "frame.h".
	(print_subexp): Use user_reg_map_regnum_to_name, instead of
	frame_map_regnum_to_name.
	* frame.c: Include "user-regs.h" instead of "builtin-regs.h".
	(frame_map_name_to_regnum): Simplify, call
	user_reg_map_name_to_regnum.
	(frame_map_regnum_to_name): Simplify, call
	user_reg_map_regnum_to_name.
	(frame_register_unwind): Update.
	* std-regs.c: Include "user-regs.h" instead of "builtin-regs.h".
	(_initialize_frame_reg): Call user_reg_add_builtin.
	* findvar.c: Include "user-regs.h" instead of "builtin-regs.h".
	(value_of_register): Use value_of_user_reg.
	* eval.c (evaluate_subexp_standard): Update.
	* parse.c (write_dollar_variable): Update.
	* d10v-tdep.c (d10v_print_registers_info): Update.
	* infcmd.c (registers_info): Update.
	* Makefile.in (SFILES): Delete "builtin-regs.c", add "user-regs.c".
	(builtin_regs_h): Delete macro.
	(user_regs_h): Define.
	(COMMON_OBS): Delete "builtin-regs.o", add "user-regs.o".
	(builtin-regs.o): Delete target.
	(user-regs.o): Specify dependencies.
	(expprint.o): Update dependencies.
	(findvar.o): Update dependencies.
	(frame.o): Update dependencies.
	(std-regs.o): Update dependencies.
This commit is contained in:
Andrew Cagney 2003-07-07 14:36:58 +00:00
parent 15f8604d21
commit eb8bc28217
15 changed files with 329 additions and 187 deletions

View File

@ -1,3 +1,33 @@
2003-07-07 Andrew Cagney <cagney@redhat.com>
* expprint.c: Include "user-regs.h" instead of "frame.h".
(print_subexp): Use user_reg_map_regnum_to_name, instead of
frame_map_regnum_to_name.
* frame.c: Include "user-regs.h" instead of "builtin-regs.h".
(frame_map_name_to_regnum): Simplify, call
user_reg_map_name_to_regnum.
(frame_map_regnum_to_name): Simplify, call
user_reg_map_regnum_to_name.
(frame_register_unwind): Update.
* std-regs.c: Include "user-regs.h" instead of "builtin-regs.h".
(_initialize_frame_reg): Call user_reg_add_builtin.
* findvar.c: Include "user-regs.h" instead of "builtin-regs.h".
(value_of_register): Use value_of_user_reg.
* eval.c (evaluate_subexp_standard): Update.
* parse.c (write_dollar_variable): Update.
* d10v-tdep.c (d10v_print_registers_info): Update.
* infcmd.c (registers_info): Update.
* Makefile.in (SFILES): Delete "builtin-regs.c", add "user-regs.c".
(builtin_regs_h): Delete macro.
(user_regs_h): Define.
(COMMON_OBS): Delete "builtin-regs.o", add "user-regs.o".
(builtin-regs.o): Delete target.
(user-regs.o): Specify dependencies.
(expprint.o): Update dependencies.
(findvar.o): Update dependencies.
(frame.o): Update dependencies.
(std-regs.o): Update dependencies.
2003-07-06 Christopher Faylor <cgf@redhat.com>
* win32-nat.c (solib_symbols_add): Use one variable for all section

View File

@ -510,7 +510,7 @@ TARGET_FLAGS_TO_PASS = \
SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
ax-general.c ax-gdb.c \
bcache.c block.c blockframe.c breakpoint.c buildsym.c builtin-regs.c \
bcache.c block.c blockframe.c breakpoint.c buildsym.c \
c-exp.y c-lang.c c-typeprint.c c-valprint.c \
charset.c cli-out.c coffread.c coff-pe-read.c \
complaints.c completer.c corefile.c \
@ -554,6 +554,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \
ui-out.c utils.c ui-file.h ui-file.c \
user-regs.c \
valarith.c valops.c valprint.c values.c varobj.c \
wrapper.c
@ -618,7 +619,6 @@ bcache_h = bcache.h
block_h = block.h
breakpoint_h = breakpoint.h $(frame_h) $(value_h) $(gdb_events_h)
buildsym_h = buildsym.h
builtin_regs_h = builtin-regs.h
c_lang_h = c-lang.h $(value_h) $(macroexp_h)
call_cmds_h = call-cmds.h
ch_lang_h = ch-lang.h
@ -749,6 +749,7 @@ tracepoint_h = tracepoint.h
typeprint_h = typeprint.h
ui_file_h = ui-file.h
ui_out_h = ui-out.h
user_regs_h = user-regs.h
valprint_h = valprint.h
value_h = value.h $(doublest_h) $(frame_h) $(symtab_h) $(gdbtypes_h) $(expression_h)
varobj_h = varobj.h $(symtab_h) $(gdbtypes_h)
@ -862,7 +863,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
event-loop.o event-top.o inf-loop.o completer.o \
gdbarch.o arch-utils.o gdbtypes.o osabi.o copying.o $(DEPFILES) \
memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
builtin-regs.o std-regs.o \
std-regs.o \
signals.o \
kod.o kod-cisco.o \
gdb-events.o \
@ -882,6 +883,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
nlmread.o serial.o mdebugread.o top.o utils.o \
ui-file.o \
user-regs.o \
frame.o frame-unwind.o doublest.o \
frame-base.o \
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
@ -1597,8 +1599,6 @@ buildsym.o: buildsym.c $(defs_h) $(bfd_h) $(gdb_obstack_h) $(symtab_h) \
$(complaints_h) $(gdb_string_h) $(expression_h) $(language_h) \
$(bcache_h) $(filenames_h) $(macrotab_h) $(demangle_h) $(buildsym_h) \
$(stabsread_h) $(block_h) $(cp_support_h) $(dictionary_h)
builtin-regs.o: builtin-regs.c $(defs_h) $(builtin_regs_h) $(gdbtypes_h) \
$(gdb_string_h) $(gdb_assert_h)
c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(c_lang_h) $(valprint_h) \
$(macroscope_h) $(gdb_assert_h) $(charset_h) $(gdb_string_h) \
@ -1728,8 +1728,8 @@ exec.o: exec.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcmd_h) \
$(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h) \
$(readline_h)
expprint.o: expprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(value_h) $(language_h) $(parser_defs_h) $(target_h) $(gdb_string_h) \
$(block_h)
$(value_h) $(language_h) $(parser_defs_h) $(user_regs_h) $(target_h) \
$(gdb_string_h) $(block_h)
f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \
$(valprint_h) $(value_h)
@ -1744,12 +1744,12 @@ fbsd-proc.o: fbsd-proc.c $(defs_h) $(gdbcore_h) $(inferior_h) \
findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
$(builtin_regs_h) $(block_h)
$(user_regs_h) $(block_h)
fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
$(inferior_h) $(target_h) $(gdb_wait_h) $(gdb_vfork_h) $(gdbcore_h) \
$(terminal_h) $(gdbthread_h) $(command_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(user_regs_h) \
$(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) $(gdbcore_h) \
$(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \
$(command_h) $(gdbcmd_h)
@ -2288,7 +2288,7 @@ stack.o: stack.c $(defs_h) $(gdb_string_h) $(value_h) $(symtab_h) \
$(gdb_assert_h) $(dictionary_h)
standalone.o: standalone.c $(gdb_stat_h) $(defs_h) $(symtab_h) $(frame_h) \
$(inferior_h) $(gdb_wait_h)
std-regs.o: std-regs.c $(defs_h) $(builtin_regs_h) $(frame_h) $(gdbtypes_h) \
std-regs.o: std-regs.c $(defs_h) $(user_regs_h) $(frame_h) $(gdbtypes_h) \
$(value_h) $(gdb_string_h)
stop-gdb.o: stop-gdb.c $(defs_h)
sun3-nat.o: sun3-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h)
@ -2342,6 +2342,8 @@ typeprint.o: typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \
ui-file.o: ui-file.c $(defs_h) $(ui_file_h) $(gdb_string_h)
ui-out.o: ui-out.c $(defs_h) $(gdb_string_h) $(expression_h) $(language_h) \
$(ui_out_h) $(gdb_assert_h)
user-regs.o: user-regs.c $(defs_h) $(user_regs_h) $(gdbtypes_h) \
$(gdb_string_h) $(gdb_assert_h) $(frame_h)
utils.o: utils.c $(config_h) $(defs_h) $(gdb_assert_h) $(gdb_string_h) \
$(event_top_h) $(gdbcmd_h) $(serial_h) $(bfd_h) $(target_h) \
$(demangle_h) $(expression_h) $(language_h) $(annotate_h) \

View File

@ -1,86 +0,0 @@
/* Builtin registers, for GDB, the GNU debugger.
Copyright 2002 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "builtin-regs.h"
#include "gdbtypes.h"
#include "gdb_string.h"
#include "gdb_assert.h"
/* Implement builtin register types. Builtin registers have regnum's
that live above of the range [0 .. NUM_REGS + NUM_PSEUDO_REGS)
(which is controlled by the target). The target should never see a
builtin register's regnum value. */
/* An array of builtin registers. Always append, never delete. By
doing this, the relative regnum (offset from NUM_REGS +
NUM_PSEUDO_REGS) assigned to each builtin register never changes. */
struct builtin_reg
{
const char *name;
struct value *(*value) (struct frame_info * frame);
};
static struct builtin_reg *builtin_regs;
int nr_builtin_regs;
void
add_builtin_reg (const char *name, struct value *(*value) (struct frame_info * frame))
{
nr_builtin_regs++;
builtin_regs = xrealloc (builtin_regs,
nr_builtin_regs * sizeof (builtin_regs[0]));
builtin_regs[nr_builtin_regs - 1].name = name;
builtin_regs[nr_builtin_regs - 1].value = value;
}
int
builtin_reg_map_name_to_regnum (const char *name, int len)
{
int reg;
for (reg = 0; reg < nr_builtin_regs; reg++)
{
if (len == strlen (builtin_regs[reg].name)
&& strncmp (builtin_regs[reg].name, name, len) == 0)
return NUM_REGS + NUM_PSEUDO_REGS + reg;
}
return -1;
}
const char *
builtin_reg_map_regnum_to_name (int regnum)
{
int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
if (reg < 0 || reg >= nr_builtin_regs)
return NULL;
return builtin_regs[reg].name;
}
struct value *
value_of_builtin_reg (int regnum, struct frame_info *frame)
{
int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
gdb_assert (reg >= 0 && reg < nr_builtin_regs);
return builtin_regs[reg].value (frame);
}

View File

@ -1,39 +0,0 @@
/* Builtin registers, for GDB, the GNU debugger.
Copyright 2002 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef BUILTIN_REGS_H
#define BUILTIN_REGS_H
struct frame_info;
extern int builtin_reg_map_name_to_regnum (const char *str, int len);
extern const char *builtin_reg_map_regnum_to_name (int regnum);
extern struct value *value_of_builtin_reg (int regnum,
struct frame_info *frame);
extern void add_builtin_reg (const char *name,
struct value *(value) (struct frame_info * frame));
#endif

View File

@ -797,9 +797,9 @@ d10v_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
ULONGEST pc, psw, rpt_s, rpt_e, rpt_c;
frame_read_unsigned_register (frame, D10V_PC_REGNUM, &pc);
frame_read_unsigned_register (frame, PSW_REGNUM, &psw);
frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_s", -1), &rpt_s);
frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_e", -1), &rpt_e);
frame_read_unsigned_register (frame, frame_map_name_to_regnum ("rpt_c", -1), &rpt_c);
frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_s", -1), &rpt_s);
frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_e", -1), &rpt_e);
frame_read_unsigned_register (frame, frame_map_name_to_regnum (frame, "rpt_c", -1), &rpt_c);
fprintf_filtered (file, "PC=%04lx (0x%lx) PSW=%04lx RPT_S=%04lx RPT_E=%04lx RPT_C=%04lx\n",
(long) pc, (long) d10v_make_iaddr (pc), (long) psw,
(long) rpt_s, (long) rpt_e, (long) rpt_c);

View File

@ -454,7 +454,7 @@ evaluate_subexp_standard (struct type *expect_type,
(*pos) += 2;
if (val == NULL)
error ("Value of register %s not available.",
frame_map_regnum_to_name (regno));
frame_map_regnum_to_name (get_selected_frame (), regno));
else
return val;
}

View File

@ -27,7 +27,7 @@
#include "value.h"
#include "language.h"
#include "parser-defs.h"
#include "frame.h" /* For frame_map_regnum_to_name. */
#include "user-regs.h" /* For user_reg_map_regnum_to_name. */
#include "target.h"
#include "gdb_string.h"
#include "block.h"
@ -126,8 +126,10 @@ print_subexp (register struct expression *exp, register int *pos,
case OP_REGISTER:
{
int regnum = longest_to_int (exp->elts[pc + 1].longconst);
const char *name = user_reg_map_regnum_to_name (current_gdbarch,
regnum);
(*pos) += 2;
fprintf_filtered (stream, "$%s", frame_map_regnum_to_name (regnum));
fprintf_filtered (stream, "$%s", name);
return;
}

View File

@ -34,7 +34,7 @@
#include "floatformat.h"
#include "symfile.h" /* for overlay functions */
#include "regcache.h"
#include "builtin-regs.h"
#include "user-regs.h"
#include "block.h"
/* Basic byte-swapping routines. GDB has needed these for a long time...
@ -263,10 +263,10 @@ value_of_register (int regnum, struct frame_info *frame)
char raw_buffer[MAX_REGISTER_SIZE];
enum lval_type lval;
/* Builtin registers lie completly outside of the range of normal
/* User registers lie completly outside of the range of normal
registers. Catch them early so that the target never sees them. */
if (regnum >= NUM_REGS + NUM_PSEUDO_REGS)
return value_of_builtin_reg (regnum, frame);
return value_of_user_reg (regnum, frame);
frame_register (frame, regnum, &optim, &lval, &addr, &realnum, raw_buffer);

View File

@ -28,7 +28,7 @@
#include "regcache.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "builtin-regs.h"
#include "user-regs.h"
#include "gdb_obstack.h"
#include "dummy-frame.h"
#include "sentinel-frame.h"
@ -497,7 +497,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
{
fprintf_unfiltered (gdb_stdlog,
"{ frame_register_unwind (frame=%d,regnum=\"%s\",...) ",
frame->level, frame_map_regnum_to_name (regnum));
frame->level, frame_map_regnum_to_name (frame, regnum));
}
/* Require all but BUFFERP to be valid. A NULL BUFFERP indicates
@ -773,42 +773,15 @@ frame_register_read (struct frame_info *frame, int regnum, void *myaddr)
includes builtin registers. */
int
frame_map_name_to_regnum (const char *name, int len)
frame_map_name_to_regnum (struct frame_info *frame, const char *name, int len)
{
int i;
if (len < 0)
len = strlen (name);
/* Search register name space. */
for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
if (REGISTER_NAME (i) && len == strlen (REGISTER_NAME (i))
&& strncmp (name, REGISTER_NAME (i), len) == 0)
{
return i;
}
/* Try builtin registers. */
i = builtin_reg_map_name_to_regnum (name, len);
if (i >= 0)
{
/* A builtin register doesn't fall into the architecture's
register range. */
gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS);
return i;
}
return -1;
return user_reg_map_name_to_regnum (get_frame_arch (frame), name, len);
}
const char *
frame_map_regnum_to_name (int regnum)
frame_map_regnum_to_name (struct frame_info *frame, int regnum)
{
if (regnum < 0)
return NULL;
if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
return REGISTER_NAME (regnum);
return builtin_reg_map_regnum_to_name (regnum);
return user_reg_map_regnum_to_name (get_frame_arch (frame), regnum);
}
/* Create a sentinel frame. */

View File

@ -409,8 +409,10 @@ extern void put_frame_register (struct frame_info *frame, int regnum,
includes builtin registers. If NAMELEN is negative, use the NAME's
length when doing the comparison. */
extern int frame_map_name_to_regnum (const char *name, int namelen);
extern const char *frame_map_regnum_to_name (int regnum);
extern int frame_map_name_to_regnum (struct frame_info *frame,
const char *name, int namelen);
extern const char *frame_map_regnum_to_name (struct frame_info *frame,
int regnum);
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a

View File

@ -1651,7 +1651,8 @@ registers_info (char *addr_exp, int fpregs)
/* A register name? */
{
int regnum = frame_map_name_to_regnum (start, end - start);
int regnum = frame_map_name_to_regnum (deprecated_selected_frame,
start, end - start);
if (regnum >= 0)
{
gdbarch_print_registers_info (current_gdbarch, gdb_stdout,

View File

@ -455,7 +455,8 @@ write_dollar_variable (struct stoken str)
/* Handle tokens that refer to machine registers:
$ followed by a register name. */
i = frame_map_name_to_regnum (str.ptr + 1, str.length - 1);
i = frame_map_name_to_regnum (deprecated_selected_frame,
str.ptr + 1, str.length - 1);
if (i >= 0)
goto handle_register;

View File

@ -22,7 +22,7 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "builtin-regs.h"
#include "user-regs.h"
#include "frame.h"
#include "gdbtypes.h"
#include "value.h"
@ -147,14 +147,14 @@ _initialize_frame_reg (void)
/* Frame based $fp, $pc, $sp and $ps. These only come into play
when the target does not define its own version of these
registers. */
add_builtin_reg ("fp", value_of_builtin_frame_fp_reg);
add_builtin_reg ("pc", value_of_builtin_frame_pc_reg);
add_builtin_reg ("sp", value_of_builtin_frame_sp_reg);
add_builtin_reg ("ps", value_of_builtin_frame_ps_reg);
user_reg_add_builtin ("fp", value_of_builtin_frame_fp_reg);
user_reg_add_builtin ("pc", value_of_builtin_frame_pc_reg);
user_reg_add_builtin ("sp", value_of_builtin_frame_sp_reg);
user_reg_add_builtin ("ps", value_of_builtin_frame_ps_reg);
/* NOTE: cagney/2002-04-05: For moment leave the $frame / $gdbframe
/ $gdb.frame disabled. It isn't yet clear which of the many
options is the best. */
if (0)
add_builtin_reg ("frame", value_of_builtin_frame_reg);
user_reg_add_builtin ("frame", value_of_builtin_frame_reg);
}

186
gdb/user-regs.c Normal file
View File

@ -0,0 +1,186 @@
/* User visible, per-frame registers, for GDB, the GNU debugger.
Copyright 2002 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "user-regs.h"
#include "gdbtypes.h"
#include "gdb_string.h"
#include "gdb_assert.h"
#include "frame.h"
/* A table of user registers.
User registers have regnum's that live above of the range [0
.. NUM_REGS + NUM_PSEUDO_REGS) (which is controlled by the target).
The target should never see a user register's regnum value.
Always append, never delete. By doing this, the relative regnum
(offset from NUM_REGS + NUM_PSEUDO_REGS) assigned to each user
register never changes. */
struct user_reg
{
const char *name;
struct value *(*read) (struct frame_info * frame);
};
struct user_regs
{
struct user_reg *user;
int nr;
};
static void
append_user_reg (struct user_regs *regs,
const char *name, user_reg_read_ftype *read)
{
regs->nr++;
regs->user = xrealloc (regs->user,
regs->nr * sizeof (struct user_reg));
regs->user[regs->nr - 1].name = name;
regs->user[regs->nr - 1].read = read;
}
/* An array of the builtin user registers. */
static struct user_regs builtin_user_regs;
void
user_reg_add_builtin (const char *name, user_reg_read_ftype *read)
{
append_user_reg (&builtin_user_regs, name, read);
}
/* Per-architecture user registers. Start with the builtin user
registers and then, again, append. */
static struct gdbarch_data *user_regs_data;
static void *
user_regs_init (struct gdbarch *gdbarch)
{
int i;
struct user_regs *regs = XMALLOC (struct user_regs);
memset (regs, 0, sizeof (struct user_regs));
for (i = 0; i < builtin_user_regs.nr; i++)
append_user_reg (regs, builtin_user_regs.user[i].name,
builtin_user_regs.user[i].read);
return regs;
}
static void
user_regs_free (struct gdbarch *gdbarch, void *data)
{
struct user_regs *regs = data;
xfree (regs->user);
xfree (regs);
}
void
user_reg_add (struct gdbarch *gdbarch, const char *name,
user_reg_read_ftype *read)
{
struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
if (regs == NULL)
{
/* ULGH, called during architecture initialization. Patch
things up. */
regs = user_regs_init (gdbarch);
set_gdbarch_data (gdbarch, user_regs_data, regs);
}
append_user_reg (regs, name, read);
}
int
user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
int len)
{
/* Make life easy, set the len to something reasonable. */
if (len < 0)
len = strlen (name);
/* Search register name space first - always let an architecture
specific register override the user registers. */
{
int i;
int maxregs = (gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch));
for (i = 0; i < maxregs; i++)
{
const char *regname = gdbarch_register_name (gdbarch, i);
if (regname != NULL && len == strlen (regname)
&& strncmp (regname, name, len) == 0)
{
return i;
}
}
}
/* Search the user name space. */
{
struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
int reg;
for (reg = 0; reg < regs->nr; reg++)
{
if ((len < 0 && strcmp (regs->user[reg].name, name))
|| (len == strlen (regs->user[reg].name)
&& strncmp (regs->user[reg].name, name, len) == 0))
return NUM_REGS + NUM_PSEUDO_REGS + reg;
}
}
return -1;
}
const char *
user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum)
{
int maxregs = (gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch));
struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
if (regnum < 0)
return NULL;
if (regnum < maxregs)
return gdbarch_register_name (gdbarch, regnum);
if (regnum < (maxregs + regs->nr))
return regs->user[regnum - maxregs].name;
return NULL;
}
struct value *
value_of_user_reg (int regnum, struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
gdb_assert (reg >= 0 && reg < regs->nr);
return regs->user[reg].read (frame);
}
extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
void
_initialize_user_regs (void)
{
user_regs_data = register_gdbarch_data (user_regs_init, user_regs_free);
}

70
gdb/user-regs.h Normal file
View File

@ -0,0 +1,70 @@
/* Per-frame user registers, for GDB, the GNU debugger.
Copyright 2002, 2003 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef USER_REGS_H
#define USER_REGS_H
/* Implement both builtin, and architecture specific, per-frame user
visible registers.
Builtin registers apply to all architectures, where as architecture
specific registers are present when the architecture is selected.
These registers are assigned register numbers outside the
architecture's register range [0 .. NUM_REGS + NUM_PSEUDO_REGS).
Their values should be constructed using per-frame information. */
/* TODO: cagney/2003-06-27: Need to think more about how these
registers are added, read, and modified. At present they are kind
of assumed to be read-only. Should it, for instance, return a
register descriptor that contains all the relvent access methods. */
struct frame_info;
/* Given an architecture, map a user visible register name onto its
index. */
extern int user_reg_map_name_to_regnum (struct gdbarch *gdbarch,
const char *str, int len);
extern const char *user_reg_map_regnum_to_name (struct gdbarch *gdbarch,
int regnum);
/* Return the value of the frame register in the specified frame.
Note; These methods return a "struct value" instead of the raw
bytes as, at the time the register is being added, the type needed
to describe the register has not bee initialized. */
typedef struct value *(user_reg_read_ftype) (struct frame_info *frame);
extern struct value *value_of_user_reg (int regnum, struct frame_info *frame);
/* Add a builtin register (present in all architectures). */
extern void user_reg_add_builtin (const char *name,
user_reg_read_ftype *read);
/* Add a per-architecture frame register. */
extern void user_reg_add (struct gdbarch *gdbarch, const char *name,
user_reg_read_ftype *read);
#endif