]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Merge ten gdb and gdbserver patches for MIPS/MIPS64 support.
authorDaniel Jacobowitz <drow@false.org>
Wed, 15 Mar 2006 19:53:38 +0000 (19:53 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 15 Mar 2006 19:53:38 +0000 (19:53 +0000)
16 files changed:
gdb/Makefile.in
gdb/gdb_proc_service.h
gdb/gdbserver/Makefile.in
gdb/gdbserver/config.in
gdb/gdbserver/configure
gdb/gdbserver/configure.ac
gdb/gdbserver/linux-i386-low.c
gdb/gdbserver/linux-mips-low.c
gdb/gdbserver/linux-x86-64-low.c
gdb/gdbserver/proc-service.c
gdb/gdbserver/thread-db.c
gdb/mips-linux-nat.c
gdb/mips-linux-tdep.c
gdb/mips-mdebug-tdep.c
gdb/mips-tdep.c
gdb/proc-service.c

index acba593b0ebc92c0e14e57778fae41855d6eef6c..99aa888c29f49e95f01f2d5cb524fe6935d98429 100644 (file)
@@ -737,6 +737,7 @@ macrotab_h = macrotab.h
 main_h = main.h
 mdebugread_h = mdebugread.h $(coff_sym_h) $(coff_symconst_h)
 memattr_h = memattr.h
+mips_linux_tdep_h = mips-linux-tdep.h
 mips_mdebug_tdep_h = mips-mdebug-tdep.h
 mipsnbsd_tdep_h = mipsnbsd-tdep.h
 mips_tdep_h = mips-tdep.h
@@ -2295,11 +2296,12 @@ mips64obsd-tdep.o: mips64obsd-tdep.c $(defs_h) $(osabi_h) $(regcache_h) \
        $(gdb_string_h) $(mips_tdep_h) $(solib_svr4_h)
 mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h)
 mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \
-       $(linux_nat_h)
+       $(linux_nat_h) $(gdb_proc_service_h) $(mips_linux_tdep_h) \
+       $(inferior_h)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
        $(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \
        $(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \
-       $(tramp_frame_h)
+       $(tramp_frame_h) $(floatformat_h) $(mips_linux_tdep_h)
 mips-mdebug-tdep.o: mips-mdebug-tdep.c $(defs_h) $(frame_h) $(mips_tdep_h) \
        $(trad_frame_h) $(block_h) $(symtab_h) $(objfiles_h) $(elf_mips_h) \
        $(elf_bfd_h) $(gdb_assert_h) $(frame_unwind_h) $(frame_base_h) \
index 408a87b0d4eaeebf11ffa9c05b6cfc1113d38a3b..fc559bed88fdcfbb99c160d08b09a40b9ef7fff8 100644 (file)
@@ -1,5 +1,5 @@
 /* <proc_service.h> replacement for systems that don't have it.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -48,10 +48,11 @@ typedef enum
 typedef unsigned int lwpid_t;
 #endif
 
-typedef unsigned long paddr_t;
-
 #ifndef HAVE_PSADDR_T
 typedef unsigned long psaddr_t;
+typedef unsigned long paddr_t;
+#else
+typedef psaddr_t paddr_t;
 #endif
 
 #ifndef HAVE_PRGREGSET_T
index 19ee78b221fe79f2d9c83aa7610911e09fa8d45d..0da5f6cde6876f717af6248e9b9c097ebb38053a 100644 (file)
@@ -242,7 +242,7 @@ version.o: version.c $(server_h)
 # will remove them.
 MAKEOVERRIDES=
 
-gdb_proc_service_h = $(srcdir)/../gdb_proc_service.h $(srcdir)/../gregset.h
+gdb_proc_service_h = $(srcdir)/gdb_proc_service.h
 regdat_sh = $(srcdir)/../regformats/regdat.sh
 regdef_h = $(srcdir)/../regformats/regdef.h
 regcache_h = $(srcdir)/regcache.h
@@ -272,15 +272,18 @@ linux-low.o: linux-low.c $(linux_low_h) $(server_h)
 linux-arm-low.o: linux-arm-low.c $(linux_low_h) $(server_h)
 linux-cris-low.o: linux-cris-low.c $(linux_low_h) $(server_h)
 linux-crisv32-low.o: linux-crisv32-low.c $(linux_low_h) $(server_h)
-linux-i386-low.o: linux-i386-low.c $(linux_low_h) $(server_h)
+linux-i386-low.o: linux-i386-low.c $(linux_low_h) $(server_h) \
+       $(gdb_proc_service_h)
 linux-ia64-low.o: linux-ia64-low.c $(linux_low_h) $(server_h)
 linux-m32r-low.o: linux-m32r-low.c $(linux_low_h) $(server_h)
-linux-mips-low.o: linux-mips-low.c $(linux_low_h) $(server_h)
+linux-mips-low.o: linux-mips-low.c $(linux_low_h) $(server_h) \
+       $(gdb_proc_service_h)
 linux-ppc-low.o: linux-ppc-low.c $(linux_low_h) $(server_h)
 linux-ppc64-low.o: linux-ppc64-low.c $(linux_low_h) $(server_h)
 linux-s390-low.o: linux-s390-low.c $(linux_low_h) $(server_h)
 linux-sh-low.o: linux-sh-low.c $(linux_low_h) $(server_h)
-linux-x86-64-low.o: linux-x86-64-low.c $(linux_low_h) $(server_h)
+linux-x86-64-low.o: linux-x86-64-low.c $(linux_low_h) $(server_h) \
+       $(gdb_proc_service_h)
 
 reg-arm.o : reg-arm.c $(regdef_h)
 reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh)
index 59e56bc8e8e2af3e2ffad7adf2236cfdf4269d53..3aa2811ecef410469545f0832ef4d33cbc620ecd 100644 (file)
@@ -25,9 +25,6 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
-/* Define if <sys/procfs.h> has prfpregset_t. */
-#undef HAVE_PRFPREGSET_T
-
 /* Define if <sys/procfs.h> has prgregset_t. */
 #undef HAVE_PRGREGSET_T
 
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Define if the prfpregset_t type is broken. */
-#undef PRFPREGSET_T_BROKEN
-
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
index 1373538d1dd218ed0691a3d319ca1adf2f62b1ff..262d5ef99acc4b81db9f544fcf4553c3f8273994 100755 (executable)
@@ -3544,131 +3544,6 @@ _ACEOF
  echo "$as_me:$LINENO: result: $bfd_cv_have_sys_procfs_type_prgregset_t" >&5
 echo "${ECHO_T}$bfd_cv_have_sys_procfs_type_prgregset_t" >&6
 
-  echo "$as_me:$LINENO: checking for prfpregset_t in sys/procfs.h" >&5
-echo $ECHO_N "checking for prfpregset_t in sys/procfs.h... $ECHO_C" >&6
- if test "${bfd_cv_have_sys_procfs_type_prfpregset_t+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-#define _SYSCALL32
-#include <sys/procfs.h>
-int
-main ()
-{
-prfpregset_t avar
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  bfd_cv_have_sys_procfs_type_prfpregset_t=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-bfd_cv_have_sys_procfs_type_prfpregset_t=no
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
- if test $bfd_cv_have_sys_procfs_type_prfpregset_t = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_PRFPREGSET_T 1
-_ACEOF
-
- fi
- echo "$as_me:$LINENO: result: $bfd_cv_have_sys_procfs_type_prfpregset_t" >&5
-echo "${ECHO_T}$bfd_cv_have_sys_procfs_type_prfpregset_t" >&6
-
-
-
-
-  if test $bfd_cv_have_sys_procfs_type_prfpregset_t = yes; then
-    echo "$as_me:$LINENO: checking whether prfpregset_t type is broken" >&5
-echo $ECHO_N "checking whether prfpregset_t type is broken... $ECHO_C" >&6
-    if test "${gdb_cv_prfpregset_t_broken+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test "$cross_compiling" = yes; then
-  gdb_cv_prfpregset_t_broken=yes
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/procfs.h>
-       int main ()
-       {
-         if (sizeof (prfpregset_t) == sizeof (void *))
-           return 1;
-         return 0;
-       }
-_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  gdb_cv_prfpregset_t_broken=no
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-gdb_cv_prfpregset_t_broken=yes
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-fi
-
-    echo "$as_me:$LINENO: result: $gdb_cv_prfpregset_t_broken" >&5
-echo "${ECHO_T}$gdb_cv_prfpregset_t_broken" >&6
-    if test $gdb_cv_prfpregset_t_broken = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define PRFPREGSET_T_BROKEN 1
-_ACEOF
-
-    fi
-  fi
-
   echo "$as_me:$LINENO: checking for elf_fpregset_t in sys/procfs.h" >&5
 echo $ECHO_N "checking for elf_fpregset_t in sys/procfs.h... $ECHO_C" >&6
  if test "${bfd_cv_have_sys_procfs_type_elf_fpregset_t+set}" = set; then
index fabd94db517e0a96f1b5c4026b4e8a2d4dca32ba..a952af5d83cac8be6c086fff3aab2917311b3d0d 100644 (file)
@@ -1,5 +1,6 @@
 dnl Autoconf configure script for GDB server.
-dnl Copyright (C) 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+dnl Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006
+dnl Free Software Foundation, Inc.
 dnl
 dnl This file is part of GDB.
 dnl
@@ -88,35 +89,6 @@ if test "$ac_cv_header_sys_procfs_h" = yes; then
   BFD_HAVE_SYS_PROCFS_TYPE(lwpid_t)
   BFD_HAVE_SYS_PROCFS_TYPE(psaddr_t)
   BFD_HAVE_SYS_PROCFS_TYPE(prgregset_t)
-  BFD_HAVE_SYS_PROCFS_TYPE(prfpregset_t)
-
-  dnl Check for broken prfpregset_t type
-
-  dnl For Linux/i386, glibc 2.1.3 was released with a bogus
-  dnl prfpregset_t type (it's a typedef for the pointer to a struct
-  dnl instead of the struct itself).  We detect this here, and work
-  dnl around it in gdb_proc_service.h.
-
-  if test $bfd_cv_have_sys_procfs_type_prfpregset_t = yes; then
-    AC_MSG_CHECKING(whether prfpregset_t type is broken)
-    AC_CACHE_VAL(gdb_cv_prfpregset_t_broken,
-      [AC_TRY_RUN([#include <sys/procfs.h>
-       int main ()
-       {
-         if (sizeof (prfpregset_t) == sizeof (void *))
-           return 1;
-         return 0;
-       }],
-       gdb_cv_prfpregset_t_broken=no,
-       gdb_cv_prfpregset_t_broken=yes,
-       gdb_cv_prfpregset_t_broken=yes)])
-    AC_MSG_RESULT($gdb_cv_prfpregset_t_broken)
-    if test $gdb_cv_prfpregset_t_broken = yes; then
-      AC_DEFINE(PRFPREGSET_T_BROKEN, 1,
-               [Define if the prfpregset_t type is broken.])
-    fi
-  fi
-
   BFD_HAVE_SYS_PROCFS_TYPE(elf_fpregset_t)
 fi
 
index 96359fb92e11b086c240f0f469e04907ff60601c..c0daf0b76ca1f89d24120334f049b0d5e4dd879a 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU/Linux/i386 specific low level interface, for the remote server for GDB.
-   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2004, 2005
+   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "linux-low.h"
 #include "i387-fp.h"
 
-/* Correct for all GNU/Linux targets (for quite some time).  */
-#define GDB_GREGSET_T elf_gregset_t
-#define GDB_FPREGSET_T elf_fpregset_t
-
-#ifndef HAVE_ELF_FPREGSET_T
-/* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
-   via <sys/procfs.h>.  */
-#ifdef HAVE_LINUX_ELF_H   
-#include <linux/elf.h>    
-#endif
-#endif
-   
-#include "../gdb_proc_service.h"
+#include "gdb_proc_service.h"
 
 #include <sys/ptrace.h>
 
index 695bd29bf0d545407efc348b1fe21638b4a74920..78295505f31ee913de4b17ab0dca9769d52d6cc4 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU/Linux/MIPS specific low level interface, for the remote server for GDB.
-   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005
+   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "server.h"
 #include "linux-low.h"
 
+#include <sys/ptrace.h>
+
+#include "gdb_proc_service.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
 #ifdef HAVE_SYS_REG_H
 #include <sys/reg.h>
 #endif
@@ -140,6 +148,23 @@ mips_breakpoint_at (CORE_ADDR where)
   return 0;
 }
 
+/* Fetch the thread-local storage pointer for libthread_db.  */
+
+ps_err_e
+ps_get_thread_area (const struct ps_prochandle *ph,
+                    lwpid_t lwpid, int idx, void **base)
+{
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (void *) ((char *)*base - idx);
+
+  return PS_OK;
+}
+
 struct linux_target_ops the_low_target = {
   mips_num_regs,
   mips_regmap,
index 7a4a76aa4437af4c687fbb7c585023ea3b8cd407..43cd10b0b396d4078dae648953741bc0d0d93933 100644 (file)
@@ -1,6 +1,6 @@
 /* GNU/Linux/x86-64 specific low level interface, for the remote server
    for GDB.
-   Copyright (C) 2002, 2004, 2005
+   Copyright (C) 2002, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 #include "linux-low.h"
 #include "i387-fp.h"
 
-/* Correct for all GNU/Linux targets (for quite some time).  */
-#define GDB_GREGSET_T elf_gregset_t
-#define GDB_FPREGSET_T elf_fpregset_t
-
-#ifndef HAVE_ELF_FPREGSET_T
-/* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
-   via <sys/procfs.h>.  */
-#ifdef HAVE_LINUX_ELF_H   
-#include <linux/elf.h>    
-#endif
-#endif
-   
-#include "../gdb_proc_service.h"
+#include "gdb_proc_service.h"
 
 #include <sys/reg.h>
 #include <sys/procfs.h>
index a64919e54eec5b94f2f74f09bdb678b3bc7f8b5d..99083f1733340e9e49c8bfa2808d8cc94e731326 100644 (file)
@@ -1,5 +1,5 @@
 /* libthread_db helper functions for the remote server for GDB.
-   Copyright (C) 2002, 2004, 2005
+   Copyright (C) 2002, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
 
 #include "linux-low.h"
 
-/* Correct for all GNU/Linux targets (for quite some time).  */
-#define GDB_GREGSET_T elf_gregset_t
-#define GDB_FPREGSET_T elf_fpregset_t
-
-#ifndef HAVE_ELF_FPREGSET_T
-/* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
-   via <sys/procfs.h>.  */
-#ifdef HAVE_LINUX_ELF_H   
-#include <linux/elf.h>    
-#endif
-#endif
-
-#include "../gdb_proc_service.h"
+#include "gdb_proc_service.h"
 
 typedef struct ps_prochandle *gdb_ps_prochandle_t;
 typedef void *gdb_ps_read_buf_t;
@@ -75,14 +63,14 @@ gregset_info(void)
 
 ps_err_e
 ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
-                  const char *name, paddr_t *sym_addr)
+                  const char *name, psaddr_t *sym_addr)
 {
   CORE_ADDR addr;
 
   if (look_up_one_symbol (name, &addr) == 0)
     return PS_NOSYM;
 
-  *sym_addr = (paddr_t) (unsigned long) addr;
+  *sym_addr = (psaddr_t) (unsigned long) addr;
   return PS_OK;
 }
 
@@ -90,20 +78,20 @@ ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
    them into BUF.  */
 
 ps_err_e
-ps_pdread (gdb_ps_prochandle_t ph, paddr_t addr,
+ps_pdread (gdb_ps_prochandle_t ph, psaddr_t addr,
           gdb_ps_read_buf_t buf, gdb_ps_size_t size)
 {
-  read_inferior_memory (addr, buf, size);
+  read_inferior_memory ((unsigned long) addr, buf, size);
   return PS_OK;
 }
 
 /* Write SIZE bytes from BUF into the target process PH at address ADDR.  */
 
 ps_err_e
-ps_pdwrite (gdb_ps_prochandle_t ph, paddr_t addr,
+ps_pdwrite (gdb_ps_prochandle_t ph, psaddr_t addr,
            gdb_ps_write_buf_t buf, gdb_ps_size_t size)
 {
-  return write_inferior_memory (addr, buf, size);
+  return write_inferior_memory ((unsigned long) addr, buf, size);
 }
 
 /* Get the general registers of LWP LWPID within the target process PH
@@ -149,8 +137,7 @@ ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, const prgregset_t gregset)
    process PH and store them in FPREGSET.  */
 
 ps_err_e
-ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
-              gdb_prfpregset_t *fpregset)
+ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, void *fpregset)
 {
   /* Unneeded.  */
   return PS_ERR;
@@ -160,8 +147,7 @@ ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
    process PH from FPREGSET.  */
 
 ps_err_e
-ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
-              const gdb_prfpregset_t *fpregset)
+ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, void *fpregset)
 {
   /* Unneeded.  */
   return PS_ERR;
index 561e3809231901d2c740022d3ae2ac549637f006..b47f576d2e98f49b2e0aa0c04ad834468c9f5327 100644 (file)
@@ -1,5 +1,5 @@
 /* Thread management interface, for the remote server for GDB.
-   Copyright (C) 2002, 2004, 2005
+   Copyright (C) 2002, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
@@ -31,19 +31,7 @@ extern int debug_threads;
 #include <thread_db.h>
 #endif
 
-/* Correct for all GNU/Linux targets (for quite some time).  */
-#define GDB_GREGSET_T elf_gregset_t
-#define GDB_FPREGSET_T elf_fpregset_t
-
-#ifndef HAVE_ELF_FPREGSET_T
-/* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
-   via <sys/procfs.h>.  */
-#ifdef HAVE_LINUX_ELF_H
-#include <linux/elf.h>
-#endif
-#endif
-
-#include "../gdb_proc_service.h"
+#include "gdb_proc_service.h"
 
 /* Structure that identifies the child process for the
    <proc_service.h> interface.  */
index 0d581d180bad74783ca5fd7e921c0ce2c4ab13ea..985ff2781d34f3a97618e256f7fda91cba7d3aa2 100644 (file)
@@ -1,6 +1,7 @@
 /* Native-dependent code for GNU/Linux on MIPS processors.
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
+#include "inferior.h"
 #include "mips-tdep.h"
 #include "target.h"
 #include "linux-nat.h"
+#include "mips-linux-tdep.h"
+
+#include "gdb_proc_service.h"
+
+#include <sys/ptrace.h>
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+/* Assume that we have PTRACE_GETREGS et al. support.  If we do not,
+   we'll clear this and use PTRACE_PEEKUSER instead.  */
+static int have_ptrace_regsets = 1;
+
+/* Saved function pointers to fetch and store a single register using
+   PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
+
+void (*super_fetch_registers) (int);
+void (*super_store_registers) (int);
 
 /* Pseudo registers can not be read.  ptrace does not provide a way to
    read (or set) MIPS_PS_REGNUM, and there's no point in reading or
@@ -65,10 +86,178 @@ mips_linux_cannot_store_register (int regno)
     return 1;
 }
 
+/* Fetch the thread-local storage pointer for libthread_db.  */
+
+ps_err_e
+ps_get_thread_area (const struct ps_prochandle *ph,
+                    lwpid_t lwpid, int idx, void **base)
+{
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (void *) ((char *)*base - idx);
+
+  return PS_OK;
+}
+
+/* Fetch REGNO (or all registers if REGNO == -1) from the target
+   using PTRACE_GETREGS et al.  */
+
+static void
+mips64_linux_regsets_fetch_registers (int regno)
+{
+  int is_fp;
+  int tid;
+
+  if (regno >= mips_regnum (current_gdbarch)->fp0
+      && regno <= mips_regnum (current_gdbarch)->fp0 + 32)
+    is_fp = 1;
+  else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+    is_fp = 1;
+  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
+    is_fp = 1;
+  else
+    is_fp = 0;
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  if (regno == -1 || !is_fp)
+    {
+      mips64_elf_gregset_t regs;
+
+      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
+       {
+         if (errno == EIO)
+           {
+             have_ptrace_regsets = 0;
+             return;
+           }
+         perror_with_name (_("Couldn't get registers"));
+       }
+
+      mips64_supply_gregset (&regs);
+    }
+
+  if (regno == -1 || is_fp)
+    {
+      mips64_elf_fpregset_t fp_regs;
+
+      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+                 (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+       {
+         if (errno == EIO)
+           {
+             have_ptrace_regsets = 0;
+             return;
+           }
+         perror_with_name (_("Couldn't get FP registers"));
+       }
+
+      mips64_supply_fpregset (&fp_regs);
+    }
+}
+
+/* Store REGNO (or all registers if REGNO == -1) to the target
+   using PTRACE_SETREGS et al.  */
+
+static void
+mips64_linux_regsets_store_registers (int regno)
+{
+  int is_fp;
+  int tid;
+
+  if (regno >= mips_regnum (current_gdbarch)->fp0
+      && regno <= mips_regnum (current_gdbarch)->fp0 + 32)
+    is_fp = 1;
+  else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+    is_fp = 1;
+  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
+    is_fp = 1;
+  else
+    is_fp = 0;
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  if (regno == -1 || !is_fp)
+    {
+      mips64_elf_gregset_t regs;
+
+      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
+       perror_with_name (_("Couldn't get registers"));
+
+      mips64_fill_gregset (&regs, regno);
+
+      if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
+       perror_with_name (_("Couldn't set registers"));
+    }
+
+  if (regno == -1 || is_fp)
+    {
+      mips64_elf_fpregset_t fp_regs;
+
+      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
+                 (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+       perror_with_name (_("Couldn't get FP registers"));
+
+      mips64_fill_fpregset (&fp_regs, regno);
+
+      if (ptrace (PTRACE_SETFPREGS, tid, 0L,
+                 (PTRACE_TYPE_ARG3) &fp_regs) == -1)
+       perror_with_name (_("Couldn't set FP registers"));
+    }
+}
+
+/* Fetch REGNO (or all registers if REGNO == -1) from the target
+   using any working method.  */
+
+static void
+mips64_linux_fetch_registers (int regnum)
+{
+  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
+  if (have_ptrace_regsets)
+    mips64_linux_regsets_fetch_registers (regnum);
+
+  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
+     back to PTRACE_PEEKUSER.  */
+  if (!have_ptrace_regsets)
+    super_fetch_registers (regnum);
+}
+
+/* Store REGNO (or all registers if REGNO == -1) to the target
+   using any working method.  */
+
+static void
+mips64_linux_store_registers (int regnum)
+{
+  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
+  if (have_ptrace_regsets)
+    mips64_linux_regsets_store_registers (regnum);
+
+  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
+     back to PTRACE_PEEKUSER.  */
+  if (!have_ptrace_regsets)
+    super_store_registers (regnum);
+}
+
 void _initialize_mips_linux_nat (void);
 
 void
 _initialize_mips_linux_nat (void)
 {
-  add_target (linux_target ());
+  struct target_ops *t = linux_target ();
+
+  super_fetch_registers = t->to_fetch_registers;
+  super_store_registers = t->to_store_registers;
+
+  t->to_fetch_registers = mips64_linux_fetch_registers;
+  t->to_store_registers = mips64_linux_store_registers;
+
+  add_target (t);
 }
index 021edc7116b6bf19243e8de69f1f881cb4990d8a..5d789d245771a49b1204176030e8ee6ff72b8f48 100644 (file)
 #include "regcache.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
-
-/* Copied from <asm/elf.h>.  */
-#define ELF_NGREG       45
-#define ELF_NFPREG      33
-
-typedef unsigned char elf_greg_t[4];
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef unsigned char elf_fpreg_t[8];
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-
-/* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
-#define FPR_BASE        32
-#define PC              64
-#define CAUSE           65
-#define BADVADDR        66
-#define MMHI            67
-#define MMLO            68
-#define FPC_CSR         69
-#define FPC_EIR         70
-
-#define EF_REG0                        6
-#define EF_REG31               37
-#define EF_LO                  38
-#define EF_HI                  39
-#define EF_CP0_EPC             40
-#define EF_CP0_BADVADDR                41
-#define EF_CP0_STATUS          42
-#define EF_CP0_CAUSE           43
-
-#define EF_SIZE                        180
+#include "floatformat.h"
+#include "mips-linux-tdep.h"
 
 /* Figure out where the longjmp will land.
    We expect the first arg to be a pointer to the jmp_buf structure
@@ -98,7 +69,7 @@ mips_linux_get_longjmp_target (CORE_ADDR *pc)
 static void
 supply_32bit_reg (int regnum, const void *addr)
 {
-  char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
   store_signed_integer (buf, register_size (current_gdbarch, regnum),
                         extract_signed_integer (addr, 4));
   regcache_raw_supply (current_regcache, regnum, buf);
@@ -106,11 +77,11 @@ supply_32bit_reg (int regnum, const void *addr)
 
 /* Unpack an elf_gregset_t into GDB's register cache.  */
 
-void 
-supply_gregset (elf_gregset_t *gregsetp)
+void
+mips_supply_gregset (mips_elf_gregset_t *gregsetp)
 {
   int regi;
-  elf_greg_t *regp = *gregsetp;
+  mips_elf_greg_t *regp = *gregsetp;
   char zerobuf[MAX_REGISTER_SIZE];
 
   memset (zerobuf, 0, MAX_REGISTER_SIZE);
@@ -142,23 +113,23 @@ supply_gregset (elf_gregset_t *gregsetp)
 /* Pack our registers (or one register) into an elf_gregset_t.  */
 
 void
-fill_gregset (elf_gregset_t *gregsetp, int regno)
+mips_fill_gregset (mips_elf_gregset_t *gregsetp, int regno)
 {
   int regaddr, regi;
-  elf_greg_t *regp = *gregsetp;
+  mips_elf_greg_t *regp = *gregsetp;
   void *dst;
 
   if (regno == -1)
     {
-      memset (regp, 0, sizeof (elf_gregset_t));
+      memset (regp, 0, sizeof (mips_elf_gregset_t));
       for (regi = 0; regi < 32; regi++)
-        fill_gregset (gregsetp, regi);
-      fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
-      fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
-      fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
-      fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
-      fill_gregset (gregsetp, MIPS_PS_REGNUM);
-      fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
+       mips_fill_gregset (gregsetp, regi);
+      mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
+      mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
+      mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
+      mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
+      mips_fill_gregset (gregsetp, MIPS_PS_REGNUM);
+      mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
 
       return;
    }
@@ -195,7 +166,7 @@ fill_gregset (elf_gregset_t *gregsetp, int regno)
 /* Likewise, unpack an elf_fpregset_t.  */
 
 void
-supply_fpregset (elf_fpregset_t *fpregsetp)
+mips_supply_fpregset (mips_elf_fpregset_t *fpregsetp)
 {
   int regi;
   char zerobuf[MAX_REGISTER_SIZE];
@@ -220,7 +191,7 @@ supply_fpregset (elf_fpregset_t *fpregsetp)
    elf_fpregset_t.  */
 
 void
-fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
+mips_fill_fpregset (mips_elf_fpregset_t *fpregsetp, int regno)
 {
   char *from, *to;
 
@@ -239,9 +210,9 @@ fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
       int regi;
 
       for (regi = 0; regi < 32; regi++)
-       fill_fpregset (fpregsetp, FP0_REGNUM + regi);
-      fill_fpregset (fpregsetp,
-                    mips_regnum (current_gdbarch)->fp_control_status);
+       mips_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
+      mips_fill_fpregset (fpregsetp,
+                         mips_regnum (current_gdbarch)->fp_control_status);
     }
 }
 
@@ -283,37 +254,6 @@ mips_linux_register_addr (int regno, CORE_ADDR blockend)
 
 /* Support for 64-bit ABIs.  */
 
-/* Copied from <asm/elf.h>.  */
-#define MIPS64_ELF_NGREG       45
-#define MIPS64_ELF_NFPREG      33
-
-typedef unsigned char mips64_elf_greg_t[8];
-typedef mips64_elf_greg_t mips64_elf_gregset_t[MIPS64_ELF_NGREG];
-
-typedef unsigned char mips64_elf_fpreg_t[8];
-typedef mips64_elf_fpreg_t mips64_elf_fpregset_t[MIPS64_ELF_NFPREG];
-
-/* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
-#define MIPS64_FPR_BASE                 32
-#define MIPS64_PC                       64
-#define MIPS64_CAUSE                    65
-#define MIPS64_BADVADDR                 66
-#define MIPS64_MMHI                     67
-#define MIPS64_MMLO                     68
-#define MIPS64_FPC_CSR                  69
-#define MIPS64_FPC_EIR                  70
-
-#define MIPS64_EF_REG0                  0
-#define MIPS64_EF_REG31                        31
-#define MIPS64_EF_LO                   32
-#define MIPS64_EF_HI                   33
-#define MIPS64_EF_CP0_EPC              34
-#define MIPS64_EF_CP0_BADVADDR         35
-#define MIPS64_EF_CP0_STATUS           36
-#define MIPS64_EF_CP0_CAUSE            37
-
-#define MIPS64_EF_SIZE                 304
-
 /* Figure out where the longjmp will land.
    We expect the first arg to be a pointer to the jmp_buf structure
    from which we extract the pc (MIPS_LINUX_JB_PC) that we will land
@@ -342,39 +282,49 @@ mips64_linux_get_longjmp_target (CORE_ADDR *pc)
   return 1;
 }
 
-/* Unpack an elf_gregset_t into GDB's register cache.  */
+/* Register set support functions.  These operate on standard 64-bit
+   regsets, but work whether the target is 32-bit or 64-bit.  A 32-bit
+   target will still use the 64-bit format for PTRACE_GETREGS.  */
+
+/* Supply a 64-bit register.  */
+
+void
+supply_64bit_reg (int regnum, const gdb_byte *buf)
+{
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
+      && register_size (current_gdbarch, regnum) == 4)
+    regcache_raw_supply (current_regcache, regnum, buf + 4);
+  else
+    regcache_raw_supply (current_regcache, regnum, buf);
+}
+
+/* Unpack a 64-bit elf_gregset_t into GDB's register cache.  */
 
-static void 
+void
 mips64_supply_gregset (mips64_elf_gregset_t *gregsetp)
 {
   int regi;
   mips64_elf_greg_t *regp = *gregsetp;
-  char zerobuf[MAX_REGISTER_SIZE];
+  gdb_byte zerobuf[MAX_REGISTER_SIZE];
 
   memset (zerobuf, 0, MAX_REGISTER_SIZE);
 
   for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++)
-    regcache_raw_supply (current_regcache, (regi - MIPS64_EF_REG0),
-                        (char *)(regp + regi));
-
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->lo,
-                      (char *) (regp + MIPS64_EF_LO));
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->hi,
-                      (char *) (regp + MIPS64_EF_HI));
-
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->pc,
-                      (char *) (regp + MIPS64_EF_CP0_EPC));
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->badvaddr,
-                      (char *) (regp + MIPS64_EF_CP0_BADVADDR));
-  regcache_raw_supply (current_regcache, MIPS_PS_REGNUM,
-                      (char *) (regp + MIPS64_EF_CP0_STATUS));
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->cause,
-                      (char *) (regp + MIPS64_EF_CP0_CAUSE));
+    supply_64bit_reg (regi - MIPS64_EF_REG0, (gdb_byte *)(regp + regi));
+
+  supply_64bit_reg (mips_regnum (current_gdbarch)->lo,
+                   (gdb_byte *) (regp + MIPS64_EF_LO));
+  supply_64bit_reg (mips_regnum (current_gdbarch)->hi,
+                   (gdb_byte *) (regp + MIPS64_EF_HI));
+
+  supply_64bit_reg (mips_regnum (current_gdbarch)->pc,
+                   (gdb_byte *) (regp + MIPS64_EF_CP0_EPC));
+  supply_64bit_reg (mips_regnum (current_gdbarch)->badvaddr,
+                   (gdb_byte *) (regp + MIPS64_EF_CP0_BADVADDR));
+  supply_64bit_reg (MIPS_PS_REGNUM,
+                   (gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
+  supply_64bit_reg (mips_regnum (current_gdbarch)->cause,
+                   (gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
 
   /* Fill inaccessible registers with zero.  */
   regcache_raw_supply (current_regcache, MIPS_UNUSED_REGNUM, zerobuf);
@@ -384,9 +334,9 @@ mips64_supply_gregset (mips64_elf_gregset_t *gregsetp)
     regcache_raw_supply (current_regcache, regi, zerobuf);
 }
 
-/* Pack our registers (or one register) into an elf_gregset_t.  */
+/* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
 
-static void
+void
 mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
 {
   int regaddr, regi;
@@ -411,13 +361,8 @@ mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
    }
 
   if (regno < 32)
-    {
-      dst = regp + regno + MIPS64_EF_REG0;
-      regcache_raw_collect (current_regcache, regno, dst);
-      return;
-    }
-
-  if (regno == mips_regnum (current_gdbarch)->lo)
+    regaddr = regno + MIPS64_EF_REG0;
+  else if (regno == mips_regnum (current_gdbarch)->lo)
     regaddr = MIPS64_EF_LO;
   else if (regno == mips_regnum (current_gdbarch)->hi)
     regaddr = MIPS64_EF_HI;
@@ -434,52 +379,97 @@ mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
 
   if (regaddr != -1)
     {
+      gdb_byte buf[MAX_REGISTER_SIZE];
+      LONGEST val;
+
+      regcache_raw_collect (current_regcache, regno, buf);
+      val = extract_signed_integer (buf,
+                                   register_size (current_gdbarch, regno));
       dst = regp + regaddr;
-      regcache_raw_collect (current_regcache, regno, dst);
+      store_signed_integer (dst, 8, val);
     }
 }
 
 /* Likewise, unpack an elf_fpregset_t.  */
 
-static void
+void
 mips64_supply_fpregset (mips64_elf_fpregset_t *fpregsetp)
 {
   int regi;
-  char zerobuf[MAX_REGISTER_SIZE];
 
-  memset (zerobuf, 0, MAX_REGISTER_SIZE);
-
-  for (regi = 0; regi < 32; regi++)
-    regcache_raw_supply (current_regcache, FP0_REGNUM + regi,
-                        (char *)(*fpregsetp + regi));
-
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->fp_control_status,
-                      (char *)(*fpregsetp + 32));
-
-  /* FIXME: how can we supply FCRIR?  The ABI doesn't tell us.  */
-  regcache_raw_supply (current_regcache,
-                      mips_regnum (current_gdbarch)->fp_implementation_revision,
-                      zerobuf);
+  /* See mips_linux_o32_sigframe_init for a description of the
+     peculiar FP register layout.  */
+  if (register_size (current_gdbarch, FP0_REGNUM) == 4)
+    for (regi = 0; regi < 32; regi++)
+      {
+       gdb_byte *reg_ptr = (gdb_byte *) (*fpregsetp + (regi & ~1));
+       if ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) != (regi & 1))
+         reg_ptr += 4;
+       regcache_raw_supply (current_regcache, FP0_REGNUM + regi, reg_ptr);
+      }
+  else
+    for (regi = 0; regi < 32; regi++)
+      regcache_raw_supply (current_regcache, FP0_REGNUM + regi,
+                          (char *)(*fpregsetp + regi));
+
+  supply_32bit_reg (mips_regnum (current_gdbarch)->fp_control_status,
+                   (gdb_byte *)(*fpregsetp + 32));
+
+  /* The ABI doesn't tell us how to supply FCRIR, and core dumps don't
+     include it - but the result of PTRACE_GETFPREGS does.  The best we
+     can do is to assume that its value is present.  */
+  supply_32bit_reg (mips_regnum (current_gdbarch)->fp_implementation_revision,
+                   (gdb_byte *)(*fpregsetp + 32) + 4);
 }
 
 /* Likewise, pack one or all floating point registers into an
    elf_fpregset_t.  */
 
-static void
+void
 mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
 {
-  char *from, *to;
+  gdb_byte *to;
 
   if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
     {
-      to = (char *) (*fpregsetp + regno - FP0_REGNUM);
-      regcache_raw_collect (current_regcache, regno, to);
+      /* See mips_linux_o32_sigframe_init for a description of the
+        peculiar FP register layout.  */
+      if (register_size (current_gdbarch, regno) == 4)
+       {
+         int regi = regno - FP0_REGNUM;
+
+         to = (gdb_byte *) (*fpregsetp + (regi & ~1));
+         if ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) != (regi & 1))
+           to += 4;
+         regcache_raw_collect (current_regcache, regno, to);
+       }
+      else
+       {
+         to = (gdb_byte *) (*fpregsetp + regno - FP0_REGNUM);
+         regcache_raw_collect (current_regcache, regno, to);
+       }
     }
   else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
     {
-      to = (char *) (*fpregsetp + 32);
-      regcache_raw_collect (current_regcache, regno, to);
+      gdb_byte buf[MAX_REGISTER_SIZE];
+      LONGEST val;
+
+      regcache_raw_collect (current_regcache, regno, buf);
+      val = extract_signed_integer (buf,
+                                   register_size (current_gdbarch, regno));
+      to = (gdb_byte *) (*fpregsetp + 32);
+      store_signed_integer (to, 4, val);
+    }
+  else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
+    {
+      gdb_byte buf[MAX_REGISTER_SIZE];
+      LONGEST val;
+
+      regcache_raw_collect (current_regcache, regno, buf);
+      val = extract_signed_integer (buf,
+                                   register_size (current_gdbarch, regno));
+      to = (gdb_byte *) (*fpregsetp + 32) + 4;
+      store_signed_integer (to, 4, val);
     }
   else if (regno == -1)
     {
@@ -487,8 +477,10 @@ mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
 
       for (regi = 0; regi < 32; regi++)
        mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
-      mips64_fill_fpregset(fpregsetp,
-                          mips_regnum (current_gdbarch)->fp_control_status);
+      mips64_fill_fpregset (fpregsetp,
+                           mips_regnum (current_gdbarch)->fp_control_status);
+      mips64_fill_fpregset (fpregsetp, (mips_regnum (current_gdbarch)
+                                       ->fp_implementation_revision));
     }
 }
 
@@ -536,8 +528,8 @@ static void
 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
                      int which, CORE_ADDR reg_addr)
 {
-  elf_gregset_t gregset;
-  elf_fpregset_t fpregset;
+  mips_elf_gregset_t gregset;
+  mips_elf_fpregset_t fpregset;
   mips64_elf_gregset_t gregset64;
   mips64_elf_fpregset_t fpregset64;
 
@@ -546,7 +538,7 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
       if (core_reg_size == sizeof (gregset))
        {
          memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
-         supply_gregset (&gregset);
+         mips_supply_gregset (&gregset);
        }
       else if (core_reg_size == sizeof (gregset64))
        {
@@ -563,7 +555,7 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
       if (core_reg_size == sizeof (fpregset))
        {
          memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
-         supply_fpregset (&fpregset);
+         mips_supply_fpregset (&fpregset);
        }
       else if (core_reg_size == sizeof (fpregset64))
        {
@@ -1084,6 +1076,49 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
                                     func));
 }
 
+/* Wrapper functions.  These are only used by libthread_db.  */
+
+void
+supply_gregset (mips_elf_gregset_t *gregsetp)
+{
+  if (mips_isa_regsize (current_gdbarch) == 4)
+    mips_supply_gregset (gregsetp);
+  else
+    mips64_supply_gregset ((void *) gregsetp);
+}
+
+void
+fill_gregset (mips_elf_gregset_t *gregsetp, int regno)
+{
+  if (mips_isa_regsize (current_gdbarch) == 4)
+    mips_fill_gregset (gregsetp, regno);
+  else
+    mips64_fill_gregset ((void *) gregsetp, regno);
+}
+
+/* Likewise, unpack an elf_fpregset_t.  */
+
+void
+supply_fpregset (mips_elf_fpregset_t *fpregsetp)
+{
+  if (mips_isa_regsize (current_gdbarch) == 4)
+    mips_supply_fpregset (fpregsetp);
+  else
+    mips64_supply_fpregset ((void *) fpregsetp);
+}
+
+/* Likewise, pack one or all floating point registers into an
+   elf_fpregset_t.  */
+
+void
+fill_fpregset (mips_elf_fpregset_t *fpregsetp, int regno)
+{
+  if (mips_isa_regsize (current_gdbarch) == 4)
+    mips_fill_fpregset (fpregsetp, regno);
+  else
+    mips64_fill_fpregset ((void *) fpregsetp, regno);
+}
+
 /* Initialize one of the GNU/Linux OS ABIs.  */
 
 static void
@@ -1110,6 +1145,15 @@ mips_linux_init_abi (struct gdbarch_info info,
        set_solib_svr4_fetch_link_map_offsets
          (gdbarch, svr4_ilp32_fetch_link_map_offsets);
        set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
+       set_gdbarch_long_double_bit (gdbarch, 128);
+       /* These floatformats should probably be renamed.  MIPS uses
+          the same 128-bit IEEE floating point format that IA-64 uses,
+          except that the quiet/signalling NaN bit is reversed (GDB
+          does not distinguish between quiet and signalling NaNs).  */
+       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+         set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_big);
+       else
+         set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_little);
        tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
        break;
       case MIPS_ABI_N64:
@@ -1118,6 +1162,15 @@ mips_linux_init_abi (struct gdbarch_info info,
        set_solib_svr4_fetch_link_map_offsets
          (gdbarch, svr4_lp64_fetch_link_map_offsets);
        set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
+       set_gdbarch_long_double_bit (gdbarch, 128);
+       /* These floatformats should probably be renamed.  MIPS uses
+          the same 128-bit IEEE floating point format that IA-64 uses,
+          except that the quiet/signalling NaN bit is reversed (GDB
+          does not distinguish between quiet and signalling NaNs).  */
+       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+         set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_big);
+       else
+         set_gdbarch_long_double_format (gdbarch, &floatformat_ia64_quad_little);
        tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
        break;
       default:
index 43e1c9646f8b3e3f488e50b31d048f5002341df9..db79713a6f43f2debd3b0042a05fd8bb4d950c9d 100644 (file)
@@ -2,8 +2,8 @@
    the GNU Debugger.
 
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
-   Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -63,8 +63,8 @@ static bfd *the_bfd;
 static int
 compare_pdr_entries (const void *a, const void *b)
 {
-  CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
-  CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
+  CORE_ADDR lhs = bfd_get_signed_32 (the_bfd, (bfd_byte *) a);
+  CORE_ADDR rhs = bfd_get_signed_32 (the_bfd, (bfd_byte *) b);
 
   if (lhs < rhs)
     return -1;
@@ -215,17 +215,17 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
              PROC_LOW_ADDR (proc_desc) = pdr_pc;
 
              PROC_FRAME_OFFSET (proc_desc)
-               = bfd_get_32 (sec->objfile->obfd, ptr + 20);
+               = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20);
              PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                       ptr + 24);
              PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                      ptr + 4);
              PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                       ptr + 12);
-             PROC_REG_OFFSET (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                       ptr + 8);
+             PROC_REG_OFFSET (proc_desc)
+               = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8);
              PROC_FREG_OFFSET (proc_desc)
-               = bfd_get_32 (sec->objfile->obfd, ptr + 16);
+               = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16);
              PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
                                                    ptr + 28);
              proc_desc->pdr.isym = (long) sym;
index 679dd9df9c7785d1ecb78bd239da84a2e9d2d37b..880dfcc34946c124a5abfc5c4d61ab5c6a8479b9 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
@@ -202,7 +202,7 @@ is_mips16_addr (CORE_ADDR addr)
 static CORE_ADDR
 unmake_mips16_addr (CORE_ADDR addr)
 {
-  return ((addr) & ~1);
+  return ((addr) & ~(CORE_ADDR) 1);
 }
 
 /* Return the contents of register REGNUM as a signed integer.  */
@@ -989,14 +989,14 @@ mips32_next_pc (CORE_ADDR pc)
            unsigned long reg;
            reg = jtype_target (inst) << 2;
            /* Upper four bits get never changed... */
-           pc = reg + ((pc + 4) & 0xf0000000);
+           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff);
          }
          break;
          /* FIXME case JALX : */
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
-           pc = reg + ((pc + 4) & 0xf0000000) + 1;     /* yes, +1 */
+           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + 1;        /* yes, +1 */
            /* Add 1 to indicate 16 bit mode - Invert ISA mode */
          }
          break;                /* The new PC will be alternate mode */
@@ -1202,7 +1202,7 @@ unpack_mips16 (CORE_ADDR pc,
 static CORE_ADDR
 add_offset_16 (CORE_ADDR pc, int offset)
 {
-  return ((offset << 2) | ((pc + 2) & (0xf0000000)));
+  return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)));
 }
 
 static CORE_ADDR
@@ -2910,6 +2910,24 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
       || TYPE_CODE (type) == TYPE_CODE_ARRAY
       || TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
     return RETURN_VALUE_STRUCT_CONVENTION;
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) == 16
+          && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A 128-bit floating-point value fills both $f0 and $f2.  The
+        two registers are used in the same as memory order, so the
+        eight bytes with the lower memory address are in $f0.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $f0 and $f2\n");
+      mips_xfer_register (regcache,
+                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+                         8, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+      mips_xfer_register (regcache,
+                         NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 2,
+                         8, TARGET_BYTE_ORDER, readbuf ? readbuf + 8 : readbuf,
+                         writebuf ? writebuf + 8 : writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
           && tdep->mips_fpu_type != MIPS_FPU_NONE)
     {
@@ -4037,7 +4055,6 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
   int regnum;
 
   /* For GP registers, we print a separate row of names above the vals */
-  fprintf_filtered (file, "     ");
   for (col = 0, regnum = start_regnum;
        col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
     {
@@ -4046,11 +4063,17 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
       if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
          TYPE_CODE_FLT)
        break;                  /* end the row: reached FP register */
+      if (col == 0)
+       fprintf_filtered (file, "     ");
       fprintf_filtered (file,
                        mips_abi_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
                        REGISTER_NAME (regnum));
       col++;
     }
+
+  if (col == 0)
+    return regnum;
+
   /* print the R0 to R31 names */
   if ((start_regnum % NUM_REGS) < MIPS_NUMREGS)
     fprintf_filtered (file, "\n R%-4d", start_regnum % NUM_REGS);
@@ -4741,6 +4764,13 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
+  /* Default 64-bit objects to N64 instead of O32.  */
+  if (found_abi == MIPS_ABI_UNKNOWN
+      && info.abfd != NULL
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
+      && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+    found_abi = MIPS_ABI_N64;
+
   if (gdbarch_debug)
     fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: found_abi = %d\n",
                        found_abi);
index 0bcac05c0b2b8adb1cbaf05111b24750b54d9c01..2829924581ef0d0a4d1ff82ad6bb7414ae55f06e 100644 (file)
@@ -75,9 +75,9 @@ ps_xfer_memory (const struct ps_prochandle *ph, paddr_t addr,
   inferior_ptid = pid_to_ptid (ph->pid);
 
   if (write)
-    ret = target_write_memory (addr, buf, len);
+    ret = target_write_memory ((unsigned long) addr, buf, len);
   else
-    ret = target_read_memory (addr, buf, len);
+    ret = target_read_memory ((unsigned long) addr, buf, len);
 
   do_cleanups (old_chain);
 
@@ -181,7 +181,7 @@ ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj,
   if (ms == NULL)
     return PS_NOSYM;
 
-  *sym_addr = SYMBOL_VALUE_ADDRESS (ms);
+  *sym_addr = (paddr_t) (unsigned long) SYMBOL_VALUE_ADDRESS (ms);
   return PS_OK;
 }