From patchwork Mon Oct 1 00:29:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Marsais X-Patchwork-Id: 29593 Received: (qmail 566 invoked by alias); 1 Oct 2018 00:29:49 -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 551 invoked by uid 89); 1 Oct 2018 00:29:48 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.2 spammy=non, Request, UD:i386-xsave-reverse.c, sk:gdb_tes 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; Mon, 01 Oct 2018 00:29:45 +0000 Received: from localhost.localdomain (unknown [37.228.243.214]) by smtp.lse.epita.fr (Postfix) with ESMTPSA id 73A1760D2F for ; Mon, 1 Oct 2018 02:29:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=lse.epita.fr; s=smtp; t=1538353783; bh=vTteLyD9VB/7Oy6JZmrjxc/XCQmd55sisShHwbRxQ+s=; h=From:To:Subject:Date:In-Reply-To:References:From; b=y649bFgB4MvVf+ilQnRSeVVYzPO0gW4HyL7Dbhl3GPCeggJGsuDSQIDacVVCAXzfB mqo76a4PIbGAte/G7YSDFmagcdKlhf1nSF6qdCSh1Ra5/Aku/L9SNgTIgGe9Gh6A4U uzq12nZDLlJ9gArwA+CPEzsCRxyHffElgr3xOYTY= From: Pierre Marsais To: gdb-patches@sourceware.org Subject: [PATCH v2] Add support for recording xsave x86 instruction Date: Mon, 1 Oct 2018 01:29:42 +0100 Message-Id: <20181001002942.31919-1-pierre.marsais@lse.epita.fr> In-Reply-To: <20180921003827.1525-1-pierre.marsais@lse.epita.fr> References: <20180921003827.1525-1-pierre.marsais@lse.epita.fr> MIME-Version: 1.0 Latest version of glibc's ld.so use the xsave instruction in the resolver. This breaks gdb record when calling shared libraries: ``` $ gcc -o fail -ggdb -x c - < int main() { exit(0); } EOF $ gdb ./fail Reading symbols from ./fail...done. (gdb) b main Breakpoint 1 at 0x113d: file , line 4. (gdb) r Starting program: /tmp/fail Breakpoint 1, main () at :4 4 : No such file or directory. (gdb) record (gdb) c Continuing. Process record does not support instruction 0xfae64 at address 0x7ffff7fe96dc. ``` In order to record xsave instructions, we record the from the beginning of the XSAVE area to the end of the last state component in the Request Feature Bitmap (whose value is XCR0 & EDX:EAX). At the moment we don't account for non requested state component within the XSAVE area. gdb/ChangeLog: 2018-09-21 Pierre Marsais * i386-tdep.c: (i386_process_record): Handle xsave instruction. gdb/testsuite/ChangeLog: 2018-09-21 Pierre Marsais * gdb.reverse/i386-xsave-reverse.c: New file. * gdb.reverse/i386-xsave-reverse.exp: New file. --- Changes in v2: * Address Markus review * Do not support instruction when MOD == 3 * Query XSAVE area buffer size with cpuid in tests * Use X86_XSTATE_SIZE macro to get XSAVE area size instead of cpuid gdb/i386-tdep.c | 35 +++++++++ .../gdb.reverse/i386-xsave-reverse.c | 47 ++++++++++++ .../gdb.reverse/i386-xsave-reverse.exp | 75 +++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 gdb/testsuite/gdb.reverse/i386-xsave-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index a6994aaf12..9c52adbd1b 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -7385,6 +7385,41 @@ no_support_3dnow_data: return -1; break; + case 4: /* xsave */ + { + 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 XSAVE " + "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; + + if (record_full_arch_list_add_mem (tmpu64, + X86_XSTATE_SIZE (rfbm))) + return -1; + } + break; + case 5: /* lfence */ case 6: /* mfence */ case 7: /* sfence clflush */ diff --git a/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c new file mode 100644 index 0000000000..5e90d1ad9c --- /dev/null +++ b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c @@ -0,0 +1,47 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2018 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Architecture tests for intel i386 platform. */ + +#include +#include +#include + +uint32_t get_xsave_buffer_size(void) { + uint32_t size, eax, ecx, edx; + __get_cpuid_count(0xd, 0, &eax, &size, &ecx, &edx); + + return size; +} + +void xsave_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 ("xor %%eax, %%eax\n\t" + "not %%eax\n\t" + "mov %%eax, %%edx\n\t" + "xsave %0":"=m"(buf) ::"eax", "edx"); +} /* end xsave_test */ + +int +main () +{ + xsave_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 new file mode 100644 index 0000000000..f47f507101 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.exp @@ -0,0 +1,75 @@ +# Copyright 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +# +# This test tests some i386 general instructions for reverse execution. +# + +if {![supports_reverse] || ![supports_process_record]} { + return +} + +if ![istarget "*86*-*linux*"] then { + verbose "Skipping i386 reverse tests." + return +} + +standard_testfile + +# some targets have leading underscores on assembly symbols. +set additional_flags [gdb_target_symbol_prefix_flags] + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ + [list debug $additional_flags]]} { + return -1 +} + +set end_of_main [gdb_get_line_number " end of main "] +set end_xsave_test [gdb_get_line_number " end xsave_test "] + +if ![runto main] then { + fail "run to main" + return +} + +# Activate process record/replay +gdb_test_no_output "record" "turn on process record" + +global hex +global decimal + +#xsave_test + +gdb_test "break $end_xsave_test" \ + "Breakpoint $decimal at .* line $end_xsave_test\." \ + "set breakpoint at end of xsave_test" + +set test "continue to end of xsave_test" +gdb_test_multiple "continue" $test { + -re " end xsave_test .*\r\n$gdb_prompt $" { + pass $test + } + -re " Illegal instruction.*\r\n$gdb_prompt $" { + untested i386-xsave-reverse + return -1 + } +} + +gdb_test "reverse-step" "xor.*" "reverse-step to xsave" + +gdb_test "print buf" ".* = '\\\\000' " \ + "verify xsave buffer after reverse xsave"