2002-02-27 Daniel Jacobowitz <drow@mvista.com>

* gdbserver/acconfig.h: New file.
        * gdbserver/i387-fp.c: New file.
        * gdbserver/i387-fp.h: New file.
        * gdbserver/linux-x86-64.c: New file.
        * regformats/reg-x86-64.dat: New file.
        * configure.tgt: Add x86_64-*-linux* gdbserver support.
        & gdbserver/configure.srv: Add x86_64-*-linux* and regset support.
        * gdbserver/configure.in: Add support for regsets.
        * gdbserver/config.in: Regenerate.
        * gdbserver/configure: Regenerate.
        * gdbserver/Makefile.in: Likewise.  Add $(linux_low_h).
        * gdbserver/linux-low.h: New file.
        * gdbserver/linux-low.c: Include "linux-low.h".  Add support
        for regsets.
        * gdbserver/linux-arm-low.c: Include "linux-low.h".
        * gdbserver/linux-ia64-low.c: Include "linux-low.h".
        * gdbserver/linux-m68k-low.c: Include "linux-low.h".
        * gdbserver/linux-mips-low.c: Include "linux-low.h".
        * gdbserver/linux-ppc-low.c: Include "linux-low.h".
        * gdbserver/linux-sh-low.c: Include "linux-low.h".
        * gdbserver/linux-i386-low.c: Include "linux-low.h".  Include
        "i387-fp.h".  Add PTRACE_GETREGS and friends.
        * gdbserver/regcache.c (supply_register): New function.
        (supply_register_by_name): New function.
        (collect_register): New function.
        (collect_register_by_name): New function.
This commit is contained in:
Daniel Jacobowitz 2002-02-27 07:07:49 +00:00
parent 936521746c
commit 58caa3dcdb
22 changed files with 925 additions and 24 deletions

View file

@ -1,3 +1,32 @@
2002-02-27 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/acconfig.h: New file.
* gdbserver/i387-fp.c: New file.
* gdbserver/i387-fp.h: New file.
* gdbserver/linux-x86-64.c: New file.
* regformats/reg-x86-64.dat: New file.
* configure.tgt: Add x86_64-*-linux* gdbserver support.
* gdbserver/configure.srv: Add x86_64-*-linux* and regset support.
* gdbserver/configure.in: Add support for regsets.
* gdbserver/config.in: Regenerate.
* gdbserver/configure: Regenerate.
* gdbserver/Makefile.in: Likewise. Add $(linux_low_h).
* gdbserver/linux-low.h: New file.
* gdbserver/linux-low.c: Include "linux-low.h". Add support
for regsets.
* gdbserver/linux-arm-low.c: Include "linux-low.h".
* gdbserver/linux-ia64-low.c: Include "linux-low.h".
* gdbserver/linux-m68k-low.c: Include "linux-low.h".
* gdbserver/linux-mips-low.c: Include "linux-low.h".
* gdbserver/linux-ppc-low.c: Include "linux-low.h".
* gdbserver/linux-sh-low.c: Include "linux-low.h".
* gdbserver/linux-i386-low.c: Include "linux-low.h". Include
"i387-fp.h". Add PTRACE_GETREGS and friends.
* gdbserver/regcache.c (supply_register): New function.
(supply_register_by_name): New function.
(collect_register): New function.
(collect_register_by_name): New function.
2002-02-27 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/Makefile.in (INTERNAL_CFLAGS): Remove -DGDBSERVER.

View file

@ -290,7 +290,9 @@ v850*-*-*) gdb_target=v850
esac
;;
x86_64-*-linux*) gdb_target=x86-64linux ;;
x86_64-*-linux*) gdb_target=x86-64linux
build_gdbserver=yes
;;
z8k-*-coff*) gdb_target=z8k ;;

View file

@ -183,7 +183,7 @@ clean:
rm -f *.o ${ADD_FILES} *~
rm -f gdbserver gdbreplay core make.log
rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m68k.c reg-mips.c
rm -f reg-ppc.c reg-sh.c reg-i386-linux.c
rm -f reg-ppc.c reg-sh.c reg-x86-64.c reg-i386-linux.c
distclean: clean
rm -f nm.h tm.h xm.h config.status
@ -232,13 +232,18 @@ remote-utils.o: remote-utils.c terminal.h $(server_h)
utils.o: utils.c $(server_h)
regcache.o: regcache.c $(server_h) $(regdef_h)
linux-low.o: linux-low.c $(server_h)
linux-arm-low.o: linux-arm-low.c $(server_h)
linux-i386-low.o: linux-i386-low.c $(server_h)
linux-ia64-low.o: linux-ia64-low.c $(server_h)
linux-mips-low.o: linux-mips-low.c $(server_h)
linux-ppc-low.o: linux-ppc-low.c $(server_h)
linux-sh-low.o: linux-sh-low.c $(server_h)
i387-fp.o: i387-fp.c $(server_h)
linux_low_h = $(srcdir)/linux-low.h
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-i386-low.o: linux-i386-low.c $(linux_low_h) $(server_h)
linux-ia64-low.o: linux-ia64-low.c $(linux_low_h) $(server_h)
linux-mips-low.o: linux-mips-low.c $(linux_low_h) $(server_h)
linux-ppc-low.o: linux-ppc-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)
# OBSOLETE TARGETS
# OBSOLETE # low-lynx.o : ${srcdir}/low-lynx.c ${srcdir}/server.h
@ -272,5 +277,8 @@ reg-ppc.c : $(srcdir)/../regformats/reg-ppc.dat $(regdat_sh)
reg-sh.o : reg-sh.c $(regdef_h)
reg-sh.c : $(srcdir)/../regformats/reg-sh.dat $(regdat_sh)
sh $(regdat_sh) $(srcdir)/../regformats/reg-sh.dat reg-sh.c
reg-x86-64.o : reg-x86-64.c $(regdef_h)
reg-x86-64.c : $(srcdir)/../regformats/reg-x86-64.dat $(regdat_sh)
sh $(regdat_sh) $(srcdir)/../regformats/reg-x86-64.dat reg-x86-64.c
# This is the end of "Makefile.in".

9
gdb/gdbserver/acconfig.h Normal file
View file

@ -0,0 +1,9 @@
/* Define if the target supports PTRACE_PEEKUSR for register access. */
#undef HAVE_LINUX_USRREGS
/* Define if the target supports PTRACE_GETREGS for register access. */
#undef HAVE_LINUX_REGSETS
/* Define if the target supports PTRACE_GETFPXREGS for extended
register access. */
#undef HAVE_PTRACE_GETFPXREGS

View file

@ -3,6 +3,16 @@
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if the target supports PTRACE_PEEKUSR for register access. */
#undef HAVE_LINUX_USRREGS
/* Define if the target supports PTRACE_GETREGS for register access. */
#undef HAVE_LINUX_REGSETS
/* Define if the target supports PTRACE_GETFPXREGS for extended
register access. */
#undef HAVE_PTRACE_GETFPXREGS
/* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H

View file

@ -1148,6 +1148,81 @@ done
. ${srcdir}/configure.srv
if test "${srv_linux_usrregs}" = "yes"; then
cat >> confdefs.h <<\EOF
#define HAVE_LINUX_USRREGS 1
EOF
fi
if test "${srv_linux_regsets}" = "yes"; then
echo $ac_n "checking for PTRACE_GETREGS""... $ac_c" 1>&6
echo "configure:1161: checking for PTRACE_GETREGS" >&5
if eval "test \"`echo '$''{'gdbsrv_cv_have_ptrace_getregs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1166 "configure"
#include "confdefs.h"
#include <sys/ptrace.h>
int main() {
PTRACE_GETREGS;
; return 0; }
EOF
if { (eval echo configure:1173: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gdbsrv_cv_have_ptrace_getregs=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
gdbsrv_cv_have_ptrace_getregs=no
fi
rm -f conftest*
fi
echo "$ac_t""$gdbsrv_cv_have_ptrace_getregs" 1>&6
if test "${gdbsrv_cv_have_ptrace_getregs}" = "yes"; then
cat >> confdefs.h <<\EOF
#define HAVE_LINUX_REGSETS 1
EOF
fi
echo $ac_n "checking for PTRACE_GETFPXREGS""... $ac_c" 1>&6
echo "configure:1194: checking for PTRACE_GETFPXREGS" >&5
if eval "test \"`echo '$''{'gdbsrv_cv_have_ptrace_getfpxregs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1199 "configure"
#include "confdefs.h"
#include <sys/ptrace.h>
int main() {
PTRACE_GETFPXREGS;
; return 0; }
EOF
if { (eval echo configure:1206: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gdbsrv_cv_have_ptrace_getfpxregs=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
gdbsrv_cv_have_ptrace_getfpxregs=no
fi
rm -f conftest*
fi
echo "$ac_t""$gdbsrv_cv_have_ptrace_getfpxregs" 1>&6
if test "${gdbsrv_cv_have_ptrace_getfpxregs}" = "yes"; then
cat >> confdefs.h <<\EOF
#define HAVE_PTRACE_GETFPXREGS 1
EOF
fi
fi
GDBSERVER_DEPFILES="$srv_regobj $srv_tgtobj"

View file

@ -34,6 +34,34 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h)
. ${srcdir}/configure.srv
if test "${srv_linux_usrregs}" = "yes"; then
AC_DEFINE(HAVE_LINUX_USRREGS)
fi
if test "${srv_linux_regsets}" = "yes"; then
AC_MSG_CHECKING(for PTRACE_GETREGS)
AC_CACHE_VAL(gdbsrv_cv_have_ptrace_getregs,
[AC_TRY_COMPILE([#include <sys/ptrace.h>],
[PTRACE_GETREGS;],
[gdbsrv_cv_have_ptrace_getregs=yes],
[gdbsrv_cv_have_ptrace_getregs=no])])
AC_MSG_RESULT($gdbsrv_cv_have_ptrace_getregs)
if test "${gdbsrv_cv_have_ptrace_getregs}" = "yes"; then
AC_DEFINE(HAVE_LINUX_REGSETS)
fi
AC_MSG_CHECKING(for PTRACE_GETFPXREGS)
AC_CACHE_VAL(gdbsrv_cv_have_ptrace_getfpxregs,
[AC_TRY_COMPILE([#include <sys/ptrace.h>],
[PTRACE_GETFPXREGS;],
[gdbsrv_cv_have_ptrace_getfpxregs=yes],
[gdbsrv_cv_have_ptrace_getfpxregs=no])])
AC_MSG_RESULT($gdbsrv_cv_have_ptrace_getfpxregs)
if test "${gdbsrv_cv_have_ptrace_getfpxregs}" = "yes"; then
AC_DEFINE(HAVE_PTRACE_GETFPXREGS)
fi
fi
GDBSERVER_DEPFILES="$srv_regobj $srv_tgtobj"
AC_SUBST(GDBSERVER_DEPFILES)

View file

@ -10,30 +10,46 @@
# In addition, on GNU/Linux the following shell variables will be set:
# srv_linux_regsets Set to "yes" if ptrace(PTRACE_GETREGS) and friends
# may be available on this platform; unset otherwise.
# They will only be used if <sys/ptrace.h> defines
# PTRACE_GETREGS.
# srv_linux_usrregs Set to "yes" if we can get at registers via
# PTRACE_PEEKUSR / PTRACE_POKEUSR.
# Input is taken from the "${target}" variable.
case "${target}" in
arm*-*-linux*) srv_regobj=reg-arm.o
srv_tgtobj="linux-low.o linux-arm-low.o"
srv_linux_usrregs=yes
;;
i[3456]86-*-linux*) srv_regobj=reg-i386-linux.o
srv_tgtobj="linux-low.o linux-i386-low.o"
srv_tgtobj="linux-low.o linux-i386-low.o i387-fp.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
;;
ia64-*-linux*) srv_regobj=reg-ia64.o
srv_tgtobj="linux-low.o linux-ia64-low.o"
srv_linux_usrregs=yes
;;
m68*-*-linux*) srv_regobj=reg-m68k.o
srv_tgtobj="linux-low.o linux-m68k-low.o"
srv_linux_usrregs=yes
;;
mips*-*-linux*) srv_regobj=reg-mips.o
srv_tgtobj="linux-low.o linux-mips-low.o"
srv_linux_usrregs=yes
;;
powerpc*-*-linux*) srv_regobj=reg-ppc.o
srv_tgtobj="linux-low.o linux-ppc-low.o"
srv_linux_usrregs=yes
;;
sh*-*-linux*) srv_regobj=reg-sh.o
srv_tgtobj="linux-low.o linux-sh-low.o"
srv_linux_usrregs=yes
;;
x86_64-*-linux*) srv_regobj=reg-x86-64.o
srv_tgtobj="linux-low.o linux-x86-64-low.o i387-fp.o"
srv_linux_regsets=yes
;;
*) echo "Error: target not supported by gdbserver."
exit 1

290
gdb/gdbserver/i387-fp.c Normal file
View file

@ -0,0 +1,290 @@
/* i387-specific utility functions, for the remote server for GDB.
Copyright 2000, 2001, 2002
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. */
#include "server.h"
int num_xmm_registers = 8;
/* Note: These functions preserve the reserved bits in control registers.
However, gdbserver promptly throws away that information. */
/* These structs should have the proper sizes and alignment on both
i386 and x86-64 machines. */
struct i387_fsave {
/* All these are only sixteen bits, plus padding, except for fop (which
is only eleven bits), and fooff / fioff (which are 32 bits each). */
unsigned int fctrl;
unsigned int fstat;
unsigned int ftag;
unsigned int fioff;
unsigned short fiseg;
unsigned short fop;
unsigned int fooff;
unsigned int foseg;
/* Space for eight 80-bit FP values. */
char st_space[80];
};
struct i387_fxsave {
/* All these are only sixteen bits, plus padding, except for fop (which
is only eleven bits), and fooff / fioff (which are 32 bits each). */
unsigned short fctrl;
unsigned short fstat;
unsigned short ftag;
unsigned short fop;
unsigned int fioff;
unsigned int fiseg;
unsigned int fooff;
unsigned int foseg;
unsigned int mxcsr;
unsigned int _pad1;
/* Space for eight 80-bit FP values in 128-bit spaces. */
char st_space[128];
/* Space for eight 128-bit XMM values, or 16 on x86-64. */
char xmm_space[256];
};
void
i387_cache_to_fsave (void *buf)
{
struct i387_fsave *fp = (struct i387_fsave *) buf;
int i;
int st0_regnum = find_regno ("st0");
unsigned long val, val2;
for (i = 0; i < 8; i++)
collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10);
collect_register_by_name ("fioff", &fp->fioff);
collect_register_by_name ("fooff", &fp->fooff);
/* This one's 11 bits... */
collect_register_by_name ("fop", &val2);
fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
/* Some registers are 16-bit. */
collect_register_by_name ("fctrl", &val);
*(unsigned short *) &fp->fctrl = val;
collect_register_by_name ("fstat", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->fstat = val;
collect_register_by_name ("ftag", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->ftag = val;
collect_register_by_name ("fiseg", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->fiseg = val;
collect_register_by_name ("foseg", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->foseg = val;
}
void
i387_fsave_to_cache (void *buf)
{
struct i387_fsave *fp = (struct i387_fsave *) buf;
int i;
int st0_regnum = find_regno ("st0");
unsigned long val;
for (i = 0; i < 8; i++)
supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10);
supply_register_by_name ("fioff", &fp->fioff);
supply_register_by_name ("fooff", &fp->fooff);
/* Some registers are 16-bit. */
val = fp->fctrl & 0xFFFF;
supply_register_by_name ("fctrl", &val);
val = fp->fstat & 0xFFFF;
supply_register_by_name ("fstat", &val);
val = fp->ftag & 0xFFFF;
supply_register_by_name ("ftag", &val);
val = fp->fiseg & 0xFFFF;
supply_register_by_name ("fiseg", &val);
val = fp->foseg & 0xFFFF;
supply_register_by_name ("foseg", &val);
val = (fp->fop) & 0x7FF;
supply_register_by_name ("fop", &val);
}
void
i387_cache_to_fxsave (void *buf)
{
struct i387_fxsave *fp = (struct i387_fxsave *) buf;
int i;
int st0_regnum = find_regno ("st0");
int xmm0_regnum = find_regno ("xmm0");
unsigned long val, val2;
for (i = 0; i < 8; i++)
collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16);
for (i = 0; i < num_xmm_registers; i++)
collect_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16);
collect_register_by_name ("fioff", &fp->fioff);
collect_register_by_name ("fooff", &fp->fooff);
collect_register_by_name ("mxcsr", &fp->mxcsr);
/* This one's 11 bits... */
collect_register_by_name ("fop", &val2);
fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
/* Some registers are 16-bit. */
collect_register_by_name ("fctrl", &val);
*(unsigned short *) &fp->fctrl = val;
collect_register_by_name ("fstat", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->fstat = val;
/* Convert to the simplifed tag form stored in fxsave data. */
collect_register_by_name ("ftag", &val);
val &= 0xFFFF;
for (i = 7; i >= 0; i--)
{
int tag = (val >> (i * 2)) & 3;
if (tag != 3)
val2 |= (1 << i);
}
*(unsigned short *) &fp->ftag = val2;
collect_register_by_name ("fiseg", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->fiseg = val;
collect_register_by_name ("foseg", &val);
val &= 0xFFFF;
*(unsigned short *) &fp->foseg = val;
}
static int
i387_ftag (struct i387_fxsave *fp, int regno)
{
unsigned char *raw = &fp->st_space[regno * 16];
unsigned int exponent;
unsigned long fraction[2];
int integer;
integer = raw[7] & 0x80;
exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
| (raw[5] << 8) | raw[4]);
if (exponent == 0x7fff)
{
/* Special. */
return (2);
}
else if (exponent == 0x0000)
{
if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
{
/* Zero. */
return (1);
}
else
{
/* Special. */
return (2);
}
}
else
{
if (integer)
{
/* Valid. */
return (0);
}
else
{
/* Special. */
return (2);
}
}
}
void
i387_fxsave_to_cache (void *buf)
{
struct i387_fxsave *fp = (struct i387_fxsave *) buf;
int i, top;
int st0_regnum = find_regno ("st0");
int xmm0_regnum = find_regno ("xmm0");
unsigned long val;
for (i = 0; i < 8; i++)
supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16);
for (i = 0; i < num_xmm_registers; i++)
supply_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16);
supply_register_by_name ("fioff", &fp->fioff);
supply_register_by_name ("fooff", &fp->fooff);
supply_register_by_name ("mxcsr", &fp->mxcsr);
/* Some registers are 16-bit. */
val = fp->fctrl & 0xFFFF;
supply_register_by_name ("fctrl", &val);
val = fp->fstat & 0xFFFF;
supply_register_by_name ("fstat", &val);
/* Generate the form of ftag data that GDB expects. */
top = (fp->fstat >> 11) & 0x7;
val = 0;
for (i = 7; i >= 0; i--)
{
int tag;
if (val & (1 << i))
tag = i387_ftag (fp, (i + 8 - top) % 8);
else
tag = 3;
val |= tag << (2 * i);
}
supply_register_by_name ("ftag", &val);
val = fp->fiseg & 0xFFFF;
supply_register_by_name ("fiseg", &val);
val = fp->foseg & 0xFFFF;
supply_register_by_name ("foseg", &val);
val = (fp->fop) & 0x7FF;
supply_register_by_name ("fop", &val);
}

33
gdb/gdbserver/i387-fp.h Normal file
View file

@ -0,0 +1,33 @@
/* i387-specific utility functions, for the remote server for GDB.
Copyright 2000, 2001, 2002
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. */
#ifndef I387_FP_H
#define I387_FP_H
void i387_cache_to_fsave (void *buf);
void i387_fsave_to_cache (void *buf);
void i387_cache_to_fxsave (void *buf);
void i387_fxsave_to_cache (void *buf);
extern int num_xmm_registers;
#endif /* I387_FP_H */

View file

@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>

View file

@ -20,17 +20,14 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#include "i387-fp.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
/* This module only supports access to the general purpose registers.
Adjust the relevant constants accordingly.
FIXME: kettenis/2001-03-28: We should really use PTRACE_GETREGS to
get at the registers. Better yet, we should try to share code with
i386-linux-nat.c. */
/* This module only supports access to the general purpose registers. */
int num_regs = 16;
@ -57,3 +54,70 @@ cannot_fetch_register (int regno)
{
return (regno >= num_regs);
}
#ifdef HAVE_LINUX_REGSETS
#include <sys/procfs.h>
#include <sys/ptrace.h>
static void
i386_fill_gregset (void *buf)
{
int i;
for (i = 0; i < num_regs; i++)
collect_register (i, ((char *) buf) + regmap[i]);
collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
}
static void
i386_store_gregset (void *buf)
{
int i;
for (i = 0; i < num_regs; i++)
supply_register (i, ((char *) buf) + regmap[i]);
supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
}
static void
i386_fill_fpregset (void *buf)
{
i387_cache_to_fsave (buf);
}
static void
i386_store_fpregset (void *buf)
{
i387_fsave_to_cache (buf);
}
static void
i386_fill_fpxregset (void *buf)
{
i387_cache_to_fxsave (buf);
}
static void
i386_store_fpxregset (void *buf)
{
i387_fxsave_to_cache (buf);
}
struct regset_info target_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
i386_fill_gregset, i386_store_gregset },
#ifdef HAVE_PTRACE_GETFPXREGS
{ PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t),
i386_fill_fpxregset, i386_store_fpxregset },
#endif
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
i386_fill_fpregset, i386_store_fpregset },
{ 0, 0, -1, NULL, NULL }
};
#endif /* HAVE_LINUX_REGSETS */

View file

@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>

View file

@ -20,8 +20,9 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include <sys/wait.h>
#include "linux-low.h"
#include <sys/wait.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
@ -37,6 +38,10 @@
#define PTRACE_ARG3_TYPE long
#define PTRACE_XFER_TYPE int
#ifdef HAVE_LINUX_REGSETS
static int use_regsets_p = 1;
#endif
extern int errno;
extern int num_regs;
extern int regmap[];
@ -166,8 +171,11 @@ register_addr (int regnum)
return addr;
}
/* Fetch one register. */
#ifdef HAVE_LINUX_USRREGS
/* Fetch one register. */
static void
fetch_register (int regno)
{
@ -203,9 +211,8 @@ error_exit:;
}
/* Fetch all registers, or just one, from the child process. */
void
fetch_inferior_registers (int regno)
static void
usr_fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
for (regno = 0; regno < num_regs; regno++)
@ -217,9 +224,8 @@ fetch_inferior_registers (int regno)
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (int regno)
static void
usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
int i;
@ -259,6 +265,139 @@ store_inferior_registers (int regno)
for (regno = 0; regno < num_regs; regno++)
store_inferior_registers (regno);
}
#endif /* HAVE_LINUX_USRREGS */
#ifdef HAVE_LINUX_REGSETS
static int
regsets_fetch_inferior_registers (void)
{
struct regset_info *regset;
regset = target_regsets;
while (regset->size >= 0)
{
void *buf;
int res;
if (regset->size == 0)
{
regset ++;
continue;
}
buf = malloc (regset->size);
res = ptrace (regset->get_request, inferior_pid, 0, (int) buf);
if (res < 0)
{
if (errno == EIO)
{
/* If we get EIO on the first regset, do not try regsets again.
If we get EIO on a later regset, disable that regset. */
if (regset == target_regsets)
{
use_regsets_p = 0;
return -1;
}
else
{
regset->size = 0;
continue;
}
}
else
{
perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
}
}
regset->store_function (buf);
regset ++;
}
}
static int
regsets_store_inferior_registers (void)
{
struct regset_info *regset;
regset = target_regsets;
while (regset->size >= 0)
{
void *buf;
int res;
if (regset->size == 0)
{
regset ++;
continue;
}
buf = malloc (regset->size);
regset->fill_function (buf);
res = ptrace (regset->set_request, inferior_pid, 0, (int) buf);
if (res < 0)
{
if (errno == EIO)
{
/* If we get EIO on the first regset, do not try regsets again.
If we get EIO on a later regset, disable that regset. */
if (regset == target_regsets)
{
use_regsets_p = 0;
return -1;
}
else
{
regset->size = 0;
continue;
}
}
else
{
perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
}
}
regset ++;
}
}
#endif /* HAVE_LINUX_REGSETS */
void
fetch_inferior_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
{
if (regsets_fetch_inferior_registers () == 0)
return;
}
#endif
#ifdef HAVE_LINUX_USRREGS
usr_fetch_inferior_registers (regno);
#endif
}
void
store_inferior_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
{
if (regsets_store_inferior_registers () == 0)
return;
}
#endif
#ifdef HAVE_LINUX_USRREGS
usr_store_inferior_registers (regno);
#endif
}
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */

37
gdb/gdbserver/linux-low.h Normal file
View file

@ -0,0 +1,37 @@
/* Internal interfaces for the GNU/Linux specific target code for gdbserver.
Copyright 2002, 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. */
#ifdef HAVE_LINUX_USR_REGISTERS
extern int regmap[];
extern int num_regs;
int cannot_fetch_register (int regno);
int cannot_store_register (int regno);
#endif
#ifdef HAVE_LINUX_REGSETS
typedef void (*regset_func) (void *);
struct regset_info
{
int get_request, set_request;
int size;
regset_func fill_function, store_function;
};
extern struct regset_info target_regsets[];
#endif

View file

@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>

View file

@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>

View file

@ -21,6 +21,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#include <asm/ptrace.h>

View file

@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "linux-low.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>

View file

@ -0,0 +1,79 @@
/* GNU/Linux/x86-64 specific low level interface, for the remote server
for GDB.
Copyright 2002
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. */
#include "server.h"
#include "linux-low.h"
#include "i387-fp.h"
#include <sys/reg.h>
#include <sys/procfs.h>
#include <sys/ptrace.h>
static int regmap[] = {
RAX, RDX, RCX, RBX,
RSI, RDI, RBP, RSP,
R8, R9, R10, R11,
R12, R13, R14, R15,
RIP, EFLAGS
};
static void
x86_64_fill_gregset (void *buf)
{
int i;
for (i = 0; i < 18; i++)
collect_register (i, ((char *) buf) + regmap[i]);
}
static void
x86_64_store_gregset (void *buf)
{
int i;
for (i = 0; i < 18; i++)
supply_register (i, ((char *) buf) + regmap[i]);
}
static void
x86_64_fill_fpregset (void *buf)
{
i387_cache_to_fxsave (buf);
}
static void
x86_64_store_fpregset (void *buf)
{
i387_fxsave_to_cache (buf);
}
struct regset_info target_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
x86_64_fill_gregset, x86_64_store_gregset },
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
x86_64_fill_fpregset, x86_64_store_fpregset },
{ 0, 0, -1, NULL, NULL }
};
#endif /* HAVE_LINUX_REGSETS */

View file

@ -122,3 +122,26 @@ register_data (int n)
return registers + (reg_defs[n].offset / 8);
}
void
supply_register (int n, const char *buf)
{
memcpy (register_data (n), buf, register_size (n));
}
void
supply_register_by_name (const char *name, const char *buf)
{
supply_register (find_regno (name), buf);
}
void
collect_register (int n, char *buf)
{
memcpy (buf, register_data (n), register_size (n));
}
void
collect_register_by_name (const char *name, char *buf)
{
collect_register (find_regno (name), buf);
}

View file

@ -0,0 +1,53 @@
name:x86_64
expedite:rbp,rsp,rip
64:rax
64:rdx
64:rcx
64:rbx
64:rsi
64:rdi
64:rbp
64:rsp
64:r8
64:r9
64:r10
64:r11
64:r12
64:r13
64:r14
64:r15
64:rip
32:eflags
80:st0
80:st1
80:st2
80:st3
80:st4
80:st5
80:st6
80:st7
32:fctrl
32:fstat
32:ftag
32:fiseg
32:fioff
32:foseg
32:fooff
32:fop
128:xmm0
128:xmm1
128:xmm2
128:xmm3
128:xmm4
128:xmm5
128:xmm6
128:xmm7
128:xmm8
128:xmm9
128:xmm10
128:xmm11
128:xmm12
128:xmm13
128:xmm14
128:xmm15
32:mxcsr