+2002-05-11 Andrew Cagney <ac131313@redhat.com>
+
+ * regcache.c (regcache_restore): New function.
+ * regcache.h (regcache_restore): Declare.
+
+ * infrun.c (build_infrun): Allocate stop_registers using
+ regbuf_xmalloc.
+ (_initialize_infrun): Don't call build_infrun.
+
+ * Makefile.in (infrun.o): Add dependency on "regbuf.h".
+
+ * infrun.c: Include "regbuf.h".
+ (struct inferior_status): Change type of stop_registers
+ and registers to ``struct regbuf''.
+ (xmalloc_inferior_status): Allocate stop_registers and registers
+ using regbuf_xmalloc.
+ (free_inferior_status): Free registers and stop_registers using
+ regbuf_xfree.
+ (xmalloc_inferior_status): Delete.
+ (save_inferior_status): XMALLOC inf_status directly. Use
+ regbuf_dup and regbuf_xmalloc.
+ (free_inferior_status): Delete.
+ (discard_inferior_status): Free inf_status directly.
+ (restore_inferior_status): Free inf_status directly. Restore
+ stop_registers by replacing buffer.
+ (write_inferior_status_register): Use regbuf_write.
+
+ * Makefile.in (infcmd.o): Add $(regbuf_h).
+
+ * infcmd.c: Include "regbuf.h".
+ (run_stack_dummy): Duplicate the stop_registers.
+
+
+ * rs6000-tdep.c (rs6000_extract_struct_value_address): Change type
+ of regbuf parameter to ``struct regbuf''.
+
+ * Makefile.in (rs6000-tdep.o): Add $(regbuf_h).
+
+ * rs6000-tdep.c: Include "regbuf.h".
+
+ * infrun.c (normal_stop): Use regcache_save.
+
+ * rs6000-tdep.c (rs6000_extract_return_value): Change regbuf type
+ to ``struct regbuf''. Use grub_around_regbuf_for_registers.
+
+ * inferior.h (stop_registers): Change type to a ``struct regbuf''.
+ * infrun.c (stop_registers): Update.
+
+ * values.c (value_being_returned): Update.
+
+ * infcmd.c (run_stack_dummy): Update.
+
+ * gdbarch.sh (EXTRACT_STRUCT_VALUE_ADDRESS): Change type of regbuf
+ to ``struct regbuf''.
+ (EXTRACT_RETURN_VALUE):
+
+ * value.h (value_being_returned): Change regbuf parameter type to
+ ``struct retbuf''.
+
+ * inferior.h (run_stack_dummy): Change retbuf parameter type to
+ ``struct regbuf''.
+
+ * valops.c (hand_function_call): Make retbuf a ``struct regbuf''.
+
+ * blockframe.c (generic_pop_dummy_frame): Use
+ regcache_restore_no_writethrough and regbuf_xfree.
+
+ * regcache.c (regcache_restore_no_writethrough): New function.
+ (regcache_save): New function.
+ * regcache.h (regcache_save): Declare.
+ (regcache_restore_no_writethrough): Declare.
+
+ * blockframe.c (generic_pop_dummy_frame): Use regbuf_xfree and
+ regcache_restore_regbuf.
+ (generic_get_saved_register): Use regbuf_read.
+
+
+ * blockframe.c: Include "regbuf.h".
+ (generic_push_dummy_frame): Use regbuf_xfree and regcache_save.
+
+ * frame.h (generic_find_dummy_frame): Change return type to
+ ``struct regbuf''.
+
+ * Makefile.in (blockframe.o): Add dependency on $(regbuf_h).
+
+ * blockframe.c (struct dummy_frame): Replace registers with
+ regbuf.
+ (generic_find_dummy_frame): Change return type to `struct regbuf',
+ return regbuf.
+ (generic_read_register_dummy): Rewrite using
+ regbuf_read_as_address.
+
+ * regcache.c: Include "regbuf.h".
+ (_initialize_regcache): Register regcache_regbuf for swapping.
+ (regcache_regbuf): Define.
+ (build_regcache): Rewrite using regbuf_xmalloc,
+ grub_around_regbuf_for_registers and
+ grub_around_regbuf_for_register_valid.
+
+ * Makefile.in (regcache.o): Add $(regbuf_h).
+
+ * defs.h (XCALLOC): Define.
+ * regbuf.c, regbuf.c: New files.
+ * Makefile.in (SFILES): Add regbuf.c.
+ (regbuf_h): Define.
+ (COMMON_OBS): Add regbuf.o.
+ (regbuf.o): Specify dependencies.
+
2002-05-15 Jim Blandy <jimb@redhat.com>
Add macro structures to GDB's symbol tables. Nobody puts anything
demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
event-loop.c event-top.c \
expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
- findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c \
+ findvar.c regcache.c regbuf.c gdbarch.c arch-utils.c gdbtypes.c \
inf-loop.c infcmd.c inflow.c infrun.c language.c \
kod.c kod-cisco.c \
ui-out.c cli-out.c \
monitor_h = monitor.h
objfiles_h = objfiles.h
parser_defs_h = parser-defs.h $(doublest_h)
+regbuf_h = regbuf.h
regcache_h = regcache.h
remote_h = remote.h
remote_utils_h = remote-utils.h $(target_h)
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 \
+ signals.o regbuf.o \
kod.o kod-cisco.o \
gdb-events.o \
exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
bcache.o: bcache.c $(bcache_h) $(defs_h)
blockframe.o: blockframe.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(objfiles_h) $(symfile_h) $(target_h) $(regcache_h)
+ $(objfiles_h) $(symfile_h) $(target_h) $(regcache_h) $(regbuf_h)
breakpoint.o: breakpoint.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) $(language_h) $(target_h) $(gdbthread_h) \
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
$(regcache_h)
-regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h)
+regbuf.o: regbuf.c $(defs_h) $(regbuf_h) gdb_assert.h
+
+regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(regcache_h) \
+ $(regbuf_h)
fork-child.o: fork-child.c $(gdb_wait_h) $(defs_h) $(gdbcore_h) \
$(inferior_h) $(target_h) $(terminal_h) $(gdbthread_h) $(gdb_string_h)
infcmd.o: infcmd.c $(defs_h) environ.h $(gdbcmd_h) $(gdbcore_h) \
$(inferior_h) $(target_h) $(language_h) $(symfile_h) $(gdb_string_h) \
- $(ui_out_h) $(completer_h)
+ $(ui_out_h) $(completer_h) $(regbuf_h)
inflow.o: inflow.c $(bfd_h) $(command_h) $(defs_h) $(inferior_h) \
$(target_h) $(terminal_h) $(gdbthread_h) $(gdb_string_h)
$(gdb_stabs_h) $(regcache_h) $(arch_utils_h)
rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
+ $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h) \
+ $(regbuf_h)
s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
#include "inferior.h" /* for read_pc */
#include "annotate.h"
#include "regcache.h"
+#include "regbuf.h"
/* Prototypes for exported functions. */
CORE_ADDR fp;
CORE_ADDR sp;
CORE_ADDR top;
- char *registers;
+ struct regbuf *regbuf;
/* Address range of the call dummy code. Look for PC in the range
[LO..HI) (after allowing for DECR_PC_AFTER_BREAK). */
adjust for DECR_PC_AFTER_BREAK. This is because it is only legal
to call this function after the PC has been adjusted. */
-char *
+struct regbuf *
generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
{
struct dummy_frame *dummyframe;
|| fp == dummyframe->sp
|| fp == dummyframe->top))
/* The frame in question lies between the saved fp and sp, inclusive */
- return dummyframe->registers;
+ return dummyframe->regbuf;
return 0;
}
CORE_ADDR
generic_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
{
- char *dummy_regs = generic_find_dummy_frame (pc, fp);
+ struct regbuf *dummy_regs = generic_find_dummy_frame (pc, fp);
if (dummy_regs)
- return extract_address (&dummy_regs[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
+ return regbuf_read_as_address (dummy_regs, regno);
else
return 0;
}
if (INNER_THAN (dummy_frame->fp, fp)) /* stale -- destroy! */
{
dummy_frame_stack = dummy_frame->next;
- xfree (dummy_frame->registers);
+ regbuf_xfree (dummy_frame->regbuf);
xfree (dummy_frame);
dummy_frame = dummy_frame_stack;
}
dummy_frame = dummy_frame->next;
dummy_frame = xmalloc (sizeof (struct dummy_frame));
- dummy_frame->registers = xmalloc (REGISTER_BYTES);
+ dummy_frame->regbuf = regbuf_xmalloc (current_gdbarch);
+ regcache_save (dummy_frame->regbuf);
dummy_frame->pc = read_pc ();
dummy_frame->sp = read_sp ();
dummy_frame->top = dummy_frame->sp;
dummy_frame->fp = fp;
- read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
dummy_frame->next = dummy_frame_stack;
dummy_frame_stack = dummy_frame;
}
if (!dummy_frame)
error ("Can't pop dummy frame!");
dummy_frame_stack = dummy_frame->next;
- write_register_bytes (0, dummy_frame->registers, REGISTER_BYTES);
+ regcache_restore (dummy_frame->regbuf);
flush_cached_frames ();
- xfree (dummy_frame->registers);
+ regbuf_xfree (dummy_frame->regbuf);
xfree (dummy_frame);
}
if (lval) /* found it in a CALL_DUMMY frame */
*lval = not_lval;
if (raw_buffer)
- memcpy (raw_buffer,
- generic_find_dummy_frame (frame->pc, frame->frame) +
- REGISTER_BYTE (regnum),
- REGISTER_RAW_SIZE (regnum));
+ regbuf_read (generic_find_dummy_frame (frame->pc, frame->frame),
+ regnum, raw_buffer);
return;
}
"libiberty.h". */
extern void xfree (void *);
-/* Utility macro to allocate typed memory. Avoids errors like
+/* Utility macros to allocate typed memory. Avoids errors like
``struct foo *foo = xmalloc (sizeof bar)'' and ``struct foo *foo =
(struct foo *) xmalloc (sizeof bar)''. */
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
+#define XCALLOC(NR, TYPE) ((TYPE*) xcalloc ((NR), sizeof (TYPE)));
/* Like asprintf/vasprintf but get an internal_error if the call
fails. */
extern int generic_pc_in_call_dummy (CORE_ADDR pc,
CORE_ADDR sp, CORE_ADDR fp);
-extern char *generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp);
+extern struct regbuf *generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp);
extern void generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
int nargs, struct value **args,
}
void
-gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, char *regbuf, char *valbuf)
+gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regbuf *regbuf, char *valbuf)
{
gdb_assert (gdbarch != NULL);
if (gdbarch->extract_return_value == 0)
}
CORE_ADDR
-gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, char *regbuf)
+gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, struct regbuf *regbuf)
{
gdb_assert (gdbarch != NULL);
if (gdbarch->extract_struct_value_address == 0)
struct value;
struct objfile;
struct minimal_symbol;
+struct regbuf;
extern struct gdbarch *current_gdbarch;
#endif
#endif
-typedef void (gdbarch_extract_return_value_ftype) (struct type *type, char *regbuf, char *valbuf);
-extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, char *regbuf, char *valbuf);
+typedef void (gdbarch_extract_return_value_ftype) (struct type *type, struct regbuf *regbuf, char *valbuf);
+extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regbuf *regbuf, char *valbuf);
extern void set_gdbarch_extract_return_value (struct gdbarch *gdbarch, gdbarch_extract_return_value_ftype *extract_return_value);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (EXTRACT_RETURN_VALUE)
#error "Non multi-arch definition of EXTRACT_RETURN_VALUE"
#define EXTRACT_STRUCT_VALUE_ADDRESS(regbuf) (internal_error (__FILE__, __LINE__, "EXTRACT_STRUCT_VALUE_ADDRESS"), 0)
#endif
-typedef CORE_ADDR (gdbarch_extract_struct_value_address_ftype) (char *regbuf);
-extern CORE_ADDR gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, char *regbuf);
+typedef CORE_ADDR (gdbarch_extract_struct_value_address_ftype) (struct regbuf *regbuf);
+extern CORE_ADDR gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, struct regbuf *regbuf);
extern void set_gdbarch_extract_struct_value_address (struct gdbarch *gdbarch, gdbarch_extract_struct_value_address_ftype *extract_struct_value_address);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (EXTRACT_STRUCT_VALUE_ADDRESS)
#error "Non multi-arch definition of EXTRACT_STRUCT_VALUE_ADDRESS"
F:2:INTEGER_TO_ADDRESS:CORE_ADDR:integer_to_address:struct type *type, void *buf:type, buf
#
f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
-f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf::0:0
+f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, struct regbuf *regbuf, char *valbuf:type, regbuf, valbuf::0:0
f:2:PUSH_ARGUMENTS:CORE_ADDR:push_arguments:int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr:nargs, args, sp, struct_return, struct_addr:::default_push_arguments::0
f:2:PUSH_DUMMY_FRAME:void:push_dummy_frame:void:-:::0
F:2:PUSH_RETURN_ADDRESS:CORE_ADDR:push_return_address:CORE_ADDR pc, CORE_ADDR sp:pc, sp:::0
#
f:2:STORE_STRUCT_RETURN:void:store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp:::0
f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, char *valbuf:type, valbuf:::0
-F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:char *regbuf:regbuf:::0
+F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:struct regbuf *regbuf:regbuf:::0
f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0
#
f:2:FRAME_INIT_SAVED_REGS:void:frame_init_saved_regs:struct frame_info *frame:frame::0:0
struct value;
struct objfile;
struct minimal_symbol;
+struct regbuf;
extern struct gdbarch *current_gdbarch;
#include "ui-out.h"
#include "event-top.h"
#include "parser-defs.h"
+#include "regbuf.h"
/* Functions exported for general use: */
will eventually be popped when we do hit the dummy end breakpoint). */
int
-run_stack_dummy (CORE_ADDR addr, char *buffer)
+run_stack_dummy (CORE_ADDR addr, struct regbuf **buffer)
{
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
int saved_async = 0;
return 2;
/* On normal return, the stack dummy has been popped already. */
-
- memcpy (buffer, stop_registers, REGISTER_BYTES);
+ *buffer = regbuf_dup (stop_registers);
return 0;
}
\f
#define INFERIOR_H 1
struct gdbarch;
+struct regbuf;
/* For bpstat. */
#include "breakpoint.h"
extern void terminal_ours (void);
-extern int run_stack_dummy (CORE_ADDR, char *);
+extern int run_stack_dummy (CORE_ADDR, struct regbuf **retbuf);
extern CORE_ADDR read_pc (void);
Thus this contains the return value from the called function (assuming
values are returned in a register). */
-extern char *stop_registers;
+extern struct regbuf *stop_registers;
/* Nonzero if the child process in inferior_ptid was attached rather
than forked. */
#include "inf-loop.h"
#include "regcache.h"
#include "value.h"
+#include "regbuf.h"
/* Prototypes for local functions */
static void set_follow_fork_mode_command (char *arg, int from_tty,
struct cmd_list_element * c);
-static struct inferior_status *xmalloc_inferior_status (void);
-
-static void free_inferior_status (struct inferior_status *);
-
static int restore_selected_frame (void *);
static void build_infrun (void);
Thus this contains the return value from the called function (assuming
values are returned in a register). */
-char *stop_registers;
+struct regbuf *stop_registers;
/* Nonzero if program stopped due to error trying to insert breakpoints. */
/* Save the function value return registers, if we care.
We might be about to restore their previous contents. */
if (proceed_to_finish)
- read_register_bytes (0, stop_registers, REGISTER_BYTES);
+ regcache_save (stop_registers);
if (stop_stack_dummy)
{
int stop_after_trap;
int stop_soon_quietly;
CORE_ADDR selected_frame_address;
- char *stop_registers;
+ struct regbuf *stop_registers;
/* These are here because if call_function_by_hand has written some
registers and then decides to call error(), we better not have changed
any registers. */
- char *registers;
+ struct regbuf *registers;
int selected_level;
int breakpoint_proceeded;
int proceed_to_finish;
};
-static struct inferior_status *
-xmalloc_inferior_status (void)
-{
- struct inferior_status *inf_status;
- inf_status = xmalloc (sizeof (struct inferior_status));
- inf_status->stop_registers = xmalloc (REGISTER_BYTES);
- inf_status->registers = xmalloc (REGISTER_BYTES);
- return inf_status;
-}
-
-static void
-free_inferior_status (struct inferior_status *inf_status)
-{
- xfree (inf_status->registers);
- xfree (inf_status->stop_registers);
- xfree (inf_status);
-}
-
void
write_inferior_status_register (struct inferior_status *inf_status, int regno,
LONGEST val)
int size = REGISTER_RAW_SIZE (regno);
void *buf = alloca (size);
store_signed_integer (buf, size, val);
- memcpy (&inf_status->registers[REGISTER_BYTE (regno)], buf, size);
+ regbuf_write (inf_status->registers, regno, buf);
}
/* Save all of the information associated with the inferior<==>gdb
struct inferior_status *
save_inferior_status (int restore_stack_info)
{
- struct inferior_status *inf_status = xmalloc_inferior_status ();
+ struct inferior_status *inf_status = XMALLOC (struct inferior_status);
inf_status->stop_signal = stop_signal;
inf_status->stop_pc = stop_pc;
inf_status->restore_stack_info = restore_stack_info;
inf_status->proceed_to_finish = proceed_to_finish;
- memcpy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
-
- read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+ inf_status->stop_registers = regbuf_dup (stop_registers);
+ inf_status->registers = regbuf_xmalloc (current_gdbarch);
+ regcache_save (inf_status->registers);
record_selected_frame (&(inf_status->selected_frame_address),
&(inf_status->selected_level));
breakpoint_proceeded = inf_status->breakpoint_proceeded;
proceed_to_finish = inf_status->proceed_to_finish;
- /* FIXME: Is the restore of stop_registers always needed */
- memcpy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+ /* FIXME: Is the restore of stop_registers always needed? */
+ regbuf_xfree (stop_registers);
+ stop_registers = inf_status->stop_registers;
/* The inferior can be gone if the user types "print exit(0)"
(and perhaps other times). */
if (target_has_execution)
- write_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+ regcache_restore (inf_status->registers);
+ regbuf_xfree (inf_status->registers);
/* FIXME: If we are being called after stopping in a function which
is called from gdb, we should not be trying to restore the
}
- free_inferior_status (inf_status);
+ xfree (inf_status);
}
static void
{
/* See save_inferior_status for info on stop_bpstat. */
bpstat_clear (&inf_status->stop_bpstat);
- free_inferior_status (inf_status);
+ regbuf_xfree (inf_status->registers);
+ regbuf_xfree (inf_status->stop_registers);
+ xfree (inf_status);
}
/* Oft used ptids */
static void
build_infrun (void)
{
- stop_registers = xmalloc (REGISTER_BYTES);
+ stop_registers = regbuf_xmalloc (current_gdbarch);
}
void
register int numsigs;
struct cmd_list_element *c;
- build_infrun ();
-
register_gdbarch_swap (&stop_registers, sizeof (stop_registers), NULL);
register_gdbarch_swap (NULL, 0, build_infrun);
+2002-05-11 Andrew Cagney <ac131313@redhat.com>
+
+ * mi-main.c: Include "regbuf.h".
+ (old_regs): Change type of old_regs to a regbuf.
+ (register_changed_p): Use regbuf_read and regbuf_write.
+ (setup_architecture_data): Use regbuf_xmalloc.
+
2002-04-14 Andrew Cagney <ac131313@redhat.com>
* mi-main.c (mi_cmd_exec_return):
#include "gdb.h"
#include <ctype.h>
#include <sys/time.h>
+#include "regbuf.h"
enum
{
static char *last_async_command;
static char *previous_async_command;
static char *mi_error_message;
-static char *old_regs;
+static struct regbuf *old_regs;
extern void _initialize_mi_main (void);
static char *mi_input (char *);
register_changed_p (int regnum)
{
char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE);
+ char *old_buffer = alloca (MAX_REGISTER_RAW_SIZE);
if (! frame_register_read (selected_frame, regnum, raw_buffer))
return -1;
-
- if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
- REGISTER_RAW_SIZE (regnum)) == 0)
+ regbuf_read (old_regs, regnum, old_buffer);
+ if (memcmp (old_buffer, raw_buffer, REGISTER_RAW_SIZE (regnum)) == 0)
return 0;
- /* Found a changed register. Return 1. */
-
- memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
- REGISTER_RAW_SIZE (regnum));
-
+ /* Found a changed register. Update the buffer and return 1. */
+ regbuf_write (old_regs, regnum, raw_buffer);
return 1;
}
static void
setup_architecture_data (void)
{
- /* don't trust REGISTER_BYTES to be zero. */
- old_regs = xmalloc (REGISTER_BYTES + 1);
- memset (old_regs, 0, REGISTER_BYTES + 1);
+ old_regs = regbuf_xmalloc (current_gdbarch);
}
static void
--- /dev/null
+/* Register buffer sufficient to hold all raw registers
+
+ Copyright 2002 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ Contributed by Red Hat, Inc.
+
+ 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 "regbuf.h"
+#include "gdb_assert.h"
+
+extern void _initialize_regbuf (void);
+
+/* Per-architecture object describing the layout of a register buffer.
+ Computed once when the architecture is created */
+
+struct gdbarch_data *regbuf_data_handle;
+
+struct regbuf_descr
+{
+ struct gdbarch *gdbarch;
+ /* Size of the register buffer, over-allocate making room for both
+ real and pseudo-registers. */
+ /* FIXME: cagney/2002-05-11: This over-allocation shouldn't be
+ necessary, only some targets store values in the pseudo-register
+ section and we want to be sure that GDB won't trash memory. */
+ long sizeof_registers;
+ /* Total number of registers in the buffer. */
+ int nr_registers;
+ /* Offset into the register buffer for each register. */
+ long *register_offset;
+ /* Size, in ``bytes'', of a register. */
+ long *sizeof_register;
+};
+
+static struct regbuf_descr *
+regbuf_descr (struct gdbarch *gdbarch)
+{
+ int i;
+ /* FIXME: cagney/2002-05-11: gdbarch_data() should take that
+ ``gdbarch'' as a parameter. */
+ struct regbuf_descr *descr = gdbarch_data (/* gdbarch, */
+ regbuf_data_handle);
+ if (descr != NULL)
+ return descr;
+
+ descr = XMALLOC (struct regbuf_descr);
+ descr->gdbarch = gdbarch;
+ /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
+ in the register buffer. Unfortunatly some architectures are
+ storing pseudo register values in the raw register buffer. */
+ descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
+ /* FIXME: cagney/2002-05-11: Instead of using REGISTER_BYTE() this
+ should compute, at runtime, an offset table describing where each
+ register is in the register table. This currently isn't possible
+ because some targets overlap registers, ulgh! */
+ descr->register_offset = XCALLOC (descr->nr_registers, long);
+ descr->sizeof_register = XCALLOC (descr->nr_registers, long);
+ for (i = 0; i < descr->nr_registers; i++)
+ {
+ descr->register_offset[i] = REGISTER_BYTE (i);
+ descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
+ }
+ /* Come up with the real size of the registers buffer. */
+ descr->sizeof_registers = REGISTER_BYTES; /* OK use. */
+ for (i = 0; i < descr->nr_registers; i++)
+ {
+ long regend;
+ /* Keep extending the buffer so that there is always enough
+ space for all registers. The comparison is necessary since
+ legacy code is free to put registers in random places in the
+ buffer separated by holes. Once REGISTER_BYTE() is killed
+ this can be greatly simplified. */
+ /* FIXME: cagney/2001-12-04: This code shouldn't need to use
+ REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
+ buffer out so that certain registers just happen to overlap.
+ Ulgh! New targets use gdbarch's register read/write and
+ entirely avoid this uglyness. */
+ regend = descr->register_offset[i] + descr->sizeof_register[i];
+ if (descr->sizeof_registers < regend)
+ descr->sizeof_registers = regend;
+ }
+ set_gdbarch_data (gdbarch, regbuf_data_handle, descr);
+ return descr;
+}
+
+static void
+xfree_regbuf (struct gdbarch *gdbarch, void *ptr)
+{
+ struct regbuf_descr *descr = ptr;
+ if (descr == NULL)
+ return;
+ xfree (descr->register_offset);
+ xfree (descr->sizeof_register);
+ xfree (descr);
+}
+
+/* For moment, ``struct regbuf'' is just a character buffer. */
+
+struct regbuf
+{
+ struct regbuf_descr *descr;
+ char *registers;
+ char *valid_p;
+};
+
+struct regbuf *
+regbuf_xmalloc (struct gdbarch *gdbarch)
+{
+ struct regbuf_descr *descr = regbuf_descr (gdbarch);
+ struct regbuf *regbuf = XMALLOC (struct regbuf);
+ regbuf->descr = descr;
+ regbuf->registers = xmalloc (descr->sizeof_registers);
+ regbuf->valid_p = xmalloc (descr->nr_registers);
+ return regbuf;
+}
+
+void
+regbuf_xfree (struct regbuf *regbuf)
+{
+ gdb_assert (regbuf != NULL);
+ xfree (regbuf->registers);
+ xfree (regbuf->valid_p);
+ xfree (regbuf);
+}
+
+void
+do_regbuf_xfree (void *buf)
+{
+ regbuf_xfree (buf);
+}
+
+struct regbuf *
+regbuf_xmalloc_with_cleanup (struct gdbarch *gdbarch)
+{
+ struct regbuf *regbuf = regbuf_xmalloc (gdbarch);
+ make_cleanup (do_regbuf_xfree, regbuf);
+ return regbuf;
+}
+
+struct regbuf *
+regbuf_dup (struct regbuf *regbuf)
+{
+ struct regbuf *newbuf = regbuf_xmalloc (regbuf->descr->gdbarch);
+ memcpy (newbuf->registers, regbuf->registers,
+ regbuf->descr->sizeof_registers);
+ memcpy (newbuf->valid_p, regbuf->valid_p, regbuf->descr->nr_registers);
+ return newbuf;
+}
+
+int
+regbuf_valid_p (struct regbuf *regbuf, int regnum)
+{
+ gdb_assert (regnum != NULL);
+ gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
+ return regbuf->valid_p[regnum];
+}
+
+void
+regbuf_read (struct regbuf *regbuf, int regnum, void *buf)
+{
+ gdb_assert (regbuf != NULL);
+ gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
+ memcpy (buf, regbuf->registers + regbuf->descr->register_offset[regnum],
+ regbuf->descr->sizeof_register[regnum]);
+}
+
+void
+regbuf_write (struct regbuf *regbuf, int regnum, const void *buf)
+{
+ gdb_assert (regbuf != NULL);
+ gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
+ memcpy (regbuf->registers + regbuf->descr->register_offset[regnum], buf,
+ regbuf->descr->sizeof_register[regnum]);
+ regbuf->valid_p[regnum] = 1;
+}
+
+CORE_ADDR
+regbuf_read_as_address (struct regbuf *regbuf, int regnum)
+{
+ char *buf;
+ gdb_assert (regbuf != NULL);
+ gdb_assert (regnum >= 0 && regnum < regbuf->descr->nr_registers);
+ buf = alloca (regbuf->descr->sizeof_register[regnum]);
+ regbuf_read (regbuf, regnum, buf);
+ return extract_address (buf, regbuf->descr->sizeof_register[regnum]);
+}
+
+char *
+grub_around_regbuf_for_registers (struct regbuf *regbuf)
+{
+ return regbuf->registers;
+}
+
+char *
+grub_around_regbuf_for_register_valid (struct regbuf *regbuf)
+{
+ return regbuf->valid_p;
+}
+
+void
+_initialize_regbuf (void)
+{
+ regbuf_data_handle = register_gdbarch_data (NULL, xfree_regbuf);
+}
--- /dev/null
+/* Register buffer sufficient to hold all raw registers
+
+ Copyright 2002 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ Contributed by Red Hat, Inc.
+
+ 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 REGBUF_H
+#define REGBUF_H
+
+struct regbuf;
+
+/* Create/destroy the register buffer. */
+
+extern struct regbuf *regbuf_xmalloc (struct gdbarch *gdbarch);
+extern void regbuf_xfree (struct regbuf *regbuf);
+extern struct regbuf *regbuf_xmalloc_with_cleanup (struct gdbarch *gdbarch);
+
+/* Duplicate a regbuf and all contents. */
+
+extern struct regbuf *regbuf_dup (struct regbuf *regbuf);
+
+/* Is the regbuf entry valid. */
+
+int regbuf_valid_p (struct regbuf *regbuf, int regnum);
+
+/* Access the register buffer. */
+
+extern void regbuf_read (struct regbuf *regbuf, int rawnum, void *buf);
+extern void regbuf_write (struct regbuf *regbuf, int rawnum, const void *buf);
+
+/* Convenience routines for reading/writing registers using an
+ internal format. */
+
+extern CORE_ADDR regbuf_read_as_address (struct regbuf *regbuf, int regnum);
+
+/* FIXME: cagney/2002-05-11: This is here simply to prop up the
+ `registers' and `register_valid' global arrays. */
+
+extern char *grub_around_regbuf_for_registers (struct regbuf *regbuf);
+extern char *grub_around_regbuf_for_register_valid (struct regbuf *regbuf);
+
+#endif /* REGBUF_H */
#include "gdbcmd.h"
#include "regcache.h"
#include "gdb_assert.h"
+#include "regbuf.h"
/*
* DATA STRUCTURE
* Here is the actual register cache.
*/
+/* Global structure containing the current regbuf. */
+/* FIXME: cagney/2002-05-11: The two global arrays registers[] and
+ register_valid[] currently point into this structure. */
+
+struct regbuf *regcache_regbuf;
+
/* NOTE: this is a write-through cache. There is no "dirty" bit for
recording if the register values have been changed (eg. by the
user). Therefore all registers must be written back to the
static void
build_regcache (void)
{
- int i;
- int sizeof_register_valid;
- /* Come up with the real size of the registers buffer. */
- int sizeof_registers = REGISTER_BYTES; /* OK use. */
- for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
- {
- long regend;
- /* Keep extending the buffer so that there is always enough
- space for all registers. The comparison is necessary since
- legacy code is free to put registers in random places in the
- buffer separated by holes. Once REGISTER_BYTE() is killed
- this can be greatly simplified. */
- /* FIXME: cagney/2001-12-04: This code shouldn't need to use
- REGISTER_BYTE(). Unfortunatly, legacy code likes to lay the
- buffer out so that certain registers just happen to overlap.
- Ulgh! New targets use gdbarch's register read/write and
- entirely avoid this uglyness. */
- regend = REGISTER_BYTE (i) + REGISTER_RAW_SIZE (i);
- if (sizeof_registers < regend)
- sizeof_registers = regend;
- }
- registers = xmalloc (sizeof_registers);
- sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
- * sizeof (*register_valid));
- register_valid = xmalloc (sizeof_register_valid);
- memset (register_valid, 0, sizeof_register_valid);
+ regcache_regbuf = regbuf_xmalloc (current_gdbarch);
+ registers = grub_around_regbuf_for_registers (regcache_regbuf);
+ register_valid = grub_around_regbuf_for_register_valid (regcache_regbuf);
+}
+
+void
+regcache_save (struct regbuf *regbuf)
+{
+ /* FIXME: cagney/2002-05-11: This assumes that the current
+ architecture and the regbuf architecture are identical. */
+ char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
+ char *regbuf_register_valid = grub_around_regbuf_for_register_valid (regbuf);
+ memcpy (regbuf_registers, registers, REGISTER_BYTES);
+ memcpy (regbuf_register_valid, register_valid, NUM_REGS + NUM_PSEUDO_REGS);
+}
+
+void
+regcache_restore (struct regbuf *regbuf)
+{
+ char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
+ write_register_bytes (0, regbuf_registers, REGISTER_BYTES);
+}
+
+void
+regcache_restore_no_writethrough (struct regbuf *regbuf)
+{
+ char *regbuf_registers = grub_around_regbuf_for_registers (regbuf);
+ memcpy (registers, regbuf_registers, REGISTER_BYTES);
}
void
_initialize_regcache (void)
{
+ REGISTER_GDBARCH_SWAP (regcache_regbuf);
register_gdbarch_swap (®isters, sizeof (registers), NULL);
register_gdbarch_swap (®ister_valid, sizeof (register_valid), NULL);
register_gdbarch_swap (NULL, 0, build_regcache);
#ifndef REGCACHE_H
#define REGCACHE_H
+struct regbuf;
+
/* Transfer a raw register [0..NUM_REGS) between core-gdb and the
regcache. */
extern signed char *register_valid;
+/* Save/restore the register cache using the regbuf. The operation is
+ write through - it is strictly for code that needs to restore the
+ target's registers to a previous state. */
+
+extern void regcache_save (struct regbuf *regbuf);
+extern void regcache_restore (struct regbuf *regbufx);
+extern void regcache_restore_no_writethrough (struct regbuf *regbufx);
+
extern int register_cached (int regnum);
extern void set_register_cached (int regnum, int state);
#include "solib-svr4.h"
#include "ppc-tdep.h"
+#include "regbuf.h" /* For grub_around_regbuf_for_registers. */
+
/* If the kernel has to deliver a signal, it pushes a sigcontext
structure on the stack and then calls the signal handler, passing
the address of the sigcontext in an argument register. Usually
REGBUF, and copy that return value into VALBUF in virtual format. */
static void
-rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
+rs6000_extract_return_value (struct type *valtype, struct regbuf *regs,
+ char *valbuf)
{
int offset = 0;
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ char *regbuf = grub_around_regbuf_for_registers (regs);
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
as a CORE_ADDR (or an expression that can be used as one). */
static CORE_ADDR
-rs6000_extract_struct_value_address (char *regbuf)
+rs6000_extract_struct_value_address (struct regbuf *regs)
{
+ /* FIXME: cagney/2002-05-11: This global variable is just a hack! */
return rs6000_struct_return_address;
}
SAVE_DUMMY_FRAME_TOS (sp);
{
- char *retbuf = (char*) alloca (REGISTER_BYTES);
+ struct regbuf *retbuf = NULL;
char *name;
struct symbol *symbol;
/* Execute the stack dummy routine, calling FUNCTION.
When it is done, discard the empty frame
after storing the contents of all regs into retbuf. */
- rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
+ rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, &retbuf);
if (rc == 1)
{
#if !defined (VALUE_H)
#define VALUE_H 1
+struct regbuf;
+
#include "doublest.h"
/*
extern struct value *value_subscript (struct value *array, struct value *idx);
extern struct value *value_being_returned (struct type *valtype,
- char *retbuf, int struct_return);
+ struct regbuf *retbuf,
+ int struct_return);
extern struct value *value_in (struct value *element, struct value *set);
/* ARGSUSED */
struct value *
-value_being_returned (struct type *valtype, char *retbuf, int struct_return)
+value_being_returned (struct type *valtype, struct regbuf *retbuf,
+ int struct_return)
{
struct value *val;
CORE_ADDR addr;