From patchwork Sat Oct 6 00:15:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Marsais X-Patchwork-Id: 29661 Received: (qmail 4385 invoked by alias); 6 Oct 2018 00:16:24 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 4048 invoked by uid 89); 6 Oct 2018 00:16:03 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=obtained, sk:printf_, sk:record_, highly X-HELO: smtp.lse.epita.fr Received: from lse.epita.fr (HELO smtp.lse.epita.fr) (163.5.55.17) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 06 Oct 2018 00:15:59 +0000 Received: from localhost.localdomain (unknown [37.228.243.108]) by smtp.lse.epita.fr (Postfix) with ESMTPSA id 4147160F5D for ; Sat, 6 Oct 2018 02:15:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=lse.epita.fr; s=smtp; t=1538784940; bh=lRXozVRkb7Mee250hL3/8trf2o9FQpGZi3x8cepuqAQ=; h=From:To:Subject:Date:In-Reply-To:References:From; b=fqpQDchArSoKZfUgZvKics8EXM2AjIEOjTCO0GH+kT7G7EXkPpsmBI9mkc6mbtrXX agcxwapPWfdHrOb8hiIh6JFdcV1Fwn30uFj+VU5J+/jgKobo5XZ662Icvao00k0ubI 8xfwWDnTmSjXpVLhAWs1zACLCq2f+ojZf/uCMGyc= From: Pierre Marsais To: gdb-patches@sourceware.org Subject: [PATCH v4 3/3] Add support for recording xsavec x86 instruction Date: Sat, 6 Oct 2018 01:15:39 +0100 Message-Id: <20181006001539.32414-3-pierre.marsais@lse.epita.fr> In-Reply-To: <20181006001539.32414-1-pierre.marsais@lse.epita.fr> References: <20180921003827.1525-1-pierre.marsais@lse.epita.fr> <20181006001539.32414-1-pierre.marsais@lse.epita.fr> MIME-Version: 1.0 This patch add support of the xsavec instruction. The logic is highly similar to the logic of xsave. The "init optimization" is not handled in this patch. The values of X86_XSAVEC_* were obtained by testing for AVX and MPX, by reading Intel x86 manuals, and looking at arch/x86/include/asm/fpu/types.h in Linux source. gdb/ChangeLog: 2018-10-05 Pierre Marsais * common/x86-xstate.h (X86_XSAVEC_AVX_SIZE, X86_XSAVEC_BNDREGS_SIZE, X86_XSAVEC_BNDCFG_SIZE, X86_XSAVEC_K_SIZE, X86_XSAVEC_ZMM_H_SIZE, X86_XSAVEC_ZMM_SIZE, X86_XSAVEC_PKRU_SIZE, X86_XSAVEC_SIZE(XCR0)): New macros. * i386-tdep.c: (i386_process_record): Handle xsavec instruction. gdb/testsuite/ChangeLog: 2018-10-05 Pierre Marsais * gdb.reverse/i386-xsave-reverse.c (xsavec_test): New function. (main): Use xsavec_test. * gdb.reverse/i386-xsave-reverse.exp: Test for xsavec instruction. --- gdb/common/x86-xstate.h | 17 +++++++ gdb/i386-tdep.c | 44 +++++++++++++++++++ .../gdb.reverse/i386-xsave-reverse.c | 9 ++++ .../gdb.reverse/i386-xsave-reverse.exp | 33 ++++++++++++-- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/gdb/common/x86-xstate.h b/gdb/common/x86-xstate.h index 51e5c3c785..8a5b167610 100644 --- a/gdb/common/x86-xstate.h +++ b/gdb/common/x86-xstate.h @@ -72,6 +72,23 @@ (HAS_MPX (XCR0) ? X86_XSTATE_BNDCFG_SIZE : \ (HAS_AVX (XCR0) ? X86_XSTATE_AVX_SIZE : X86_XSTATE_SSE_SIZE)))) +#define X86_XSAVEC_AVX_SIZE 256 +#define X86_XSAVEC_BNDREGS_SIZE 64 +#define X86_XSAVEC_BNDCFG_SIZE 64 +#define X86_XSAVEC_K_SIZE 64 +#define X86_XSAVEC_ZMM_H_SIZE 512 +#define X86_XSAVEC_ZMM_SIZE 1024 +#define X86_XSAVEC_PKRU_SIZE 8 + +#define X86_XSAVEC_SIZE(XCR0) \ + (((XCR0) & X86_XSTATE_AVX ? X86_XSAVEC_AVX_SIZE : 0 ) + \ + ((XCR0) & X86_XSTATE_BNDREGS ? X86_XSAVEC_BNDREGS_SIZE : 0) + \ + ((XCR0) & X86_XSTATE_BNDCFG ? X86_XSAVEC_BNDCFG_SIZE : 0) + \ + ((XCR0) & X86_XSTATE_K ? X86_XSAVEC_K_SIZE : 0) + \ + ((XCR0) & X86_XSTATE_ZMM_H ? X86_XSAVEC_ZMM_H_SIZE : 0) + \ + ((XCR0) & X86_XSTATE_ZMM ? X86_XSAVEC_ZMM_SIZE : 0) + \ + ((XCR0) & X86_XSTATE_PKRU ? X86_XSAVEC_PKRU_SIZE : 0)) + /* Initial value for fctrl register, as defined in the X86 manual, and confirmed in the (Linux) kernel source. When the x87 floating point feature is not enabled in an inferior we use this as the value of the diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 90c78e0bbc..c97a4978aa 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -5491,6 +5491,50 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, return -1; I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; + case 4: /* xsavec */ + { + if (ir.mod == 3) { + opcode = (opcode << 8) | ir.modrm; + goto no_support; + } + + ULONGEST rfbm_eax, rfbm_edx; + + regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &rfbm_eax); + rfbm_eax &= (1ULL << 32) - 1; + + regcache_raw_read_unsigned (regcache, I386_EDX_REGNUM, &rfbm_edx); + rfbm_edx &= (1ULL << 32) - 1; + + uint64_t rfbm = tdep->xcr0 & (rfbm_eax | (rfbm_edx << 32)); + + if (rfbm & ~X86_XSTATE_ALL_MASK) { + printf_unfiltered (_("Process record does not support XSAVEC " + "instruction with RFBM=%" PRIx64 ".\n"), + rfbm); + opcode = (opcode << 8) | ir.modrm; + goto no_support; + } + + uint64_t tmpu64; + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) + return -1; + + uint64_t legacy_size = 160; /* x87 xsave size */ + if (rfbm & X86_XSTATE_SSE) { + if (ir.regmap[X86_RECORD_R8_REGNUM]) + legacy_size = 416; /* 64-bit sse xsave size */ + else + legacy_size = 288; /* 32-bit sse xsave size */ + } + if (record_full_arch_list_add_mem (tmpu64, legacy_size)) + return -1; + + uint64_t size = X86_XSAVEC_SIZE (rfbm); + if (record_full_arch_list_add_mem (tmpu64 + 512, size)) + return -1; + } + break; case 6: /* rdrand */ case 7: /* rdseed */ if (ir.mod != 3) diff --git a/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c index 18453405a6..965ca60133 100644 --- a/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c +++ b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c @@ -44,10 +44,19 @@ void xsave_no_sse_test (void) { asm ("xsave %0":"=m"(buf): "a"((1 << 1) ^ ~0L), "d"(~0L)); } /* end xsave_no_sse_test */ +void xsavec_test (void) { + uint32_t xsave_buf_sze = get_xsave_buffer_size (); + char buf[xsave_buf_sze] __attribute__ ((aligned (64))); + memset (buf, 0, xsave_buf_sze); + + asm ("xsavec %0":"=m"(buf) : "a"(~0L), "d"(~0L)); +} /* end xsavec_test */ + int main () { xsave_test (); xsave_no_sse_test (); + xsavec_test (); return 0; /* end of main */ } diff --git a/gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp index f3c0f93bfc..d8fa64cdae 100644 --- a/gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp +++ b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp @@ -38,9 +38,10 @@ if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ return -1 } -set end_of_main [gdb_get_line_number " end of main "] -set end_xsave_test [gdb_get_line_number " end xsave_test "] -set end_xsave_no_sse_test [gdb_get_line_number " end xsave_no_sse_test "] +set end_of_main [gdb_get_line_number " end of main "] +set end_xsave_test [gdb_get_line_number " end xsave_test "] +set end_xsave_no_sse_test [gdb_get_line_number " end xsave_no_sse_test "] +set end_xsavec_test [gdb_get_line_number " end xsavec_test "] if ![runto main] then { fail "run to main" @@ -100,3 +101,29 @@ gdb_test "reverse-step" "xsave.*" "reverse-step to xsave" gdb_test "print buf" ".* = '\\\\000' " \ "verify xsave buffer after reverse xsave (no sse)" + +#xsavec_test + +gdb_test "continue" \ + " end xsave_no_sse_test .*" \ + "continue to end of xsave_no_sse_test" + +gdb_test "break $end_xsavec_test" \ + "Breakpoint $decimal at .* line $end_xsavec_test\." \ + "set breakpoint at end of xsavec_test" + +set test "continue to end of xsavec_test" +gdb_test_multiple "continue" $test { + -re " end xsavec_test .*\r\n$gdb_prompt $" { + pass $test + } + -re " Illegal instruction.*\r\n$gdb_prompt $" { + untested i386-xsavec-no-sse-reverse + return -1 + } +} + +gdb_test "reverse-step" "xsavec.*" "reverse-step to xsavec" + +gdb_test "print buf" ".* = '\\\\000' " \ + "verify xsave buffer after reverse xsavec"