From: Philippe Waroquiers Date: Thu, 24 May 2012 21:33:17 +0000 (+0000) Subject: gdbserver: introduce support to show the AVX registers. X-Git-Tag: svn/VALGRIND_3_8_0~287 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2478728636800e223b3d36385c1acdc53b4eb595;p=thirdparty%2Fvalgrind.git gdbserver: introduce support to show the AVX registers. This implies to change the interface between the arch independent gdbserver files and the arch dependent files as AVX implies a choice of xml files at run time. In valgrind-low-amd64.c, the xml files and the nr of registers are different depending on AVX support or not. Other platforms still have a fully static nr of registers. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12581 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 2cc83b982f..5d0462cbc0 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -469,6 +469,9 @@ GDBSERVER_XML_FILES = \ m_gdbserver/32bit-sse-valgrind-s1.xml \ m_gdbserver/32bit-sse-valgrind-s2.xml \ m_gdbserver/32bit-sse.xml \ + m_gdbserver/64bit-avx-valgrind-s2.xml \ + m_gdbserver/64bit-avx-valgrind-s1.xml \ + m_gdbserver/64bit-avx.xml \ m_gdbserver/64bit-core-valgrind-s1.xml \ m_gdbserver/64bit-core-valgrind-s2.xml \ m_gdbserver/64bit-core.xml \ @@ -478,6 +481,10 @@ GDBSERVER_XML_FILES = \ m_gdbserver/64bit-sse-valgrind-s1.xml \ m_gdbserver/64bit-sse-valgrind-s2.xml \ m_gdbserver/64bit-sse.xml \ + m_gdbserver/amd64-avx-coresse-valgrind.xml \ + m_gdbserver/amd64-avx-coresse.xml \ + m_gdbserver/amd64-avx-linux-valgrind.xml \ + m_gdbserver/amd64-avx-linux.xml \ m_gdbserver/amd64-coresse-valgrind.xml \ m_gdbserver/amd64-linux-valgrind.xml \ m_gdbserver/arm-core-valgrind-s1.xml \ diff --git a/coregrind/m_gdbserver/64bit-avx-valgrind-s1.xml b/coregrind/m_gdbserver/64bit-avx-valgrind-s1.xml new file mode 100644 index 0000000000..cc2bb59920 --- /dev/null +++ b/coregrind/m_gdbserver/64bit-avx-valgrind-s1.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/64bit-avx-valgrind-s2.xml b/coregrind/m_gdbserver/64bit-avx-valgrind-s2.xml new file mode 100644 index 0000000000..f82cb16a58 --- /dev/null +++ b/coregrind/m_gdbserver/64bit-avx-valgrind-s2.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/64bit-avx.xml b/coregrind/m_gdbserver/64bit-avx.xml new file mode 100644 index 0000000000..838bd6a0a5 --- /dev/null +++ b/coregrind/m_gdbserver/64bit-avx.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/amd64-avx-coresse-valgrind.xml b/coregrind/m_gdbserver/amd64-avx-coresse-valgrind.xml new file mode 100644 index 0000000000..2b757155fe --- /dev/null +++ b/coregrind/m_gdbserver/amd64-avx-coresse-valgrind.xml @@ -0,0 +1,22 @@ + + + + + + + + i386:x86-64 + + + + + + + + + + diff --git a/coregrind/m_gdbserver/amd64-avx-coresse.xml b/coregrind/m_gdbserver/amd64-avx-coresse.xml new file mode 100644 index 0000000000..c46b318388 --- /dev/null +++ b/coregrind/m_gdbserver/amd64-avx-coresse.xml @@ -0,0 +1,16 @@ + + + + + + + + i386:x86-64 + + + + diff --git a/coregrind/m_gdbserver/amd64-avx-linux-valgrind.xml b/coregrind/m_gdbserver/amd64-avx-linux-valgrind.xml new file mode 100644 index 0000000000..d69266482a --- /dev/null +++ b/coregrind/m_gdbserver/amd64-avx-linux-valgrind.xml @@ -0,0 +1,26 @@ + + + + + + + + i386:x86-64 + GNU/Linux + + + + + + + + + + + + + diff --git a/coregrind/m_gdbserver/amd64-avx-linux.xml b/coregrind/m_gdbserver/amd64-avx-linux.xml new file mode 100644 index 0000000000..3fea2e4686 --- /dev/null +++ b/coregrind/m_gdbserver/amd64-avx-linux.xml @@ -0,0 +1,18 @@ + + + + + + + + i386:x86-64 + GNU/Linux + + + + + diff --git a/coregrind/m_gdbserver/server.c b/coregrind/m_gdbserver/server.c index 58fb2295ac..661041ed76 100644 --- a/coregrind/m_gdbserver/server.c +++ b/coregrind/m_gdbserver/server.c @@ -532,8 +532,7 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p) } } - if ( (valgrind_target_xml() != NULL - || valgrind_shadow_target_xml() != NULL) + if (valgrind_target_xml(VG_(clo_vgdb_shadow_registers)) != NULL && strncmp ("qXfer:features:read:", arg_own_buf, 20) == 0) { CORE_ADDR ofs; unsigned int len, doc_len; @@ -549,19 +548,11 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p) } if (strcmp (annex, "target.xml") == 0) { - annex = NULL; // to replace it by the corresponding filename. - - /* If VG_(clo_vgdb_shadow_registers), try to use - shadow_target_xml. Fallback to target_xml - if not defined. */ - if (VG_(clo_vgdb_shadow_registers)) { - annex = valgrind_shadow_target_xml(); - if (annex != NULL) - /* Ensure the shadow registers are initialized. */ - initialize_shadow_low(True); + annex = valgrind_target_xml(VG_(clo_vgdb_shadow_registers)); + if (annex != NULL && VG_(clo_vgdb_shadow_registers)) { + /* Ensure the shadow registers are initialized. */ + initialize_shadow_low(True); } - if (annex == NULL) - annex = valgrind_target_xml(); if (annex == NULL) { strcpy (arg_own_buf, "E00"); return; @@ -669,8 +660,7 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p) if (VG_(client_auxv)) strcat (arg_own_buf, ";qXfer:auxv:read+"); - if (valgrind_target_xml() != NULL - || valgrind_shadow_target_xml() != NULL) { + if (valgrind_target_xml(VG_(clo_vgdb_shadow_registers)) != NULL) { strcat (arg_own_buf, ";qXfer:features:read+"); /* if a new gdb connects to us, we have to reset the register set to the normal register sets to allow this new gdb to diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c index 0a4094e1d9..905efb929f 100644 --- a/coregrind/m_gdbserver/target.c +++ b/coregrind/m_gdbserver/target.c @@ -491,14 +491,9 @@ int valgrind_point (Bool insert, char type, CORE_ADDR addr, int len) return 1; /* error or unsupported */ } -char* valgrind_target_xml (void) +char* valgrind_target_xml (Bool shadow_mode) { - return (char *) the_low_target.target_xml; -} - -char* valgrind_shadow_target_xml (void) -{ - return (char *) the_low_target.shadow_target_xml; + return (*the_low_target.target_xml) (shadow_mode); } int valgrind_insert_watchpoint (char type, CORE_ADDR addr, int len) diff --git a/coregrind/m_gdbserver/target.h b/coregrind/m_gdbserver/target.h index b5adda14b7..2cd41fd918 100644 --- a/coregrind/m_gdbserver/target.h +++ b/coregrind/m_gdbserver/target.h @@ -58,12 +58,12 @@ extern void valgrind_initialize_target(void); extern void initialize_shadow_low (Bool shadow_mode); /* Returns the name of the xml target description file. - returns NULL if no xml target description available. */ -extern char* valgrind_target_xml (void); - -/* Same but describes also the shadow registers. */ -extern char* valgrind_shadow_target_xml (void); - + returns NULL if no xml target description available. + if shadow_mode, then returns the xml target description + with the shadow registers + else returns the xml target description only for + the normal registers. */ +extern char* valgrind_target_xml (Bool shadow_mode); /* -------------------------------------------------------------------------- */ diff --git a/coregrind/m_gdbserver/valgrind-low-amd64.c b/coregrind/m_gdbserver/valgrind-low-amd64.c index d46afec0f2..3d6d84553f 100644 --- a/coregrind/m_gdbserver/valgrind-low-amd64.c +++ b/coregrind/m_gdbserver/valgrind-low-amd64.c @@ -27,7 +27,7 @@ #include "regcache.h" #include "pub_core_aspacemgr.h" -#include "pub_tool_machine.h" +#include "pub_core_machine.h" #include "pub_core_threadstate.h" #include "pub_core_transtab.h" #include "pub_core_gdbserver.h" @@ -100,11 +100,29 @@ struct reg regs[] = { { "xmm15", 4128, 128 }, { "mxcsr", 4256, 32 }, #if defined(VGO_linux) - { "orig_rax", 4288, 64 } + { "orig_rax", 4288, 64 }, #endif + { "ymm0h", 4352, 128 }, // The ymm?h registers only to be given to GDB + { "ymm1h", 4480, 128 }, // if Valgrind is running with AVX instructions. + { "ymm2h", 4608, 128 }, + { "ymm3h", 4736, 128 }, + { "ymm4h", 4864, 128 }, + { "ymm5h", 4992, 128 }, + { "ymm6h", 5120, 128 }, + { "ymm7h", 5248, 128 }, + { "ymm8h", 5376, 128 }, + { "ymm9h", 5504, 128 }, + { "ymm10h", 5632, 128 }, + { "ymm11h", 5760, 128 }, + { "ymm12h", 5888, 128 }, + { "ymm13h", 6016, 128 }, + { "ymm14h", 6144, 128 }, + { "ymm15h", 6272, 128 } }; static const char *expedite_regs[] = { "rbp", "rsp", "rip", 0 }; -#define num_regs (sizeof (regs) / sizeof (regs[0])) +#define max_num_regs (sizeof (regs) / sizeof (regs[0])) +static int dyn_num_regs; // if no AVX, we have to give less registers to gdb. + static CORE_ADDR get_pc (void) @@ -135,8 +153,8 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, transfer_direction dir, int size, Bool *mod) { ThreadState* tst = VG_(get_ThreadState)(tid); - int set = abs_regno / num_regs; - int regno = abs_regno % num_regs; + int set = abs_regno / dyn_num_regs; + int regno = abs_regno % dyn_num_regs; *mod = False; VexGuestAMD64State* amd64 = (VexGuestAMD64State*) get_arch (set, tst); @@ -269,29 +287,83 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } break; case 57: *mod = False; break; // GDBTD???? VEX equivalent { "orig_rax"}, + case 58: VG_(transfer) (&amd64->guest_YMM0[4], buf, dir, size, mod); break; + case 59: VG_(transfer) (&amd64->guest_YMM1[4], buf, dir, size, mod); break; + case 60: VG_(transfer) (&amd64->guest_YMM2[4], buf, dir, size, mod); break; + case 61: VG_(transfer) (&amd64->guest_YMM3[4], buf, dir, size, mod); break; + case 62: VG_(transfer) (&amd64->guest_YMM4[4], buf, dir, size, mod); break; + case 63: VG_(transfer) (&amd64->guest_YMM5[4], buf, dir, size, mod); break; + case 64: VG_(transfer) (&amd64->guest_YMM6[4], buf, dir, size, mod); break; + case 65: VG_(transfer) (&amd64->guest_YMM7[4], buf, dir, size, mod); break; + case 66: VG_(transfer) (&amd64->guest_YMM8[4], buf, dir, size, mod); break; + case 67: VG_(transfer) (&amd64->guest_YMM9[4], buf, dir, size, mod); break; + case 68: VG_(transfer) (&amd64->guest_YMM10[4], buf, dir, size, mod); break; + case 69: VG_(transfer) (&amd64->guest_YMM11[4], buf, dir, size, mod); break; + case 70: VG_(transfer) (&amd64->guest_YMM12[4], buf, dir, size, mod); break; + case 71: VG_(transfer) (&amd64->guest_YMM13[4], buf, dir, size, mod); break; + case 72: VG_(transfer) (&amd64->guest_YMM14[4], buf, dir, size, mod); break; + case 73: VG_(transfer) (&amd64->guest_YMM15[4], buf, dir, size, mod); break; default: vg_assert(0); } } +static +Bool have_avx(void) +{ + VexArch va; + VexArchInfo vai; + VG_(machine_get_VexArchInfo) (&va, &vai); + return (vai.hwcaps & VEX_HWCAPS_AMD64_AVX ? True : False); +} +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { +#if defined(VGO_linux) + if (have_avx()) + return "amd64-avx-linux-valgrind.xml"; + else + return "amd64-linux-valgrind.xml"; +#else + if (have_avx()) + return "amd64-avx-coresse-valgrind.xml"; + else + return "amd64-coresse-valgrind.xml"; +#endif + } else { +#if defined(VGO_linux) + if (have_avx()) + return "amd64-avx-linux.xml"; + else + return NULL; +#else + if (have_avx()) + return "amd64-avx-coresse.xml"; + else + return NULL; +#endif + } +} + static struct valgrind_target_ops low_target = { - num_regs, + -1, // Must be computed at init time. regs, 7, //RSP transfer_register, get_pc, set_pc, "amd64", - NULL, // target_xml not needed. -#if defined(VGO_linux) - "amd64-linux-valgrind.xml" -#else - "amd64-coresse-valgrind.xml" -#endif + target_xml }; void amd64_init_architecture (struct valgrind_target_ops *target) { *target = low_target; - set_register_cache (regs, num_regs); + if (have_avx()) + dyn_num_regs = max_num_regs; + else + dyn_num_regs = max_num_regs - 16; // remove the AVX "high" registers. + target->num_regs = dyn_num_regs; + set_register_cache (regs, dyn_num_regs); gdbserver_expedite_regs = expedite_regs; } diff --git a/coregrind/m_gdbserver/valgrind-low-arm.c b/coregrind/m_gdbserver/valgrind-low-arm.c index 5767793e96..1c00a270f7 100644 --- a/coregrind/m_gdbserver/valgrind-low-arm.c +++ b/coregrind/m_gdbserver/valgrind-low-arm.c @@ -277,6 +277,16 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } } +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { + return "arm-with-vfpv3-valgrind.xml"; + } else { + return "arm-with-vfpv3.xml"; + } +} + static struct valgrind_target_ops low_target = { num_regs, regs, @@ -285,8 +295,7 @@ static struct valgrind_target_ops low_target = { get_pc, set_pc, "arm", - "arm-with-vfpv3.xml", - "arm-with-vfpv3-valgrind.xml" + target_xml }; void arm_init_architecture (struct valgrind_target_ops *target) diff --git a/coregrind/m_gdbserver/valgrind-low-ppc32.c b/coregrind/m_gdbserver/valgrind-low-ppc32.c index a7e282ed64..fccdb64625 100644 --- a/coregrind/m_gdbserver/valgrind-low-ppc32.c +++ b/coregrind/m_gdbserver/valgrind-low-ppc32.c @@ -322,6 +322,16 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } } +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { + return "powerpc-altivec32l-valgrind.xml"; + } else { + return "powerpc-altivec32l.xml"; + } +} + static struct valgrind_target_ops low_target = { num_regs, regs, @@ -330,8 +340,7 @@ static struct valgrind_target_ops low_target = { get_pc, set_pc, "ppc32", - "powerpc-altivec32l.xml", - "powerpc-altivec32l-valgrind.xml" + target_xml }; void ppc32_init_architecture (struct valgrind_target_ops *target) diff --git a/coregrind/m_gdbserver/valgrind-low-ppc64.c b/coregrind/m_gdbserver/valgrind-low-ppc64.c index f2fdbecc8b..6f1075768b 100644 --- a/coregrind/m_gdbserver/valgrind-low-ppc64.c +++ b/coregrind/m_gdbserver/valgrind-low-ppc64.c @@ -319,6 +319,16 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } } +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { + return "powerpc-altivec64l-valgrind.xml"; + } else { + return "powerpc-altivec64l.xml"; + } +} + static struct valgrind_target_ops low_target = { num_regs, regs, @@ -327,8 +337,7 @@ static struct valgrind_target_ops low_target = { get_pc, set_pc, "ppc64", - "powerpc-altivec64l.xml", - "powerpc-altivec64l-valgrind.xml" + target_xml }; void ppc64_init_architecture (struct valgrind_target_ops *target) diff --git a/coregrind/m_gdbserver/valgrind-low-s390x.c b/coregrind/m_gdbserver/valgrind-low-s390x.c index aae9355150..15d216249e 100644 --- a/coregrind/m_gdbserver/valgrind-low-s390x.c +++ b/coregrind/m_gdbserver/valgrind-low-s390x.c @@ -187,6 +187,16 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } } +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { + return "s390x-generic-valgrind.xml"; + } else { + return "s390x-generic.xml"; + } +} + static struct valgrind_target_ops low_target = { num_regs, regs, @@ -195,8 +205,7 @@ static struct valgrind_target_ops low_target = { get_pc, set_pc, "s390x", - "s390x-generic.xml", - "s390x-generic-valgrind.xml" + target_xml }; void s390x_init_architecture (struct valgrind_target_ops *target) diff --git a/coregrind/m_gdbserver/valgrind-low-x86.c b/coregrind/m_gdbserver/valgrind-low-x86.c index 991b8bd70e..50d3193193 100644 --- a/coregrind/m_gdbserver/valgrind-low-x86.c +++ b/coregrind/m_gdbserver/valgrind-low-x86.c @@ -243,6 +243,20 @@ void transfer_register (ThreadId tid, int abs_regno, void * buf, } } +static +char* target_xml (Bool shadow_mode) +{ + if (shadow_mode) { +#if defined(VGO_linux) + return "i386-linux-valgrind.xml"; +#else + return "i386-coresse-valgrind.xml"; +#endif + } else { + return NULL; + } +} + static struct valgrind_target_ops low_target = { num_regs, regs, @@ -251,12 +265,7 @@ static struct valgrind_target_ops low_target = { get_pc, set_pc, "i386", - NULL, // target_xml not needed. -#if defined(VGO_linux) - "i386-linux-valgrind.xml" -#else - "i386-coresse-valgrind.xml" -#endif + target_xml }; void x86_init_architecture (struct valgrind_target_ops *target) diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h index e89c2dcfde..29dafcdd82 100644 --- a/coregrind/m_gdbserver/valgrind_low.h +++ b/coregrind/m_gdbserver/valgrind_low.h @@ -54,17 +54,17 @@ struct valgrind_target_ops or NULL not to answer. */ const char *arch_string; - /* Description of the set of registers. + /* Returns the target xml description of the set of registers. For some architectures (e.g. arm), it is mandatory to give a description of the registers, otherwise gdb does not understand the reply to the 'g' packet - (which is used to get the registers). */ - const char *target_xml; + (which is used to get the registers). + If shadow_mode, returns a target xml description + including the two shadow registers sets. + This is mandatory to use the option --vgdb-shadow-registers=yes. + Returns NULL if there is no target xml file*/ + char* (*target_xml) (Bool shadow_mode); - /* Same as target_xml, but describes also the two shadow - registers set. - This is mandatory to use the option --vgdb-shadow-registers=yes. */ - const char *shadow_target_xml; }; extern void x86_init_architecture (struct valgrind_target_ops *target); diff --git a/docs/xml/manual-core-adv.xml b/docs/xml/manual-core-adv.xml index efde71102f..46d33ee353 100644 --- a/docs/xml/manual-core-adv.xml +++ b/docs/xml/manual-core-adv.xml @@ -700,6 +700,25 @@ $3 = 0 values instead of float values, as it is expected that these shadow values are mostly used for memcheck validity bits. +Intel/amd64 AVX registers ymm0 +to ymm15 have also their shadow +registers. However, GDB presents the shadow values using two +"half" registers. For example, the half shadow registers for +ymm9 are +xmm9s1 (lower half for set 1), +ymm9hs1 (upper half for set 1), +xmm9s2 (lower half for set 2), +ymm9hs2 (upper half for set 2). +Note the inconsistent notation for the names of the half registers: +the lower part starts with an x, +the upper part starts with an y +and has an h before the shadow postfix. + +The special presentation of the AVX shadow registers is due +to the fact that GDB retrieves independently the lower and upper half +of the ymm registers. GDB however +does not know that the shadow half registers have to be shown combined. +