This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[rfc] [03/18] Cell multi-arch: Save/restore current_gdbarch
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Sun, 7 Sep 2008 23:12:00 +0200 (CEST)
- Subject: [rfc] [03/18] Cell multi-arch: Save/restore current_gdbarch
Hello,
this patch would be unnecessary if we were already rid of current_gdbarch.
However, right now it is necessary in a multi-arch debugger to occasionally
temporarily set current_gdbarch to the architecture a subsystem is supposed
to be dealing with. Those locations include:
- during target routines called from regcache_raw_read/write
- while calling frame sniffer callbacks or gdbarch data post_init callbacks
- while handling one frame during backtrace output
To do that, this patch introduced a new save_current_gdbarch routine
(that works like save_inferior_ptid) and adds calls at the appropriate places.
Bye,
Ulrich
ChangeLog:
* arch-utils.h (save_current_gdbarch): New.
* arch-utils.c (restore_current_gdbarch): New function.
(save_current_gdbarch): Likewise.
* frame.c: Include "arch-utils.h".
(get_frame_id): Reset current_gdbarch while calling frame
sniffer callbacks.
(frame_unwind_register_value): Likewise.
(get_frame_type): Likewise.
(frame_arch_unwind): Likewise.
* stack.c: Include "arch-utils.h".
(print_stack_frame): Reset current_gdbarch to frame arch
while handling one frame.
(print_frame_args): Likewise.
(print_frame_info): Likewise.
(print_frame_local_vars): Likewise.
* regcache.c (regcache_raw_read): Reset current_gdbarch
while calling target routines.
(regcache_raw_write): Likewise.
* gdbarch.sh (gdbarch_data): Reset current_gdbarch while
calling data post_init callback.
* gdbarch.c: Regenerate.
Index: src/gdb/arch-utils.c
===================================================================
--- src.orig/gdb/arch-utils.c
+++ src/gdb/arch-utils.c
@@ -720,6 +720,27 @@ gdbarch_info_fill (struct gdbarch_info *
gdb_assert (info->bfd_arch_info != NULL);
}
+
+/* restore_current_gdbarch() will be used by the cleanup machinery
+ to restore the current_gdbarch value saved in a call to
+ save_current_gdbarch(). */
+
+static void
+restore_current_gdbarch (void *arg)
+{
+ current_gdbarch = arg;
+}
+
+/* Save the value of current so that it may be restored by a
+ later call to do_cleanups(). Returns the struct cleanup pointer
+ needed for later doing the cleanup. */
+
+struct cleanup *
+save_current_gdbarch (void)
+{
+ return make_cleanup (restore_current_gdbarch, current_gdbarch);
+}
+
/* */
extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */
Index: src/gdb/arch-utils.h
===================================================================
--- src.orig/gdb/arch-utils.h
+++ src/gdb/arch-utils.h
@@ -139,4 +139,9 @@ extern void gdbarch_info_fill (struct gd
extern struct gdbarch *gdbarch_from_bfd (bfd *abfd);
+/* Save value of current_gdbarch so that it may be restored by
+ a later call to do_cleanups(). Returns the struct cleanup
+ pointer needed for later doing the cleanup. */
+struct cleanup *save_current_gdbarch (void);
+
#endif
Index: src/gdb/frame.c
===================================================================
--- src.orig/gdb/frame.c
+++ src/gdb/frame.c
@@ -41,6 +41,7 @@
#include "objfiles.h"
#include "exceptions.h"
#include "gdbthread.h"
+#include "arch-utils.h"
static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
@@ -261,6 +262,9 @@ get_frame_id (struct frame_info *fi)
}
if (!fi->this_id.p)
{
+ struct cleanup *old_chain = save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (fi);
+
if (frame_debug)
fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ",
fi->level);
@@ -276,6 +280,8 @@ get_frame_id (struct frame_info *fi)
fprint_frame_id (gdb_stdlog, fi->this_id.value);
fprintf_unfiltered (gdb_stdlog, " }\n");
}
+
+ do_cleanups (old_chain);
}
return fi->this_id.value;
}
@@ -659,6 +665,7 @@ frame_unwind_register_value (struct fram
{
struct gdbarch *gdbarch;
struct value *value;
+ struct cleanup *old_chain;
gdb_assert (frame != NULL);
gdbarch = frame_arch_unwind (frame);
@@ -671,6 +678,9 @@ frame_unwind_register_value (struct fram
user_reg_map_regnum_to_name (gdbarch, regnum));
}
+ old_chain = save_current_gdbarch ();
+ current_gdbarch = gdbarch;
+
/* Find the unwinder. */
if (frame->unwind == NULL)
frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
@@ -712,6 +722,7 @@ frame_unwind_register_value (struct fram
fprintf_unfiltered (gdb_stdlog, " }\n");
}
+ do_cleanups (old_chain);
return value;
}
@@ -1715,9 +1726,17 @@ enum frame_type
get_frame_type (struct frame_info *frame)
{
if (frame->unwind == NULL)
- /* Initialize the frame's unwinder because that's what
- provides the frame's type. */
- frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
+ {
+ struct cleanup *old_chain = save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (frame);
+
+ /* Initialize the frame's unwinder because that's what
+ provides the frame's type. */
+ frame->unwind = frame_unwind_find_by_frame (frame,
+ &frame->prologue_cache);
+ do_cleanups (old_chain);
+ }
+
return frame->unwind->type;
}
@@ -1798,6 +1817,10 @@ frame_arch_unwind (struct frame_info *ne
if (!next_frame->prev_arch.p)
{
struct gdbarch *arch;
+ struct cleanup *old_chain = save_current_gdbarch ();
+
+ if (next_frame->level >= 0)
+ current_gdbarch = get_frame_arch (next_frame);
if (next_frame->unwind == NULL)
next_frame->unwind
@@ -1817,6 +1840,8 @@ frame_arch_unwind (struct frame_info *ne
"{ frame_arch_unwind (next_frame=%d) -> %s }\n",
next_frame->level,
gdbarch_bfd_arch_info (arch)->printable_name);
+
+ do_cleanups (old_chain);
}
return next_frame->prev_arch.arch;
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c
+++ src/gdb/gdbarch.c
@@ -3368,10 +3368,15 @@ gdbarch_data (struct gdbarch *gdbarch, s
(as all fields are valid), but be careful to also detect
recursive references. */
{
+ struct cleanup *old_chain = save_current_gdbarch ();
+ current_gdbarch = gdbarch;
+
gdb_assert (data->init_p);
data->init_p = 0;
gdbarch->data[data->index] = data->post_init (gdbarch);
data->init_p = 1;
+
+ do_cleanups (old_chain);
}
else
/* The architecture initialization hasn't completed - punt -
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh
+++ src/gdb/gdbarch.sh
@@ -1725,10 +1725,15 @@ gdbarch_data (struct gdbarch *gdbarch, s
(as all fields are valid), but be careful to also detect
recursive references. */
{
+ struct cleanup *old_chain = save_current_gdbarch ();
+ current_gdbarch = gdbarch;
+
gdb_assert (data->init_p);
data->init_p = 0;
gdbarch->data[data->index] = data->post_init (gdbarch);
data->init_p = 1;
+
+ do_cleanups (old_chain);
}
else
/* The architecture initialization hasn't completed - punt -
Index: src/gdb/regcache.c
===================================================================
--- src.orig/gdb/regcache.c
+++ src/gdb/regcache.c
@@ -29,6 +29,7 @@
#include "gdb_string.h"
#include "gdbcmd.h" /* For maintenanceprintlist. */
#include "observer.h"
+#include "arch-utils.h"
/*
* DATA STRUCTURE
@@ -544,6 +545,8 @@ regcache_raw_read (struct regcache *regc
{
struct cleanup *old_chain = save_inferior_ptid ();
inferior_ptid = regcache->ptid;
+ save_current_gdbarch ();
+ current_gdbarch = get_regcache_arch (regcache);
target_fetch_registers (regcache, regnum);
do_cleanups (old_chain);
}
@@ -702,6 +705,8 @@ regcache_raw_write (struct regcache *reg
old_chain = save_inferior_ptid ();
inferior_ptid = regcache->ptid;
+ save_current_gdbarch ();
+ current_gdbarch = get_regcache_arch (regcache);
target_prepare_to_store (regcache);
memcpy (register_buffer (regcache, regnum), buf,
Index: src/gdb/stack.c
===================================================================
--- src.orig/gdb/stack.c
+++ src/gdb/stack.c
@@ -45,6 +45,7 @@
#include "valprint.h"
#include "gdbthread.h"
#include "cp-support.h"
+#include "arch-utils.h"
#include "gdb_assert.h"
#include <ctype.h>
@@ -109,6 +110,8 @@ print_stack_frame (struct frame_info *fr
enum print_what print_what)
{
struct print_stack_frame_args args;
+ struct cleanup *old_chain = save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (frame);
args.frame = frame;
args.print_level = print_level;
@@ -118,6 +121,7 @@ print_stack_frame (struct frame_info *fr
args.print_args = 1;
catch_errors (print_stack_frame_stub, &args, "", RETURN_MASK_ERROR);
+ do_cleanups (old_chain);
}
struct print_args_args
@@ -223,6 +227,9 @@ print_frame_args (struct symbol *func, s
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
+ save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (frame);
+
if (func)
{
struct block *b = SYMBOL_BLOCK_VALUE (func);
@@ -471,6 +478,7 @@ print_frame_info (struct frame_info *fra
struct symtab_and_line sal;
int source_print;
int location_print;
+ struct cleanup *old_chain;
if (get_frame_type (frame) == DUMMY_FRAME
|| get_frame_type (frame) == SIGTRAMP_FRAME
@@ -524,6 +532,10 @@ print_frame_info (struct frame_info *fra
the next frame is a SIGTRAMP_FRAME or a DUMMY_FRAME, then the
next frame was not entered as the result of a call, and we want
to get the line containing FRAME->pc. */
+
+ old_chain = save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (frame);
+
find_frame_sal (frame, &sal);
location_print = (print_what == LOCATION
@@ -577,6 +589,7 @@ print_frame_info (struct frame_info *fra
annotate_frame_end ();
gdb_flush (gdb_stdout);
+ do_cleanups (old_chain);
}
static void
@@ -1436,6 +1449,7 @@ static void
print_frame_local_vars (struct frame_info *frame, int num_tabs,
struct ui_file *stream)
{
+ struct cleanup *old_chain;
struct block *block = get_frame_block (frame, 0);
int values_printed = 0;
@@ -1445,6 +1459,9 @@ print_frame_local_vars (struct frame_inf
return;
}
+ old_chain = save_current_gdbarch ();
+ current_gdbarch = get_frame_arch (frame);
+
while (block)
{
if (print_block_frame_locals (block, frame, num_tabs, stream))
@@ -1458,6 +1475,8 @@ print_frame_local_vars (struct frame_inf
if (!values_printed)
fprintf_filtered (stream, _("No locals.\n"));
+
+ do_cleanups (old_chain);
}
/* Same, but print labels. */
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com