From patchwork Fri Sep 21 00:38:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Marsais X-Patchwork-Id: 29496 Received: (qmail 51532 invoked by alias); 21 Sep 2018 00:38:34 -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 51522 invoked by uid 89); 21 Sep 2018 00:38:33 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=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=Pierre, pierre, recording, repeats 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; Fri, 21 Sep 2018 00:38:30 +0000 Received: from localhost.localdomain (LFbn-1-12752-160.w90-90.abo.wanadoo.fr [90.90.55.160]) by smtp.lse.epita.fr (Postfix) with ESMTPSA id 77B1E610AD for ; Fri, 21 Sep 2018 02:38:27 +0200 (CEST) From: Pierre Marsais To: gdb-patches@sourceware.org Subject: [PATCH] Add support for recording xsave x86 instruction Date: Fri, 21 Sep 2018 02:38:27 +0200 Message-Id: <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 first 512 bytes of legacy XSAVE Area and the following 64 bytes of XSAVE Header, and for each the feature of bit set of xcr0. At the moment we don't check if the user requested to save less fields, we record all the supported fields. gdb/ChangeLog: 2018-09-21 Pierre Marsais * i386-tdep.c: Include "nat/x86-cpuid.h". (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. --- gdb/i386-tdep.c | 23 ++++++ .../gdb.reverse/i386-xsave-reverse.c | 34 +++++++++ .../gdb.reverse/i386-xsave-reverse.exp | 75 +++++++++++++++++++ 3 files changed, 132 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..78dbbfe5f0 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -31,6 +31,7 @@ #include "gdbcmd.h" #include "gdbcore.h" #include "gdbtypes.h" +#include "nat/x86-cpuid.h" #include "objfiles.h" #include "osabi.h" #include "regcache.h" @@ -7385,6 +7386,28 @@ no_support_3dnow_data: return -1; break; + case 4: /* xsave */ + uint64_t tmpu64; + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) + return -1; + if (record_full_arch_list_add_mem (tmpu64, 512 + 64)) + return -1; + + for (int i = 2; i < 64; i++) { + if (!((1 << i) & tdep->xcr0)) + continue; + + unsigned int size, offset, tmp1, tmp2; + + if (!__get_cpuid_count(0xd, i, &size, &offset, &tmp1, &tmp2)) + return -1; + + if (record_full_arch_list_add_mem (tmpu64 + offset, size)) + 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..d0e87158a2 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/i386-xsave-reverse.c @@ -0,0 +1,34 @@ +/* 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. */ + +void xsave_test(void) { + char buf[4096] __attribute__ ((aligned (64))) = { 0 }; + + 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..3ea8935c0e --- /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] { + 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 "] + +runto main + +if [supports_process_record] { + # 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"