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:
H.J. Lu 2010-04-07 18:49:46 +00:00
parent c302619d21
commit 1570b33e44
19 changed files with 633 additions and 57 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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 */

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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

View File

@ -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;

View File

@ -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 };

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 }
}; };

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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
}; };

View File

@ -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

View File

@ -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);

View File

@ -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);