summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2006-03-15 19:53:38 +0000
committerDaniel Jacobowitz <dan@debian.org>2006-03-15 19:53:38 +0000
commitbcb1742124488f3c1e386cd46f3f732267a47ead (patch)
tree723511ae23e81d87a3eca5322fce95fec79ea775
parent3b5523feb62288960e78ec3ae8e8f2701a46eaa7 (diff)
downloadgdb-bcb1742124488f3c1e386cd46f3f732267a47ead.tar.gz
Merge ten gdb and gdbserver patches for MIPS/MIPS64 support.
-rw-r--r--gdb/Makefile.in6
-rw-r--r--gdb/gdb_proc_service.h7
-rw-r--r--gdb/gdbserver/Makefile.in11
-rw-r--r--gdb/gdbserver/config.in6
-rwxr-xr-xgdb/gdbserver/configure125
-rw-r--r--gdb/gdbserver/configure.ac32
-rw-r--r--gdb/gdbserver/gdb_proc_service.h75
-rw-r--r--gdb/gdbserver/linux-i386-low.c16
-rw-r--r--gdb/gdbserver/linux-mips-low.c27
-rw-r--r--gdb/gdbserver/linux-x86-64-low.c16
-rw-r--r--gdb/gdbserver/proc-service.c34
-rw-r--r--gdb/gdbserver/thread-db.c16
-rw-r--r--gdb/mips-linux-nat.c193
-rw-r--r--gdb/mips-linux-tdep.c339
-rw-r--r--gdb/mips-linux-tdep.h94
-rw-r--r--gdb/mips-mdebug-tdep.c16
-rw-r--r--gdb/mips-tdep.c42
-rw-r--r--gdb/proc-service.c6
18 files changed, 662 insertions, 399 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index acba593b0eb..99aa888c29f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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) \
diff --git a/gdb/gdb_proc_service.h b/gdb/gdb_proc_service.h
index 408a87b0d4e..fc559bed88f 100644
--- a/gdb/gdb_proc_service.h
+++ b/gdb/gdb_proc_service.h
@@ -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
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 19ee78b221f..0da5f6cde68 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -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)
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index 59e56bc8e8e..3aa2811ecef 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -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
@@ -104,8 +101,5 @@
/* 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
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 1373538d1dd..262d5ef99ac 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -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
diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac
index fabd94db517..a952af5d83c 100644
--- a/gdb/gdbserver/configure.ac
+++ b/gdb/gdbserver/configure.ac
@@ -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
diff --git a/gdb/gdbserver/gdb_proc_service.h b/gdb/gdbserver/gdb_proc_service.h
new file mode 100644
index 00000000000..e5aefbdd418
--- /dev/null
+++ b/gdb/gdbserver/gdb_proc_service.h
@@ -0,0 +1,75 @@
+/* <proc_service.h> replacement for systems that don't have it.
+ Copyright (C) 2000, 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifndef GDB_PROC_SERVICE_H
+#define GDB_PROC_SERVICE_H
+
+#include <sys/types.h>
+
+#ifdef HAVE_PROC_SERVICE_H
+#include <proc_service.h>
+#else
+
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+
+/* Not all platforms bring in <linux/elf.h> via <sys/procfs.h>. If
+ <sys/procfs.h> wasn't enough to find elf_fpregset_t, try the kernel
+ headers also (but don't if we don't need to). */
+#ifndef HAVE_ELF_FPREGSET_T
+# ifdef HAVE_LINUX_ELF_H
+# include <linux/elf.h>
+# endif
+#endif
+
+typedef enum
+{
+ PS_OK, /* Success. */
+ PS_ERR, /* Generic error. */
+ PS_BADPID, /* Bad process handle. */
+ PS_BADLID, /* Bad LWP id. */
+ PS_BADADDR, /* Bad address. */
+ PS_NOSYM, /* Symbol not found. */
+ PS_NOFREGS /* FPU register set not available. */
+} ps_err_e;
+
+#ifndef HAVE_LWPID_T
+typedef unsigned int lwpid_t;
+#endif
+
+#ifndef HAVE_PSADDR_T
+typedef unsigned long psaddr_t;
+#endif
+
+#ifndef HAVE_PRGREGSET_T
+typedef elf_gregset_t prgregset_t;
+#endif
+
+#endif /* HAVE_PROC_SERVICE_H */
+
+/* Structure that identifies the target process. */
+struct ps_prochandle
+{
+ /* The process id is all we need. */
+ pid_t pid;
+};
+
+#endif /* gdb_proc_service.h */
diff --git a/gdb/gdbserver/linux-i386-low.c b/gdb/gdbserver/linux-i386-low.c
index 96359fb92e1..c0daf0b76ca 100644
--- a/gdb/gdbserver/linux-i386-low.c
+++ b/gdb/gdbserver/linux-i386-low.c
@@ -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.
@@ -23,19 +23,7 @@
#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>
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index 695bd29bf0d..78295505f31 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -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.
@@ -22,6 +22,14 @@
#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,
diff --git a/gdb/gdbserver/linux-x86-64-low.c b/gdb/gdbserver/linux-x86-64-low.c
index 7a4a76aa443..43cd10b0b39 100644
--- a/gdb/gdbserver/linux-x86-64-low.c
+++ b/gdb/gdbserver/linux-x86-64-low.c
@@ -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.
@@ -24,19 +24,7 @@
#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>
diff --git a/gdb/gdbserver/proc-service.c b/gdb/gdbserver/proc-service.c
index a64919e54ee..99083f17333 100644
--- a/gdb/gdbserver/proc-service.c
+++ b/gdb/gdbserver/proc-service.c
@@ -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.
@@ -29,19 +29,7 @@
#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;
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index 561e3809231..b47f576d2e9 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -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. */
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 0d581d180ba..985ff2781d3 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -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.
@@ -20,9 +21,29 @@
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);
}
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 021edc7116b..5d789d24577 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -32,37 +32,8 @@
#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:
diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h
new file mode 100644
index 00000000000..4914b638a23
--- /dev/null
+++ b/gdb/mips-linux-tdep.h
@@ -0,0 +1,94 @@
+/* Target-dependent code for GNU/Linux on MIPS processors.
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Copied from <asm/elf.h>. */
+#define ELF_NGREG 45
+#define ELF_NFPREG 33
+
+typedef unsigned char mips_elf_greg_t[4];
+typedef mips_elf_greg_t mips_elf_gregset_t[ELF_NGREG];
+
+typedef unsigned char mips_elf_fpreg_t[8];
+typedef mips_elf_fpreg_t mips_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
+
+void mips_supply_gregset (mips_elf_gregset_t *);
+void mips_fill_gregset (mips_elf_gregset_t *, int);
+void mips_supply_fpregset (mips_elf_fpregset_t *);
+void mips_fill_fpregset (mips_elf_fpregset_t *, int);
+
+/* 64-bit support. */
+
+/* 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
+
+void mips64_supply_gregset (mips64_elf_gregset_t *);
+void mips64_fill_gregset (mips64_elf_gregset_t *, int);
+void mips64_supply_fpregset (mips64_elf_fpregset_t *);
+void mips64_fill_fpregset (mips64_elf_fpregset_t *, int);
diff --git a/gdb/mips-mdebug-tdep.c b/gdb/mips-mdebug-tdep.c
index 43e1c9646f8..db79713a6f4 100644
--- a/gdb/mips-mdebug-tdep.c
+++ b/gdb/mips-mdebug-tdep.c
@@ -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;
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 679dd9df9c7..880dfcc3494 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -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
@@ -2911,6 +2911,24 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
|| 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)
{
/* A floating-point value belongs in the least significant part
@@ -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);
diff --git a/gdb/proc-service.c b/gdb/proc-service.c
index 0bcac05c0b2..2829924581e 100644
--- a/gdb/proc-service.c
+++ b/gdb/proc-service.c
@@ -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;
}