This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Support libthread_db xregs interface


This patch adds support to GDB for the libthread_db 'xregs' functions,
which allow registers not present in 'gregset_t' or 'fpregset_t' to be
passed through libthread_db.  The contents of the 'xregs' register set
is not specified by GDB; the libthread_db client can specify whatever
size it likes, and libthread_db will pass it through unchanged.

I'll post a second patch which defines an 'xregs' register set for the
PowerPC E500 SPE registers.

At present, the GNU C library's libthread_db's xregs functions are
stubbed out; I also have a patch to glibc to implement them, which
I'll be submitting.  If GDB loads a libthread_db that does not
implement the xregs functions, this patch handles that case.

These have all been tested on E500 powerpc-unknown-linux-gnu and on
i686-pc-linux-gnu (where they should have no effect).

This patch should allow us to remove the call to dummy_sse_values in
supply_fpregset.  Not that that call is especially necessary or
helpful at the moment anyway, as far as I can tell.

This patch was originally posted here:
http://sources.redhat.com/ml/gdb-patches/2004-03/msg00571.html

I believe it's been revised to implement the suggestions made there.



This is kind of a weird case.  This patch and the E500 xregs patch
have no effect on GDB's visible behavior (other than producing a
warning message (once) when the architecture needs xregs but
libthread_db doesn't implement the xregs functions).  Using a patched
libthread_db, it is impossible to write a test that detects its
presence.

So what's the point?

Well, if the gdb_assert in regcache.c:regcache_raw_read were enabled,
then you'd definitely be able to detect its presence: without the
patch, that assertion would fail, because the call to
target_fetch_registers does not mark the SPE vector registers as
supplied.  The data is there, given the way proc-service.c works, but
the register contents are marked 'invalid'.

But we've found that there's a lot of other work that needs to be done
before that assertion can be enabled.  The sloppiness that this patch
is meant to work around is pretty endemic amongst GDB targets at the
moment.

So the argument against this patch is that it introduces complexity
with no visible effect.  The argument for this patch is that it is a
step towards being able to enable that assert.

But it's been suggested that we not use libthread_db's register access
functions to carry register values at all.  If that's pursued, then
again, this patch is unnecessary.

What do folks think?


2004-06-07  Jim Blandy  <jimb@redhat.com>

	Allow targets to specify an extended register set, to be passed
	through libthread_db via its 'xregs' functions.
	* gdbarch.sh (XREGS_REGSET, XREGS_SIZE, XREGS_NAME): New gdbarch
	members.
	* gdbarch.c, gdbarch.h: Regenerated.
	* proc-service.c: #include "regset.h" and "regcache.h".
	(ps_lgetxregsize, ps_lgetxregs, ps_lsetxregs): Fill in real
	implementations of these functions.
	* thread-db.c: #include "regset.h".
	(td_thr_getxregsize_p, td_thr_getxregs_p, td_thr_setxregs_p): New
	variables.
	(thread_db_load): Initialize them.
	(warned_xregs_not_implemented): New variable.
	(thread_db_new_objfile): Clear it here.
	(thread_db_fetch_registers, thread_db_store_registers): Supply and
	collect the xregset, too, if the architecture says it has one, and
	libthread_db seems to be able to support it.
	* Makefile.in (proc-service.o, thread-db.o): Update dependencies.

Index: gdb/gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.345
diff -c -p -r1.345 gdbarch.sh
*** gdb/gdbarch.sh	8 Aug 2004 20:50:57 -0000	1.345
--- gdb/gdbarch.sh	12 Aug 2004 22:07:57 -0000
*************** F:=:CORE_ADDR:fetch_pointer_argument:str
*** 664,669 ****
--- 664,699 ----
  # Return the appropriate register set for a core file section with
  # name SECT_NAME and size SECT_SIZE.
  M::const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size
+ 
+ # The libthread_db interface passes registers in and out using the same
+ # structures that appear in core files: gregset_t and fpregset_t.
+ # Whether reading or writing:
+ # - GDB first moves data out of the regcache into a struct (using
+ #   fill_gregset or fill_fpregset),
+ # - crosses the thread_db boundary (for writing, calls
+ #   td_thr_setregs; for reading, returns from td_thr_getregs), and
+ # - moves the data from the struct back into the regcache (using
+ #   supply_gregset or supply_fpregset).
+ # 
+ # Some platforms define even more register sets; for example,
+ # members of the PowerPC family supporting the Signal Processing
+ # Extension ("SPE") have 'struct speregset'.  These need to be passed
+ # back and forth across the thread_db boundary.
+ # 
+ # An architecture that has such a register set should:
+ # - choose a structure to hold the extra registers,
+ # - set gdbarch_xregs_regset to a 'struct regset' that can move register
+ #   values into and out of that structure,
+ # - set gdbarch_xregs_size to the structure's size, in bytes, and
+ # - set gdbarch_xregs_name to a string that can be used to refer to the
+ #   structure in error messages and the like.
+ #
+ # Architectures without such a register set should leave
+ # gdbarch_xregs_regset set to zero.
+ v:=:const struct regset *:xregs_regset:::0
+ v:=:int:xregs_size:::0
+ v:=:const char *:xregs_name:::0
+ 
  EOF
  }
  
Index: gdb/gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.310
diff -c -p -r1.310 gdbarch.c
*** gdb/gdbarch.c	8 Aug 2004 19:49:40 -0000	1.310
--- gdb/gdbarch.c	12 Aug 2004 22:07:55 -0000
*************** struct gdbarch
*** 229,234 ****
--- 229,237 ----
    gdbarch_register_reggroup_p_ftype *register_reggroup_p;
    gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
    gdbarch_regset_from_core_section_ftype *regset_from_core_section;
+   const struct regset * xregs_regset;
+   int xregs_size;
+   const char * xregs_name;
  };
  
  
*************** struct gdbarch startup_gdbarch =
*** 355,360 ****
--- 358,366 ----
    default_register_reggroup_p,  /* register_reggroup_p */
    0,  /* fetch_pointer_argument */
    0,  /* regset_from_core_section */
+   0,  /* xregs_regset */
+   0,  /* xregs_size */
+   0,  /* xregs_name */
    /* startup_gdbarch() */
  };
  
*************** gdbarch_dump (struct gdbarch *current_gd
*** 1625,1630 ****
--- 1631,1660 ----
    fprintf_unfiltered (file,
                        "gdbarch_dump: write_pc = <0x%lx>\n",
                        (long) current_gdbarch->write_pc);
+ #ifdef XREGS_NAME
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: XREGS_NAME # %s\n",
+                       XSTRING (XREGS_NAME));
+ #endif
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: xregs_name = %s\n",
+                       paddr_d (current_gdbarch->xregs_name));
+ #ifdef XREGS_REGSET
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: XREGS_REGSET # %s\n",
+                       XSTRING (XREGS_REGSET));
+ #endif
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: xregs_regset = %s\n",
+                       paddr_d (current_gdbarch->xregs_regset));
+ #ifdef XREGS_SIZE
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: XREGS_SIZE # %s\n",
+                       XSTRING (XREGS_SIZE));
+ #endif
+   fprintf_unfiltered (file,
+                       "gdbarch_dump: xregs_size = %s\n",
+                       paddr_d (current_gdbarch->xregs_size));
    if (current_gdbarch->dump_tdep != NULL)
      current_gdbarch->dump_tdep (current_gdbarch, file);
  }
*************** set_gdbarch_regset_from_core_section (st
*** 3673,3678 ****
--- 3703,3756 ----
    gdbarch->regset_from_core_section = regset_from_core_section;
  }
  
+ const struct regset *
+ gdbarch_xregs_regset (struct gdbarch *gdbarch)
+ {
+   gdb_assert (gdbarch != NULL);
+   if (gdbarch_debug >= 2)
+     fprintf_unfiltered (gdb_stdlog, "gdbarch_xregs_regset called\n");
+   return gdbarch->xregs_regset;
+ }
+ 
+ void
+ set_gdbarch_xregs_regset (struct gdbarch *gdbarch,
+                           const struct regset * xregs_regset)
+ {
+   gdbarch->xregs_regset = xregs_regset;
+ }
+ 
+ int
+ gdbarch_xregs_size (struct gdbarch *gdbarch)
+ {
+   gdb_assert (gdbarch != NULL);
+   if (gdbarch_debug >= 2)
+     fprintf_unfiltered (gdb_stdlog, "gdbarch_xregs_size called\n");
+   return gdbarch->xregs_size;
+ }
+ 
+ void
+ set_gdbarch_xregs_size (struct gdbarch *gdbarch,
+                         int xregs_size)
+ {
+   gdbarch->xregs_size = xregs_size;
+ }
+ 
+ const char *
+ gdbarch_xregs_name (struct gdbarch *gdbarch)
+ {
+   gdb_assert (gdbarch != NULL);
+   if (gdbarch_debug >= 2)
+     fprintf_unfiltered (gdb_stdlog, "gdbarch_xregs_name called\n");
+   return gdbarch->xregs_name;
+ }
+ 
+ void
+ set_gdbarch_xregs_name (struct gdbarch *gdbarch,
+                         const char * xregs_name)
+ {
+   gdbarch->xregs_name = xregs_name;
+ }
+ 
  
  /* Keep a registry of per-architecture data-pointers required by GDB
     modules. */
Index: gdb/gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.272
diff -c -p -r1.272 gdbarch.h
*** gdb/gdbarch.h	8 Aug 2004 20:50:57 -0000	1.272
--- gdb/gdbarch.h	12 Aug 2004 22:07:56 -0000
*************** typedef const struct regset * (gdbarch_r
*** 1435,1440 ****
--- 1435,1493 ----
  extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
  extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);
  
+ /* The libthread_db interface passes registers in and out using the same
+    structures that appear in core files: gregset_t and fpregset_t.
+    Whether reading or writing:
+    - GDB first moves data out of the regcache into a struct (using
+      fill_gregset or fill_fpregset),
+    - crosses the thread_db boundary (for writing, calls
+      td_thr_setregs; for reading, returns from td_thr_getregs), and
+    - moves the data from the struct back into the regcache (using
+      supply_gregset or supply_fpregset).
+   
+    Some platforms define even more register sets; for example,
+    members of the PowerPC family supporting the Signal Processing
+    Extension ("SPE") have 'struct speregset'.  These need to be passed
+    back and forth across the thread_db boundary.
+   
+    An architecture that has such a register set should:
+    - choose a structure to hold the extra registers,
+    - set gdbarch_xregs_regset to a 'struct regset' that can move register
+      values into and out of that structure,
+    - set gdbarch_xregs_size to the structure's size, in bytes, and
+    - set gdbarch_xregs_name to a string that can be used to refer to the
+      structure in error messages and the like.
+   
+    Architectures without such a register set should leave
+    gdbarch_xregs_regset set to zero. */
+ 
+ extern const struct regset * gdbarch_xregs_regset (struct gdbarch *gdbarch);
+ extern void set_gdbarch_xregs_regset (struct gdbarch *gdbarch, const struct regset * xregs_regset);
+ #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (XREGS_REGSET)
+ #error "Non multi-arch definition of XREGS_REGSET"
+ #endif
+ #if !defined (XREGS_REGSET)
+ #define XREGS_REGSET (gdbarch_xregs_regset (current_gdbarch))
+ #endif
+ 
+ extern int gdbarch_xregs_size (struct gdbarch *gdbarch);
+ extern void set_gdbarch_xregs_size (struct gdbarch *gdbarch, int xregs_size);
+ #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (XREGS_SIZE)
+ #error "Non multi-arch definition of XREGS_SIZE"
+ #endif
+ #if !defined (XREGS_SIZE)
+ #define XREGS_SIZE (gdbarch_xregs_size (current_gdbarch))
+ #endif
+ 
+ extern const char * gdbarch_xregs_name (struct gdbarch *gdbarch);
+ extern void set_gdbarch_xregs_name (struct gdbarch *gdbarch, const char * xregs_name);
+ #if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (XREGS_NAME)
+ #error "Non multi-arch definition of XREGS_NAME"
+ #endif
+ #if !defined (XREGS_NAME)
+ #define XREGS_NAME (gdbarch_xregs_name (current_gdbarch))
+ #endif
+ 
  extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
  
  
Index: gdb/proc-service.c
===================================================================
RCS file: /cvs/src/src/gdb/proc-service.c,v
retrieving revision 1.7
diff -c -p -r1.7 proc-service.c
*** gdb/proc-service.c	24 Feb 2002 22:31:19 -0000	1.7
--- gdb/proc-service.c	12 Aug 2004 22:07:58 -0000
***************
*** 27,32 ****
--- 27,34 ----
  #include "inferior.h"
  #include "symtab.h"
  #include "target.h"
+ #include "regset.h"
+ #include "regcache.h"
  
  /* Prototypes for supply_gregset etc.  */
  #include "gregset.h"
*************** ps_lcontinue (gdb_ps_prochandle_t ph, lw
*** 131,137 ****
  ps_err_e
  ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
  {
!   /* FIXME: Not supported yet.  */
    return PS_OK;
  }
  
--- 133,143 ----
  ps_err_e
  ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
  {
!   if (! gdbarch_xregs_regset (current_gdbarch))
!     /* This architecture has no extra registers.  */
!     return PS_ERR;
! 
!   *xregsize = gdbarch_xregs_size (current_gdbarch);
    return PS_OK;
  }
  
*************** ps_lgetxregsize (gdb_ps_prochandle_t ph,
*** 141,147 ****
  ps_err_e
  ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
  {
!   /* FIXME: Not supported yet.  */
    return PS_OK;
  }
  
--- 147,167 ----
  ps_err_e
  ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
  {
!   struct cleanup *old_chain = save_inferior_ptid ();
!   struct regset *xregs_regset = gdbarch_xregs_regset (current_gdbarch);
! 
!   if (! xregs_regset)
!     /* This target has no extra registers.  */
!     return PS_OK;
! 
!   inferior_ptid = BUILD_LWP (lwpid, ph->pid);
! 
!   target_fetch_registers (-1);
!   xregs_regset->collect_regset (xregs_regset, current_regcache, -1,
!                                 (void *) xregset, 
!                                 gdbarch_xregs_size (current_gdbarch));
! 
!   do_cleanups (old_chain);
    return PS_OK;
  }
  
*************** ps_lgetxregs (gdb_ps_prochandle_t ph, lw
*** 151,157 ****
  ps_err_e
  ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
  {
!   /* FIXME: Not supported yet.  */
    return PS_OK;
  }
  
--- 171,193 ----
  ps_err_e
  ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
  {
!   struct cleanup *old_chain = save_inferior_ptid ();
!   struct regset *xregs_regset = gdbarch_xregs_regset (current_gdbarch);
! 
!   if (! xregs_regset)
!     /* This architecture has no extended register set.  */
!     return PS_OK;
! 
!   inferior_ptid = BUILD_LWP (lwpid, ph->pid);
! 
!   xregs_regset->supply_regset (xregs_regset, current_regcache, -1,
!                                (void *) xregset,
!                                gdbarch_xregs_size (current_gdbarch));
! 
!   target_store_registers (-1);
! 
!   do_cleanups (old_chain);
! 
    return PS_OK;
  }
  
Index: gdb/thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/thread-db.c,v
retrieving revision 1.43
diff -c -p -r1.43 thread-db.c
*** gdb/thread-db.c	22 Jul 2004 01:31:49 -0000	1.43
--- gdb/thread-db.c	12 Aug 2004 22:07:59 -0000
***************
*** 32,37 ****
--- 32,38 ----
  #include "symfile.h"
  #include "objfiles.h"
  #include "target.h"
+ #include "regset.h"
  #include "regcache.h"
  #include "solib-svr4.h"
  
*************** static td_err_e (*td_ta_event_getmsg_p) 
*** 105,118 ****
--- 106,125 ----
  static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
  static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
  				      td_thrinfo_t *infop);
+ static td_err_e (*td_thr_getxregsize_p) (const td_thrhandle_t *__th,
+                                          int *__sizep);
  static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
  				       gdb_prfpregset_t *regset);
  static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
  				      prgregset_t gregs);
+ static td_err_e (*td_thr_getxregs_p) (const td_thrhandle_t *__th,
+                                       void *__xregs);
  static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
  				       const gdb_prfpregset_t *fpregs);
  static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
  				      prgregset_t gregs);
+ static td_err_e (*td_thr_setxregs_p) (const td_thrhandle_t *__th,
+                                       const void *__addr);
  static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
  					  int event);
  
*************** static CORE_ADDR td_create_bp_addr;
*** 130,135 ****
--- 137,150 ----
  /* Location of the thread death event breakpoint.  */
  static CORE_ADDR td_death_bp_addr;
  
+ /* On some architectures, there are additional regs beyond the gregset
+    and fpregset.  The libthread_db interface has functions to access
+    these, but on some versions of libthread_db they are not
+    implemented.  We want to warn the user about this, but not treat it
+    as a fatal error, since you can still access the other
+    registers.  */
+ static int warned_xregs_not_implemented;
+ 
  /* Prototypes for local functions.  */
  static void thread_db_find_new_threads (void);
  static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
*************** thread_db_load (void)
*** 470,475 ****
--- 485,494 ----
    if (td_thr_get_info_p == NULL)
      return 0;
  
+   td_thr_getxregsize_p = verbose_dlsym (handle, "td_thr_getxregsize");
+   if (td_thr_getxregsize_p == NULL)
+     return 0;
+ 
    td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
    if (td_thr_getfpregs_p == NULL)
      return 0;
*************** thread_db_load (void)
*** 478,483 ****
--- 497,506 ----
    if (td_thr_getgregs_p == NULL)
      return 0;
  
+   td_thr_getxregs_p = verbose_dlsym (handle, "td_thr_getxregs");
+   if (td_thr_getxregs_p == NULL)
+     return 0;
+ 
    td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
    if (td_thr_setfpregs_p == NULL)
      return 0;
*************** thread_db_load (void)
*** 486,491 ****
--- 509,518 ----
    if (td_thr_setgregs_p == NULL)
      return 0;
  
+   td_thr_setxregs_p = verbose_dlsym (handle, "td_thr_setxregs");
+   if (td_thr_setxregs_p == NULL)
+     return 0;
+ 
    /* Initialize the library.  */
    err = td_init_p ();
    if (err != TD_OK)
*************** thread_db_new_objfile (struct objfile *o
*** 703,708 ****
--- 730,740 ----
        push_target (&thread_db_ops);
        using_thread_db = 1;
  
+       /* If the gdbarch says we have an extended register set, but we are
+          unable to access them via libthread_db, we want to issue one
+          warning each time we active libthread_db.  */
+       warned_xregs_not_implemented = 0;
+ 
        /* If the thread library was detected in the main symbol file
           itself, we assume that the program was statically linked
           against the thread library and well have to keep this
*************** thread_db_fetch_registers (int regno)
*** 1024,1029 ****
--- 1056,1064 ----
    struct thread_info *thread_info;
    prgregset_t gregset;
    gdb_prfpregset_t fpregset;
+   void *xregs = 0;
+   int fetched_xregs = 0;
+   struct regset *xregs_regset = gdbarch_xregs_regset (current_gdbarch);
    td_err_e err;
  
    if (!is_thread (inferior_ptid))
*************** thread_db_fetch_registers (int regno)
*** 1036,1041 ****
--- 1071,1079 ----
    thread_info = find_thread_pid (inferior_ptid);
    thread_db_map_id2thr (thread_info, 1);
  
+   if (xregs_regset)
+     xregs = alloca (gdbarch_xregs_size (current_gdbarch));
+ 
    err = td_thr_getgregs_p (&thread_info->private->th, gregset);
    if (err != TD_OK)
      error ("Cannot fetch general-purpose registers for thread %ld: %s",
*************** thread_db_fetch_registers (int regno)
*** 1046,1056 ****
--- 1084,1124 ----
      error ("Cannot get floating-point registers for thread %ld: %s",
  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
  
+   if (xregs_regset)
+     {
+       err = td_thr_getxregs_p (&thread_info->private->th, xregs);
+       switch (err)
+         {
+         case TD_OK:
+           fetched_xregs = 1;
+           break;
+ 
+         case TD_NOXREGS:
+           if (! warned_xregs_not_implemented)
+             {
+               warning ("thread debugging library is too old to access "
+                        "%s registers.",
+                        gdbarch_xregs_name (current_gdbarch));
+               warned_xregs_not_implemented = 1;
+             }
+           break;
+ 
+         default:
+           error ("Cannot get %s registers for thread %ld: %s",
+                  gdbarch_xregs_name (current_gdbarch),
+                  (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+         }
+     }
+ 
    /* Note that we must call supply_gregset after calling the thread_db
       routines because the thread_db routines call ps_lgetgregs and
       friends which clobber GDB's register cache.  */
    supply_gregset ((gdb_gregset_t *) gregset);
    supply_fpregset (&fpregset);
+ 
+   if (fetched_xregs)
+     xregs_regset->supply_regset (xregs_regset, current_regcache, -1, xregs,
+                                  gdbarch_xregs_size (current_gdbarch));
  }
  
  static void
*************** thread_db_store_registers (int regno)
*** 1058,1063 ****
--- 1126,1133 ----
  {
    prgregset_t gregset;
    gdb_prfpregset_t fpregset;
+   void *xregs = 0;
+   struct regset *xregs_regset = gdbarch_xregs_regset (current_gdbarch);
    td_err_e err;
    struct thread_info *thread_info;
  
*************** thread_db_store_registers (int regno)
*** 1071,1076 ****
--- 1141,1149 ----
    thread_info = find_thread_pid (inferior_ptid);
    thread_db_map_id2thr (thread_info, 1);
  
+   if (xregs_regset)
+     xregs = alloca (gdbarch_xregs_size (current_gdbarch));
+ 
    if (regno != -1)
      {
        char raw[MAX_REGISTER_SIZE];
*************** thread_db_store_registers (int regno)
*** 1082,1087 ****
--- 1155,1164 ----
  
    fill_gregset ((gdb_gregset_t *) gregset, -1);
    fill_fpregset (&fpregset, -1);
+   if (xregs_regset)
+     xregs_regset->collect_regset (xregs_regset, current_regcache, -1,
+                                   (void *) xregs,
+                                   gdbarch_xregs_size (current_gdbarch));
  
    err = td_thr_setgregs_p (&thread_info->private->th, gregset);
    if (err != TD_OK)
*************** thread_db_store_registers (int regno)
*** 1091,1096 ****
--- 1168,1191 ----
    if (err != TD_OK)
      error ("Cannot store floating-point registers  for thread %ld: %s",
  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+   if (xregs_regset)
+     {
+       err = td_thr_setxregs_p (&thread_info->private->th, xregs);
+       if (err == TD_NOXREGS)
+         {
+           if (! warned_xregs_not_implemented)
+             {
+               warning ("thread debugging library is too old to access"
+                        " %s registers.",
+                        gdbarch_xregs_name (current_gdbarch));
+               warned_xregs_not_implemented = 1;
+             }
+         }
+       else if (err != TD_OK)
+         error ("Cannot store %s registers for thread %ld: %s",
+                gdbarch_xregs_name (current_gdbarch),
+                (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
+     }
  }
  
  static void
Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.607
diff -c -p -r1.607 Makefile.in
*** gdb/Makefile.in	8 Aug 2004 19:27:09 -0000	1.607
--- gdb/Makefile.in	12 Aug 2004 22:07:53 -0000
*************** procfs.o: procfs.c $(defs_h) $(inferior_
*** 2309,2315 ****
  	$(gdb_string_h) $(gdb_assert_h) $(inflow_h) $(auxv_h) \
  	$(gdb_dirent_h) $(X_OK) $(gdb_stat_h) $(proc_utils_h) $(gregset_h)
  proc-service.o: proc-service.c $(defs_h) $(gdb_proc_service_h) $(inferior_h) \
! 	$(symtab_h) $(target_h) $(gregset_h)
  proc-why.o: proc-why.c $(defs_h) $(proc_utils_h)
  p-typeprint.o: p-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \
  	$(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(target_h) \
--- 2309,2315 ----
  	$(gdb_string_h) $(gdb_assert_h) $(inflow_h) $(auxv_h) \
  	$(gdb_dirent_h) $(X_OK) $(gdb_stat_h) $(proc_utils_h) $(gregset_h)
  proc-service.o: proc-service.c $(defs_h) $(gdb_proc_service_h) $(inferior_h) \
! 	$(symtab_h) $(target_h) $(regset_h) $(regcache_h) $(gregset_h)
  proc-why.o: proc-why.c $(defs_h) $(proc_utils_h)
  p-typeprint.o: p-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \
  	$(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(target_h) \
*************** thread.o: thread.c $(defs_h) $(symtab_h)
*** 2580,2586 ****
  	$(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) $(ui_out_h)
  thread-db.o: thread-db.c $(defs_h) $(gdb_assert_h) $(gdb_proc_service_h) \
  	$(gdb_thread_db_h) $(bfd_h) $(gdbthread_h) $(inferior_h) \
! 	$(symfile_h) $(objfiles_h) $(target_h) $(regcache_h) $(solib_svr4_h)
  top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \
  	$(cli_script_h) $(cli_setshow_h) $(cli_decode_h) $(symtab_h) \
  	$(inferior_h) $(target_h) $(breakpoint_h) $(gdbtypes_h) \
--- 2580,2587 ----
  	$(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) $(ui_out_h)
  thread-db.o: thread-db.c $(defs_h) $(gdb_assert_h) $(gdb_proc_service_h) \
  	$(gdb_thread_db_h) $(bfd_h) $(gdbthread_h) $(inferior_h) \
! 	$(symfile_h) $(objfiles_h) $(target_h) $(regset_h) $(regcache_h) \
! 	$(solib_svr4_h)
  top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \
  	$(cli_script_h) $(cli_setshow_h) $(cli_decode_h) $(symtab_h) \
  	$(inferior_h) $(target_h) $(breakpoint_h) $(gdbtypes_h) \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]