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>
|
||||
|
||||
* inferiors.c (add_thread): Set last_status kind to
|
||||
|
@ -217,6 +217,8 @@ clean:
|
||||
rm -f powerpc-isa205-vsx64l.c
|
||||
rm -f s390-linux32.c s390-linux64.c s390x-linux64.c
|
||||
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
|
||||
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.c : $(srcdir)/../regformats/i386/i386-linux.dat $(regdat_sh)
|
||||
$(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.c : $(srcdir)/../regformats/reg-ia64.dat $(regdat_sh)
|
||||
$(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.c : $(srcdir)/../regformats/i386/amd64-linux.dat $(regdat_sh)
|
||||
$(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.c : $(srcdir)/../regformats/reg-xtensa.dat $(regdat_sh)
|
||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-xtensa.dat reg-xtensa.c
|
||||
|
@ -22,17 +22,17 @@
|
||||
# Default hostio_last_error implementation
|
||||
srv_hostio_err_objs="hostio-errno.o"
|
||||
|
||||
srv_i386_regobj=i386.o
|
||||
srv_i386_linux_regobj=i386-linux.o
|
||||
srv_amd64_regobj=amd64.o
|
||||
srv_amd64_linux_regobj=amd64-linux.o
|
||||
srv_i386_regobj="i386.o i386-avx.o"
|
||||
srv_i386_linux_regobj="i386-linux.o i386-avx-linux.o"
|
||||
srv_amd64_regobj="amd64.o x86-64-avx.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_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml"
|
||||
srv_i386_xmlfiles="i386/i386.xml $srv_i386_32bit_xmlfiles"
|
||||
srv_amd64_xmlfiles="i386/amd64.xml $srv_i386_64bit_xmlfiles"
|
||||
srv_i386_linux_xmlfiles="i386/i386-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_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 i386/64bit-avx.xml"
|
||||
srv_i386_xmlfiles="i386/i386.xml i386/i386-avx.xml $srv_i386_32bit_xmlfiles"
|
||||
srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml $srv_i386_64bit_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/amd64-avx-linux.xml i386/64bit-linux.xml $srv_i386_64bit_xmlfiles"
|
||||
|
||||
# Input is taken from the "${target}" variable.
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "server.h"
|
||||
#include "i387-fp.h"
|
||||
#include "i386-xstate.h"
|
||||
|
||||
int num_xmm_registers = 8;
|
||||
|
||||
@ -72,6 +73,46 @@ struct i387_fxsave {
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
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_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;
|
||||
|
||||
#endif /* I387_FP_H */
|
||||
|
@ -354,16 +354,16 @@ arm_arch_setup (void)
|
||||
}
|
||||
|
||||
struct regset_info target_regsets[] = {
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, 18 * 4,
|
||||
GENERAL_REGS,
|
||||
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,
|
||||
arm_fill_wmmxregset, arm_store_wmmxregset },
|
||||
{ PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 32 * 8 + 4,
|
||||
{ PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 0, 32 * 8 + 4,
|
||||
EXTENDED_REGS,
|
||||
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 = {
|
||||
|
@ -365,9 +365,9 @@ cris_store_gregset (const void *buf)
|
||||
typedef unsigned long elf_gregset_t[cris_num_regs];
|
||||
|
||||
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 },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
struct linux_target_ops the_low_target = {
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/uio.h>
|
||||
#ifndef ELFMAG0
|
||||
/* 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
|
||||
@ -2977,14 +2978,15 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
|
||||
struct regset_info *regset;
|
||||
int saw_general_regs = 0;
|
||||
int pid;
|
||||
struct iovec iov;
|
||||
|
||||
regset = target_regsets;
|
||||
|
||||
pid = lwpid_of (get_thread_lwp (current_inferior));
|
||||
while (regset->size >= 0)
|
||||
{
|
||||
void *buf;
|
||||
int res;
|
||||
void *buf, *data;
|
||||
int nt_type, res;
|
||||
|
||||
if (regset->size == 0 || disabled_regsets[regset - target_regsets])
|
||||
{
|
||||
@ -2993,10 +2995,21 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
|
||||
}
|
||||
|
||||
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__
|
||||
res = ptrace (regset->get_request, pid, 0, buf);
|
||||
res = ptrace (regset->get_request, pid, nt_type, data);
|
||||
#else
|
||||
res = ptrace (regset->get_request, pid, buf, 0);
|
||||
res = ptrace (regset->get_request, pid, data, nt_type);
|
||||
#endif
|
||||
if (res < 0)
|
||||
{
|
||||
@ -3034,14 +3047,15 @@ regsets_store_inferior_registers (struct regcache *regcache)
|
||||
struct regset_info *regset;
|
||||
int saw_general_regs = 0;
|
||||
int pid;
|
||||
struct iovec iov;
|
||||
|
||||
regset = target_regsets;
|
||||
|
||||
pid = lwpid_of (get_thread_lwp (current_inferior));
|
||||
while (regset->size >= 0)
|
||||
{
|
||||
void *buf;
|
||||
int res;
|
||||
void *buf, *data;
|
||||
int nt_type, res;
|
||||
|
||||
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,
|
||||
in case there are any items in the kernel's regset that are
|
||||
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__
|
||||
res = ptrace (regset->get_request, pid, 0, buf);
|
||||
res = ptrace (regset->get_request, pid, nt_type, data);
|
||||
#else
|
||||
res = ptrace (regset->get_request, pid, buf, 0);
|
||||
res = ptrace (regset->get_request, pid, &iov, data);
|
||||
#endif
|
||||
|
||||
if (res == 0)
|
||||
@ -3067,9 +3092,9 @@ regsets_store_inferior_registers (struct regcache *regcache)
|
||||
|
||||
/* Only now do we write the register set. */
|
||||
#ifndef __sparc__
|
||||
res = ptrace (regset->set_request, pid, 0, buf);
|
||||
res = ptrace (regset->set_request, pid, nt_type, data);
|
||||
#else
|
||||
res = ptrace (regset->set_request, pid, buf, 0);
|
||||
res = ptrace (regset->set_request, pid, data, nt_type);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -4133,6 +4158,13 @@ linux_core_of_thread (ptid_t ptid)
|
||||
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 = {
|
||||
linux_create_inferior,
|
||||
linux_attach,
|
||||
@ -4176,7 +4208,8 @@ static struct target_ops linux_target_ops = {
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
linux_core_of_thread
|
||||
linux_core_of_thread,
|
||||
linux_process_qsupported
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -35,6 +35,9 @@ enum regset_type {
|
||||
struct regset_info
|
||||
{
|
||||
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;
|
||||
enum regset_type type;
|
||||
regset_fill_func fill_function;
|
||||
@ -111,6 +114,9 @@ struct linux_target_ops
|
||||
|
||||
/* Hook to call prior to resuming a thread. */
|
||||
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;
|
||||
|
@ -112,14 +112,14 @@ m68k_store_fpregset (struct regcache *regcache, const void *buf)
|
||||
|
||||
struct regset_info target_regsets[] = {
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||
GENERAL_REGS,
|
||||
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,
|
||||
m68k_fill_fpregset, m68k_store_fpregset },
|
||||
#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 };
|
||||
|
@ -343,12 +343,12 @@ mips_store_fpregset (struct regcache *regcache, const void *buf)
|
||||
|
||||
struct regset_info target_regsets[] = {
|
||||
#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 },
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 33 * 8, FP_REGS,
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, 33 * 8, FP_REGS,
|
||||
mips_fill_fpregset, mips_store_fpregset },
|
||||
#endif /* HAVE_PTRACE_GETREGS */
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
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
|
||||
general registers. Some kernels support these, but not the newer
|
||||
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 },
|
||||
{ PTRACE_GETVRREGS, PTRACE_SETVRREGS, SIZEOF_VRREGS, EXTENDED_REGS,
|
||||
{ PTRACE_GETVRREGS, PTRACE_SETVRREGS, 0, SIZEOF_VRREGS, EXTENDED_REGS,
|
||||
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 },
|
||||
{ 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, 0, GENERAL_REGS, ppc_fill_gregset, NULL },
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{ 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, 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[] = {
|
||||
{ 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, 0, GENERAL_REGS, sh_fill_gregset, NULL },
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
struct linux_target_ops the_low_target = {
|
||||
|
@ -260,13 +260,13 @@ sparc_reinsert_addr (void)
|
||||
|
||||
|
||||
struct regset_info target_regsets[] = {
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||
GENERAL_REGS,
|
||||
sparc_fill_gregset, sparc_store_gregset },
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (fpregset_t),
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (fpregset_t),
|
||||
FP_REGS,
|
||||
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 = {
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "linux-low.h"
|
||||
#include "i387-fp.h"
|
||||
#include "i386-low.h"
|
||||
#include "i386-xstate.h"
|
||||
#include "elf/common.h"
|
||||
|
||||
#include "gdb_proc_service.h"
|
||||
|
||||
@ -31,10 +33,35 @@
|
||||
void init_registers_i386_linux (void);
|
||||
/* Defined in auto-generated file amd64-linux.c. */
|
||||
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/procfs.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
|
||||
#define PTRACE_GET_THREAD_AREA 25
|
||||
@ -252,6 +279,18 @@ x86_store_fpxregset (struct regcache *regcache, const void *buf)
|
||||
|
||||
#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.
|
||||
Once in i387_.*fsave.* and once in i387_.*fxsave.*.
|
||||
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[] =
|
||||
{
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||
GENERAL_REGS,
|
||||
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__
|
||||
# ifdef HAVE_PTRACE_GETFPXREGS
|
||||
{ PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t),
|
||||
{ PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, 0, sizeof (elf_fpxregset_t),
|
||||
EXTENDED_REGS,
|
||||
x86_fill_fpxregset, x86_store_fpxregset },
|
||||
# endif
|
||||
# endif
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (elf_fpregset_t),
|
||||
FP_REGS,
|
||||
x86_fill_fpregset, x86_store_fpregset },
|
||||
#endif /* HAVE_PTRACE_GETREGS */
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static CORE_ADDR
|
||||
@ -780,6 +821,128 @@ x86_siginfo_fixup (struct siginfo *native, void *inf, int direction)
|
||||
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. */
|
||||
|
||||
static void
|
||||
@ -800,8 +963,6 @@ x86_arch_setup (void)
|
||||
}
|
||||
else if (use_64bit)
|
||||
{
|
||||
init_registers_amd64_linux ();
|
||||
|
||||
/* Amd64 doesn't have HAVE_LINUX_USRREGS. */
|
||||
the_low_target.num_regs = -1;
|
||||
the_low_target.regmap = NULL;
|
||||
@ -811,14 +972,13 @@ x86_arch_setup (void)
|
||||
/* Amd64 has 16 xmm regs. */
|
||||
num_xmm_registers = 16;
|
||||
|
||||
x86_linux_update_xmltarget ();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ok we have a 32-bit inferior. */
|
||||
|
||||
init_registers_i386_linux ();
|
||||
|
||||
the_low_target.num_regs = I386_NUM_REGS;
|
||||
the_low_target.regmap = i386_regmap;
|
||||
the_low_target.cannot_fetch_register = i386_cannot_fetch_register;
|
||||
@ -826,6 +986,8 @@ x86_arch_setup (void)
|
||||
|
||||
/* I386 has 8 xmm regs. */
|
||||
num_xmm_registers = 8;
|
||||
|
||||
x86_linux_update_xmltarget ();
|
||||
}
|
||||
|
||||
/* This is initialized assuming an amd64 target.
|
||||
@ -858,5 +1020,6 @@ struct linux_target_ops the_low_target =
|
||||
x86_siginfo_fixup,
|
||||
x86_linux_new_process,
|
||||
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[] = {
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
|
||||
GENERAL_REGS,
|
||||
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,
|
||||
xtensa_fill_xtregset, xtensa_store_xtregset },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
{ 0, 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
#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];
|
||||
|
||||
/* Start processing qSupported packet. */
|
||||
target_process_qsupported (NULL);
|
||||
|
||||
/* Process each feature being provided by GDB. The first
|
||||
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 ())
|
||||
multi_process = 1;
|
||||
}
|
||||
else
|
||||
target_process_qsupported (p);
|
||||
}
|
||||
|
||||
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. */
|
||||
int (*core_of_thread) (ptid_t);
|
||||
|
||||
/* Target specific qSupported support. */
|
||||
void (*process_qsupported) (const char *);
|
||||
};
|
||||
|
||||
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) () : 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. */
|
||||
|
||||
int start_non_stop (int nonstop);
|
||||
|
Loading…
Reference in New Issue
Block a user