Add x86 AVX support to gdbserver.
2010-04-07 H.J. Lu <hongjiu.lu@intel.com> * Makefile.in (clean): Updated. (i386-avx.o): New. (i386-avx.c): Likewise. (i386-avx-linux.o): Likewise. (i386-avx-linux.c): Likewise. (amd64-avx.o): Likewise. (amd64-avx.c): Likewise. (amd64-avx-linux.o): Likewise. (amd64-avx-linux.c): Likewise. * configure.srv (srv_i386_regobj): Add i386-avx.o. (srv_i386_linux_regobj): Add i386-avx-linux.o. (srv_amd64_regobj): Add amd64-avx.o. (srv_amd64_linux_regobj): Add amd64-avx-linux.o. (srv_i386_32bit_xmlfiles): Add i386/32bit-avx.xml. (srv_i386_64bit_xmlfiles): Add i386/64bit-avx.xml. (srv_i386_xmlfiles): Add i386/i386-avx.xml. (srv_amd64_xmlfiles): Add i386/amd64-avx.xml. (srv_i386_linux_xmlfiles): Add i386/i386-avx-linux.xml. (srv_amd64_linux_xmlfiles): Add i386/amd64-avx-linux.xml. * i387-fp.c: Include "i386-xstate.h". (i387_xsave): New. (i387_cache_to_xsave): Likewise. (i387_xsave_to_cache): Likewise. (x86_xcr0): Likewise. * i387-fp.h (i387_cache_to_xsave): Likewise. (i387_xsave_to_cache): Likewise. (x86_xcr0): Likewise. * linux-arm-low.c (target_regsets): Initialize nt_type to 0. * linux-crisv32-low.c (target_regsets): Likewise. * linux-m68k-low.c (target_regsets): Likewise. * linux-mips-low.c (target_regsets): Likewise. * linux-ppc-low.c (target_regsets): Likewise. * linux-s390-low.c (target_regsets): Likewise. * linux-sh-low.c (target_regsets): Likewise. * linux-sparc-low.c (target_regsets): Likewise. * linux-xtensa-low.c (target_regsets): Likewise. * linux-low.c: Include <sys/uio.h>. (regsets_fetch_inferior_registers): Support nt_type. (regsets_store_inferior_registers): Likewise. (linux_process_qsupported): New. (linux_target_ops): Add linux_process_qsupported. * linux-low.h (regset_info): Add nt_type. (linux_target_ops): Add process_qsupported. * linux-x86-low.c: Include "i386-xstate.h", "elf/common.h" and <sys/uio.h>. (init_registers_i386_avx_linux): New. (init_registers_amd64_avx_linux): Likewise. (xmltarget_i386_linux_no_xml): Likewise. (xmltarget_amd64_linux_no_xml): Likewise. (PTRACE_GETREGSET): Likewise. (PTRACE_SETREGSET): Likewise. (x86_fill_xstateregset): Likewise. (x86_store_xstateregset): Likewise. (use_xml): Likewise. (x86_linux_update_xmltarget): Likewise. (x86_linux_process_qsupported): Likewise. (target_regsets): Add NT_X86_XSTATE entry and Initialize nt_type. (x86_arch_setup): Don't call init_registers_amd64_linux nor init_registers_i386_linux here. Call x86_linux_update_xmltarget. (the_low_target): Add x86_linux_process_qsupported. * server.c (handle_query): Call target_process_qsupported. * target.h (target_ops): Add process_qsupported. (target_process_qsupported): New.
This commit is contained in:
parent
c302619d21
commit
1570b33e44
@ -1,3 +1,79 @@
|
|||||||
|
2010-04-07 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* Makefile.in (clean): Updated.
|
||||||
|
(i386-avx.o): New.
|
||||||
|
(i386-avx.c): Likewise.
|
||||||
|
(i386-avx-linux.o): Likewise.
|
||||||
|
(i386-avx-linux.c): Likewise.
|
||||||
|
(amd64-avx.o): Likewise.
|
||||||
|
(amd64-avx.c): Likewise.
|
||||||
|
(amd64-avx-linux.o): Likewise.
|
||||||
|
(amd64-avx-linux.c): Likewise.
|
||||||
|
|
||||||
|
* configure.srv (srv_i386_regobj): Add i386-avx.o.
|
||||||
|
(srv_i386_linux_regobj): Add i386-avx-linux.o.
|
||||||
|
(srv_amd64_regobj): Add amd64-avx.o.
|
||||||
|
(srv_amd64_linux_regobj): Add amd64-avx-linux.o.
|
||||||
|
(srv_i386_32bit_xmlfiles): Add i386/32bit-avx.xml.
|
||||||
|
(srv_i386_64bit_xmlfiles): Add i386/64bit-avx.xml.
|
||||||
|
(srv_i386_xmlfiles): Add i386/i386-avx.xml.
|
||||||
|
(srv_amd64_xmlfiles): Add i386/amd64-avx.xml.
|
||||||
|
(srv_i386_linux_xmlfiles): Add i386/i386-avx-linux.xml.
|
||||||
|
(srv_amd64_linux_xmlfiles): Add i386/amd64-avx-linux.xml.
|
||||||
|
|
||||||
|
* i387-fp.c: Include "i386-xstate.h".
|
||||||
|
(i387_xsave): New.
|
||||||
|
(i387_cache_to_xsave): Likewise.
|
||||||
|
(i387_xsave_to_cache): Likewise.
|
||||||
|
(x86_xcr0): Likewise.
|
||||||
|
|
||||||
|
* i387-fp.h (i387_cache_to_xsave): Likewise.
|
||||||
|
(i387_xsave_to_cache): Likewise.
|
||||||
|
(x86_xcr0): Likewise.
|
||||||
|
|
||||||
|
* linux-arm-low.c (target_regsets): Initialize nt_type to 0.
|
||||||
|
* linux-crisv32-low.c (target_regsets): Likewise.
|
||||||
|
* linux-m68k-low.c (target_regsets): Likewise.
|
||||||
|
* linux-mips-low.c (target_regsets): Likewise.
|
||||||
|
* linux-ppc-low.c (target_regsets): Likewise.
|
||||||
|
* linux-s390-low.c (target_regsets): Likewise.
|
||||||
|
* linux-sh-low.c (target_regsets): Likewise.
|
||||||
|
* linux-sparc-low.c (target_regsets): Likewise.
|
||||||
|
* linux-xtensa-low.c (target_regsets): Likewise.
|
||||||
|
|
||||||
|
* linux-low.c: Include <sys/uio.h>.
|
||||||
|
(regsets_fetch_inferior_registers): Support nt_type.
|
||||||
|
(regsets_store_inferior_registers): Likewise.
|
||||||
|
(linux_process_qsupported): New.
|
||||||
|
(linux_target_ops): Add linux_process_qsupported.
|
||||||
|
|
||||||
|
* linux-low.h (regset_info): Add nt_type.
|
||||||
|
(linux_target_ops): Add process_qsupported.
|
||||||
|
|
||||||
|
* linux-x86-low.c: Include "i386-xstate.h", "elf/common.h"
|
||||||
|
and <sys/uio.h>.
|
||||||
|
(init_registers_i386_avx_linux): New.
|
||||||
|
(init_registers_amd64_avx_linux): Likewise.
|
||||||
|
(xmltarget_i386_linux_no_xml): Likewise.
|
||||||
|
(xmltarget_amd64_linux_no_xml): Likewise.
|
||||||
|
(PTRACE_GETREGSET): Likewise.
|
||||||
|
(PTRACE_SETREGSET): Likewise.
|
||||||
|
(x86_fill_xstateregset): Likewise.
|
||||||
|
(x86_store_xstateregset): Likewise.
|
||||||
|
(use_xml): Likewise.
|
||||||
|
(x86_linux_update_xmltarget): Likewise.
|
||||||
|
(x86_linux_process_qsupported): Likewise.
|
||||||
|
(target_regsets): Add NT_X86_XSTATE entry and Initialize nt_type.
|
||||||
|
(x86_arch_setup): Don't call init_registers_amd64_linux nor
|
||||||
|
init_registers_i386_linux here. Call
|
||||||
|
x86_linux_update_xmltarget.
|
||||||
|
(the_low_target): Add x86_linux_process_qsupported.
|
||||||
|
|
||||||
|
* server.c (handle_query): Call target_process_qsupported.
|
||||||
|
|
||||||
|
* target.h (target_ops): Add process_qsupported.
|
||||||
|
(target_process_qsupported): New.
|
||||||
|
|
||||||
2010-04-03 Pedro Alves <pedro@codesourcery.com>
|
2010-04-03 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* inferiors.c (add_thread): Set last_status kind to
|
* inferiors.c (add_thread): Set last_status kind to
|
||||||
|
@ -217,6 +217,8 @@ clean:
|
|||||||
rm -f powerpc-isa205-vsx64l.c
|
rm -f powerpc-isa205-vsx64l.c
|
||||||
rm -f s390-linux32.c s390-linux64.c s390x-linux64.c
|
rm -f s390-linux32.c s390-linux64.c s390x-linux64.c
|
||||||
rm -f xml-builtin.c stamp-xml
|
rm -f xml-builtin.c stamp-xml
|
||||||
|
rm -f i386-avx.c i386-avx-linux.c
|
||||||
|
rm -f amd64-avx.c amd64-avx-linux.c
|
||||||
|
|
||||||
maintainer-clean realclean distclean: clean
|
maintainer-clean realclean distclean: clean
|
||||||
rm -f nm.h tm.h xm.h config.status config.h stamp-h config.log
|
rm -f nm.h tm.h xm.h config.status config.h stamp-h config.log
|
||||||
@ -351,6 +353,12 @@ i386.c : $(srcdir)/../regformats/i386/i386.dat $(regdat_sh)
|
|||||||
i386-linux.o : i386-linux.c $(regdef_h)
|
i386-linux.o : i386-linux.c $(regdef_h)
|
||||||
i386-linux.c : $(srcdir)/../regformats/i386/i386-linux.dat $(regdat_sh)
|
i386-linux.c : $(srcdir)/../regformats/i386/i386-linux.dat $(regdat_sh)
|
||||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-linux.dat i386-linux.c
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-linux.dat i386-linux.c
|
||||||
|
i386-avx.o : i386-avx.c $(regdef_h)
|
||||||
|
i386-avx.c : $(srcdir)/../regformats/i386/i386-avx.dat $(regdat_sh)
|
||||||
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-avx.dat i386-avx.c
|
||||||
|
i386-avx-linux.o : i386-avx-linux.c $(regdef_h)
|
||||||
|
i386-avx-linux.c : $(srcdir)/../regformats/i386/i386-avx-linux.dat $(regdat_sh)
|
||||||
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-avx-linux.dat i386-avx-linux.c
|
||||||
reg-ia64.o : reg-ia64.c $(regdef_h)
|
reg-ia64.o : reg-ia64.c $(regdef_h)
|
||||||
reg-ia64.c : $(srcdir)/../regformats/reg-ia64.dat $(regdat_sh)
|
reg-ia64.c : $(srcdir)/../regformats/reg-ia64.dat $(regdat_sh)
|
||||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-ia64.dat reg-ia64.c
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-ia64.dat reg-ia64.c
|
||||||
@ -438,6 +446,12 @@ amd64.c : $(srcdir)/../regformats/i386/amd64.dat $(regdat_sh)
|
|||||||
amd64-linux.o : amd64-linux.c $(regdef_h)
|
amd64-linux.o : amd64-linux.c $(regdef_h)
|
||||||
amd64-linux.c : $(srcdir)/../regformats/i386/amd64-linux.dat $(regdat_sh)
|
amd64-linux.c : $(srcdir)/../regformats/i386/amd64-linux.dat $(regdat_sh)
|
||||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-linux.dat amd64-linux.c
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-linux.dat amd64-linux.c
|
||||||
|
amd64-avx.o : amd64-avx.c $(regdef_h)
|
||||||
|
amd64-avx.c : $(srcdir)/../regformats/i386/amd64-avx.dat $(regdat_sh)
|
||||||
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-avx.dat amd64-avx.c
|
||||||
|
amd64-avx-linux.o : amd64-avx-linux.c $(regdef_h)
|
||||||
|
amd64-avx-linux.c : $(srcdir)/../regformats/i386/amd64-avx-linux.dat $(regdat_sh)
|
||||||
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-avx-linux.dat amd64-avx-linux.c
|
||||||
reg-xtensa.o : reg-xtensa.c $(regdef_h)
|
reg-xtensa.o : reg-xtensa.c $(regdef_h)
|
||||||
reg-xtensa.c : $(srcdir)/../regformats/reg-xtensa.dat $(regdat_sh)
|
reg-xtensa.c : $(srcdir)/../regformats/reg-xtensa.dat $(regdat_sh)
|
||||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-xtensa.dat reg-xtensa.c
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-xtensa.dat reg-xtensa.c
|
||||||
|
@ -22,17 +22,17 @@
|
|||||||
# Default hostio_last_error implementation
|
# Default hostio_last_error implementation
|
||||||
srv_hostio_err_objs="hostio-errno.o"
|
srv_hostio_err_objs="hostio-errno.o"
|
||||||
|
|
||||||
srv_i386_regobj=i386.o
|
srv_i386_regobj="i386.o i386-avx.o"
|
||||||
srv_i386_linux_regobj=i386-linux.o
|
srv_i386_linux_regobj="i386-linux.o i386-avx-linux.o"
|
||||||
srv_amd64_regobj=amd64.o
|
srv_amd64_regobj="amd64.o x86-64-avx.o"
|
||||||
srv_amd64_linux_regobj=amd64-linux.o
|
srv_amd64_linux_regobj="amd64-linux.o amd64-avx-linux.o"
|
||||||
|
|
||||||
srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml"
|
srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml"
|
||||||
srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml"
|
srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml"
|
||||||
srv_i386_xmlfiles="i386/i386.xml $srv_i386_32bit_xmlfiles"
|
srv_i386_xmlfiles="i386/i386.xml i386/i386-avx.xml $srv_i386_32bit_xmlfiles"
|
||||||
srv_amd64_xmlfiles="i386/amd64.xml $srv_i386_64bit_xmlfiles"
|
srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml $srv_i386_64bit_xmlfiles"
|
||||||
srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
|
srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
|
||||||
srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/64bit-linux.xml $srv_i386_64bit_xmlfiles"
|
srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/64bit-linux.xml $srv_i386_64bit_xmlfiles"
|
||||||
|
|
||||||
# Input is taken from the "${target}" variable.
|
# Input is taken from the "${target}" variable.
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "i387-fp.h"
|
#include "i387-fp.h"
|
||||||
|
#include "i386-xstate.h"
|
||||||
|
|
||||||
int num_xmm_registers = 8;
|
int num_xmm_registers = 8;
|
||||||
|
|
||||||
@ -72,6 +73,46 @@ struct i387_fxsave {
|
|||||||
unsigned char xmm_space[256];
|
unsigned char xmm_space[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct i387_xsave {
|
||||||
|
/* 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 short fiseg;
|
||||||
|
unsigned short pad1;
|
||||||
|
unsigned int fooff;
|
||||||
|
unsigned short foseg;
|
||||||
|
unsigned short pad12;
|
||||||
|
|
||||||
|
unsigned int mxcsr;
|
||||||
|
unsigned int mxcsr_mask;
|
||||||
|
|
||||||
|
/* Space for eight 80-bit FP values in 128-bit spaces. */
|
||||||
|
unsigned char st_space[128];
|
||||||
|
|
||||||
|
/* Space for eight 128-bit XMM values, or 16 on x86-64. */
|
||||||
|
unsigned char xmm_space[256];
|
||||||
|
|
||||||
|
unsigned char reserved1[48];
|
||||||
|
|
||||||
|
/* The extended control register 0 (the XFEATURE_ENABLED_MASK
|
||||||
|
register). */
|
||||||
|
unsigned long long xcr0;
|
||||||
|
|
||||||
|
unsigned char reserved2[40];
|
||||||
|
|
||||||
|
/* The XSTATE_BV bit vector. */
|
||||||
|
unsigned long long xstate_bv;
|
||||||
|
|
||||||
|
unsigned char reserved3[56];
|
||||||
|
|
||||||
|
/* Space for eight upper 128-bit YMM values, or 16 on x86-64. */
|
||||||
|
unsigned char ymmh_space[256];
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
i387_cache_to_fsave (struct regcache *regcache, void *buf)
|
i387_cache_to_fsave (struct regcache *regcache, void *buf)
|
||||||
{
|
{
|
||||||
@ -199,6 +240,128 @@ i387_cache_to_fxsave (struct regcache *regcache, void *buf)
|
|||||||
fp->foseg = val;
|
fp->foseg = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i387_cache_to_xsave (struct regcache *regcache, void *buf)
|
||||||
|
{
|
||||||
|
struct i387_xsave *fp = (struct i387_xsave *) buf;
|
||||||
|
int i;
|
||||||
|
unsigned long val, val2;
|
||||||
|
unsigned int clear_bv;
|
||||||
|
unsigned long long xstate_bv = 0;
|
||||||
|
char raw[16];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* The supported bits in `xstat_bv' are 1 byte. Clear part in
|
||||||
|
vector registers if its bit in xstat_bv is zero. */
|
||||||
|
clear_bv = (~fp->xstate_bv) & x86_xcr0;
|
||||||
|
|
||||||
|
/* Clear part in x87 and vector registers if its bit in xstat_bv is
|
||||||
|
zero. */
|
||||||
|
if (clear_bv)
|
||||||
|
{
|
||||||
|
if ((clear_bv & I386_XSTATE_X87))
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
|
||||||
|
|
||||||
|
if ((clear_bv & I386_XSTATE_SSE))
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
|
||||||
|
|
||||||
|
if ((clear_bv & I386_XSTATE_AVX))
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any x87 registers are changed. */
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_X87))
|
||||||
|
{
|
||||||
|
int st0_regnum = find_regno ("st0");
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
collect_register (regcache, i + st0_regnum, raw);
|
||||||
|
p = ((char *) &fp->st_space[0]) + i * 16;
|
||||||
|
if (memcmp (raw, p, 10))
|
||||||
|
{
|
||||||
|
xstate_bv |= I386_XSTATE_X87;
|
||||||
|
memcpy (p, raw, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any SSE registers are changed. */
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_SSE))
|
||||||
|
{
|
||||||
|
int xmm0_regnum = find_regno ("xmm0");
|
||||||
|
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
{
|
||||||
|
collect_register (regcache, i + xmm0_regnum, raw);
|
||||||
|
p = ((char *) &fp->xmm_space[0]) + i * 16;
|
||||||
|
if (memcmp (raw, p, 16))
|
||||||
|
{
|
||||||
|
xstate_bv |= I386_XSTATE_SSE;
|
||||||
|
memcpy (p, raw, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any AVX registers are changed. */
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_AVX))
|
||||||
|
{
|
||||||
|
int ymm0h_regnum = find_regno ("ymm0h");
|
||||||
|
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
{
|
||||||
|
collect_register (regcache, i + ymm0h_regnum, raw);
|
||||||
|
p = ((char *) &fp->ymmh_space[0]) + i * 16;
|
||||||
|
if (memcmp (raw, p, 16))
|
||||||
|
{
|
||||||
|
xstate_bv |= I386_XSTATE_AVX;
|
||||||
|
memcpy (p, raw, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the corresponding bits in xstate_bv if any SSE/AVX
|
||||||
|
registers are changed. */
|
||||||
|
fp->xstate_bv |= xstate_bv;
|
||||||
|
|
||||||
|
collect_register_by_name (regcache, "fioff", &fp->fioff);
|
||||||
|
collect_register_by_name (regcache, "fooff", &fp->fooff);
|
||||||
|
collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
|
||||||
|
|
||||||
|
/* This one's 11 bits... */
|
||||||
|
collect_register_by_name (regcache, "fop", &val2);
|
||||||
|
fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
|
||||||
|
|
||||||
|
/* Some registers are 16-bit. */
|
||||||
|
collect_register_by_name (regcache, "fctrl", &val);
|
||||||
|
fp->fctrl = val;
|
||||||
|
|
||||||
|
collect_register_by_name (regcache, "fstat", &val);
|
||||||
|
fp->fstat = val;
|
||||||
|
|
||||||
|
/* Convert to the simplifed tag form stored in fxsave data. */
|
||||||
|
collect_register_by_name (regcache, "ftag", &val);
|
||||||
|
val &= 0xFFFF;
|
||||||
|
val2 = 0;
|
||||||
|
for (i = 7; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int tag = (val >> (i * 2)) & 3;
|
||||||
|
|
||||||
|
if (tag != 3)
|
||||||
|
val2 |= (1 << i);
|
||||||
|
}
|
||||||
|
fp->ftag = val2;
|
||||||
|
|
||||||
|
collect_register_by_name (regcache, "fiseg", &val);
|
||||||
|
fp->fiseg = val;
|
||||||
|
|
||||||
|
collect_register_by_name (regcache, "foseg", &val);
|
||||||
|
fp->foseg = val;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
i387_ftag (struct i387_fxsave *fp, int regno)
|
i387_ftag (struct i387_fxsave *fp, int regno)
|
||||||
{
|
{
|
||||||
@ -296,3 +459,107 @@ i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
|
|||||||
val = (fp->fop) & 0x7FF;
|
val = (fp->fop) & 0x7FF;
|
||||||
supply_register_by_name (regcache, "fop", &val);
|
supply_register_by_name (regcache, "fop", &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
i387_xsave_to_cache (struct regcache *regcache, const void *buf)
|
||||||
|
{
|
||||||
|
struct i387_xsave *fp = (struct i387_xsave *) buf;
|
||||||
|
struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
|
||||||
|
int i, top;
|
||||||
|
unsigned long val;
|
||||||
|
unsigned int clear_bv;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* The supported bits in `xstat_bv' are 1 byte. Clear part in
|
||||||
|
vector registers if its bit in xstat_bv is zero. */
|
||||||
|
clear_bv = (~fp->xstate_bv) & x86_xcr0;
|
||||||
|
|
||||||
|
/* Check if any x87 registers are changed. */
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_X87))
|
||||||
|
{
|
||||||
|
int st0_regnum = find_regno ("st0");
|
||||||
|
|
||||||
|
if ((clear_bv & I386_XSTATE_X87))
|
||||||
|
p = NULL;
|
||||||
|
else
|
||||||
|
p = (char *) buf;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
p = ((char *) &fp->st_space[0]) + i * 16;
|
||||||
|
supply_register (regcache, i + st0_regnum, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_SSE))
|
||||||
|
{
|
||||||
|
int xmm0_regnum = find_regno ("xmm0");
|
||||||
|
|
||||||
|
if ((clear_bv & I386_XSTATE_SSE))
|
||||||
|
p = NULL;
|
||||||
|
else
|
||||||
|
p = (char *) buf;
|
||||||
|
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
p = ((char *) &fp->xmm_space[0]) + i * 16;
|
||||||
|
supply_register (regcache, i + xmm0_regnum, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x86_xcr0 & I386_XSTATE_AVX))
|
||||||
|
{
|
||||||
|
int ymm0h_regnum = find_regno ("ymm0h");
|
||||||
|
|
||||||
|
if ((clear_bv & I386_XSTATE_AVX))
|
||||||
|
p = NULL;
|
||||||
|
else
|
||||||
|
p = (char *) buf;
|
||||||
|
|
||||||
|
for (i = 0; i < num_xmm_registers; i++)
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
p = ((char *) &fp->ymmh_space[0]) + i * 16;
|
||||||
|
supply_register (regcache, i + ymm0h_regnum, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
supply_register_by_name (regcache, "fioff", &fp->fioff);
|
||||||
|
supply_register_by_name (regcache, "fooff", &fp->fooff);
|
||||||
|
supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
|
||||||
|
|
||||||
|
/* Some registers are 16-bit. */
|
||||||
|
val = fp->fctrl & 0xFFFF;
|
||||||
|
supply_register_by_name (regcache, "fctrl", &val);
|
||||||
|
|
||||||
|
val = fp->fstat & 0xFFFF;
|
||||||
|
supply_register_by_name (regcache, "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 (fp->ftag & (1 << i))
|
||||||
|
tag = i387_ftag (fxp, (i + 8 - top) % 8);
|
||||||
|
else
|
||||||
|
tag = 3;
|
||||||
|
val |= tag << (2 * i);
|
||||||
|
}
|
||||||
|
supply_register_by_name (regcache, "ftag", &val);
|
||||||
|
|
||||||
|
val = fp->fiseg & 0xFFFF;
|
||||||
|
supply_register_by_name (regcache, "fiseg", &val);
|
||||||
|
|
||||||
|
val = fp->foseg & 0xFFFF;
|
||||||
|
supply_register_by_name (regcache, "foseg", &val);
|
||||||
|
|
||||||
|
val = (fp->fop) & 0x7FF;
|
||||||
|
supply_register_by_name (regcache, "fop", &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default to SSE. */
|
||||||
|
unsigned long long x86_xcr0 = I386_XSTATE_SSE_MASK;
|
||||||
|
@ -26,6 +26,11 @@ void i387_fsave_to_cache (struct regcache *regcache, const void *buf);
|
|||||||
void i387_cache_to_fxsave (struct regcache *regcache, void *buf);
|
void i387_cache_to_fxsave (struct regcache *regcache, void *buf);
|
||||||
void i387_fxsave_to_cache (struct regcache *regcache, const void *buf);
|
void i387_fxsave_to_cache (struct regcache *regcache, const void *buf);
|
||||||
|
|
||||||
|
void i387_cache_to_xsave (struct regcache *regcache, void *buf);
|
||||||
|
void i387_xsave_to_cache (struct regcache *regcache, const void *buf);
|
||||||
|
|
||||||
|
extern unsigned long long x86_xcr0;
|
||||||
|
|
||||||
extern int num_xmm_registers;
|
extern int num_xmm_registers;
|
||||||
|
|
||||||
#endif /* I387_FP_H */
|
#endif /* I387_FP_H */
|
||||||
|
@ -354,16 +354,16 @@ arm_arch_setup (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 18 * 4,
|
||||||
GENERAL_REGS,
|
GENERAL_REGS,
|
||||||
arm_fill_gregset, arm_store_gregset },
|
arm_fill_gregset, arm_store_gregset },
|
||||||
{ PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 16 * 8 + 6 * 4,
|
{ PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 0, 16 * 8 + 6 * 4,
|
||||||
EXTENDED_REGS,
|
EXTENDED_REGS,
|
||||||
arm_fill_wmmxregset, arm_store_wmmxregset },
|
arm_fill_wmmxregset, arm_store_wmmxregset },
|
||||||
{ PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 32 * 8 + 4,
|
{ PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, 32 * 8 + 4,
|
||||||
EXTENDED_REGS,
|
EXTENDED_REGS,
|
||||||
arm_fill_vfpregset, arm_store_vfpregset },
|
arm_fill_vfpregset, arm_store_vfpregset },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -365,9 +365,9 @@ cris_store_gregset (const void *buf)
|
|||||||
typedef unsigned long elf_gregset_t[cris_num_regs];
|
typedef unsigned long elf_gregset_t[cris_num_regs];
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||||
GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
|
GENERAL_REGS, cris_fill_gregset, cris_store_gregset },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
#ifndef ELFMAG0
|
#ifndef ELFMAG0
|
||||||
/* Don't include <linux/elf.h> here. If it got included by gdb_proc_service.h
|
/* Don't include <linux/elf.h> here. If it got included by gdb_proc_service.h
|
||||||
then ELFMAG0 will have been defined. If it didn't get included by
|
then ELFMAG0 will have been defined. If it didn't get included by
|
||||||
@ -2977,14 +2978,15 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
|
|||||||
struct regset_info *regset;
|
struct regset_info *regset;
|
||||||
int saw_general_regs = 0;
|
int saw_general_regs = 0;
|
||||||
int pid;
|
int pid;
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
regset = target_regsets;
|
regset = target_regsets;
|
||||||
|
|
||||||
pid = lwpid_of (get_thread_lwp (current_inferior));
|
pid = lwpid_of (get_thread_lwp (current_inferior));
|
||||||
while (regset->size >= 0)
|
while (regset->size >= 0)
|
||||||
{
|
{
|
||||||
void *buf;
|
void *buf, *data;
|
||||||
int res;
|
int nt_type, res;
|
||||||
|
|
||||||
if (regset->size == 0 || disabled_regsets[regset - target_regsets])
|
if (regset->size == 0 || disabled_regsets[regset - target_regsets])
|
||||||
{
|
{
|
||||||
@ -2993,10 +2995,21 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf = xmalloc (regset->size);
|
buf = xmalloc (regset->size);
|
||||||
|
|
||||||
|
nt_type = regset->nt_type;
|
||||||
|
if (nt_type)
|
||||||
|
{
|
||||||
|
iov.iov_base = buf;
|
||||||
|
iov.iov_len = regset->size;
|
||||||
|
data = (void *) &iov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data = buf;
|
||||||
|
|
||||||
#ifndef __sparc__
|
#ifndef __sparc__
|
||||||
res = ptrace (regset->get_request, pid, 0, buf);
|
res = ptrace (regset->get_request, pid, nt_type, data);
|
||||||
#else
|
#else
|
||||||
res = ptrace (regset->get_request, pid, buf, 0);
|
res = ptrace (regset->get_request, pid, data, nt_type);
|
||||||
#endif
|
#endif
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
@ -3034,14 +3047,15 @@ regsets_store_inferior_registers (struct regcache *regcache)
|
|||||||
struct regset_info *regset;
|
struct regset_info *regset;
|
||||||
int saw_general_regs = 0;
|
int saw_general_regs = 0;
|
||||||
int pid;
|
int pid;
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
regset = target_regsets;
|
regset = target_regsets;
|
||||||
|
|
||||||
pid = lwpid_of (get_thread_lwp (current_inferior));
|
pid = lwpid_of (get_thread_lwp (current_inferior));
|
||||||
while (regset->size >= 0)
|
while (regset->size >= 0)
|
||||||
{
|
{
|
||||||
void *buf;
|
void *buf, *data;
|
||||||
int res;
|
int nt_type, res;
|
||||||
|
|
||||||
if (regset->size == 0 || disabled_regsets[regset - target_regsets])
|
if (regset->size == 0 || disabled_regsets[regset - target_regsets])
|
||||||
{
|
{
|
||||||
@ -3054,10 +3068,21 @@ regsets_store_inferior_registers (struct regcache *regcache)
|
|||||||
/* First fill the buffer with the current register set contents,
|
/* First fill the buffer with the current register set contents,
|
||||||
in case there are any items in the kernel's regset that are
|
in case there are any items in the kernel's regset that are
|
||||||
not in gdbserver's regcache. */
|
not in gdbserver's regcache. */
|
||||||
|
|
||||||
|
nt_type = regset->nt_type;
|
||||||
|
if (nt_type)
|
||||||
|
{
|
||||||
|
iov.iov_base = buf;
|
||||||
|
iov.iov_len = regset->size;
|
||||||
|
data = (void *) &iov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data = buf;
|
||||||
|
|
||||||
#ifndef __sparc__
|
#ifndef __sparc__
|
||||||
res = ptrace (regset->get_request, pid, 0, buf);
|
res = ptrace (regset->get_request, pid, nt_type, data);
|
||||||
#else
|
#else
|
||||||
res = ptrace (regset->get_request, pid, buf, 0);
|
res = ptrace (regset->get_request, pid, &iov, data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
@ -3067,9 +3092,9 @@ regsets_store_inferior_registers (struct regcache *regcache)
|
|||||||
|
|
||||||
/* Only now do we write the register set. */
|
/* Only now do we write the register set. */
|
||||||
#ifndef __sparc__
|
#ifndef __sparc__
|
||||||
res = ptrace (regset->set_request, pid, 0, buf);
|
res = ptrace (regset->set_request, pid, nt_type, data);
|
||||||
#else
|
#else
|
||||||
res = ptrace (regset->set_request, pid, buf, 0);
|
res = ptrace (regset->set_request, pid, data, nt_type);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4133,6 +4158,13 @@ linux_core_of_thread (ptid_t ptid)
|
|||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_process_qsupported (const char *query)
|
||||||
|
{
|
||||||
|
if (the_low_target.process_qsupported != NULL)
|
||||||
|
the_low_target.process_qsupported (query);
|
||||||
|
}
|
||||||
|
|
||||||
static struct target_ops linux_target_ops = {
|
static struct target_ops linux_target_ops = {
|
||||||
linux_create_inferior,
|
linux_create_inferior,
|
||||||
linux_attach,
|
linux_attach,
|
||||||
@ -4176,7 +4208,8 @@ static struct target_ops linux_target_ops = {
|
|||||||
#else
|
#else
|
||||||
NULL,
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
linux_core_of_thread
|
linux_core_of_thread,
|
||||||
|
linux_process_qsupported
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -35,6 +35,9 @@ enum regset_type {
|
|||||||
struct regset_info
|
struct regset_info
|
||||||
{
|
{
|
||||||
int get_request, set_request;
|
int get_request, set_request;
|
||||||
|
/* If NT_TYPE isn't 0, it will be passed to ptrace as the 3rd
|
||||||
|
argument and the 4th argument should be "const struct iovec *". */
|
||||||
|
int nt_type;
|
||||||
int size;
|
int size;
|
||||||
enum regset_type type;
|
enum regset_type type;
|
||||||
regset_fill_func fill_function;
|
regset_fill_func fill_function;
|
||||||
@ -111,6 +114,9 @@ struct linux_target_ops
|
|||||||
|
|
||||||
/* Hook to call prior to resuming a thread. */
|
/* Hook to call prior to resuming a thread. */
|
||||||
void (*prepare_to_resume) (struct lwp_info *);
|
void (*prepare_to_resume) (struct lwp_info *);
|
||||||
|
|
||||||
|
/* Hook to support target specific qSupported. */
|
||||||
|
void (*process_qsupported) (const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct linux_target_ops the_low_target;
|
extern struct linux_target_ops the_low_target;
|
||||||
|
@ -112,14 +112,14 @@ m68k_store_fpregset (struct regcache *regcache, const void *buf)
|
|||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
#ifdef HAVE_PTRACE_GETREGS
|
#ifdef HAVE_PTRACE_GETREGS
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||||
GENERAL_REGS,
|
GENERAL_REGS,
|
||||||
m68k_fill_gregset, m68k_store_gregset },
|
m68k_fill_gregset, m68k_store_gregset },
|
||||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
|
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (elf_fpregset_t),
|
||||||
FP_REGS,
|
FP_REGS,
|
||||||
m68k_fill_fpregset, m68k_store_fpregset },
|
m68k_fill_fpregset, m68k_store_fpregset },
|
||||||
#endif /* HAVE_PTRACE_GETREGS */
|
#endif /* HAVE_PTRACE_GETREGS */
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F };
|
static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F };
|
||||||
|
@ -343,12 +343,12 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
|
|||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
#ifdef HAVE_PTRACE_GETREGS
|
#ifdef HAVE_PTRACE_GETREGS
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 38 * 8, GENERAL_REGS,
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 38 * 8, GENERAL_REGS,
|
||||||
mips_fill_gregset, mips_store_gregset },
|
mips_fill_gregset, mips_store_gregset },
|
||||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 33 * 8, FP_REGS,
|
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
|
||||||
mips_fill_fpregset, mips_store_fpregset },
|
mips_fill_fpregset, mips_store_fpregset },
|
||||||
#endif /* HAVE_PTRACE_GETREGS */
|
#endif /* HAVE_PTRACE_GETREGS */
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -593,14 +593,14 @@ struct regset_info target_regsets[] = {
|
|||||||
fetch them every time, but still fall back to PTRACE_PEEKUSER for the
|
fetch them every time, but still fall back to PTRACE_PEEKUSER for the
|
||||||
general registers. Some kernels support these, but not the newer
|
general registers. Some kernels support these, but not the newer
|
||||||
PPC_PTRACE_GETREGS. */
|
PPC_PTRACE_GETREGS. */
|
||||||
{ PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, SIZEOF_VSXREGS, EXTENDED_REGS,
|
{ PTRACE_GETVSXREGS, PTRACE_SETVSXREGS, 0, SIZEOF_VSXREGS, EXTENDED_REGS,
|
||||||
ppc_fill_vsxregset, ppc_store_vsxregset },
|
ppc_fill_vsxregset, ppc_store_vsxregset },
|
||||||
{ PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
|
{ PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, SIZEOF_VRREGS, EXTENDED_REGS,
|
||||||
ppc_fill_vrregset, ppc_store_vrregset },
|
ppc_fill_vrregset, ppc_store_vrregset },
|
||||||
{ PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 32 * 4 + 8 + 4, EXTENDED_REGS,
|
{ PTRACE_GETEVRREGS, PTRACE_SETEVRREGS, 0, 32 * 4 + 8 + 4, EXTENDED_REGS,
|
||||||
ppc_fill_evrregset, ppc_store_evrregset },
|
ppc_fill_evrregset, ppc_store_evrregset },
|
||||||
{ 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
|
{ 0, 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -181,8 +181,8 @@ static void s390_fill_gregset (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
|
{ 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,8 +104,8 @@ static void sh_fill_gregset (struct regcache *regcache, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
|
{ 0, 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -260,13 +260,13 @@ sparc_reinsert_addr (void)
|
|||||||
|
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||||
GENERAL_REGS,
|
GENERAL_REGS,
|
||||||
sparc_fill_gregset, sparc_store_gregset },
|
sparc_fill_gregset, sparc_store_gregset },
|
||||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (fpregset_t),
|
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (fpregset_t),
|
||||||
FP_REGS,
|
FP_REGS,
|
||||||
sparc_fill_fpregset, sparc_store_fpregset },
|
sparc_fill_fpregset, sparc_store_fpregset },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_target_ops the_low_target = {
|
struct linux_target_ops the_low_target = {
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include "linux-low.h"
|
#include "linux-low.h"
|
||||||
#include "i387-fp.h"
|
#include "i387-fp.h"
|
||||||
#include "i386-low.h"
|
#include "i386-low.h"
|
||||||
|
#include "i386-xstate.h"
|
||||||
|
#include "elf/common.h"
|
||||||
|
|
||||||
#include "gdb_proc_service.h"
|
#include "gdb_proc_service.h"
|
||||||
|
|
||||||
@ -31,10 +33,35 @@
|
|||||||
void init_registers_i386_linux (void);
|
void init_registers_i386_linux (void);
|
||||||
/* Defined in auto-generated file amd64-linux.c. */
|
/* Defined in auto-generated file amd64-linux.c. */
|
||||||
void init_registers_amd64_linux (void);
|
void init_registers_amd64_linux (void);
|
||||||
|
/* Defined in auto-generated file i386-avx-linux.c. */
|
||||||
|
void init_registers_i386_avx_linux (void);
|
||||||
|
/* Defined in auto-generated file amd64-avx-linux.c. */
|
||||||
|
void init_registers_amd64_avx_linux (void);
|
||||||
|
|
||||||
|
/* Backward compatibility for gdb without XML support. */
|
||||||
|
|
||||||
|
static const char *xmltarget_i386_linux_no_xml = "@<target>\
|
||||||
|
<architecture>i386</architecture>\
|
||||||
|
<osabi>GNU/Linux</osabi>\
|
||||||
|
</target>";
|
||||||
|
static const char *xmltarget_amd64_linux_no_xml = "@<target>\
|
||||||
|
<architecture>i386:x86-64</architecture>\
|
||||||
|
<osabi>GNU/Linux</osabi>\
|
||||||
|
</target>";
|
||||||
|
|
||||||
#include <sys/reg.h>
|
#include <sys/reg.h>
|
||||||
#include <sys/procfs.h>
|
#include <sys/procfs.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#ifndef PTRACE_GETREGSET
|
||||||
|
#define PTRACE_GETREGSET 0x4204
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PTRACE_SETREGSET
|
||||||
|
#define PTRACE_SETREGSET 0x4205
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef PTRACE_GET_THREAD_AREA
|
#ifndef PTRACE_GET_THREAD_AREA
|
||||||
#define PTRACE_GET_THREAD_AREA 25
|
#define PTRACE_GET_THREAD_AREA 25
|
||||||
@ -252,6 +279,18 @@ x86_store_fpxregset (struct regcache *regcache, const void *buf)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
x86_fill_xstateregset (struct regcache *regcache, void *buf)
|
||||||
|
{
|
||||||
|
i387_cache_to_xsave (regcache, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x86_store_xstateregset (struct regcache *regcache, const void *buf)
|
||||||
|
{
|
||||||
|
i387_xsave_to_cache (regcache, buf);
|
||||||
|
}
|
||||||
|
|
||||||
/* ??? The non-biarch i386 case stores all the i387 regs twice.
|
/* ??? The non-biarch i386 case stores all the i387 regs twice.
|
||||||
Once in i387_.*fsave.* and once in i387_.*fxsave.*.
|
Once in i387_.*fsave.* and once in i387_.*fxsave.*.
|
||||||
This is, presumably, to handle the case where PTRACE_[GS]ETFPXREGS
|
This is, presumably, to handle the case where PTRACE_[GS]ETFPXREGS
|
||||||
@ -264,21 +303,23 @@ x86_store_fpxregset (struct regcache *regcache, const void *buf)
|
|||||||
struct regset_info target_regsets[] =
|
struct regset_info target_regsets[] =
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PTRACE_GETREGS
|
#ifdef HAVE_PTRACE_GETREGS
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||||
GENERAL_REGS,
|
GENERAL_REGS,
|
||||||
x86_fill_gregset, x86_store_gregset },
|
x86_fill_gregset, x86_store_gregset },
|
||||||
|
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_X86_XSTATE, 0,
|
||||||
|
EXTENDED_REGS, x86_fill_xstateregset, x86_store_xstateregset },
|
||||||
# ifndef __x86_64__
|
# ifndef __x86_64__
|
||||||
# ifdef HAVE_PTRACE_GETFPXREGS
|
# ifdef HAVE_PTRACE_GETFPXREGS
|
||||||
{ PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t),
|
{ PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, 0, sizeof (elf_fpxregset_t),
|
||||||
EXTENDED_REGS,
|
EXTENDED_REGS,
|
||||||
x86_fill_fpxregset, x86_store_fpxregset },
|
x86_fill_fpxregset, x86_store_fpxregset },
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
|
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (elf_fpregset_t),
|
||||||
FP_REGS,
|
FP_REGS,
|
||||||
x86_fill_fpregset, x86_store_fpregset },
|
x86_fill_fpregset, x86_store_fpregset },
|
||||||
#endif /* HAVE_PTRACE_GETREGS */
|
#endif /* HAVE_PTRACE_GETREGS */
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
@ -780,6 +821,128 @@ x86_siginfo_fixup (struct siginfo *native, void *inf, int direction)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int use_xml;
|
||||||
|
|
||||||
|
/* Update gdbserver_xmltarget. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
x86_linux_update_xmltarget (void)
|
||||||
|
{
|
||||||
|
static unsigned long long xcr0;
|
||||||
|
static int have_ptrace_getregset = -1;
|
||||||
|
|
||||||
|
if (!current_inferior)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
if (num_xmm_registers == 8)
|
||||||
|
init_registers_i386_linux ();
|
||||||
|
else
|
||||||
|
init_registers_amd64_linux ();
|
||||||
|
#else
|
||||||
|
init_registers_i386_linux ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!use_xml)
|
||||||
|
{
|
||||||
|
/* Don't use XML. */
|
||||||
|
#ifdef __x86_64__
|
||||||
|
if (num_xmm_registers == 8)
|
||||||
|
gdbserver_xmltarget = xmltarget_i386_linux_no_xml;
|
||||||
|
else
|
||||||
|
gdbserver_xmltarget = xmltarget_amd64_linux_no_xml;
|
||||||
|
#else
|
||||||
|
gdbserver_xmltarget = xmltarget_i386_linux_no_xml;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
x86_xcr0 = I386_XSTATE_SSE_MASK;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if XSAVE extended state is supported. */
|
||||||
|
if (have_ptrace_getregset == -1)
|
||||||
|
{
|
||||||
|
int pid = pid_of (get_thread_lwp (current_inferior));
|
||||||
|
unsigned long long xstateregs[I386_XSTATE_SSE_SIZE / sizeof (long long)];
|
||||||
|
struct iovec iov;
|
||||||
|
struct regset_info *regset;
|
||||||
|
|
||||||
|
iov.iov_base = xstateregs;
|
||||||
|
iov.iov_len = sizeof (xstateregs);
|
||||||
|
|
||||||
|
/* Check if PTRACE_GETREGSET works. */
|
||||||
|
if (ptrace (PTRACE_GETREGSET, pid, (unsigned int) NT_X86_XSTATE,
|
||||||
|
&iov) < 0)
|
||||||
|
{
|
||||||
|
have_ptrace_getregset = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
have_ptrace_getregset = 1;
|
||||||
|
|
||||||
|
/* Get XCR0 from XSAVE extended state at byte 464. */
|
||||||
|
xcr0 = xstateregs[464 / sizeof (long long)];
|
||||||
|
|
||||||
|
/* Use PTRACE_GETREGSET if it is available. */
|
||||||
|
for (regset = target_regsets;
|
||||||
|
regset->fill_function != NULL; regset++)
|
||||||
|
if (regset->get_request == PTRACE_GETREGSET)
|
||||||
|
regset->size = I386_XSTATE_SIZE (xcr0);
|
||||||
|
else if (regset->type != GENERAL_REGS)
|
||||||
|
regset->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_ptrace_getregset)
|
||||||
|
{
|
||||||
|
/* AVX is the highest feature we support. */
|
||||||
|
if ((xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK)
|
||||||
|
{
|
||||||
|
x86_xcr0 = xcr0;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
/* I386 has 8 xmm regs. */
|
||||||
|
if (num_xmm_registers == 8)
|
||||||
|
init_registers_i386_avx_linux ();
|
||||||
|
else
|
||||||
|
init_registers_amd64_avx_linux ();
|
||||||
|
#else
|
||||||
|
init_registers_i386_avx_linux ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process qSupported query, "xmlRegisters=". Update the buffer size for
|
||||||
|
PTRACE_GETREGSET. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
x86_linux_process_qsupported (const char *query)
|
||||||
|
{
|
||||||
|
/* Return if gdb doesn't support XML. If gdb sends "xmlRegisters="
|
||||||
|
with "i386" in qSupported query, it supports x86 XML target
|
||||||
|
descriptions. */
|
||||||
|
use_xml = 0;
|
||||||
|
if (query != NULL && strncmp (query, "xmlRegisters=", 13) == 0)
|
||||||
|
{
|
||||||
|
char *copy = xstrdup (query + 13);
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for (p = strtok (copy, ","); p != NULL; p = strtok (NULL, ","))
|
||||||
|
{
|
||||||
|
if (strcmp (p, "i386") == 0)
|
||||||
|
{
|
||||||
|
use_xml = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free (copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
x86_linux_update_xmltarget ();
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize gdbserver for the architecture of the inferior. */
|
/* Initialize gdbserver for the architecture of the inferior. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -800,8 +963,6 @@ x86_arch_setup (void)
|
|||||||
}
|
}
|
||||||
else if (use_64bit)
|
else if (use_64bit)
|
||||||
{
|
{
|
||||||
init_registers_amd64_linux ();
|
|
||||||
|
|
||||||
/* Amd64 doesn't have HAVE_LINUX_USRREGS. */
|
/* Amd64 doesn't have HAVE_LINUX_USRREGS. */
|
||||||
the_low_target.num_regs = -1;
|
the_low_target.num_regs = -1;
|
||||||
the_low_target.regmap = NULL;
|
the_low_target.regmap = NULL;
|
||||||
@ -811,14 +972,13 @@ x86_arch_setup (void)
|
|||||||
/* Amd64 has 16 xmm regs. */
|
/* Amd64 has 16 xmm regs. */
|
||||||
num_xmm_registers = 16;
|
num_xmm_registers = 16;
|
||||||
|
|
||||||
|
x86_linux_update_xmltarget ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Ok we have a 32-bit inferior. */
|
/* Ok we have a 32-bit inferior. */
|
||||||
|
|
||||||
init_registers_i386_linux ();
|
|
||||||
|
|
||||||
the_low_target.num_regs = I386_NUM_REGS;
|
the_low_target.num_regs = I386_NUM_REGS;
|
||||||
the_low_target.regmap = i386_regmap;
|
the_low_target.regmap = i386_regmap;
|
||||||
the_low_target.cannot_fetch_register = i386_cannot_fetch_register;
|
the_low_target.cannot_fetch_register = i386_cannot_fetch_register;
|
||||||
@ -826,6 +986,8 @@ x86_arch_setup (void)
|
|||||||
|
|
||||||
/* I386 has 8 xmm regs. */
|
/* I386 has 8 xmm regs. */
|
||||||
num_xmm_registers = 8;
|
num_xmm_registers = 8;
|
||||||
|
|
||||||
|
x86_linux_update_xmltarget ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is initialized assuming an amd64 target.
|
/* This is initialized assuming an amd64 target.
|
||||||
@ -858,5 +1020,6 @@ struct linux_target_ops the_low_target =
|
|||||||
x86_siginfo_fixup,
|
x86_siginfo_fixup,
|
||||||
x86_linux_new_process,
|
x86_linux_new_process,
|
||||||
x86_linux_new_thread,
|
x86_linux_new_thread,
|
||||||
x86_linux_prepare_to_resume
|
x86_linux_prepare_to_resume,
|
||||||
|
x86_linux_process_qsupported
|
||||||
};
|
};
|
||||||
|
@ -131,13 +131,13 @@ xtensa_store_xtregset (struct regcache *regcache, const void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct regset_info target_regsets[] = {
|
struct regset_info target_regsets[] = {
|
||||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||||
GENERAL_REGS,
|
GENERAL_REGS,
|
||||||
xtensa_fill_gregset, xtensa_store_gregset },
|
xtensa_fill_gregset, xtensa_store_gregset },
|
||||||
{ PTRACE_GETXTREGS, PTRACE_SETXTREGS, XTENSA_ELF_XTREG_SIZE,
|
{ PTRACE_GETXTREGS, PTRACE_SETXTREGS, 0, XTENSA_ELF_XTREG_SIZE,
|
||||||
EXTENDED_REGS,
|
EXTENDED_REGS,
|
||||||
xtensa_fill_xtregset, xtensa_store_xtregset },
|
xtensa_fill_xtregset, xtensa_store_xtregset },
|
||||||
{ 0, 0, -1, -1, NULL, NULL }
|
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if XCHAL_HAVE_BE
|
#if XCHAL_HAVE_BE
|
||||||
|
@ -1289,6 +1289,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
|||||||
{
|
{
|
||||||
char *p = &own_buf[10];
|
char *p = &own_buf[10];
|
||||||
|
|
||||||
|
/* Start processing qSupported packet. */
|
||||||
|
target_process_qsupported (NULL);
|
||||||
|
|
||||||
/* Process each feature being provided by GDB. The first
|
/* Process each feature being provided by GDB. The first
|
||||||
feature will follow a ':', and latter features will follow
|
feature will follow a ':', and latter features will follow
|
||||||
';'. */
|
';'. */
|
||||||
@ -1304,6 +1307,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
|||||||
if (target_supports_multi_process ())
|
if (target_supports_multi_process ())
|
||||||
multi_process = 1;
|
multi_process = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
target_process_qsupported (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
|
sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
|
||||||
|
@ -286,6 +286,9 @@ struct target_ops
|
|||||||
|
|
||||||
/* Returns the core given a thread, or -1 if not known. */
|
/* Returns the core given a thread, or -1 if not known. */
|
||||||
int (*core_of_thread) (ptid_t);
|
int (*core_of_thread) (ptid_t);
|
||||||
|
|
||||||
|
/* Target specific qSupported support. */
|
||||||
|
void (*process_qsupported) (const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct target_ops *the_target;
|
extern struct target_ops *the_target;
|
||||||
@ -326,6 +329,10 @@ void set_target_ops (struct target_ops *);
|
|||||||
(the_target->supports_multi_process ? \
|
(the_target->supports_multi_process ? \
|
||||||
(*the_target->supports_multi_process) () : 0)
|
(*the_target->supports_multi_process) () : 0)
|
||||||
|
|
||||||
|
#define target_process_qsupported(query) \
|
||||||
|
if (the_target->process_qsupported) \
|
||||||
|
the_target->process_qsupported (query)
|
||||||
|
|
||||||
/* Start non-stop mode, returns 0 on success, -1 on failure. */
|
/* Start non-stop mode, returns 0 on success, -1 on failure. */
|
||||||
|
|
||||||
int start_non_stop (int nonstop);
|
int start_non_stop (int nonstop);
|
||||||
|
Loading…
Reference in New Issue
Block a user