From 0406ec40ea7e42729731ad29cb31aed0c8b35574 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Tue, 9 Apr 2002 03:06:14 +0000 Subject: [PATCH] * findvar.c: Include "builtin-regs.h". (value_of_register): Call value_of_builtin_reg when applicable. * parse.c: Include "builtin-regs.h" and "gdb_assert.h". (target_map_name_to_register): Call builtin_reg_map_name_to_regnum. * Makefile.in (SFILES): Add builtin-regs.c and std-regs.c. (COMMON_OBS): Add builtin-regs.o and std-regs.o. (builtin_regs_h): Define. (builtin-regs.o): New target. (findvar.o): Add $(builtin_regs_h). * builtin-regs.c, builtin-regs.h: New files. * std-regs.c: New file. Partial fix for PR gdb/251. --- gdb/ChangeLog | 16 +++++ gdb/Makefile.in | 11 +++- gdb/builtin-regs.c | 77 +++++++++++++++++++++++ gdb/builtin-regs.h | 35 +++++++++++ gdb/findvar.c | 6 ++ gdb/parse.c | 10 +++ gdb/std-regs.c | 150 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 gdb/builtin-regs.c create mode 100644 gdb/builtin-regs.h create mode 100644 gdb/std-regs.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d73b1e85501..e85ab396157 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2002-04-08 Andrew Cagney + + * findvar.c: Include "builtin-regs.h". + (value_of_register): Call value_of_builtin_reg when applicable. + * parse.c: Include "builtin-regs.h" and "gdb_assert.h". + (target_map_name_to_register): Call + builtin_reg_map_name_to_regnum. + * Makefile.in (SFILES): Add builtin-regs.c and std-regs.c. + (COMMON_OBS): Add builtin-regs.o and std-regs.o. + (builtin_regs_h): Define. + (builtin-regs.o): New target. + (findvar.o): Add $(builtin_regs_h). + * builtin-regs.c, builtin-regs.h: New files. + * std-regs.c: New file. + Partial fix for PR gdb/251. + 2002-04-08 Kevin Buettner * rs6000-tdep.c (rs6000_gdbarch_init): Don't set tm_print_insn; diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 95c99c0b3b2..7c56bcca8e3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -550,6 +550,7 @@ SFILES = ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \ tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \ ui-file.h ui-file.c \ frame.c doublest.c \ + builtin-regs.c std-regs.c \ gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -589,6 +590,7 @@ annotate_h = annotate.h $(symtab_h) $(gdbtypes_h) arch_utils_h = arch-utils.h ax_h = ax.h $(doublest_h) bcache_h = bcache.h +builtin_regs_h = builtin-regs.h breakpoint_h = breakpoint.h $(frame_h) $(value_h) buildsym_h = buildsym.h c_lang_h = c-lang.h $(value_h) @@ -708,6 +710,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 copying.o $(DEPFILES) \ memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \ + builtin-regs.o std-regs.o \ signals.o \ kod.o kod-cisco.o \ gdb-events.o \ @@ -1273,6 +1276,9 @@ breakpoint.o: breakpoint.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ buildsym.o: buildsym.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \ $(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h) +builtin-regs.o: builtin-regs.c $(defs.h) $(builtin_regs_h) $(gdbtypes_h) \ + $(gdb_string_h) $(value_h) $(frame_h) + c-lang.o: c-lang.c $(c_lang_h) $(defs_h) $(expression_h) $(gdbtypes_h) \ $(language_h) $(parser_defs_h) $(symtab_h) @@ -1407,7 +1413,7 @@ expprint.o: expprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \ $(language_h) $(parser_defs_h) $(symtab_h) $(value_h) findvar.o: findvar.c $(defs_h) $(gdbcore_h) $(inferior_h) $(target_h) \ - $(gdb_string_h) $(regcache_h) + $(gdb_string_h) $(regcache_h) $(builtin_regs_h) frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \ $(regcache_h) @@ -1804,6 +1810,9 @@ somread.o: somread.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \ somsolib.o: somsolib.c $(defs_h) $(regcache_h) +std-regs.o: std-regs.c $(defs_h) $(builtin_regs_h) $(frame_h) \ + $(gdbtypes_h) $(value_h) + pa64solib.o: pa64solib.c $(defs_h) $(regcache_h) hpux-thread.o: hpux-thread.c $(defs_h) $(gdbthread_h) $(target_h) inferior.h \ diff --git a/gdb/builtin-regs.c b/gdb/builtin-regs.c new file mode 100644 index 00000000000..f9a67818bf2 --- /dev/null +++ b/gdb/builtin-regs.c @@ -0,0 +1,77 @@ +/* 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; +} + +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); +} diff --git a/gdb/builtin-regs.h b/gdb/builtin-regs.h new file mode 100644 index 00000000000..b35c4e91362 --- /dev/null +++ b/gdb/builtin-regs.h @@ -0,0 +1,35 @@ +/* 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 + +extern int builtin_reg_map_name_to_regnum (const char *str, int len); + +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 diff --git a/gdb/findvar.c b/gdb/findvar.c index e94c1507b83..06ad4987a1b 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -33,6 +33,7 @@ #include "floatformat.h" #include "symfile.h" /* for overlay functions */ #include "regcache.h" +#include "builtin-regs.h" /* Basic byte-swapping routines. GDB has needed these for a long time... All extract a target-format integer at ADDR which is LEN bytes long. */ @@ -299,6 +300,11 @@ value_of_register (int regnum, struct frame_info *frame) char *raw_buffer = (char*) alloca (MAX_REGISTER_RAW_SIZE); enum lval_type lval; + /* Builtin 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, selected_frame); + get_saved_register (raw_buffer, &optim, &addr, frame, regnum, &lval); diff --git a/gdb/parse.c b/gdb/parse.c index 40491cfb381..eae55865f28 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -47,6 +47,8 @@ #include "inferior.h" /* for NUM_PSEUDO_REGS. NOTE: replace with "gdbarch.h" when appropriate. */ #include "doublest.h" +#include "builtin-regs.h" +#include "gdb_assert.h" /* Symbols which architectures can redefine. */ @@ -133,6 +135,14 @@ target_map_name_to_register (char *str, int len) return std_regs[i].regnum; } + /* Try builtin registers. */ + i = builtin_reg_map_name_to_regnum (str, len); + if (i >= 0) + { + gdb_assert (i >= NUM_REGS + NUM_PSEUDO_REGS); + return i; + } + return -1; } diff --git a/gdb/std-regs.c b/gdb/std-regs.c new file mode 100644 index 00000000000..b96c9018783 --- /dev/null +++ b/gdb/std-regs.c @@ -0,0 +1,150 @@ +/* Builtin frame register, 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 "frame.h" +#include "gdbtypes.h" +#include "value.h" + +/* Types that describe the various builtin registers. */ + +static struct type *builtin_type_frame_reg; + +/* Constructors for those types. */ + +static void +build_builtin_type_frame_reg (void) +{ + /* $frame. */ + if (builtin_type_frame_reg == NULL) + { +#if 0 + struct frame + { + void *base; + }; +#endif + builtin_type_frame_reg = init_composite_type ("frame", TYPE_CODE_STRUCT); + append_composite_type_field (builtin_type_frame_reg, "base", + builtin_type_void_data_ptr); + } +} + +static struct value * +value_of_builtin_frame_reg (struct frame_info *frame) +{ + struct value *val; + char *buf; + build_builtin_type_frame_reg (); + val = allocate_value (builtin_type_frame_reg); + VALUE_LVAL (val) = not_lval; + buf = VALUE_CONTENTS_RAW (val); + memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0); + /* frame.base. */ + if (frame != NULL) + ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf, frame->frame); + buf += TYPE_LENGTH (builtin_type_void_data_ptr); + /* frame.XXX. */ + return val; +} + +static struct value * +value_of_builtin_frame_fp_reg (struct frame_info *frame) +{ +#ifdef FP_REGNUM + if (FP_REGNUM >= 0) + return value_of_register (FP_REGNUM, frame); +#endif + { + struct value *val = allocate_value (builtin_type_void_data_ptr); + char *buf = VALUE_CONTENTS_RAW (val); + if (frame == NULL) + memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0); + else + ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf, frame->frame); + return val; + } +} + +static struct value * +value_of_builtin_frame_pc_reg (struct frame_info *frame) +{ +#ifdef PC_REGNUM + if (PC_REGNUM >= 0) + return value_of_register (PC_REGNUM, frame); +#endif + { + struct value *val = allocate_value (builtin_type_void_data_ptr); + char *buf = VALUE_CONTENTS_RAW (val); + if (frame == NULL) + memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0); + else + ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf, frame->pc); + return val; + } +} + +static struct value * +value_of_builtin_frame_sp_reg (struct frame_info *frame) +{ +#ifdef SP_REGNUM + if (SP_REGNUM >= 0) + return value_of_register (SP_REGNUM, frame); +#endif + error ("Standard register ``$sp'' is not available for this target"); +} + +static struct value * +value_of_builtin_frame_ps_reg (struct frame_info *frame) +{ +#ifdef PS_REGNUM + if (PS_REGNUM >= 0) + return value_of_register (PS_REGNUM, frame); +#endif + error ("Standard register ``$ps'' is not available for this target"); +} + +void +_initialize_frame_reg (void) +{ + /* FIXME: cagney/2002-02-08: At present the local builtin types + can't be initialized using _initialize*() or gdbarch. Due mainly + to non-multi-arch targets, GDB initializes things piece meal and, + as a consequence can leave these types NULL. */ + REGISTER_GDBARCH_SWAP (builtin_type_frame_reg); + + /* 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); + + /* 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); +}