From patchwork Tue Sep 2 12:24:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 2625 Received: (qmail 7401 invoked by alias); 2 Sep 2014 12:24:35 -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 7340 invoked by uid 89); 2 Sep 2014 12:24:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_50, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 02 Sep 2014 12:24:16 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s82COEYo011506 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 2 Sep 2014 08:24:15 -0400 Received: from blade.nx (ovpn-116-113.ams2.redhat.com [10.36.116.113]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s82CO9DG019667 for ; Tue, 2 Sep 2014 08:24:09 -0400 Received: from blade.nx (localhost [127.0.0.1]) by blade.nx (Postfix) with ESMTP id D68CF2640E1 for ; Tue, 2 Sep 2014 13:24:08 +0100 (BST) From: Gary Benson To: gdb-patches@sourceware.org Subject: [PATCH v2] Rename 32- and 64-bit Intel files from "i386" to "x86" Date: Tue, 2 Sep 2014 13:24:08 +0100 Message-Id: <1409660648-2804-1-git-send-email-gbenson@redhat.com> In-Reply-To: <1409576744-15249-1-git-send-email-gbenson@redhat.com> References: <1409576744-15249-1-git-send-email-gbenson@redhat.com> X-IsSubscribed: yes I found three more files that needed renaming. Updated patch inlined below. I will reply to this message with a "git diff -M" version. Gary Benson wrote: > Hi all, > > This patch renames six files that contain code used by both 32- and > 64-bit Intel ports such that their names are prefixed with "x86" > rather than "i386". All types, functions and variables within these > files are likewise renamed such that their names are prefixed with > "x86" rather than "i386". This makes GDB follow the convention used > by gdbserver such that 32-bit Intel code lives in files called > "i386-*", 64-bit Intel code lives in files called "amd64-*", and > code for both 32- and 64-bit Intel lives in files called "x86-*". > > This patch only renames OS-independent files. The Linux ports of > both GDB and gdbserver now follow the i386/amd64/x86 convention > fully. Some ports still use the old convention where "i386" in > file/function/ type/variable names can mean "32-bit only" or "32- > and 64-bit" but I don't want to touch ports I can't fully test > except where absolutely necessary. > > Built and regtested on RHEL 6.5 (i686 and x86_64). > Cross-built with MinGW (32-bit) to check the Windows changes. > > Ok to commit? > > Thanks, > Gary --- gdb/ChangeLog: * i386-nat.h: Renamed as... * x86-nat.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * i386-nat.c: Renamed as... * x86-nat.c: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * common/i386-xstate.h: Renamed as... * common/x86-xstate.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * nat/i386-cpuid.h: Renamed as... * nat/x86-cpuid.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * nat/i386-gcc-cpuid.h: Renamed as... * nat/x86-gcc-cpuid.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * nat/i386-dregs.h: Renamed as... * nat/x86-dregs.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * nat/i386-dregs.c: Renamed as... * nat/x86-dregs.c: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. gdb/gdbserver/ChangeLog: * i386-low.h: Renamed as... * x86-low.h: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. * i386-low.c: Renamed as... * x86-low.c: New file. All type, function and variable name prefixes changed from "i386_" to "x86_". All references updated. --- gdb/ChangeLog | 26 ++ gdb/Makefile.in | 14 +- gdb/amd64-linux-nat.c | 6 +- gdb/amd64-linux-tdep.c | 14 +- gdb/amd64-windows-nat.c | 4 +- gdb/amd64fbsd-nat.c | 18 +- gdb/common/i386-xstate.h | 67 ---- gdb/common/x86-xstate.h | 67 ++++ gdb/config/i386/cygwin.mh | 2 +- gdb/config/i386/cygwin64.mh | 2 +- gdb/config/i386/darwin.mh | 2 +- gdb/config/i386/fbsd.mh | 2 +- gdb/config/i386/fbsd64.mh | 2 +- gdb/config/i386/go32.mh | 2 +- gdb/config/i386/linux.mh | 2 +- gdb/config/i386/linux64.mh | 2 +- gdb/config/i386/mingw.mh | 2 +- gdb/config/i386/mingw64.mh | 2 +- gdb/gdbserver/ChangeLog | 9 + gdb/gdbserver/Makefile.in | 4 +- gdb/gdbserver/configure.srv | 14 +- gdb/gdbserver/i386-low.c | 38 -- gdb/gdbserver/i386-low.h | 24 -- gdb/gdbserver/i387-fp.c | 92 +++--- gdb/gdbserver/linux-x86-low.c | 80 ++-- gdb/gdbserver/win32-i386-low.c | 54 ++-- gdb/gdbserver/x86-low.c | 38 ++ gdb/gdbserver/x86-low.h | 24 ++ gdb/go32-nat.c | 26 +- gdb/i386-darwin-nat.c | 18 +- gdb/i386-linux-nat.c | 6 +- gdb/i386-linux-tdep.c | 22 +- gdb/i386-nat.c | 313 ---------------- gdb/i386-nat.h | 57 --- gdb/i386-tdep.c | 30 +- gdb/i386-windows-nat.c | 4 +- gdb/i386fbsd-nat.c | 16 +- gdb/i387-tdep.c | 122 ++++---- gdb/nat/i386-cpuid.h | 63 ---- gdb/nat/i386-dregs.c | 655 ---------------------------------- gdb/nat/i386-dregs.h | 126 ------- gdb/nat/i386-gcc-cpuid.h | 278 -------------- gdb/nat/linux-btrace.c | 6 +- gdb/nat/x86-cpuid.h | 63 ++++ gdb/nat/x86-dregs.c | 655 ++++++++++++++++++++++++++++++++++ gdb/nat/x86-dregs.h | 126 +++++++ gdb/nat/x86-gcc-cpuid.h | 278 ++++++++++++++ gdb/testsuite/gdb.arch/i386-avx.c | 4 +- gdb/testsuite/gdb.arch/i386-avx512.c | 2 +- gdb/testsuite/gdb.arch/i386-mpx.c | 2 +- gdb/testsuite/gdb.arch/i386-sse.c | 4 +- gdb/windows-nat.c | 22 +- gdb/x86-linux-nat.c | 56 ++-- gdb/x86-nat.c | 313 ++++++++++++++++ gdb/x86-nat.h | 57 +++ 55 files changed, 1986 insertions(+), 1951 deletions(-) delete mode 100644 gdb/common/i386-xstate.h create mode 100644 gdb/common/x86-xstate.h delete mode 100644 gdb/gdbserver/i386-low.c delete mode 100644 gdb/gdbserver/i386-low.h create mode 100644 gdb/gdbserver/x86-low.c create mode 100644 gdb/gdbserver/x86-low.h delete mode 100644 gdb/i386-nat.c delete mode 100644 gdb/i386-nat.h delete mode 100644 gdb/nat/i386-cpuid.h delete mode 100644 gdb/nat/i386-dregs.c delete mode 100644 gdb/nat/i386-dregs.h delete mode 100644 gdb/nat/i386-gcc-cpuid.h create mode 100644 gdb/nat/x86-cpuid.h create mode 100644 gdb/nat/x86-dregs.c create mode 100644 gdb/nat/x86-dregs.h create mode 100644 gdb/nat/x86-gcc-cpuid.h create mode 100644 gdb/x86-nat.c create mode 100644 gdb/x86-nat.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b9e766f..c394ea3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -863,7 +863,7 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c HFILES_NO_SRCDIR = \ common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.h \ -common/i386-xstate.h nat/linux-ptrace.h nat/mips-linux-watch.h \ +common/x86-xstate.h nat/linux-ptrace.h nat/mips-linux-watch.h \ proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \ ppcnbsd-tdep.h cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \ exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h amd64bsd-nat.h \ @@ -921,7 +921,7 @@ psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \ amd64-darwin-tdep.h charset-list.h \ config/djgpp/langinfo.h config/djgpp/nl_types.h darwin-nat.h \ dicos-tdep.h filesystem.h gcore.h gdb_wchar.h hppabsd-tdep.h \ -i386-darwin-tdep.h i386-nat.h linux-record.h moxie-tdep.h nios2-tdep.h \ +i386-darwin-tdep.h x86-nat.h linux-record.h moxie-tdep.h nios2-tdep.h \ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ record-full.h solib-aix.h \ @@ -933,9 +933,9 @@ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/format.h common/host-defs.h utils.h common/queue.h \ nat/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \ gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h nat/linux-btrace.h \ -ctf.h nat/i386-cpuid.h nat/i386-gcc-cpuid.h target/resume.h \ +ctf.h nat/x86-cpuid.h nat/x86-gcc-cpuid.h target/resume.h \ target/wait.h target/waitstatus.h nat/linux-nat.h nat/linux-waitpid.h \ -common/print-utils.h common/rsp-low.h nat/i386-dregs.h x86-linux-nat.h \ +common/print-utils.h common/rsp-low.h nat/x86-dregs.h x86-linux-nat.h \ i386-linux-nat.h common/common-defs.h common/errors.h common/common-types.h \ common/common-debug.h common/cleanups.h common/gdb_setjmp.h \ common/common-exceptions.h target/target.h target/symbol.h \ @@ -1637,7 +1637,7 @@ ALLDEPFILES = \ i387-tdep.c \ i386-darwin-tdep.c i386-darwin-nat.c \ i386-dicos-tdep.c \ - i386-linux-tdep.c i386-nat.c \ + i386-linux-tdep.c x86-nat.c \ i386-sol2-nat.c i386-sol2-tdep.c \ i386gnu-nat.c i386gnu-tdep.c \ ia64-hpux-nat.c ia64-hpux-tdep.c \ @@ -2188,8 +2188,8 @@ waitstatus.o: ${srcdir}/target/waitstatus.c # Need to explicitly specify the compile rule as make will do nothing # or try to compile the object file into the sub-directory. -i386-dregs.o: ${srcdir}/nat/i386-dregs.c - $(COMPILE) $(srcdir)/nat/i386-dregs.c +x86-dregs.o: ${srcdir}/nat/x86-dregs.c + $(COMPILE) $(srcdir)/nat/x86-dregs.c $(POSTCOMPILE) linux-btrace.o: ${srcdir}/nat/linux-btrace.c diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index def12ee..a00fbd6 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -33,7 +33,7 @@ #include "amd64-tdep.h" #include "amd64-linux-tdep.h" #include "i386-linux-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" #include "x86-linux-nat.h" @@ -150,7 +150,7 @@ amd64_linux_fetch_inferior_registers (struct target_ops *ops, if (have_ptrace_getregset) { - char xstateregs[I386_XSTATE_MAX_SIZE]; + char xstateregs[X86_XSTATE_MAX_SIZE]; struct iovec iov; iov.iov_base = xstateregs; @@ -209,7 +209,7 @@ amd64_linux_store_inferior_registers (struct target_ops *ops, if (have_ptrace_getregset) { - char xstateregs[I386_XSTATE_MAX_SIZE]; + char xstateregs[X86_XSTATE_MAX_SIZE]; struct iovec iov; iov.iov_base = xstateregs; diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 97a2890..850ca20 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -31,7 +31,7 @@ #include "amd64-linux-tdep.h" #include "i386-linux-tdep.h" #include "linux-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" #include "amd64-tdep.h" #include "solib-svr4.h" @@ -58,7 +58,7 @@ static struct core_regset_section amd64_linux_regset_sections[] = { { ".reg", 27 * 8, "general-purpose" }, { ".reg2", 512, "floating-point" }, - { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" }, + { ".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state" }, { NULL, 0 } }; @@ -1583,20 +1583,20 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch, /* Linux/x86-64. */ uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd); - switch (xcr0 & I386_XSTATE_ALL_MASK) + switch (xcr0 & X86_XSTATE_ALL_MASK) { - case I386_XSTATE_MPX_AVX512_MASK: - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_MPX_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: if (gdbarch_ptr_bit (gdbarch) == 32) return tdesc_x32_avx512_linux; else return tdesc_amd64_avx512_linux; - case I386_XSTATE_MPX_MASK: + case X86_XSTATE_MPX_MASK: if (gdbarch_ptr_bit (gdbarch) == 32) return tdesc_x32_avx_linux; /* No x32 MPX falling back to AVX. */ else return tdesc_amd64_mpx_linux; - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_AVX_MASK: if (gdbarch_ptr_bit (gdbarch) == 32) return tdesc_x32_avx_linux; else diff --git a/gdb/amd64-windows-nat.c b/gdb/amd64-windows-nat.c index 65c4099..cd9701b 100644 --- a/gdb/amd64-windows-nat.c +++ b/gdb/amd64-windows-nat.c @@ -17,7 +17,7 @@ #include "defs.h" #include "windows-nat.h" -#include "i386-nat.h" +#include "x86-nat.h" #include "amd64-tdep.h" #include @@ -103,5 +103,5 @@ _initialize_amd64_windows_nat (void) { windows_set_context_register_offsets (mappings); windows_set_segment_register_p (amd64_windows_segment_register_p); - i386_set_debug_register_length (8); + x86_set_debug_register_length (8); } diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c index fd189ec..fe4e009 100644 --- a/gdb/amd64fbsd-nat.c +++ b/gdb/amd64fbsd-nat.c @@ -32,7 +32,7 @@ #include "amd64-tdep.h" #include "amd64-nat.h" #include "amd64bsd-nat.h" -#include "i386-nat.h" +#include "x86-nat.h" /* Offset in `struct reg' where MEMBER is stored. */ @@ -145,7 +145,7 @@ static void amd64fbsd_mourn_inferior (struct target_ops *ops) { #ifdef HAVE_PT_GETDBREGS - i386_cleanup_dregs (); + x86_cleanup_dregs (); #endif super_mourn_inferior (ops); } @@ -167,14 +167,14 @@ _initialize_amd64fbsd_nat (void) #ifdef HAVE_PT_GETDBREGS - i386_use_watchpoints (t); + x86_use_watchpoints (t); - i386_dr_low.set_control = amd64bsd_dr_set_control; - i386_dr_low.set_addr = amd64bsd_dr_set_addr; - i386_dr_low.get_addr = amd64bsd_dr_get_addr; - i386_dr_low.get_status = amd64bsd_dr_get_status; - i386_dr_low.get_control = amd64bsd_dr_get_control; - i386_set_debug_register_length (8); + x86_dr_low.set_control = amd64bsd_dr_set_control; + x86_dr_low.set_addr = amd64bsd_dr_set_addr; + x86_dr_low.get_addr = amd64bsd_dr_get_addr; + x86_dr_low.get_status = amd64bsd_dr_get_status; + x86_dr_low.get_control = amd64bsd_dr_get_control; + x86_set_debug_register_length (8); #endif /* HAVE_PT_GETDBREGS */ diff --git a/gdb/common/i386-xstate.h b/gdb/common/i386-xstate.h deleted file mode 100644 index 610eaa1..0000000 --- a/gdb/common/i386-xstate.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Common code for i386 XSAVE extended state. - - Copyright (C) 2010-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#ifndef I386_XSTATE_H -#define I386_XSTATE_H 1 - -/* The extended state feature bits. */ -#define I386_XSTATE_X87 (1ULL << 0) -#define I386_XSTATE_SSE (1ULL << 1) -#define I386_XSTATE_AVX (1ULL << 2) -#define I386_XSTATE_BNDREGS (1ULL << 3) -#define I386_XSTATE_BNDCFG (1ULL << 4) -#define I386_XSTATE_MPX (I386_XSTATE_BNDREGS | I386_XSTATE_BNDCFG) - -/* AVX 512 adds three feature bits. All three must be enabled. */ -#define I386_XSTATE_K (1ULL << 5) -#define I386_XSTATE_ZMM_H (1ULL << 6) -#define I386_XSTATE_ZMM (1ULL << 7) -#define I386_XSTATE_AVX512 (I386_XSTATE_K | I386_XSTATE_ZMM_H \ - | I386_XSTATE_ZMM) - -/* Supported mask and size of the extended state. */ -#define I386_XSTATE_X87_MASK I386_XSTATE_X87 -#define I386_XSTATE_SSE_MASK (I386_XSTATE_X87 | I386_XSTATE_SSE) -#define I386_XSTATE_AVX_MASK (I386_XSTATE_SSE_MASK | I386_XSTATE_AVX) -#define I386_XSTATE_MPX_MASK (I386_XSTATE_AVX_MASK | I386_XSTATE_MPX) -#define I386_XSTATE_AVX512_MASK (I386_XSTATE_AVX_MASK | I386_XSTATE_AVX512) -#define I386_XSTATE_MPX_AVX512_MASK (I386_XSTATE_MPX_MASK | I386_XSTATE_AVX512) - -#define I386_XSTATE_ALL_MASK (I386_XSTATE_MPX_AVX512_MASK) - -#define I386_XSTATE_SSE_SIZE 576 -#define I386_XSTATE_AVX_SIZE 832 -#define I386_XSTATE_BNDREGS_SIZE 1024 -#define I386_XSTATE_BNDCFG_SIZE 1088 -#define I386_XSTATE_AVX512_SIZE 2688 -#define I386_XSTATE_MAX_SIZE 2688 - - -/* In case one of the MPX XCR0 bits is set we consider we have MPX. */ -#define HAS_MPX(XCR0) (((XCR0) & I386_XSTATE_MPX) != 0) -#define HAS_AVX(XCR0) (((XCR0) & I386_XSTATE_AVX) != 0) -#define HAS_AVX512(XCR0) (((XCR0) & I386_XSTATE_AVX512) != 0) - -/* Get I386 XSAVE extended state size. */ -#define I386_XSTATE_SIZE(XCR0) \ - (HAS_AVX512 (XCR0) ? I386_XSTATE_AVX512_SIZE : \ - (HAS_MPX (XCR0) ? I386_XSTATE_BNDCFG_SIZE : \ - (HAS_AVX (XCR0) ? I386_XSTATE_AVX_SIZE : I386_XSTATE_SSE_SIZE))) - -#endif /* I386_XSTATE_H */ diff --git a/gdb/common/x86-xstate.h b/gdb/common/x86-xstate.h new file mode 100644 index 0000000..8bbbf17 --- /dev/null +++ b/gdb/common/x86-xstate.h @@ -0,0 +1,67 @@ +/* Common code for x86 XSAVE extended state. + + Copyright (C) 2010-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifndef X86_XSTATE_H +#define X86_XSTATE_H 1 + +/* The extended state feature bits. */ +#define X86_XSTATE_X87 (1ULL << 0) +#define X86_XSTATE_SSE (1ULL << 1) +#define X86_XSTATE_AVX (1ULL << 2) +#define X86_XSTATE_BNDREGS (1ULL << 3) +#define X86_XSTATE_BNDCFG (1ULL << 4) +#define X86_XSTATE_MPX (X86_XSTATE_BNDREGS | X86_XSTATE_BNDCFG) + +/* AVX 512 adds three feature bits. All three must be enabled. */ +#define X86_XSTATE_K (1ULL << 5) +#define X86_XSTATE_ZMM_H (1ULL << 6) +#define X86_XSTATE_ZMM (1ULL << 7) +#define X86_XSTATE_AVX512 (X86_XSTATE_K | X86_XSTATE_ZMM_H \ + | X86_XSTATE_ZMM) + +/* Supported mask and size of the extended state. */ +#define X86_XSTATE_X87_MASK X86_XSTATE_X87 +#define X86_XSTATE_SSE_MASK (X86_XSTATE_X87 | X86_XSTATE_SSE) +#define X86_XSTATE_AVX_MASK (X86_XSTATE_SSE_MASK | X86_XSTATE_AVX) +#define X86_XSTATE_MPX_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_MPX) +#define X86_XSTATE_AVX512_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_AVX512) +#define X86_XSTATE_MPX_AVX512_MASK (X86_XSTATE_MPX_MASK | X86_XSTATE_AVX512) + +#define X86_XSTATE_ALL_MASK (X86_XSTATE_MPX_AVX512_MASK) + +#define X86_XSTATE_SSE_SIZE 576 +#define X86_XSTATE_AVX_SIZE 832 +#define X86_XSTATE_BNDREGS_SIZE 1024 +#define X86_XSTATE_BNDCFG_SIZE 1088 +#define X86_XSTATE_AVX512_SIZE 2688 +#define X86_XSTATE_MAX_SIZE 2688 + + +/* In case one of the MPX XCR0 bits is set we consider we have MPX. */ +#define HAS_MPX(XCR0) (((XCR0) & X86_XSTATE_MPX) != 0) +#define HAS_AVX(XCR0) (((XCR0) & X86_XSTATE_AVX) != 0) +#define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0) + +/* Get I386 XSAVE extended state size. */ +#define X86_XSTATE_SIZE(XCR0) \ + (HAS_AVX512 (XCR0) ? X86_XSTATE_AVX512_SIZE : \ + (HAS_MPX (XCR0) ? X86_XSTATE_BNDCFG_SIZE : \ + (HAS_AVX (XCR0) ? X86_XSTATE_AVX_SIZE : X86_XSTATE_SSE_SIZE))) + +#endif /* X86_XSTATE_H */ diff --git a/gdb/config/i386/cygwin.mh b/gdb/config/i386/cygwin.mh index 07f06f2..09bee12 100644 --- a/gdb/config/i386/cygwin.mh +++ b/gdb/config/i386/cygwin.mh @@ -1,3 +1,3 @@ MH_CFLAGS= -NATDEPFILES= i386-nat.o i386-dregs.o windows-nat.o i386-windows-nat.o +NATDEPFILES= x86-nat.o x86-dregs.o windows-nat.o i386-windows-nat.o XM_CLIBS= diff --git a/gdb/config/i386/cygwin64.mh b/gdb/config/i386/cygwin64.mh index 5ce3095..3bede64 100644 --- a/gdb/config/i386/cygwin64.mh +++ b/gdb/config/i386/cygwin64.mh @@ -17,4 +17,4 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . */ -NATDEPFILES= i386-nat.o i386-dregs.o windows-nat.o amd64-windows-nat.o +NATDEPFILES= x86-nat.o x86-dregs.o windows-nat.o amd64-windows-nat.o diff --git a/gdb/config/i386/darwin.mh b/gdb/config/i386/darwin.mh index bd4d57e..16c1558 100644 --- a/gdb/config/i386/darwin.mh +++ b/gdb/config/i386/darwin.mh @@ -1,4 +1,4 @@ # Host: IA86 running Darwin NATDEPFILES = fork-child.o darwin-nat.o \ - i386-darwin-nat.o i386-nat.o i386-dregs.o amd64-nat.o darwin-nat-info.o + i386-darwin-nat.o x86-nat.o x86-dregs.o amd64-nat.o darwin-nat-info.o diff --git a/gdb/config/i386/fbsd.mh b/gdb/config/i386/fbsd.mh index 7aa6a69..e5bff3a 100644 --- a/gdb/config/i386/fbsd.mh +++ b/gdb/config/i386/fbsd.mh @@ -1,6 +1,6 @@ # Host: FreeBSD/i386 NATDEPFILES= fork-child.o inf-ptrace.o \ - fbsd-nat.o i386-nat.o i386-dregs.o i386bsd-nat.o i386fbsd-nat.o \ + fbsd-nat.o x86-nat.o x86-dregs.o i386bsd-nat.o i386fbsd-nat.o \ bsd-kvm.o NAT_FILE= nm-fbsd.h HAVE_NATIVE_GCORE_HOST = 1 diff --git a/gdb/config/i386/fbsd64.mh b/gdb/config/i386/fbsd64.mh index c37f460..329c526 100644 --- a/gdb/config/i386/fbsd64.mh +++ b/gdb/config/i386/fbsd64.mh @@ -1,7 +1,7 @@ # Host: FreeBSD/amd64 NATDEPFILES= fork-child.o inf-ptrace.o \ fbsd-nat.o amd64-nat.o amd64bsd-nat.o amd64fbsd-nat.o \ - bsd-kvm.o i386-nat.o i386-dregs.o + bsd-kvm.o x86-nat.o x86-dregs.o HAVE_NATIVE_GCORE_HOST = 1 LOADLIBES= -lkvm diff --git a/gdb/config/i386/go32.mh b/gdb/config/i386/go32.mh index 1b8ce86..b0ab60c 100644 --- a/gdb/config/i386/go32.mh +++ b/gdb/config/i386/go32.mh @@ -3,7 +3,7 @@ # We include several header files from config/djgpp MH_CFLAGS= -I$(srcdir)/config/djgpp -NATDEPFILES= go32-nat.o i386-nat.o i386-dregs.o +NATDEPFILES= go32-nat.o x86-nat.o x86-dregs.o HOST_IPC= CC= gcc diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh index 536ed3d..a4e4842 100644 --- a/gdb/config/i386/linux.mh +++ b/gdb/config/i386/linux.mh @@ -2,7 +2,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ - i386-nat.o i386-dregs.o i386-linux-nat.o x86-linux-nat.o \ + x86-nat.o x86-dregs.o i386-linux-nat.o x86-linux-nat.o \ proc-service.o linux-thread-db.o \ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \ linux-btrace.o linux-waitpid.o diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh index 8faca42..d557202 100644 --- a/gdb/config/i386/linux64.mh +++ b/gdb/config/i386/linux64.mh @@ -1,6 +1,6 @@ # Host: GNU/Linux x86-64 NATDEPFILES= inf-ptrace.o fork-child.o \ - i386-nat.o i386-dregs.o amd64-nat.o amd64-linux-nat.o \ + x86-nat.o x86-dregs.o amd64-nat.o amd64-linux-nat.o \ x86-linux-nat.o \ linux-nat.o linux-osdata.o \ proc-service.o linux-thread-db.o linux-fork.o \ diff --git a/gdb/config/i386/mingw.mh b/gdb/config/i386/mingw.mh index 07f06f2..09bee12 100644 --- a/gdb/config/i386/mingw.mh +++ b/gdb/config/i386/mingw.mh @@ -1,3 +1,3 @@ MH_CFLAGS= -NATDEPFILES= i386-nat.o i386-dregs.o windows-nat.o i386-windows-nat.o +NATDEPFILES= x86-nat.o x86-dregs.o windows-nat.o i386-windows-nat.o XM_CLIBS= diff --git a/gdb/config/i386/mingw64.mh b/gdb/config/i386/mingw64.mh index 740f508..0ee2e2c 100644 --- a/gdb/config/i386/mingw64.mh +++ b/gdb/config/i386/mingw64.mh @@ -1 +1 @@ -NATDEPFILES= i386-nat.o i386-dregs.o windows-nat.o amd64-windows-nat.o +NATDEPFILES= x86-nat.o x86-dregs.o windows-nat.o amd64-windows-nat.o diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 8a313f9..074d93d 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -149,7 +149,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \ $(srcdir)/thread-db.c $(srcdir)/utils.c $(srcdir)/debug.c \ $(srcdir)/linux-arm-low.c $(srcdir)/linux-bfin-low.c \ $(srcdir)/linux-cris-low.c $(srcdir)/linux-crisv32-low.c \ - ${srcdir}/i386-low.c $(srcdir)/i387-fp.c \ + ${srcdir}/x86-low.c $(srcdir)/i387-fp.c \ $(srcdir)/linux-ia64-low.c $(srcdir)/linux-low.c \ $(srcdir)/linux-m32r-low.c \ $(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \ @@ -558,7 +558,7 @@ waitstatus.o: ../target/waitstatus.c # Native object files rules from ../nat -i386-dregs.o: ../nat/i386-dregs.c +x86-dregs.o: ../nat/x86-dregs.c $(COMPILE) $< $(POSTCOMPILE) linux-btrace.o: ../nat/linux-btrace.c diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 8ff9c28..679fc9f 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -99,7 +99,7 @@ case "${target}" in srv_linux_thread_db=yes ;; i[34567]86-*-cygwin*) srv_regobj="$srv_i386_regobj" - srv_tgtobj="i386-low.o i386-dregs.o win32-low.o win32-i386-low.o" + srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o" srv_xmlfiles="$srv_i386_xmlfiles" ;; i[34567]86-*-linux*) srv_regobj="$srv_i386_linux_regobj" @@ -108,7 +108,7 @@ case "${target}" in srv_regobj="$srv_regobj $srv_amd64_linux_regobj" srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles" fi - srv_tgtobj="$srv_linux_obj linux-x86-low.o i386-low.o i386-dregs.o i387-fp.o" + srv_tgtobj="$srv_linux_obj linux-x86-low.o x86-low.o x86-dregs.o i387-fp.o" srv_tgtobj="${srv_tgtobj} linux-btrace.o" srv_linux_usrregs=yes srv_linux_regsets=yes @@ -125,7 +125,7 @@ case "${target}" in ;; i[34567]86-*-mingw32ce*) srv_regobj="$srv_i386_regobj" - srv_tgtobj="i386-low.o i386-dregs.o win32-low.o win32-i386-low.o" + srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o" srv_tgtobj="${srv_tgtobj} wincecompat.o" srv_xmlfiles="$srv_i386_xmlfiles" # hostio_last_error implementation is in win32-low.c @@ -134,7 +134,7 @@ case "${target}" in srv_mingwce=yes ;; i[34567]86-*-mingw*) srv_regobj="$srv_i386_regobj" - srv_tgtobj="i386-low.o i386-dregs.o win32-low.o win32-i386-low.o" + srv_tgtobj="x86-low.o x86-dregs.o win32-low.o win32-i386-low.o" srv_xmlfiles="$srv_i386_xmlfiles" srv_mingw=yes ;; @@ -315,7 +315,7 @@ case "${target}" in srv_linux_thread_db=yes ;; x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj" - srv_tgtobj="$srv_linux_obj linux-x86-low.o i386-low.o i386-dregs.o i387-fp.o" + srv_tgtobj="$srv_linux_obj linux-x86-low.o x86-low.o x86-dregs.o i387-fp.o" srv_tgtobj="${srv_tgtobj} linux-btrace.o" srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles" srv_linux_usrregs=yes # This is for i386 progs. @@ -325,12 +325,12 @@ case "${target}" in ipa_obj="${ipa_amd64_linux_regobj} linux-amd64-ipa.o" ;; x86_64-*-mingw*) srv_regobj="$srv_amd64_regobj" - srv_tgtobj="i386-low.o i386-dregs.o i387-fp.o win32-low.o win32-i386-low.o" + srv_tgtobj="x86-low.o x86-dregs.o i387-fp.o win32-low.o win32-i386-low.o" srv_xmlfiles="$srv_i386_xmlfiles $srv_amd64_xmlfiles" srv_mingw=yes ;; x86_64-*-cygwin*) srv_regobj="$srv_amd64_regobj" - srv_tgtobj="i386-low.o i386-dregs.o i387-fp.o win32-low.o win32-i386-low.o" + srv_tgtobj="x86-low.o x86-dregs.o i387-fp.o win32-low.o win32-i386-low.o" srv_xmlfiles="$srv_i386_xmlfiles" ;; diff --git a/gdb/gdbserver/i386-low.c b/gdb/gdbserver/i386-low.c deleted file mode 100644 index 845c3b0..0000000 --- a/gdb/gdbserver/i386-low.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Debug register code for the i386. - - Copyright (C) 2009-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#include "server.h" -#include "i386-low.h" - -/* Clear the reference counts and forget everything we knew about the - debug registers. */ - -void -i386_low_init_dregs (struct i386_debug_reg_state *state) -{ - int i; - - ALL_DEBUG_REGISTERS (i) - { - state->dr_mirror[i] = 0; - state->dr_ref_count[i] = 0; - } - state->dr_control_mirror = 0; - state->dr_status_mirror = 0; -} diff --git a/gdb/gdbserver/i386-low.h b/gdb/gdbserver/i386-low.h deleted file mode 100644 index e726038..0000000 --- a/gdb/gdbserver/i386-low.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Misc. low level support for i386. - - Copyright (C) 2009-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - - -#include "nat/i386-dregs.h" - -/* Initialize STATE. */ -extern void i386_low_init_dregs (struct i386_debug_reg_state *state); diff --git a/gdb/gdbserver/i387-fp.c b/gdb/gdbserver/i387-fp.c index c2d0bdf..f5e20a7 100644 --- a/gdb/gdbserver/i387-fp.c +++ b/gdb/gdbserver/i387-fp.c @@ -18,7 +18,7 @@ #include "server.h" #include "i387-fp.h" -#include "i386-xstate.h" +#include "x86-xstate.h" static const int num_mpx_bnd_registers = 4; static const int num_mpx_cfg_registers = 2; @@ -288,35 +288,35 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) zero. */ if (clear_bv) { - if ((clear_bv & I386_XSTATE_X87)) + if ((clear_bv & X86_XSTATE_X87)) for (i = 0; i < 8; i++) memset (((char *) &fp->st_space[0]) + i * 16, 0, 10); - if ((clear_bv & I386_XSTATE_SSE)) + if ((clear_bv & X86_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)) + if ((clear_bv & X86_XSTATE_AVX)) for (i = 0; i < num_xmm_registers; i++) memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16); - if ((clear_bv & I386_XSTATE_BNDREGS)) + if ((clear_bv & X86_XSTATE_BNDREGS)) for (i = 0; i < num_mpx_bnd_registers; i++) memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16); - if ((clear_bv & I386_XSTATE_BNDCFG)) + if ((clear_bv & X86_XSTATE_BNDCFG)) for (i = 0; i < num_mpx_cfg_registers; i++) memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8); - if ((clear_bv & I386_XSTATE_K)) + if ((clear_bv & X86_XSTATE_K)) for (i = 0; i < num_avx512_k_registers; i++) memset (((char *) &fp->k_space[0]) + i * 8, 0, 8); - if ((clear_bv & I386_XSTATE_ZMM_H)) + if ((clear_bv & X86_XSTATE_ZMM_H)) for (i = 0; i < num_avx512_zmmh_low_registers; i++) memset (((char *) &fp->zmmh_low_space[0]) + i * 32, 0, 32); - if ((clear_bv & I386_XSTATE_ZMM)) + if ((clear_bv & X86_XSTATE_ZMM)) { for (i = 0; i < num_avx512_zmmh_high_registers; i++) memset (((char *) &fp->zmmh_low_space[0]) + 32 + i * 64, 0, 32); @@ -328,7 +328,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } /* Check if any x87 registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_X87)) + if ((x86_xcr0 & X86_XSTATE_X87)) { int st0_regnum = find_regno (regcache->tdesc, "st0"); @@ -338,14 +338,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->st_space[0]) + i * 16; if (memcmp (raw, p, 10)) { - xstate_bv |= I386_XSTATE_X87; + xstate_bv |= X86_XSTATE_X87; memcpy (p, raw, 10); } } } /* Check if any SSE registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_SSE)) + if ((x86_xcr0 & X86_XSTATE_SSE)) { int xmm0_regnum = find_regno (regcache->tdesc, "xmm0"); @@ -355,14 +355,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->xmm_space[0]) + i * 16; if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_SSE; + xstate_bv |= X86_XSTATE_SSE; memcpy (p, raw, 16); } } } /* Check if any AVX registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_AVX)) + if ((x86_xcr0 & X86_XSTATE_AVX)) { int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h"); @@ -372,14 +372,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->ymmh_space[0]) + i * 16; if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_AVX; + xstate_bv |= X86_XSTATE_AVX; memcpy (p, raw, 16); } } } /* Check if any bound register has changed. */ - if ((x86_xcr0 & I386_XSTATE_BNDREGS)) + if ((x86_xcr0 & X86_XSTATE_BNDREGS)) { int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw"); @@ -389,14 +389,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->mpx_bnd_space[0]) + i * 16; if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_BNDREGS; + xstate_bv |= X86_XSTATE_BNDREGS; memcpy (p, raw, 16); } } } /* Check if any status register has changed. */ - if ((x86_xcr0 & I386_XSTATE_BNDCFG)) + if ((x86_xcr0 & X86_XSTATE_BNDCFG)) { int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu"); @@ -406,14 +406,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->mpx_cfg_space[0]) + i * 8; if (memcmp (raw, p, 8)) { - xstate_bv |= I386_XSTATE_BNDCFG; + xstate_bv |= X86_XSTATE_BNDCFG; memcpy (p, raw, 8); } } } /* Check if any K registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_K)) + if ((x86_xcr0 & X86_XSTATE_K)) { int k0_regnum = find_regno (regcache->tdesc, "k0"); @@ -423,14 +423,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->k_space[0]) + i * 8; if (memcmp (raw, p, 8) != 0) { - xstate_bv |= I386_XSTATE_K; + xstate_bv |= X86_XSTATE_K; memcpy (p, raw, 8); } } } /* Check if any of ZMM0H-ZMM15H registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_ZMM_H)) + if ((x86_xcr0 & X86_XSTATE_ZMM_H)) { int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h"); @@ -440,14 +440,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->zmmh_low_space[0]) + i * 32; if (memcmp (raw, p, 32) != 0) { - xstate_bv |= I386_XSTATE_ZMM_H; + xstate_bv |= X86_XSTATE_ZMM_H; memcpy (p, raw, 32); } } } /* Check if any of ZMM16H-ZMM31H registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_ZMM)) + if ((x86_xcr0 & X86_XSTATE_ZMM)) { int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h"); @@ -457,14 +457,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->zmmh_low_space[0]) + 32 + i * 64; if (memcmp (raw, p, 32) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 32); } } } /* Check if any XMM_AVX512 registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_ZMM)) + if ((x86_xcr0 & X86_XSTATE_ZMM)) { int xmm_avx512_regnum = find_regno (regcache->tdesc, "xmm16"); @@ -474,14 +474,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->zmmh_high_space[0]) + i * 64; if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } } } /* Check if any YMMH_AVX512 registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_ZMM)) + if ((x86_xcr0 & X86_XSTATE_ZMM)) { int ymmh_avx512_regnum = find_regno (regcache->tdesc, "ymm16h"); @@ -491,7 +491,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) p = ((char *) &fp->zmmh_high_space[0]) + 16 + i * 64; if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } } @@ -653,11 +653,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) clear_bv = (~fp->xstate_bv) & x86_xcr0; /* Check if any x87 registers are changed. */ - if ((x86_xcr0 & I386_XSTATE_X87) != 0) + if ((x86_xcr0 & X86_XSTATE_X87) != 0) { int st0_regnum = find_regno (regcache->tdesc, "st0"); - if ((clear_bv & I386_XSTATE_X87) != 0) + if ((clear_bv & X86_XSTATE_X87) != 0) { for (i = 0; i < 8; i++) supply_register_zeroed (regcache, i + st0_regnum); @@ -670,11 +670,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_SSE) != 0) + if ((x86_xcr0 & X86_XSTATE_SSE) != 0) { int xmm0_regnum = find_regno (regcache->tdesc, "xmm0"); - if ((clear_bv & I386_XSTATE_SSE)) + if ((clear_bv & X86_XSTATE_SSE)) { for (i = 0; i < num_xmm_registers; i++) supply_register_zeroed (regcache, i + xmm0_regnum); @@ -687,11 +687,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_AVX) != 0) + if ((x86_xcr0 & X86_XSTATE_AVX) != 0) { int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h"); - if ((clear_bv & I386_XSTATE_AVX) != 0) + if ((clear_bv & X86_XSTATE_AVX) != 0) { for (i = 0; i < num_xmm_registers; i++) supply_register_zeroed (regcache, i + ymm0h_regnum); @@ -704,12 +704,12 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_BNDREGS)) + if ((x86_xcr0 & X86_XSTATE_BNDREGS)) { int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw"); - if ((clear_bv & I386_XSTATE_BNDREGS) != 0) + if ((clear_bv & X86_XSTATE_BNDREGS) != 0) { for (i = 0; i < num_mpx_bnd_registers; i++) supply_register_zeroed (regcache, i + bnd0r_regnum); @@ -723,11 +723,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } - if ((x86_xcr0 & I386_XSTATE_BNDCFG)) + if ((x86_xcr0 & X86_XSTATE_BNDCFG)) { int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu"); - if ((clear_bv & I386_XSTATE_BNDCFG) != 0) + if ((clear_bv & X86_XSTATE_BNDCFG) != 0) { for (i = 0; i < num_mpx_cfg_registers; i++) supply_register_zeroed (regcache, i + bndcfg_regnum); @@ -740,11 +740,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_K) != 0) + if ((x86_xcr0 & X86_XSTATE_K) != 0) { int k0_regnum = find_regno (regcache->tdesc, "k0"); - if ((clear_bv & I386_XSTATE_K) != 0) + if ((clear_bv & X86_XSTATE_K) != 0) { for (i = 0; i < num_avx512_k_registers; i++) supply_register_zeroed (regcache, i + k0_regnum); @@ -757,11 +757,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_ZMM_H) != 0) + if ((x86_xcr0 & X86_XSTATE_ZMM_H) != 0) { int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h"); - if ((clear_bv & I386_XSTATE_ZMM_H) != 0) + if ((clear_bv & X86_XSTATE_ZMM_H) != 0) { for (i = 0; i < num_avx512_zmmh_low_registers; i++) supply_register_zeroed (regcache, i + zmm0h_regnum); @@ -774,13 +774,13 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } - if ((x86_xcr0 & I386_XSTATE_ZMM) != 0) + if ((x86_xcr0 & X86_XSTATE_ZMM) != 0) { int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h"); int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h"); int xmm16_regnum = find_regno (regcache->tdesc, "xmm16"); - if ((clear_bv & I386_XSTATE_ZMM) != 0) + if ((clear_bv & X86_XSTATE_ZMM) != 0) { for (i = 0; i < num_avx512_zmmh_high_registers; i++) supply_register_zeroed (regcache, i + zmm16h_regnum); @@ -837,4 +837,4 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } /* Default to SSE. */ -unsigned long long x86_xcr0 = I386_XSTATE_SSE_MASK; +unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK; diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 5175019..012cb05 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -23,8 +23,8 @@ #include #include "linux-low.h" #include "i387-fp.h" -#include "i386-low.h" -#include "i386-xstate.h" +#include "x86-low.h" +#include "x86-xstate.h" #include "gdb_proc_service.h" /* Don't include elf/common.h if linux/elf.h got included by @@ -148,7 +148,7 @@ static const char *xmltarget_amd64_linux_no_xml = "@\ struct arch_process_info { - struct i386_debug_reg_state debug_reg_state; + struct x86_debug_reg_state debug_reg_state; }; /* Per-thread arch-specific data we want to keep. */ @@ -587,7 +587,7 @@ update_debug_registers_callback (struct inferior_list_entry *entry, /* Update the inferior's debug register REGNUM from STATE. */ static void -i386_dr_low_set_addr (int regnum, CORE_ADDR addr) +x86_dr_low_set_addr (int regnum, CORE_ADDR addr) { /* Only update the threads of this process. */ int pid = pid_of (current_inferior); @@ -600,7 +600,7 @@ i386_dr_low_set_addr (int regnum, CORE_ADDR addr) /* Return the inferior's debug register REGNUM. */ static CORE_ADDR -i386_dr_low_get_addr (int regnum) +x86_dr_low_get_addr (int regnum) { ptid_t ptid = ptid_of (current_inferior); @@ -612,7 +612,7 @@ i386_dr_low_get_addr (int regnum) /* Update the inferior's DR7 debug control register from STATE. */ static void -i386_dr_low_set_control (unsigned long control) +x86_dr_low_set_control (unsigned long control) { /* Only update the threads of this process. */ int pid = pid_of (current_inferior); @@ -623,7 +623,7 @@ i386_dr_low_set_control (unsigned long control) /* Return the inferior's DR7 debug control register. */ static unsigned long -i386_dr_low_get_control (void) +x86_dr_low_get_control (void) { ptid_t ptid = ptid_of (current_inferior); @@ -634,7 +634,7 @@ i386_dr_low_get_control (void) and record it in STATE. */ static unsigned long -i386_dr_low_get_status (void) +x86_dr_low_get_status (void) { ptid_t ptid = ptid_of (current_inferior); @@ -642,13 +642,13 @@ i386_dr_low_get_status (void) } /* Low-level function vector. */ -struct i386_dr_low_type i386_dr_low = +struct x86_dr_low_type x86_dr_low = { - i386_dr_low_set_control, - i386_dr_low_set_addr, - i386_dr_low_get_addr, - i386_dr_low_get_status, - i386_dr_low_get_control, + x86_dr_low_set_control, + x86_dr_low_set_addr, + x86_dr_low_get_addr, + x86_dr_low_get_status, + x86_dr_low_get_control, sizeof (void *), }; @@ -686,10 +686,10 @@ x86_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, { enum target_hw_bp_type hw_type = raw_bkpt_type_to_target_hw_bp_type (type); - struct i386_debug_reg_state *state + struct x86_debug_reg_state *state = &proc->private->arch_private->debug_reg_state; - return i386_dr_insert_watchpoint (state, hw_type, addr, size); + return x86_dr_insert_watchpoint (state, hw_type, addr, size); } default: @@ -715,10 +715,10 @@ x86_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, { enum target_hw_bp_type hw_type = raw_bkpt_type_to_target_hw_bp_type (type); - struct i386_debug_reg_state *state + struct x86_debug_reg_state *state = &proc->private->arch_private->debug_reg_state; - return i386_dr_remove_watchpoint (state, hw_type, addr, size); + return x86_dr_remove_watchpoint (state, hw_type, addr, size); } default: /* Unsupported. */ @@ -730,7 +730,7 @@ static int x86_stopped_by_watchpoint (void) { struct process_info *proc = current_process (); - return i386_dr_stopped_by_watchpoint (&proc->private->arch_private->debug_reg_state); + return x86_dr_stopped_by_watchpoint (&proc->private->arch_private->debug_reg_state); } static CORE_ADDR @@ -738,8 +738,8 @@ x86_stopped_data_address (void) { struct process_info *proc = current_process (); CORE_ADDR addr; - if (i386_dr_stopped_data_address (&proc->private->arch_private->debug_reg_state, - &addr)) + if (x86_dr_stopped_data_address (&proc->private->arch_private->debug_reg_state, + &addr)) return addr; return 0; } @@ -751,7 +751,7 @@ x86_linux_new_process (void) { struct arch_process_info *info = xcalloc (1, sizeof (*info)); - i386_low_init_dregs (&info->debug_reg_state); + x86_low_init_dregs (&info->debug_reg_state); return info; } @@ -782,7 +782,7 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp) int i; int pid = ptid_get_pid (ptid); struct process_info *proc = find_process_pid (pid); - struct i386_debug_reg_state *state + struct x86_debug_reg_state *state = &proc->private->arch_private->debug_reg_state; x86_linux_dr_set (ptid, DR_CONTROL, 0); @@ -794,7 +794,7 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp) /* If we're setting a watchpoint, any change the inferior had done itself to the debug registers needs to be - discarded, otherwise, i386_dr_stopped_data_address can + discarded, otherwise, x86_dr_stopped_data_address can get confused. */ clear_status = 1; } @@ -1334,7 +1334,7 @@ x86_linux_read_description (void) if (!use_xml) { - x86_xcr0 = I386_XSTATE_SSE_MASK; + x86_xcr0 = X86_XSTATE_SSE_MASK; /* Don't use XML. */ #ifdef __x86_64__ @@ -1347,7 +1347,7 @@ x86_linux_read_description (void) if (have_ptrace_getregset == -1) { - uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; + uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; struct iovec iov; iov.iov_base = xstateregs; @@ -1369,7 +1369,7 @@ x86_linux_read_description (void) for (regset = x86_regsets; regset->fill_function != NULL; regset++) if (regset->get_request == PTRACE_GETREGSET) - regset->size = I386_XSTATE_SIZE (xcr0); + regset->size = X86_XSTATE_SIZE (xcr0); else if (regset->type != GENERAL_REGS) regset->size = 0; } @@ -1377,7 +1377,7 @@ x86_linux_read_description (void) /* Check the native XCR0 only if PTRACE_GETREGSET is available. */ xcr0_features = (have_ptrace_getregset - && (xcr0 & I386_XSTATE_ALL_MASK)); + && (xcr0 & X86_XSTATE_ALL_MASK)); if (xcr0_features) x86_xcr0 = xcr0; @@ -1389,15 +1389,15 @@ x86_linux_read_description (void) { if (xcr0_features) { - switch (xcr0 & I386_XSTATE_ALL_MASK) + switch (xcr0 & X86_XSTATE_ALL_MASK) { - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: return tdesc_amd64_avx512_linux; - case I386_XSTATE_MPX_MASK: + case X86_XSTATE_MPX_MASK: return tdesc_amd64_mpx_linux; - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_AVX_MASK: return tdesc_amd64_avx_linux; default: @@ -1411,13 +1411,13 @@ x86_linux_read_description (void) { if (xcr0_features) { - switch (xcr0 & I386_XSTATE_ALL_MASK) + switch (xcr0 & X86_XSTATE_ALL_MASK) { - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: return tdesc_x32_avx512_linux; - case I386_XSTATE_MPX_MASK: /* No MPX on x32. */ - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_MPX_MASK: /* No MPX on x32. */ + case X86_XSTATE_AVX_MASK: return tdesc_x32_avx_linux; default: @@ -1433,15 +1433,15 @@ x86_linux_read_description (void) { if (xcr0_features) { - switch (xcr0 & I386_XSTATE_ALL_MASK) + switch (xcr0 & X86_XSTATE_ALL_MASK) { - case (I386_XSTATE_AVX512_MASK): + case (X86_XSTATE_AVX512_MASK): return tdesc_i386_avx512_linux; - case (I386_XSTATE_MPX_MASK): + case (X86_XSTATE_MPX_MASK): return tdesc_i386_mpx_linux; - case (I386_XSTATE_AVX_MASK): + case (X86_XSTATE_AVX_MASK): return tdesc_i386_avx_linux; default: diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c index 39149f3..b4b99e8 100644 --- a/gdb/gdbserver/win32-i386-low.c +++ b/gdb/gdbserver/win32-i386-low.c @@ -17,7 +17,7 @@ #include "server.h" #include "win32-low.h" -#include "i386-low.h" +#include "x86-low.h" #ifndef CONTEXT_EXTENDED_REGISTERS #define CONTEXT_EXTENDED_REGISTERS 0 @@ -38,7 +38,7 @@ void init_registers_i386 (void); extern const struct target_desc *tdesc_i386; #endif -static struct i386_debug_reg_state debug_reg_state; +static struct x86_debug_reg_state debug_reg_state; static int debug_registers_changed = 0; static int debug_registers_used = 0; @@ -46,7 +46,7 @@ static int debug_registers_used = 0; /* Update the inferior's debug register REGNUM from STATE. */ static void -i386_dr_low_set_addr (int regnum, CORE_ADDR addr) +x86_dr_low_set_addr (int regnum, CORE_ADDR addr) { gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); @@ -58,7 +58,7 @@ i386_dr_low_set_addr (int regnum, CORE_ADDR addr) } static CORE_ADDR -i386_dr_low_get_addr (int regnum) +x86_dr_low_get_addr (int regnum) { gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); @@ -68,7 +68,7 @@ i386_dr_low_get_addr (int regnum) /* Update the inferior's DR7 debug control register from STATE. */ static void -i386_dr_low_set_control (unsigned long control) +x86_dr_low_set_control (unsigned long control) { /* debug_reg_state.dr_control_mirror is already set. Just notify i386_set_thread_context, i386_thread_added @@ -78,7 +78,7 @@ i386_dr_low_set_control (unsigned long control) } static unsigned long -i386_dr_low_get_control (void) +x86_dr_low_get_control (void) { return debug_reg_state.dr_control_mirror; } @@ -87,7 +87,7 @@ i386_dr_low_get_control (void) and record it in STATE. */ static unsigned long -i386_dr_low_get_status (void) +x86_dr_low_get_status (void) { /* We don't need to do anything here, the last call to thread_rec for current_event.dwThreadId id has already set it. */ @@ -95,13 +95,13 @@ i386_dr_low_get_status (void) } /* Low-level function vector. */ -struct i386_dr_low_type i386_dr_low = +struct x86_dr_low_type x86_dr_low = { - i386_dr_low_set_control, - i386_dr_low_set_addr, - i386_dr_low_get_addr, - i386_dr_low_get_status, - i386_dr_low_get_control, + x86_dr_low_set_control, + x86_dr_low_set_addr, + x86_dr_low_get_addr, + x86_dr_low_get_status, + x86_dr_low_get_control, sizeof (void *), }; @@ -132,8 +132,8 @@ i386_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, enum target_hw_bp_type hw_type = raw_bkpt_type_to_target_hw_bp_type (type); - return i386_dr_insert_watchpoint (&debug_reg_state, - hw_type, addr, size); + return x86_dr_insert_watchpoint (&debug_reg_state, + hw_type, addr, size); } default: /* Unsupported. */ @@ -153,8 +153,8 @@ i386_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, enum target_hw_bp_type hw_type = raw_bkpt_type_to_target_hw_bp_type (type); - return i386_dr_remove_watchpoint (&debug_reg_state, - hw_type, addr, size); + return x86_dr_remove_watchpoint (&debug_reg_state, + hw_type, addr, size); } default: /* Unsupported. */ @@ -163,16 +163,16 @@ i386_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, } static int -i386_stopped_by_watchpoint (void) +x86_stopped_by_watchpoint (void) { - return i386_dr_stopped_by_watchpoint (&debug_reg_state); + return x86_dr_stopped_by_watchpoint (&debug_reg_state); } static CORE_ADDR -i386_stopped_data_address (void) +x86_stopped_data_address (void) { CORE_ADDR addr; - if (i386_dr_stopped_data_address (&debug_reg_state, &addr)) + if (x86_dr_stopped_data_address (&debug_reg_state, &addr)) return addr; return 0; } @@ -180,7 +180,7 @@ i386_stopped_data_address (void) static void i386_initial_stuff (void) { - i386_low_init_dregs (&debug_reg_state); + x86_low_init_dregs (&debug_reg_state); debug_registers_changed = 0; debug_registers_used = 0; } @@ -216,7 +216,7 @@ i386_get_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event) if (th->tid == current_event->dwThreadId) { /* Copy dr values from the current thread. */ - struct i386_debug_reg_state *dr = &debug_reg_state; + struct x86_debug_reg_state *dr = &debug_reg_state; dr->dr_mirror[0] = th->context.Dr0; dr->dr_mirror[1] = th->context.Dr1; dr->dr_mirror[2] = th->context.Dr2; @@ -231,7 +231,7 @@ i386_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event) { if (debug_registers_changed) { - struct i386_debug_reg_state *dr = &debug_reg_state; + struct x86_debug_reg_state *dr = &debug_reg_state; th->context.Dr0 = dr->dr_mirror[0]; th->context.Dr1 = dr->dr_mirror[1]; th->context.Dr2 = dr->dr_mirror[2]; @@ -250,7 +250,7 @@ i386_thread_added (win32_thread_info *th) /* Set the debug registers for the new thread if they are used. */ if (debug_registers_used) { - struct i386_debug_reg_state *dr = &debug_reg_state; + struct x86_debug_reg_state *dr = &debug_reg_state; th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS; GetThreadContext (th->h, &th->context); @@ -460,6 +460,6 @@ struct win32_target_ops the_low_target = { i386_supports_z_point_type, i386_insert_point, i386_remove_point, - i386_stopped_by_watchpoint, - i386_stopped_data_address + x86_stopped_by_watchpoint, + x86_stopped_data_address }; diff --git a/gdb/gdbserver/x86-low.c b/gdb/gdbserver/x86-low.c new file mode 100644 index 0000000..aaa110e --- /dev/null +++ b/gdb/gdbserver/x86-low.c @@ -0,0 +1,38 @@ +/* Low level support for x86 (i386 and x86-64). + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "server.h" +#include "x86-low.h" + +/* Clear the reference counts and forget everything we knew about the + debug registers. */ + +void +x86_low_init_dregs (struct x86_debug_reg_state *state) +{ + int i; + + ALL_DEBUG_REGISTERS (i) + { + state->dr_mirror[i] = 0; + state->dr_ref_count[i] = 0; + } + state->dr_control_mirror = 0; + state->dr_status_mirror = 0; +} diff --git a/gdb/gdbserver/x86-low.h b/gdb/gdbserver/x86-low.h new file mode 100644 index 0000000..9aecff4 --- /dev/null +++ b/gdb/gdbserver/x86-low.h @@ -0,0 +1,24 @@ +/* Low level support for x86 (i386 and x86-64). + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + + +#include "nat/x86-dregs.h" + +/* Initialize STATE. */ +extern void x86_low_init_dregs (struct x86_debug_reg_state *state); diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index ed54247..8f59426 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -85,7 +85,7 @@ #include -#include "i386-nat.h" +#include "x86-nat.h" #include "inferior.h" #include "infrun.h" #include "gdbthread.h" @@ -97,7 +97,7 @@ #include "buildsym.h" #include "i387-tdep.h" #include "i386-tdep.h" -#include "nat/i386-cpuid.h" +#include "nat/x86-cpuid.h" #include "value.h" #include "regcache.h" #include "top.h" @@ -735,7 +735,7 @@ go32_mourn_inferior (struct target_ops *ops) be nice if GDB itself would take care to remove all breakpoints at all times, but it doesn't, probably under an assumption that the OS cleans up when the debuggee exits. */ - i386_cleanup_dregs (); + x86_cleanup_dregs (); ptid = inferior_ptid; inferior_ptid = null_ptid; @@ -1083,12 +1083,12 @@ go32_sysinfo (char *arg, int from_tty) { /* CPUID with EAX = 0 returns the Vendor ID. */ #if 0 - /* Ideally we would use i386_cpuid(), but it needs someone to run + /* Ideally we would use x86_cpuid(), but it needs someone to run native tests first to make sure things actually work. They should. http://sourceware.org/ml/gdb-patches/2013-05/msg00164.html */ unsigned int eax, ebx, ecx, edx; - if (i386_cpuid (0, &eax, &ebx, &ecx, &edx)) + if (x86_cpuid (0, &eax, &ebx, &ecx, &edx)) { cpuid_max = eax; memcpy (&vendor[0], &ebx, 4); @@ -1141,7 +1141,7 @@ go32_sysinfo (char *arg, int from_tty) #if 0 /* See comment above about cpuid usage. */ - i386_cpuid (1, &cpuid_eax, &cpuid_ebx, NULL, &cpuid_edx); + x86_cpuid (1, &cpuid_eax, &cpuid_ebx, NULL, &cpuid_edx); #else __asm__ __volatile__ ("movl $1, %%eax;" "cpuid;" @@ -2062,14 +2062,14 @@ _initialize_go32_nat (void) { struct target_ops *t = go32_target (); - i386_dr_low.set_control = go32_set_dr7; - i386_dr_low.set_addr = go32_set_dr; - i386_dr_low.get_status = go32_get_dr6; - i386_dr_low.get_control = go32_get_dr7; - i386_dr_low.get_addr = go32_get_dr; - i386_set_debug_register_length (4); + x86_dr_low.set_control = go32_set_dr7; + x86_dr_low.set_addr = go32_set_dr; + x86_dr_low.get_status = go32_get_dr6; + x86_dr_low.get_control = go32_get_dr7; + x86_dr_low.get_addr = go32_get_dr; + x86_set_debug_register_length (4); - i386_use_watchpoints (t); + x86_use_watchpoints (t); add_target (t); /* Initialize child's cwd as empty to be initialized when starting diff --git a/gdb/i386-darwin-nat.c b/gdb/i386-darwin-nat.c index f94c053..a60bc6c 100644 --- a/gdb/i386-darwin-nat.c +++ b/gdb/i386-darwin-nat.c @@ -33,7 +33,7 @@ #include "arch-utils.h" #include "gdbcore.h" -#include "i386-nat.h" +#include "x86-nat.h" #include "darwin-nat.h" #include "i386-darwin-tdep.h" @@ -628,19 +628,19 @@ darwin_complete_target (struct target_ops *target) amd64_native_gregset32_num_regs = i386_darwin_thread_state_num_regs; #endif - i386_use_watchpoints (target); + x86_use_watchpoints (target); - i386_dr_low.set_control = i386_darwin_dr_set_control; - i386_dr_low.set_addr = i386_darwin_dr_set_addr; - i386_dr_low.get_addr = i386_darwin_dr_get_addr; - i386_dr_low.get_status = i386_darwin_dr_get_status; - i386_dr_low.get_control = i386_darwin_dr_get_control; + x86_dr_low.set_control = i386_darwin_dr_set_control; + x86_dr_low.set_addr = i386_darwin_dr_set_addr; + x86_dr_low.get_addr = i386_darwin_dr_get_addr; + x86_dr_low.get_status = i386_darwin_dr_get_status; + x86_dr_low.get_control = i386_darwin_dr_get_control; /* Let's assume that the kernel is 64 bits iff the executable is. */ #ifdef __x86_64__ - i386_set_debug_register_length (8); + x86_set_debug_register_length (8); #else - i386_set_debug_register_length (4); + x86_set_debug_register_length (4); #endif target->to_fetch_registers = i386_darwin_fetch_inferior_registers; diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index 8227d4a..32a82e9 100644 --- a/gdb/i386-linux-nat.c +++ b/gdb/i386-linux-nat.c @@ -30,7 +30,7 @@ #include "i387-tdep.h" #include "i386-tdep.h" #include "i386-linux-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" #include "x86-linux-nat.h" @@ -321,7 +321,7 @@ store_fpregs (const struct regcache *regcache, int tid, int regno) static int fetch_xstateregs (struct regcache *regcache, int tid) { - char xstateregs[I386_XSTATE_MAX_SIZE]; + char xstateregs[X86_XSTATE_MAX_SIZE]; struct iovec iov; if (!have_ptrace_getregset) @@ -344,7 +344,7 @@ fetch_xstateregs (struct regcache *regcache, int tid) static int store_xstateregs (const struct regcache *regcache, int tid, int regno) { - char xstateregs[I386_XSTATE_MAX_SIZE]; + char xstateregs[X86_XSTATE_MAX_SIZE]; struct iovec iov; if (!have_ptrace_getregset) diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index aa60d3a..b3707f7 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -37,7 +37,7 @@ #include "xml-syscall.h" #include "i387-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml" @@ -70,7 +70,7 @@ static struct core_regset_section i386_linux_sse_regset_sections[] = static struct core_regset_section i386_linux_avx_regset_sections[] = { { ".reg", 68, "general-purpose" }, - { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" }, + { ".reg-xstate", X86_XSTATE_MAX_SIZE, "XSAVE extended state" }, { NULL, 0 } }; @@ -613,8 +613,8 @@ i386_linux_core_read_xcr0 (bfd *abfd) size_t size = bfd_section_size (abfd, xstate); /* Check extended state size. */ - if (size < I386_XSTATE_AVX_SIZE) - xcr0 = I386_XSTATE_SSE_MASK; + if (size < X86_XSTATE_AVX_SIZE) + xcr0 = X86_XSTATE_SSE_MASK; else { char contents[8]; @@ -647,18 +647,18 @@ i386_linux_core_read_description (struct gdbarch *gdbarch, /* Linux/i386. */ uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd); - switch ((xcr0 & I386_XSTATE_ALL_MASK)) + switch ((xcr0 & X86_XSTATE_ALL_MASK)) { - case I386_XSTATE_MPX_AVX512_MASK: - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_MPX_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: return tdesc_i386_avx512_linux; - case I386_XSTATE_MPX_MASK: + case X86_XSTATE_MPX_MASK: return tdesc_i386_mpx_linux; - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_AVX_MASK: return tdesc_i386_avx_linux; - case I386_XSTATE_SSE_MASK: + case X86_XSTATE_SSE_MASK: return tdesc_i386_linux; - case I386_XSTATE_X87_MASK: + case X86_XSTATE_X87_MASK: return tdesc_i386_mmx_linux; default: break; diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c deleted file mode 100644 index 4a64759..0000000 --- a/gdb/i386-nat.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Native-dependent code for the i386. - - Copyright (C) 2001-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#include "defs.h" -#include "i386-nat.h" -#include "gdbcmd.h" -#include "inferior.h" - -/* Support for hardware watchpoints and breakpoints using the i386 - debug registers. - - This provides several functions for inserting and removing - hardware-assisted breakpoints and watchpoints, testing if one or - more of the watchpoints triggered and at what address, checking - whether a given region can be watched, etc. - - The functions below implement debug registers sharing by reference - counts, and allow to watch regions up to 16 bytes long. */ - -/* Low-level function vector. */ -struct i386_dr_low_type i386_dr_low; - -/* Per-process data. We don't bind this to a per-inferior registry - because of targets like x86 GNU/Linux that need to keep track of - processes that aren't bound to any inferior (e.g., fork children, - checkpoints). */ - -struct i386_process_info -{ - /* Linked list. */ - struct i386_process_info *next; - - /* The process identifier. */ - pid_t pid; - - /* Copy of i386 hardware debug registers. */ - struct i386_debug_reg_state state; -}; - -static struct i386_process_info *i386_process_list = NULL; - -/* Find process data for process PID. */ - -static struct i386_process_info * -i386_find_process_pid (pid_t pid) -{ - struct i386_process_info *proc; - - for (proc = i386_process_list; proc; proc = proc->next) - if (proc->pid == pid) - return proc; - - return NULL; -} - -/* Add process data for process PID. Returns newly allocated info - object. */ - -static struct i386_process_info * -i386_add_process (pid_t pid) -{ - struct i386_process_info *proc; - - proc = xcalloc (1, sizeof (*proc)); - proc->pid = pid; - - proc->next = i386_process_list; - i386_process_list = proc; - - return proc; -} - -/* Get data specific info for process PID, creating it if necessary. - Never returns NULL. */ - -static struct i386_process_info * -i386_process_info_get (pid_t pid) -{ - struct i386_process_info *proc; - - proc = i386_find_process_pid (pid); - if (proc == NULL) - proc = i386_add_process (pid); - - return proc; -} - -/* Get debug registers state for process PID. */ - -struct i386_debug_reg_state * -i386_debug_reg_state (pid_t pid) -{ - return &i386_process_info_get (pid)->state; -} - -/* See declaration in i386-nat.h. */ - -void -i386_forget_process (pid_t pid) -{ - struct i386_process_info *proc, **proc_link; - - proc = i386_process_list; - proc_link = &i386_process_list; - - while (proc != NULL) - { - if (proc->pid == pid) - { - *proc_link = proc->next; - - xfree (proc); - return; - } - - proc_link = &proc->next; - proc = *proc_link; - } -} - -/* Clear the reference counts and forget everything we knew about the - debug registers. */ - -void -i386_cleanup_dregs (void) -{ - /* Starting from scratch has the same effect. */ - i386_forget_process (ptid_get_pid (inferior_ptid)); -} - -/* Insert a watchpoint to watch a memory region which starts at - address ADDR and whose length is LEN bytes. Watch memory accesses - of the type TYPE. Return 0 on success, -1 on failure. */ - -static int -i386_insert_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_insert_watchpoint (state, type, addr, len); -} - -/* Remove a watchpoint that watched the memory region which starts at - address ADDR, whose length is LEN bytes, and for accesses of the - type TYPE. Return 0 on success, -1 on failure. */ -static int -i386_remove_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_remove_watchpoint (state, type, addr, len); -} - -/* Return non-zero if we can watch a memory region that starts at - address ADDR and whose length is LEN bytes. */ - -static int -i386_region_ok_for_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_region_ok_for_watchpoint (state, addr, len); -} - -/* If the inferior has some break/watchpoint that triggered, set the - address associated with that break/watchpoint and return non-zero. - Otherwise, return zero. */ - -static int -i386_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_stopped_data_address (state, addr_p); -} - -/* Return non-zero if the inferior has some watchpoint that triggered. - Otherwise return zero. */ - -static int -i386_stopped_by_watchpoint (struct target_ops *ops) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_stopped_by_watchpoint (state); -} - -/* Insert a hardware-assisted breakpoint at BP_TGT->placed_address. - Return 0 on success, EBUSY on failure. */ - -static int -i386_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_insert_watchpoint (state, hw_execute, - bp_tgt->placed_address, 1) ? EBUSY : 0; -} - -/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address. - Return 0 on success, -1 on failure. */ - -static int -i386_remove_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, - struct bp_target_info *bp_tgt) -{ - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (inferior_ptid)); - - return i386_dr_remove_watchpoint (state, hw_execute, - bp_tgt->placed_address, 1); -} - -/* Returns the number of hardware watchpoints of type TYPE that we can - set. Value is positive if we can set CNT watchpoints, zero if - setting watchpoints of type TYPE is not supported, and negative if - CNT is more than the maximum number of watchpoints of type TYPE - that we can support. TYPE is one of bp_hardware_watchpoint, - bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint. - CNT is the number of such watchpoints used so far (including this - one). OTHERTYPE is non-zero if other types of watchpoints are - currently enabled. - - We always return 1 here because we don't have enough information - about possible overlap of addresses that they want to watch. As an - extreme example, consider the case where all the watchpoints watch - the same address and the same region length: then we can handle a - virtually unlimited number of watchpoints, due to debug register - sharing implemented via reference counts in i386-nat.c. */ - -static int -i386_can_use_hw_breakpoint (struct target_ops *self, - int type, int cnt, int othertype) -{ - return 1; -} - -static void -add_show_debug_regs_command (void) -{ - /* A maintenance command to enable printing the internal DRi mirror - variables. */ - add_setshow_boolean_cmd ("show-debug-regs", class_maintenance, - &show_debug_regs, _("\ -Set whether to show variables that mirror the x86 debug registers."), _("\ -Show whether to show variables that mirror the x86 debug registers."), _("\ -Use \"on\" to enable, \"off\" to disable.\n\ -If enabled, the debug registers values are shown when GDB inserts\n\ -or removes a hardware breakpoint or watchpoint, and when the inferior\n\ -triggers a breakpoint or watchpoint."), - NULL, - NULL, - &maintenance_set_cmdlist, - &maintenance_show_cmdlist); -} - -/* There are only two global functions left. */ - -void -i386_use_watchpoints (struct target_ops *t) -{ - /* After a watchpoint trap, the PC points to the instruction after the - one that caused the trap. Therefore we don't need to step over it. - But we do need to reset the status register to avoid another trap. */ - t->to_have_continuable_watchpoint = 1; - - t->to_can_use_hw_breakpoint = i386_can_use_hw_breakpoint; - t->to_region_ok_for_hw_watchpoint = i386_region_ok_for_watchpoint; - t->to_stopped_by_watchpoint = i386_stopped_by_watchpoint; - t->to_stopped_data_address = i386_stopped_data_address; - t->to_insert_watchpoint = i386_insert_watchpoint; - t->to_remove_watchpoint = i386_remove_watchpoint; - t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint; - t->to_remove_hw_breakpoint = i386_remove_hw_breakpoint; -} - -void -i386_set_debug_register_length (int len) -{ - /* This function should be called only once for each native target. */ - gdb_assert (i386_dr_low.debug_register_length == 0); - gdb_assert (len == 4 || len == 8); - i386_dr_low.debug_register_length = len; - add_show_debug_regs_command (); -} diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h deleted file mode 100644 index acac71a..0000000 --- a/gdb/i386-nat.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Native-dependent code for the i386. - - Low level functions to implement Oeprating System specific - code to manipulate I386 debug registers. - - Copyright (C) 2009-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#ifndef I386_NAT_H -#define I386_NAT_H 1 - -#include "nat/i386-dregs.h" - -/* Hardware-assisted breakpoints and watchpoints. */ - -/* Add watchpoint methods to the provided target_ops. - Targets using i386 family debug registers for watchpoints should call - this. */ -struct target_ops; -extern void i386_use_watchpoints (struct target_ops *); - -/* Use this function to set i386_dr_low debug_register_length field - rather than setting it directly to check that the length is only - set once. It also enables the 'maint set/show show-debug-regs' - command. */ - -extern void i386_set_debug_register_length (int len); - -/* Use this function to reset the i386-nat.c debug register state. */ - -extern void i386_cleanup_dregs (void); - -/* Return a pointer to the local mirror of the debug registers of - process PID. */ - -extern struct i386_debug_reg_state *i386_debug_reg_state (pid_t pid); - -/* Called whenever GDB is no longer debugging process PID. It deletes - data structures that keep track of debug register state. */ - -extern void i386_forget_process (pid_t pid); - -#endif /* I386_NAT_H */ diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 6a8ed55..1e68505 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -47,7 +47,7 @@ #include "exceptions.h" #include "i386-tdep.h" #include "i387-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" #include "record.h" #include "record-full.h" @@ -4478,12 +4478,12 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, ymm_avx512_regnum_p = i386_ymm_avx512_regnum_p (gdbarch, regnum); zmm_regnum_p = i386_zmm_regnum_p (gdbarch, regnum); - avx512_p = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK) - == I386_XSTATE_AVX512_MASK); - avx_p = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK) - == I386_XSTATE_AVX_MASK) && !avx512_p; - sse_p = ((tdep->xcr0 & I386_XSTATE_AVX512_MASK) - == I386_XSTATE_SSE_MASK) && !avx512_p && ! avx_p; + avx512_p = ((tdep->xcr0 & X86_XSTATE_AVX512_MASK) + == X86_XSTATE_AVX512_MASK); + avx_p = ((tdep->xcr0 & X86_XSTATE_AVX512_MASK) + == X86_XSTATE_AVX_MASK) && !avx512_p; + sse_p = ((tdep->xcr0 & X86_XSTATE_AVX512_MASK) + == X86_XSTATE_SSE_MASK) && !avx512_p && ! avx_p; if (group == vector_reggroup) return (mmx_regnum_p @@ -4512,17 +4512,17 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, bnd_regnum_p = i386_bnd_regnum_p (gdbarch, regnum); if (group == all_reggroup - && ((bnd_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) + && ((bnd_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK)))) return bnd_regnum_p; bndr_regnum_p = i386_bndr_regnum_p (gdbarch, regnum); if (group == all_reggroup - && ((bndr_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) + && ((bndr_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK)))) return 0; mpx_ctrl_regnum_p = i386_mpx_ctrl_regnum_p (gdbarch, regnum); if (group == all_reggroup - && ((mpx_ctrl_regnum_p && (tdep->xcr0 & I386_XSTATE_MPX_MASK)))) + && ((mpx_ctrl_regnum_p && (tdep->xcr0 & X86_XSTATE_MPX_MASK)))) return mpx_ctrl_regnum_p; if (group == general_reggroup) @@ -8160,7 +8160,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, if (!feature_avx) return 0; - tdep->xcr0 = I386_XSTATE_MPX_AVX512_MASK; + tdep->xcr0 = X86_XSTATE_MPX_AVX512_MASK; /* It may have been set by OSABI initialization function. */ if (tdep->k0_regnum < 0) @@ -8203,7 +8203,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, return 0; if (!feature_avx512) - tdep->xcr0 = I386_XSTATE_AVX_MASK; + tdep->xcr0 = X86_XSTATE_AVX_MASK; /* It may have been set by OSABI initialization function. */ if (tdep->num_ymm_regs == 0) @@ -8219,10 +8219,10 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, tdep->ymmh_register_names[i]); } else if (feature_sse) - tdep->xcr0 = I386_XSTATE_SSE_MASK; + tdep->xcr0 = X86_XSTATE_SSE_MASK; else { - tdep->xcr0 = I386_XSTATE_X87_MASK; + tdep->xcr0 = X86_XSTATE_X87_MASK; tdep->num_xmm_regs = 0; } @@ -8242,7 +8242,7 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep, if (feature_mpx) { - tdep->xcr0 |= I386_XSTATE_MPX_MASK; + tdep->xcr0 |= X86_XSTATE_MPX_MASK; if (tdep->bnd0r_regnum < 0) { diff --git a/gdb/i386-windows-nat.c b/gdb/i386-windows-nat.c index caa645a..37c6166 100644 --- a/gdb/i386-windows-nat.c +++ b/gdb/i386-windows-nat.c @@ -17,7 +17,7 @@ #include "defs.h" #include "windows-nat.h" -#include "i386-nat.h" +#include "x86-nat.h" #include "i386-tdep.h" #include @@ -87,5 +87,5 @@ _initialize_i386_windows_nat (void) { windows_set_context_register_offsets (mappings); windows_set_segment_register_p (i386_windows_segment_register_p); - i386_set_debug_register_length (4); + x86_set_debug_register_length (4); } diff --git a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c index 6d78171..754677f 100644 --- a/gdb/i386fbsd-nat.c +++ b/gdb/i386fbsd-nat.c @@ -28,7 +28,7 @@ #include "fbsd-nat.h" #include "i386-tdep.h" -#include "i386-nat.h" +#include "x86-nat.h" #include "i386bsd-nat.h" /* Resume execution of the inferior process. If STEP is nonzero, @@ -128,14 +128,14 @@ _initialize_i386fbsd_nat (void) #ifdef HAVE_PT_GETDBREGS - i386_use_watchpoints (t); + x86_use_watchpoints (t); - i386_dr_low.set_control = i386bsd_dr_set_control; - i386_dr_low.set_addr = i386bsd_dr_set_addr; - i386_dr_low.get_addr = i386bsd_dr_get_addr; - i386_dr_low.get_status = i386bsd_dr_get_status; - i386_dr_low.get_control = i386bsd_dr_get_control; - i386_set_debug_register_length (4); + x86_dr_low.set_control = i386bsd_dr_set_control; + x86_dr_low.set_addr = i386bsd_dr_set_addr; + x86_dr_low.get_addr = i386bsd_dr_get_addr; + x86_dr_low.get_status = i386bsd_dr_get_status; + x86_dr_low.get_control = i386bsd_dr_get_control; + x86_set_debug_register_length (4); #endif /* HAVE_PT_GETDBREGS */ diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 07bdba5..d66ac6a 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -29,7 +29,7 @@ #include "i386-tdep.h" #include "i387-tdep.h" -#include "i386-xstate.h" +#include "x86-xstate.h" /* Print the floating point number specified by RAW. */ @@ -958,7 +958,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, clear_bv = (~(*xstate_bv_p)) & tdep->xcr0; } else - clear_bv = I386_XSTATE_ALL_MASK; + clear_bv = X86_XSTATE_ALL_MASK; /* With the delayed xsave mechanism, in between the program starting, and the program accessing the vector registers for the @@ -975,7 +975,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, break; case avx512_zmm_h: - if ((clear_bv & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM))) + if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -983,7 +983,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case avx512_k: - if ((clear_bv & I386_XSTATE_K)) + if ((clear_bv & X86_XSTATE_K)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -991,7 +991,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case avx512_ymmh_avx512: - if ((clear_bv & I386_XSTATE_ZMM)) + if ((clear_bv & X86_XSTATE_ZMM)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -999,7 +999,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case avx512_xmm_avx512: - if ((clear_bv & I386_XSTATE_ZMM)) + if ((clear_bv & X86_XSTATE_ZMM)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -1007,7 +1007,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case avxh: - if ((clear_bv & I386_XSTATE_AVX)) + if ((clear_bv & X86_XSTATE_AVX)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -1015,7 +1015,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case mpx: - if ((clear_bv & I386_XSTATE_BNDREGS)) + if ((clear_bv & X86_XSTATE_BNDREGS)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -1023,7 +1023,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case sse: - if ((clear_bv & I386_XSTATE_SSE)) + if ((clear_bv & X86_XSTATE_SSE)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -1031,7 +1031,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case x87: - if ((clear_bv & I386_XSTATE_X87)) + if ((clear_bv & X86_XSTATE_X87)) regcache_raw_supply (regcache, regnum, zero); else regcache_raw_supply (regcache, regnum, @@ -1040,9 +1040,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, case all: /* Handle the upper ZMM registers. */ - if ((tdep->xcr0 & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM))) + if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) { - if ((clear_bv & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM))) + if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) { for (i = I387_ZMM0H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep); @@ -1060,9 +1060,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle AVX512 OpMask registers. */ - if ((tdep->xcr0 & I386_XSTATE_K)) + if ((tdep->xcr0 & X86_XSTATE_K)) { - if ((clear_bv & I386_XSTATE_K)) + if ((clear_bv & X86_XSTATE_K)) { for (i = I387_K0_REGNUM (tdep); i < I387_KEND_REGNUM (tdep); @@ -1080,9 +1080,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle the YMM_AVX512 registers. */ - if ((tdep->xcr0 & I386_XSTATE_ZMM)) + if ((tdep->xcr0 & X86_XSTATE_ZMM)) { - if ((clear_bv & I386_XSTATE_ZMM)) + if ((clear_bv & X86_XSTATE_ZMM)) { for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); @@ -1108,9 +1108,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } } /* Handle the upper YMM registers. */ - if ((tdep->xcr0 & I386_XSTATE_AVX)) + if ((tdep->xcr0 & X86_XSTATE_AVX)) { - if ((clear_bv & I386_XSTATE_AVX)) + if ((clear_bv & X86_XSTATE_AVX)) { for (i = I387_YMM0H_REGNUM (tdep); i < I387_YMMENDH_REGNUM (tdep); @@ -1128,9 +1128,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle the MPX registers. */ - if ((tdep->xcr0 & I386_XSTATE_BNDREGS)) + if ((tdep->xcr0 & X86_XSTATE_BNDREGS)) { - if (clear_bv & I386_XSTATE_BNDREGS) + if (clear_bv & X86_XSTATE_BNDREGS) { for (i = I387_BND0R_REGNUM (tdep); i < I387_BNDCFGU_REGNUM (tdep); i++) @@ -1146,9 +1146,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle the MPX registers. */ - if ((tdep->xcr0 & I386_XSTATE_BNDCFG)) + if ((tdep->xcr0 & X86_XSTATE_BNDCFG)) { - if (clear_bv & I386_XSTATE_BNDCFG) + if (clear_bv & X86_XSTATE_BNDCFG) { for (i = I387_BNDCFGU_REGNUM (tdep); i < I387_MPXEND_REGNUM (tdep); i++) @@ -1164,9 +1164,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle the XMM registers. */ - if ((tdep->xcr0 & I386_XSTATE_SSE)) + if ((tdep->xcr0 & X86_XSTATE_SSE)) { - if ((clear_bv & I386_XSTATE_SSE)) + if ((clear_bv & X86_XSTATE_SSE)) { for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); @@ -1183,9 +1183,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } /* Handle the x87 registers. */ - if ((tdep->xcr0 & I386_XSTATE_X87)) + if ((tdep->xcr0 & X86_XSTATE_X87)) { - if ((clear_bv & I386_XSTATE_X87)) + if ((clear_bv & X86_XSTATE_X87)) { for (i = I387_ST0_REGNUM (tdep); i < I387_FCTRL_REGNUM (tdep); @@ -1322,7 +1322,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (gcore) { /* Clear XSAVE extended state. */ - memset (regs, 0, I386_XSTATE_SIZE (tdep->xcr0)); + memset (regs, 0, X86_XSTATE_SIZE (tdep->xcr0)); /* Update XCR0 and `xstate_bv' with XCR0 for gcore. */ if (tdep->xsave_xcr0_offset != -1) @@ -1342,27 +1342,27 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, /* Clear register set if its bit in xstat_bv is zero. */ if (clear_bv) { - if ((clear_bv & I386_XSTATE_BNDREGS)) + if ((clear_bv & X86_XSTATE_BNDREGS)) for (i = I387_BND0R_REGNUM (tdep); i < I387_BNDCFGU_REGNUM (tdep); i++) memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 16); - if ((clear_bv & I386_XSTATE_BNDCFG)) + if ((clear_bv & X86_XSTATE_BNDCFG)) for (i = I387_BNDCFGU_REGNUM (tdep); i < I387_MPXEND_REGNUM (tdep); i++) memset (XSAVE_MPX_ADDR (tdep, regs, i), 0, 8); - if ((clear_bv & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM))) + if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) for (i = I387_ZMM0H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep); i++) memset (XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i), 0, 32); - if ((clear_bv & I386_XSTATE_K)) + if ((clear_bv & X86_XSTATE_K)) for (i = I387_K0_REGNUM (tdep); i < I387_KEND_REGNUM (tdep); i++) memset (XSAVE_AVX512_K_ADDR (tdep, regs, i), 0, 8); - if ((clear_bv & I386_XSTATE_ZMM)) + if ((clear_bv & X86_XSTATE_ZMM)) { for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); i++) @@ -1372,17 +1372,17 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, memset (XSAVE_XMM_AVX512_ADDR (tdep, regs, i), 0, 16); } - if ((clear_bv & I386_XSTATE_AVX)) + if ((clear_bv & X86_XSTATE_AVX)) for (i = I387_YMM0H_REGNUM (tdep); i < I387_YMMENDH_REGNUM (tdep); i++) memset (XSAVE_AVXH_ADDR (tdep, regs, i), 0, 16); - if ((clear_bv & I386_XSTATE_SSE)) + if ((clear_bv & X86_XSTATE_SSE)) for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++) memset (FXSAVE_ADDR (tdep, regs, i), 0, 16); - if ((clear_bv & I386_XSTATE_X87)) + if ((clear_bv & X86_XSTATE_X87)) for (i = I387_ST0_REGNUM (tdep); i < I387_FCTRL_REGNUM (tdep); i++) memset (FXSAVE_ADDR (tdep, regs, i), 0, 10); @@ -1391,7 +1391,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (regclass == all) { /* Check if any ZMMH registers are changed. */ - if ((tdep->xcr0 & (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM))) + if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) for (i = I387_ZMM0H_REGNUM (tdep); i < I387_ZMMENDH_REGNUM (tdep); i++) { @@ -1399,13 +1399,13 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, i); if (memcmp (raw, p, 32) != 0) { - xstate_bv |= (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM); + xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM); memcpy (p, raw, 32); } } /* Check if any K registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_K)) + if ((tdep->xcr0 & X86_XSTATE_K)) for (i = I387_K0_REGNUM (tdep); i < I387_KEND_REGNUM (tdep); i++) { @@ -1413,13 +1413,13 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVX512_K_ADDR (tdep, regs, i); if (memcmp (raw, p, 8) != 0) { - xstate_bv |= I386_XSTATE_K; + xstate_bv |= X86_XSTATE_K; memcpy (p, raw, 8); } } /* Check if any XMM or upper YMM registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_ZMM)) + if ((tdep->xcr0 & X86_XSTATE_ZMM)) { for (i = I387_YMM16H_REGNUM (tdep); i < I387_YMMH_AVX512_END_REGNUM (tdep); i++) @@ -1428,7 +1428,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_YMM_AVX512_ADDR (tdep, regs, i); if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } } @@ -1439,14 +1439,14 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_XMM_AVX512_ADDR (tdep, regs, i); if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } } } /* Check if any upper YMM registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_AVX)) + if ((tdep->xcr0 & X86_XSTATE_AVX)) for (i = I387_YMM0H_REGNUM (tdep); i < I387_YMMENDH_REGNUM (tdep); i++) { @@ -1454,12 +1454,12 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVXH_ADDR (tdep, regs, i); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_AVX; + xstate_bv |= X86_XSTATE_AVX; memcpy (p, raw, 16); } } /* Check if any upper MPX registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_BNDREGS)) + if ((tdep->xcr0 & X86_XSTATE_BNDREGS)) for (i = I387_BND0R_REGNUM (tdep); i < I387_BNDCFGU_REGNUM (tdep); i++) { @@ -1467,13 +1467,13 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_MPX_ADDR (tdep, regs, i); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_BNDREGS; + xstate_bv |= X86_XSTATE_BNDREGS; memcpy (p, raw, 16); } } /* Check if any upper MPX registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_BNDCFG)) + if ((tdep->xcr0 & X86_XSTATE_BNDCFG)) for (i = I387_BNDCFGU_REGNUM (tdep); i < I387_MPXEND_REGNUM (tdep); i++) { @@ -1481,13 +1481,13 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_MPX_ADDR (tdep, regs, i); if (memcmp (raw, p, 8)) { - xstate_bv |= I386_XSTATE_BNDCFG; + xstate_bv |= X86_XSTATE_BNDCFG; memcpy (p, raw, 8); } } /* Check if any SSE registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_SSE)) + if ((tdep->xcr0 & X86_XSTATE_SSE)) for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++) { @@ -1495,13 +1495,13 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = FXSAVE_ADDR (tdep, regs, i); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_SSE; + xstate_bv |= X86_XSTATE_SSE; memcpy (p, raw, 16); } } /* Check if any X87 registers are changed. */ - if ((tdep->xcr0 & I386_XSTATE_X87)) + if ((tdep->xcr0 & X86_XSTATE_X87)) for (i = I387_ST0_REGNUM (tdep); i < I387_FCTRL_REGNUM (tdep); i++) { @@ -1509,7 +1509,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = FXSAVE_ADDR (tdep, regs, i); if (memcmp (raw, p, 10)) { - xstate_bv |= I386_XSTATE_X87; + xstate_bv |= X86_XSTATE_X87; memcpy (p, raw, 10); } } @@ -1530,7 +1530,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 32) != 0) { - xstate_bv |= (I386_XSTATE_ZMM_H | I386_XSTATE_ZMM); + xstate_bv |= (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM); memcpy (p, raw, 32); } break; @@ -1539,7 +1539,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVX512_K_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 8) != 0) { - xstate_bv |= I386_XSTATE_K; + xstate_bv |= X86_XSTATE_K; memcpy (p, raw, 8); } break; @@ -1549,7 +1549,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_YMM_AVX512_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } break; @@ -1559,7 +1559,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_XMM_AVX512_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 16) != 0) { - xstate_bv |= I386_XSTATE_ZMM; + xstate_bv |= X86_XSTATE_ZMM; memcpy (p, raw, 16); } break; @@ -1569,7 +1569,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_AVXH_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_AVX; + xstate_bv |= X86_XSTATE_AVX; memcpy (p, raw, 16); } break; @@ -1581,14 +1581,14 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = XSAVE_MPX_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_BNDREGS; + xstate_bv |= X86_XSTATE_BNDREGS; memcpy (p, raw, 16); } } else { p = XSAVE_MPX_ADDR (tdep, regs, regnum); - xstate_bv |= I386_XSTATE_BNDCFG; + xstate_bv |= X86_XSTATE_BNDCFG; memcpy (p, raw, 8); } break; @@ -1598,7 +1598,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = FXSAVE_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 16)) { - xstate_bv |= I386_XSTATE_SSE; + xstate_bv |= X86_XSTATE_SSE; memcpy (p, raw, 16); } break; @@ -1608,7 +1608,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, p = FXSAVE_ADDR (tdep, regs, regnum); if (memcmp (raw, p, 10)) { - xstate_bv |= I386_XSTATE_X87; + xstate_bv |= X86_XSTATE_X87; memcpy (p, raw, 10); } break; diff --git a/gdb/nat/i386-cpuid.h b/gdb/nat/i386-cpuid.h deleted file mode 100644 index 9aea054..0000000 --- a/gdb/nat/i386-cpuid.h +++ /dev/null @@ -1,63 +0,0 @@ -/* C API for x86 cpuid insn. - Copyright (C) 2007-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - This file 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, 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 . */ - -#ifndef I386_CPUID_COMMON_H -#define I386_CPUID_COMMON_H - -/* Always include the header for the cpu bit defines. */ -#include "i386-gcc-cpuid.h" - -#if defined(__i386__) || defined(__x86_64__) - -/* Return cpuid data for requested cpuid level, as found in returned - eax, ebx, ecx and edx registers. The function checks if cpuid is - supported and returns 1 for valid cpuid information or 0 for - unsupported cpuid level. Pointers may be non-null. */ - -static __inline int -i386_cpuid (unsigned int __level, - unsigned int *__eax, unsigned int *__ebx, - unsigned int *__ecx, unsigned int *__edx) -{ - unsigned int __scratch; - - if (!__eax) - __eax = &__scratch; - if (!__ebx) - __ebx = &__scratch; - if (!__ecx) - __ecx = &__scratch; - if (!__edx) - __edx = &__scratch; - - return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); -} - -#else - -static __inline int -i386_cpuid (unsigned int __level, - unsigned int *__eax, unsigned int *__ebx, - unsigned int *__ecx, unsigned int *__edx) -{ - return 0; -} - -#endif /* i386 && x86_64 */ - -#endif /* I386_CPUID_COMMON_H */ diff --git a/gdb/nat/i386-dregs.c b/gdb/nat/i386-dregs.c deleted file mode 100644 index 2f22299..0000000 --- a/gdb/nat/i386-dregs.c +++ /dev/null @@ -1,655 +0,0 @@ -/* Debug register code for the i386. - - Copyright (C) 2001-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#include "common-defs.h" -#include "i386-dregs.h" -#include "break-common.h" - -/* Support for hardware watchpoints and breakpoints using the i386 - debug registers. - - This provides several functions for inserting and removing - hardware-assisted breakpoints and watchpoints, testing if one or - more of the watchpoints triggered and at what address, checking - whether a given region can be watched, etc. - - The functions below implement debug registers sharing by reference - counts, and allow to watch regions up to 16 bytes long. */ - -/* Accessor macros for low-level function vector. */ - -/* Can we update the inferior's debug registers? */ -#define i386_dr_low_can_set_addr() (i386_dr_low.set_addr != NULL) - -/* Update the inferior's debug register REGNUM from STATE. */ -#define i386_dr_low_set_addr(new_state, i) \ - (i386_dr_low.set_addr ((i), (new_state)->dr_mirror[(i)])) - -/* Return the inferior's debug register REGNUM. */ -#define i386_dr_low_get_addr(i) (i386_dr_low.get_addr ((i))) - -/* Can we update the inferior's DR7 control register? */ -#define i386_dr_low_can_set_control() (i386_dr_low.set_control != NULL) - -/* Update the inferior's DR7 debug control register from STATE. */ -#define i386_dr_low_set_control(new_state) \ - (i386_dr_low.set_control ((new_state)->dr_control_mirror)) - -/* Return the value of the inferior's DR7 debug control register. */ -#define i386_dr_low_get_control() (i386_dr_low.get_control ()) - -/* Return the value of the inferior's DR6 debug status register. */ -#define i386_dr_low_get_status() (i386_dr_low.get_status ()) - -/* Return the debug register size, in bytes. */ -#define i386_get_debug_register_length() \ - (i386_dr_low.debug_register_length) - -/* Support for 8-byte wide hw watchpoints. */ -#define TARGET_HAS_DR_LEN_8 (i386_get_debug_register_length () == 8) - -/* DR7 Debug Control register fields. */ - -/* How many bits to skip in DR7 to get to R/W and LEN fields. */ -#define DR_CONTROL_SHIFT 16 -/* How many bits in DR7 per R/W and LEN field for each watchpoint. */ -#define DR_CONTROL_SIZE 4 - -/* Watchpoint/breakpoint read/write fields in DR7. */ -#define DR_RW_EXECUTE (0x0) /* Break on instruction execution. */ -#define DR_RW_WRITE (0x1) /* Break on data writes. */ -#define DR_RW_READ (0x3) /* Break on data reads or writes. */ - -/* This is here for completeness. No platform supports this - functionality yet (as of March 2001). Note that the DE flag in the - CR4 register needs to be set to support this. */ -#ifndef DR_RW_IORW -#define DR_RW_IORW (0x2) /* Break on I/O reads or writes. */ -#endif - -/* Watchpoint/breakpoint length fields in DR7. The 2-bit left shift - is so we could OR this with the read/write field defined above. */ -#define DR_LEN_1 (0x0 << 2) /* 1-byte region watch or breakpoint. */ -#define DR_LEN_2 (0x1 << 2) /* 2-byte region watch. */ -#define DR_LEN_4 (0x3 << 2) /* 4-byte region watch. */ -#define DR_LEN_8 (0x2 << 2) /* 8-byte region watch (AMD64). */ - -/* Local and Global Enable flags in DR7. - - When the Local Enable flag is set, the breakpoint/watchpoint is - enabled only for the current task; the processor automatically - clears this flag on every task switch. When the Global Enable flag - is set, the breakpoint/watchpoint is enabled for all tasks; the - processor never clears this flag. - - Currently, all watchpoint are locally enabled. If you need to - enable them globally, read the comment which pertains to this in - i386_insert_aligned_watchpoint below. */ -#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit. */ -#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit. */ -#define DR_ENABLE_SIZE 2 /* Two enable bits per debug register. */ - -/* Local and global exact breakpoint enable flags (a.k.a. slowdown - flags). These are only required on i386, to allow detection of the - exact instruction which caused a watchpoint to break; i486 and - later processors do that automatically. We set these flags for - backwards compatibility. */ -#define DR_LOCAL_SLOWDOWN (0x100) -#define DR_GLOBAL_SLOWDOWN (0x200) - -/* Fields reserved by Intel. This includes the GD (General Detect - Enable) flag, which causes a debug exception to be generated when a - MOV instruction accesses one of the debug registers. - - FIXME: My Intel manual says we should use 0xF800, not 0xFC00. */ -#define DR_CONTROL_RESERVED (0xFC00) - -/* Auxiliary helper macros. */ - -/* A value that masks all fields in DR7 that are reserved by Intel. */ -#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED) - -/* The I'th debug register is vacant if its Local and Global Enable - bits are reset in the Debug Control register. */ -#define I386_DR_VACANT(state, i) \ - (((state)->dr_control_mirror & (3 << (DR_ENABLE_SIZE * (i)))) == 0) - -/* Locally enable the break/watchpoint in the I'th debug register. */ -#define I386_DR_LOCAL_ENABLE(state, i) \ - do { \ - (state)->dr_control_mirror |= \ - (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \ - } while (0) - -/* Globally enable the break/watchpoint in the I'th debug register. */ -#define I386_DR_GLOBAL_ENABLE(state, i) \ - do { \ - (state)->dr_control_mirror |= \ - (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \ - } while (0) - -/* Disable the break/watchpoint in the I'th debug register. */ -#define I386_DR_DISABLE(state, i) \ - do { \ - (state)->dr_control_mirror &= \ - ~(3 << (DR_ENABLE_SIZE * (i))); \ - } while (0) - -/* Set in DR7 the RW and LEN fields for the I'th debug register. */ -#define I386_DR_SET_RW_LEN(state, i, rwlen) \ - do { \ - (state)->dr_control_mirror &= \ - ~(0x0f << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \ - (state)->dr_control_mirror |= \ - ((rwlen) << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \ - } while (0) - -/* Get from DR7 the RW and LEN fields for the I'th debug register. */ -#define I386_DR_GET_RW_LEN(dr7, i) \ - (((dr7) \ - >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f) - -/* Did the watchpoint whose address is in the I'th register break? */ -#define I386_DR_WATCH_HIT(dr6, i) ((dr6) & (1 << (i))) - -/* Types of operations supported by i386_handle_nonaligned_watchpoint. */ -typedef enum { WP_INSERT, WP_REMOVE, WP_COUNT } i386_wp_op_t; - -/* Print the values of the mirrored debug registers. */ - -static void -i386_show_dr (struct i386_debug_reg_state *state, - const char *func, CORE_ADDR addr, - int len, enum target_hw_bp_type type) -{ - int i; - - debug_printf ("%s", func); - if (addr || len) - debug_printf (" (addr=%s, len=%d, type=%s)", - phex (addr, 8), len, - type == hw_write ? "data-write" - : (type == hw_read ? "data-read" - : (type == hw_access ? "data-read/write" - : (type == hw_execute ? "instruction-execute" - /* FIXME: if/when I/O read/write - watchpoints are supported, add them - here. */ - : "??unknown??")))); - debug_printf (":\n"); - debug_printf ("\tCONTROL (DR7): %s STATUS (DR6): %s\n", - phex (state->dr_control_mirror, 8), - phex (state->dr_status_mirror, 8)); - ALL_DEBUG_REGISTERS (i) - { - debug_printf ("\ -\tDR%d: addr=0x%s, ref.count=%d DR%d: addr=0x%s, ref.count=%d\n", - i, phex (state->dr_mirror[i], - i386_get_debug_register_length ()), - state->dr_ref_count[i], - i + 1, phex (state->dr_mirror[i + 1], - i386_get_debug_register_length ()), - state->dr_ref_count[i + 1]); - i++; - } -} - -/* Return the value of a 4-bit field for DR7 suitable for watching a - region of LEN bytes for accesses of type TYPE. LEN is assumed to - have the value of 1, 2, or 4. */ - -static unsigned -i386_length_and_rw_bits (int len, enum target_hw_bp_type type) -{ - unsigned rw; - - switch (type) - { - case hw_execute: - rw = DR_RW_EXECUTE; - break; - case hw_write: - rw = DR_RW_WRITE; - break; - case hw_read: - internal_error (__FILE__, __LINE__, - _("The i386 doesn't support " - "data-read watchpoints.\n")); - case hw_access: - rw = DR_RW_READ; - break; -#if 0 - /* Not yet supported. */ - case hw_io_access: - rw = DR_RW_IORW; - break; -#endif - default: - internal_error (__FILE__, __LINE__, _("\ -Invalid hardware breakpoint type %d in i386_length_and_rw_bits.\n"), - (int) type); - } - - switch (len) - { - case 1: - return (DR_LEN_1 | rw); - case 2: - return (DR_LEN_2 | rw); - case 4: - return (DR_LEN_4 | rw); - case 8: - if (TARGET_HAS_DR_LEN_8) - return (DR_LEN_8 | rw); - /* ELSE FALL THROUGH */ - default: - internal_error (__FILE__, __LINE__, _("\ -Invalid hardware breakpoint length %d in i386_length_and_rw_bits.\n"), len); - } -} - -/* Insert a watchpoint at address ADDR, which is assumed to be aligned - according to the length of the region to watch. LEN_RW_BITS is the - value of the bits from DR7 which describes the length and access - type of the region to be watched by this watchpoint. Return 0 on - success, -1 on failure. */ - -static int -i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state, - CORE_ADDR addr, unsigned len_rw_bits) -{ - int i; - - if (!i386_dr_low_can_set_addr () || !i386_dr_low_can_set_control ()) - return -1; - - /* First, look for an occupied debug register with the same address - and the same RW and LEN definitions. If we find one, we can - reuse it for this watchpoint as well (and save a register). */ - ALL_DEBUG_REGISTERS (i) - { - if (!I386_DR_VACANT (state, i) - && state->dr_mirror[i] == addr - && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits) - { - state->dr_ref_count[i]++; - return 0; - } - } - - /* Next, look for a vacant debug register. */ - ALL_DEBUG_REGISTERS (i) - { - if (I386_DR_VACANT (state, i)) - break; - } - - /* No more debug registers! */ - if (i >= DR_NADDR) - return -1; - - /* Now set up the register I to watch our region. */ - - /* Record the info in our local mirrored array. */ - state->dr_mirror[i] = addr; - state->dr_ref_count[i] = 1; - I386_DR_SET_RW_LEN (state, i, len_rw_bits); - /* Note: we only enable the watchpoint locally, i.e. in the current - task. Currently, no i386 target allows or supports global - watchpoints; however, if any target would want that in the - future, GDB should probably provide a command to control whether - to enable watchpoints globally or locally, and the code below - should use global or local enable and slow-down flags as - appropriate. */ - I386_DR_LOCAL_ENABLE (state, i); - state->dr_control_mirror |= DR_LOCAL_SLOWDOWN; - state->dr_control_mirror &= I386_DR_CONTROL_MASK; - - return 0; -} - -/* Remove a watchpoint at address ADDR, which is assumed to be aligned - according to the length of the region to watch. LEN_RW_BITS is the - value of the bits from DR7 which describes the length and access - type of the region watched by this watchpoint. Return 0 on - success, -1 on failure. */ - -static int -i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state, - CORE_ADDR addr, unsigned len_rw_bits) -{ - int i, retval = -1; - int all_vacant = 1; - - ALL_DEBUG_REGISTERS (i) - { - if (!I386_DR_VACANT (state, i) - && state->dr_mirror[i] == addr - && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits) - { - if (--state->dr_ref_count[i] == 0) /* No longer in use? */ - { - /* Reset our mirror. */ - state->dr_mirror[i] = 0; - I386_DR_DISABLE (state, i); - /* Even though not strictly necessary, clear out all - bits in DR_CONTROL related to this debug register. - Debug output is clearer when we don't have stale bits - in place. This also allows the assertion below. */ - I386_DR_SET_RW_LEN (state, i, 0); - } - retval = 0; - } - - if (!I386_DR_VACANT (state, i)) - all_vacant = 0; - } - - if (all_vacant) - { - /* Even though not strictly necessary, clear out all of - DR_CONTROL, so that when we have no debug registers in use, - we end up with DR_CONTROL == 0. The Linux support relies on - this for an optimization. Plus, it makes for clearer debug - output. */ - state->dr_control_mirror &= ~DR_LOCAL_SLOWDOWN; - - gdb_assert (state->dr_control_mirror == 0); - } - return retval; -} - -/* Insert or remove a (possibly non-aligned) watchpoint, or count the - number of debug registers required to watch a region at address - ADDR whose length is LEN for accesses of type TYPE. Return 0 on - successful insertion or removal, a positive number when queried - about the number of registers, or -1 on failure. If WHAT is not a - valid value, bombs through internal_error. */ - -static int -i386_handle_nonaligned_watchpoint (struct i386_debug_reg_state *state, - i386_wp_op_t what, CORE_ADDR addr, int len, - enum target_hw_bp_type type) -{ - int retval = 0; - int max_wp_len = TARGET_HAS_DR_LEN_8 ? 8 : 4; - - static const int size_try_array[8][8] = - { - {1, 1, 1, 1, 1, 1, 1, 1}, /* Trying size one. */ - {2, 1, 2, 1, 2, 1, 2, 1}, /* Trying size two. */ - {2, 1, 2, 1, 2, 1, 2, 1}, /* Trying size three. */ - {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size four. */ - {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size five. */ - {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size six. */ - {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size seven. */ - {8, 1, 2, 1, 4, 1, 2, 1}, /* Trying size eight. */ - }; - - while (len > 0) - { - int align = addr % max_wp_len; - /* Four (eight on AMD64) is the maximum length a debug register - can watch. */ - int try = (len > max_wp_len ? (max_wp_len - 1) : len - 1); - int size = size_try_array[try][align]; - - if (what == WP_COUNT) - { - /* size_try_array[] is defined such that each iteration - through the loop is guaranteed to produce an address and a - size that can be watched with a single debug register. - Thus, for counting the registers required to watch a - region, we simply need to increment the count on each - iteration. */ - retval++; - } - else - { - unsigned len_rw = i386_length_and_rw_bits (size, type); - - if (what == WP_INSERT) - retval = i386_insert_aligned_watchpoint (state, addr, len_rw); - else if (what == WP_REMOVE) - retval = i386_remove_aligned_watchpoint (state, addr, len_rw); - else - internal_error (__FILE__, __LINE__, _("\ -Invalid value %d of operation in i386_handle_nonaligned_watchpoint.\n"), - (int) what); - if (retval) - break; - } - - addr += size; - len -= size; - } - - return retval; -} - -/* Update the inferior debug registers state, in STATE, with the - new debug registers state, in NEW_STATE. */ - -static void -i386_update_inferior_debug_regs (struct i386_debug_reg_state *state, - struct i386_debug_reg_state *new_state) -{ - int i; - - ALL_DEBUG_REGISTERS (i) - { - if (I386_DR_VACANT (new_state, i) != I386_DR_VACANT (state, i)) - i386_dr_low_set_addr (new_state, i); - else - gdb_assert (new_state->dr_mirror[i] == state->dr_mirror[i]); - } - - if (new_state->dr_control_mirror != state->dr_control_mirror) - i386_dr_low_set_control (new_state); - - *state = *new_state; -} - -/* Insert a watchpoint to watch a memory region which starts at - address ADDR and whose length is LEN bytes. Watch memory accesses - of the type TYPE. Return 0 on success, -1 on failure. */ - -int -i386_dr_insert_watchpoint (struct i386_debug_reg_state *state, - enum target_hw_bp_type type, - CORE_ADDR addr, int len) -{ - int retval; - /* Work on a local copy of the debug registers, and on success, - commit the change back to the inferior. */ - struct i386_debug_reg_state local_state = *state; - - if (type == hw_read) - return 1; /* unsupported */ - - if (((len != 1 && len != 2 && len != 4) - && !(TARGET_HAS_DR_LEN_8 && len == 8)) - || addr % len != 0) - { - retval = i386_handle_nonaligned_watchpoint (&local_state, - WP_INSERT, - addr, len, type); - } - else - { - unsigned len_rw = i386_length_and_rw_bits (len, type); - - retval = i386_insert_aligned_watchpoint (&local_state, - addr, len_rw); - } - - if (retval == 0) - i386_update_inferior_debug_regs (state, &local_state); - - if (show_debug_regs) - i386_show_dr (state, "insert_watchpoint", addr, len, type); - - return retval; -} - -/* Remove a watchpoint that watched the memory region which starts at - address ADDR, whose length is LEN bytes, and for accesses of the - type TYPE. Return 0 on success, -1 on failure. */ - -int -i386_dr_remove_watchpoint (struct i386_debug_reg_state *state, - enum target_hw_bp_type type, - CORE_ADDR addr, int len) -{ - int retval; - /* Work on a local copy of the debug registers, and on success, - commit the change back to the inferior. */ - struct i386_debug_reg_state local_state = *state; - - if (((len != 1 && len != 2 && len != 4) - && !(TARGET_HAS_DR_LEN_8 && len == 8)) - || addr % len != 0) - { - retval = i386_handle_nonaligned_watchpoint (&local_state, - WP_REMOVE, - addr, len, type); - } - else - { - unsigned len_rw = i386_length_and_rw_bits (len, type); - - retval = i386_remove_aligned_watchpoint (&local_state, - addr, len_rw); - } - - if (retval == 0) - i386_update_inferior_debug_regs (state, &local_state); - - if (show_debug_regs) - i386_show_dr (state, "remove_watchpoint", addr, len, type); - - return retval; -} - -/* Return non-zero if we can watch a memory region that starts at - address ADDR and whose length is LEN bytes. */ - -int -i386_dr_region_ok_for_watchpoint (struct i386_debug_reg_state *state, - CORE_ADDR addr, int len) -{ - int nregs; - - /* Compute how many aligned watchpoints we would need to cover this - region. */ - nregs = i386_handle_nonaligned_watchpoint (state, WP_COUNT, - addr, len, hw_write); - return nregs <= DR_NADDR ? 1 : 0; -} - -/* If the inferior has some break/watchpoint that triggered, set the - address associated with that break/watchpoint and return non-zero. - Otherwise, return zero. */ - -int -i386_dr_stopped_data_address (struct i386_debug_reg_state *state, - CORE_ADDR *addr_p) -{ - CORE_ADDR addr = 0; - int i; - int rc = 0; - /* The current thread's DR_STATUS. We always need to read this to - check whether some watchpoint caused the trap. */ - unsigned status; - /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a - data breakpoint trap. Only fetch it when necessary, to avoid an - unnecessary extra syscall when no watchpoint triggered. */ - int control_p = 0; - unsigned control = 0; - - /* In non-stop/async, threads can be running while we change the - global dr_mirror (and friends). Say, we set a watchpoint, and - let threads resume. Now, say you delete the watchpoint, or - add/remove watchpoints such that dr_mirror changes while threads - are running. On targets that support non-stop, - inserting/deleting watchpoints updates the global dr_mirror only. - It does not update the real thread's debug registers; that's only - done prior to resume. Instead, if threads are running when the - mirror changes, a temporary and transparent stop on all threads - is forced so they can get their copy of the debug registers - updated on re-resume. Now, say, a thread hit a watchpoint before - having been updated with the new dr_mirror contents, and we - haven't yet handled the corresponding SIGTRAP. If we trusted - dr_mirror below, we'd mistake the real trapped address (from the - last time we had updated debug registers in the thread) with - whatever was currently in dr_mirror. So to fix this, dr_mirror - always represents intention, what we _want_ threads to have in - debug registers. To get at the address and cause of the trap, we - need to read the state the thread still has in its debug - registers. - - In sum, always get the current debug register values the current - thread has, instead of trusting the global mirror. If the thread - was running when we last changed watchpoints, the mirror no - longer represents what was set in this thread's debug - registers. */ - status = i386_dr_low_get_status (); - - ALL_DEBUG_REGISTERS (i) - { - if (!I386_DR_WATCH_HIT (status, i)) - continue; - - if (!control_p) - { - control = i386_dr_low_get_control (); - control_p = 1; - } - - /* This second condition makes sure DRi is set up for a data - watchpoint, not a hardware breakpoint. The reason is that - GDB doesn't call the target_stopped_data_address method - except for data watchpoints. In other words, I'm being - paranoiac. */ - if (I386_DR_GET_RW_LEN (control, i) != 0) - { - addr = i386_dr_low_get_addr (i); - rc = 1; - if (show_debug_regs) - i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write); - } - } - - if (show_debug_regs && addr == 0) - i386_show_dr (state, "stopped_data_addr", 0, 0, hw_write); - - if (rc) - *addr_p = addr; - return rc; -} - -/* Return non-zero if the inferior has some watchpoint that triggered. - Otherwise return zero. */ - -int -i386_dr_stopped_by_watchpoint (struct i386_debug_reg_state *state) -{ - CORE_ADDR addr = 0; - return i386_dr_stopped_data_address (state, &addr); -} diff --git a/gdb/nat/i386-dregs.h b/gdb/nat/i386-dregs.h deleted file mode 100644 index 16edf63..0000000 --- a/gdb/nat/i386-dregs.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Debug register code for the i386. - - Copyright (C) 2009-2014 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -/* Support for hardware watchpoints and breakpoints using the i386 - debug registers. - - This provides several functions for inserting and removing - hardware-assisted breakpoints and watchpoints, testing if one or - more of the watchpoints triggered and at what address, checking - whether a given region can be watched, etc. - - The functions below implement debug registers sharing by reference - counts, and allow to watch regions up to 16 bytes long - (32 bytes on 64 bit hosts). */ - -#ifndef I386_DREGS_H -#define I386_DREGS_H 1 - -/* Forward declaration. */ -enum target_hw_bp_type; - -/* Low-level function vector. */ - -struct i386_dr_low_type - { - /* Set the debug control (DR7) register to a given value for - all LWPs. May be NULL if the debug control register cannot - be set. */ - void (*set_control) (unsigned long); - - /* Put an address into one debug register for all LWPs. May - be NULL if debug registers cannot be set*/ - void (*set_addr) (int, CORE_ADDR); - - /* Return the address in a given debug register of the current - LWP. */ - CORE_ADDR (*get_addr) (int); - - /* Return the value of the debug status (DR6) register for - current LWP. */ - unsigned long (*get_status) (void); - - /* Return the value of the debug control (DR7) register for - current LWP. */ - unsigned long (*get_control) (void); - - /* Number of bytes used for debug registers (4 or 8). */ - int debug_register_length; - }; - -extern struct i386_dr_low_type i386_dr_low; - -/* Debug registers' indices. */ -#define DR_FIRSTADDR 0 -#define DR_LASTADDR 3 -#define DR_NADDR 4 /* The number of debug address registers. */ -#define DR_STATUS 6 /* Index of debug status register (DR6). */ -#define DR_CONTROL 7 /* Index of debug control register (DR7). */ - -/* Global state needed to track h/w watchpoints. */ - -struct i386_debug_reg_state -{ - /* Mirror the inferior's DRi registers. We keep the status and - control registers separated because they don't hold addresses. - Note that since we can change these mirrors while threads are - running, we never trust them to explain a cause of a trap. - For that, we need to peek directly in the inferior registers. */ - CORE_ADDR dr_mirror[DR_NADDR]; - unsigned dr_status_mirror, dr_control_mirror; - - /* Reference counts for each debug register. */ - int dr_ref_count[DR_NADDR]; -}; - -/* A macro to loop over all debug registers. */ -#define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++) - -/* Insert a watchpoint to watch a memory region which starts at - address ADDR and whose length is LEN bytes. Watch memory accesses - of the type TYPE. Return 0 on success, -1 on failure. */ -extern int i386_dr_insert_watchpoint (struct i386_debug_reg_state *state, - enum target_hw_bp_type type, - CORE_ADDR addr, - int len); - -/* Remove a watchpoint that watched the memory region which starts at - address ADDR, whose length is LEN bytes, and for accesses of the - type TYPE. Return 0 on success, -1 on failure. */ -extern int i386_dr_remove_watchpoint (struct i386_debug_reg_state *state, - enum target_hw_bp_type type, - CORE_ADDR addr, - int len); - -/* Return non-zero if we can watch a memory region that starts at - address ADDR and whose length is LEN bytes. */ -extern int i386_dr_region_ok_for_watchpoint (struct i386_debug_reg_state *state, - CORE_ADDR addr, int len); - -/* If the inferior has some break/watchpoint that triggered, set the - address associated with that break/watchpoint and return true. - Otherwise, return false. */ -extern int i386_dr_stopped_data_address (struct i386_debug_reg_state *state, - CORE_ADDR *addr_p); - -/* Return true if the inferior has some watchpoint that triggered. - Otherwise return false. */ -extern int i386_dr_stopped_by_watchpoint (struct i386_debug_reg_state *state); - -#endif /* I386_DREGS_H */ diff --git a/gdb/nat/i386-gcc-cpuid.h b/gdb/nat/i386-gcc-cpuid.h deleted file mode 100644 index 34ab197..0000000 --- a/gdb/nat/i386-gcc-cpuid.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Helper cpuid.h file copied from gcc-4.8.0. Code in gdb should not - * include this directly, but pull in i386-cpuid.h and use that func. - */ -/* - * Copyright (C) 2007-2014 Free Software Foundation, Inc. - * - * This file 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, or (at your option) any - * later version. - * - * This file 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. - * - * Under Section 7 of GPL version 3, you are granted additional - * permissions described in the GCC Runtime Library Exception, version - * 3.1, as published by the Free Software Foundation. - * - * You should have received a copy of the GNU General Public License and - * a copy of the GCC Runtime Library Exception along with this program; - * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - * . - */ - -/* %ecx */ -#define bit_SSE3 (1 << 0) -#define bit_PCLMUL (1 << 1) -#define bit_LZCNT (1 << 5) -#define bit_SSSE3 (1 << 9) -#define bit_FMA (1 << 12) -#define bit_CMPXCHG16B (1 << 13) -#define bit_SSE4_1 (1 << 19) -#define bit_SSE4_2 (1 << 20) -#define bit_MOVBE (1 << 22) -#define bit_POPCNT (1 << 23) -#define bit_AES (1 << 25) -#define bit_XSAVE (1 << 26) -#define bit_OSXSAVE (1 << 27) -#define bit_AVX (1 << 28) -#define bit_F16C (1 << 29) -#define bit_RDRND (1 << 30) - -/* %edx */ -#define bit_CMPXCHG8B (1 << 8) -#define bit_CMOV (1 << 15) -#define bit_MMX (1 << 23) -#define bit_FXSAVE (1 << 24) -#define bit_SSE (1 << 25) -#define bit_SSE2 (1 << 26) - -/* Extended Features */ -/* %ecx */ -#define bit_LAHF_LM (1 << 0) -#define bit_ABM (1 << 5) -#define bit_SSE4a (1 << 6) -#define bit_PRFCHW (1 << 8) -#define bit_XOP (1 << 11) -#define bit_LWP (1 << 15) -#define bit_FMA4 (1 << 16) -#define bit_TBM (1 << 21) - -/* %edx */ -#define bit_MMXEXT (1 << 22) -#define bit_LM (1 << 29) -#define bit_3DNOWP (1 << 30) -#define bit_3DNOW (1 << 31) - -/* Extended Features (%eax == 7) */ -#define bit_FSGSBASE (1 << 0) -#define bit_BMI (1 << 3) -#define bit_HLE (1 << 4) -#define bit_AVX2 (1 << 5) -#define bit_BMI2 (1 << 8) -#define bit_RTM (1 << 11) -#define bit_AVX512F (1 << 16) -#define bit_MPX (1 << 14) -#define bit_RDSEED (1 << 18) -#define bit_ADX (1 << 19) -#define bit_AVX512PF (1 << 26) -#define bit_AVX512ER (1 << 27) -#define bit_AVX512CD (1 << 28) -#define bit_SHA (1 << 29) - -/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */ -#define bit_XSAVEOPT (1 << 0) - -/* Signatures for different CPU implementations as returned in uses - of cpuid with level 0. */ -#define signature_AMD_ebx 0x68747541 -#define signature_AMD_ecx 0x444d4163 -#define signature_AMD_edx 0x69746e65 - -#define signature_CENTAUR_ebx 0x746e6543 -#define signature_CENTAUR_ecx 0x736c7561 -#define signature_CENTAUR_edx 0x48727561 - -#define signature_CYRIX_ebx 0x69727943 -#define signature_CYRIX_ecx 0x64616574 -#define signature_CYRIX_edx 0x736e4978 - -#define signature_INTEL_ebx 0x756e6547 -#define signature_INTEL_ecx 0x6c65746e -#define signature_INTEL_edx 0x49656e69 - -#define signature_TM1_ebx 0x6e617254 -#define signature_TM1_ecx 0x55504361 -#define signature_TM1_edx 0x74656d73 - -#define signature_TM2_ebx 0x756e6547 -#define signature_TM2_ecx 0x3638784d -#define signature_TM2_edx 0x54656e69 - -#define signature_NSC_ebx 0x646f6547 -#define signature_NSC_ecx 0x43534e20 -#define signature_NSC_edx 0x79622065 - -#define signature_NEXGEN_ebx 0x4778654e -#define signature_NEXGEN_ecx 0x6e657669 -#define signature_NEXGEN_edx 0x72446e65 - -#define signature_RISE_ebx 0x65736952 -#define signature_RISE_ecx 0x65736952 -#define signature_RISE_edx 0x65736952 - -#define signature_SIS_ebx 0x20536953 -#define signature_SIS_ecx 0x20536953 -#define signature_SIS_edx 0x20536953 - -#define signature_UMC_ebx 0x20434d55 -#define signature_UMC_ecx 0x20434d55 -#define signature_UMC_edx 0x20434d55 - -#define signature_VIA_ebx 0x20414956 -#define signature_VIA_ecx 0x20414956 -#define signature_VIA_edx 0x20414956 - -#define signature_VORTEX_ebx 0x74726f56 -#define signature_VORTEX_ecx 0x436f5320 -#define signature_VORTEX_edx 0x36387865 - -#if defined(__i386__) && defined(__PIC__) -/* %ebx may be the PIC register. */ -#if __GNUC__ >= 3 -#define __cpuid(level, a, b, c, d) \ - __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \ - "cpuid\n\t" \ - "xchg{l}\t{%%}ebx, %k1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level)) - -#define __cpuid_count(level, count, a, b, c, d) \ - __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \ - "cpuid\n\t" \ - "xchg{l}\t{%%}ebx, %k1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level), "2" (count)) -#else -/* Host GCCs older than 3.0 weren't supporting Intel asm syntax - nor alternatives in i386 code. */ -#define __cpuid(level, a, b, c, d) \ - __asm__ ("xchgl\t%%ebx, %k1\n\t" \ - "cpuid\n\t" \ - "xchgl\t%%ebx, %k1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level)) - -#define __cpuid_count(level, count, a, b, c, d) \ - __asm__ ("xchgl\t%%ebx, %k1\n\t" \ - "cpuid\n\t" \ - "xchgl\t%%ebx, %k1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level), "2" (count)) -#endif -#elif defined(__x86_64__) && (defined(__code_model_medium__) || defined(__code_model_large__)) && defined(__PIC__) -/* %rbx may be the PIC register. */ -#define __cpuid(level, a, b, c, d) \ - __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \ - "cpuid\n\t" \ - "xchg{q}\t{%%}rbx, %q1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level)) - -#define __cpuid_count(level, count, a, b, c, d) \ - __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \ - "cpuid\n\t" \ - "xchg{q}\t{%%}rbx, %q1\n\t" \ - : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ - : "0" (level), "2" (count)) -#else -#define __cpuid(level, a, b, c, d) \ - __asm__ ("cpuid\n\t" \ - : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ - : "0" (level)) - -#define __cpuid_count(level, count, a, b, c, d) \ - __asm__ ("cpuid\n\t" \ - : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ - : "0" (level), "2" (count)) -#endif - -/* Return highest supported input value for cpuid instruction. ext can - be either 0x0 or 0x8000000 to return highest supported value for - basic or extended cpuid information. Function returns 0 if cpuid - is not supported or whatever cpuid returns in eax register. If sig - pointer is non-null, then first four bytes of the signature - (as found in ebx register) are returned in location pointed by sig. */ - -static __inline unsigned int -__get_cpuid_max (unsigned int __ext, unsigned int *__sig) -{ - unsigned int __eax, __ebx, __ecx, __edx; - -#ifndef __x86_64__ - /* See if we can use cpuid. On AMD64 we always can. */ -#if __GNUC__ >= 3 - __asm__ ("pushf{l|d}\n\t" - "pushf{l|d}\n\t" - "pop{l}\t%0\n\t" - "mov{l}\t{%0, %1|%1, %0}\n\t" - "xor{l}\t{%2, %0|%0, %2}\n\t" - "push{l}\t%0\n\t" - "popf{l|d}\n\t" - "pushf{l|d}\n\t" - "pop{l}\t%0\n\t" - "popf{l|d}\n\t" - : "=&r" (__eax), "=&r" (__ebx) - : "i" (0x00200000)); -#else -/* Host GCCs older than 3.0 weren't supporting Intel asm syntax - nor alternatives in i386 code. */ - __asm__ ("pushfl\n\t" - "pushfl\n\t" - "popl\t%0\n\t" - "movl\t%0, %1\n\t" - "xorl\t%2, %0\n\t" - "pushl\t%0\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl\t%0\n\t" - "popfl\n\t" - : "=&r" (__eax), "=&r" (__ebx) - : "i" (0x00200000)); -#endif - - if (!((__eax ^ __ebx) & 0x00200000)) - return 0; -#endif - - /* Host supports cpuid. Return highest supported cpuid input value. */ - __cpuid (__ext, __eax, __ebx, __ecx, __edx); - - if (__sig) - *__sig = __ebx; - - return __eax; -} - -/* Return cpuid data for requested cpuid level, as found in returned - eax, ebx, ecx and edx registers. The function checks if cpuid is - supported and returns 1 for valid cpuid information or 0 for - unsupported cpuid level. All pointers are required to be non-null. */ - -static __inline int -__get_cpuid (unsigned int __level, - unsigned int *__eax, unsigned int *__ebx, - unsigned int *__ecx, unsigned int *__edx) -{ - unsigned int __ext = __level & 0x80000000; - - if (__get_cpuid_max (__ext, 0) < __level) - return 0; - - __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx); - return 1; -} diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c index ec26f0f..37c85c0 100644 --- a/gdb/nat/linux-btrace.c +++ b/gdb/nat/linux-btrace.c @@ -23,7 +23,7 @@ #include "linux-btrace.h" #include "common-regcache.h" #include "gdb_wait.h" -#include "i386-cpuid.h" +#include "x86-cpuid.h" #ifdef HAVE_SYS_SYSCALL_H #include @@ -338,7 +338,7 @@ intel_supports_btrace (void) { unsigned int cpuid, model, family; - if (!i386_cpuid (1, &cpuid, NULL, NULL, NULL)) + if (!x86_cpuid (1, &cpuid, NULL, NULL, NULL)) return 0; family = (cpuid >> 8) & 0xf; @@ -379,7 +379,7 @@ cpu_supports_btrace (void) { unsigned int ebx, ecx, edx; - if (!i386_cpuid (0, NULL, &ebx, &ecx, &edx)) + if (!x86_cpuid (0, NULL, &ebx, &ecx, &edx)) return 0; if (ebx == signature_INTEL_ebx && ecx == signature_INTEL_ecx diff --git a/gdb/nat/x86-cpuid.h b/gdb/nat/x86-cpuid.h new file mode 100644 index 0000000..3e4a481 --- /dev/null +++ b/gdb/nat/x86-cpuid.h @@ -0,0 +1,63 @@ +/* C API for x86 cpuid insn. + Copyright (C) 2007-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + This file 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, 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 . */ + +#ifndef X86_CPUID_COMMON_H +#define X86_CPUID_COMMON_H + +/* Always include the header for the cpu bit defines. */ +#include "x86-gcc-cpuid.h" + +#if defined(__i386__) || defined(__x86_64__) + +/* Return cpuid data for requested cpuid level, as found in returned + eax, ebx, ecx and edx registers. The function checks if cpuid is + supported and returns 1 for valid cpuid information or 0 for + unsupported cpuid level. Pointers may be non-null. */ + +static __inline int +x86_cpuid (unsigned int __level, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __scratch; + + if (!__eax) + __eax = &__scratch; + if (!__ebx) + __ebx = &__scratch; + if (!__ecx) + __ecx = &__scratch; + if (!__edx) + __edx = &__scratch; + + return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); +} + +#else + +static __inline int +x86_cpuid (unsigned int __level, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + return 0; +} + +#endif /* i386 && x86_64 */ + +#endif /* X86_CPUID_COMMON_H */ diff --git a/gdb/nat/x86-dregs.c b/gdb/nat/x86-dregs.c new file mode 100644 index 0000000..d571804 --- /dev/null +++ b/gdb/nat/x86-dregs.c @@ -0,0 +1,655 @@ +/* Debug register code for x86 (i386 and x86-64). + + Copyright (C) 2001-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "common-defs.h" +#include "x86-dregs.h" +#include "break-common.h" + +/* Support for hardware watchpoints and breakpoints using the x86 + debug registers. + + This provides several functions for inserting and removing + hardware-assisted breakpoints and watchpoints, testing if one or + more of the watchpoints triggered and at what address, checking + whether a given region can be watched, etc. + + The functions below implement debug registers sharing by reference + counts, and allow to watch regions up to 16 bytes long. */ + +/* Accessor macros for low-level function vector. */ + +/* Can we update the inferior's debug registers? */ +#define x86_dr_low_can_set_addr() (x86_dr_low.set_addr != NULL) + +/* Update the inferior's debug register REGNUM from STATE. */ +#define x86_dr_low_set_addr(new_state, i) \ + (x86_dr_low.set_addr ((i), (new_state)->dr_mirror[(i)])) + +/* Return the inferior's debug register REGNUM. */ +#define x86_dr_low_get_addr(i) (x86_dr_low.get_addr ((i))) + +/* Can we update the inferior's DR7 control register? */ +#define x86_dr_low_can_set_control() (x86_dr_low.set_control != NULL) + +/* Update the inferior's DR7 debug control register from STATE. */ +#define x86_dr_low_set_control(new_state) \ + (x86_dr_low.set_control ((new_state)->dr_control_mirror)) + +/* Return the value of the inferior's DR7 debug control register. */ +#define x86_dr_low_get_control() (x86_dr_low.get_control ()) + +/* Return the value of the inferior's DR6 debug status register. */ +#define x86_dr_low_get_status() (x86_dr_low.get_status ()) + +/* Return the debug register size, in bytes. */ +#define x86_get_debug_register_length() \ + (x86_dr_low.debug_register_length) + +/* Support for 8-byte wide hw watchpoints. */ +#define TARGET_HAS_DR_LEN_8 (x86_get_debug_register_length () == 8) + +/* DR7 Debug Control register fields. */ + +/* How many bits to skip in DR7 to get to R/W and LEN fields. */ +#define DR_CONTROL_SHIFT 16 +/* How many bits in DR7 per R/W and LEN field for each watchpoint. */ +#define DR_CONTROL_SIZE 4 + +/* Watchpoint/breakpoint read/write fields in DR7. */ +#define DR_RW_EXECUTE (0x0) /* Break on instruction execution. */ +#define DR_RW_WRITE (0x1) /* Break on data writes. */ +#define DR_RW_READ (0x3) /* Break on data reads or writes. */ + +/* This is here for completeness. No platform supports this + functionality yet (as of March 2001). Note that the DE flag in the + CR4 register needs to be set to support this. */ +#ifndef DR_RW_IORW +#define DR_RW_IORW (0x2) /* Break on I/O reads or writes. */ +#endif + +/* Watchpoint/breakpoint length fields in DR7. The 2-bit left shift + is so we could OR this with the read/write field defined above. */ +#define DR_LEN_1 (0x0 << 2) /* 1-byte region watch or breakpoint. */ +#define DR_LEN_2 (0x1 << 2) /* 2-byte region watch. */ +#define DR_LEN_4 (0x3 << 2) /* 4-byte region watch. */ +#define DR_LEN_8 (0x2 << 2) /* 8-byte region watch (AMD64). */ + +/* Local and Global Enable flags in DR7. + + When the Local Enable flag is set, the breakpoint/watchpoint is + enabled only for the current task; the processor automatically + clears this flag on every task switch. When the Global Enable flag + is set, the breakpoint/watchpoint is enabled for all tasks; the + processor never clears this flag. + + Currently, all watchpoint are locally enabled. If you need to + enable them globally, read the comment which pertains to this in + x86_insert_aligned_watchpoint below. */ +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit. */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit. */ +#define DR_ENABLE_SIZE 2 /* Two enable bits per debug register. */ + +/* Local and global exact breakpoint enable flags (a.k.a. slowdown + flags). These are only required on i386, to allow detection of the + exact instruction which caused a watchpoint to break; i486 and + later processors do that automatically. We set these flags for + backwards compatibility. */ +#define DR_LOCAL_SLOWDOWN (0x100) +#define DR_GLOBAL_SLOWDOWN (0x200) + +/* Fields reserved by Intel. This includes the GD (General Detect + Enable) flag, which causes a debug exception to be generated when a + MOV instruction accesses one of the debug registers. + + FIXME: My Intel manual says we should use 0xF800, not 0xFC00. */ +#define DR_CONTROL_RESERVED (0xFC00) + +/* Auxiliary helper macros. */ + +/* A value that masks all fields in DR7 that are reserved by Intel. */ +#define X86_DR_CONTROL_MASK (~DR_CONTROL_RESERVED) + +/* The I'th debug register is vacant if its Local and Global Enable + bits are reset in the Debug Control register. */ +#define X86_DR_VACANT(state, i) \ + (((state)->dr_control_mirror & (3 << (DR_ENABLE_SIZE * (i)))) == 0) + +/* Locally enable the break/watchpoint in the I'th debug register. */ +#define X86_DR_LOCAL_ENABLE(state, i) \ + do { \ + (state)->dr_control_mirror |= \ + (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \ + } while (0) + +/* Globally enable the break/watchpoint in the I'th debug register. */ +#define X86_DR_GLOBAL_ENABLE(state, i) \ + do { \ + (state)->dr_control_mirror |= \ + (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))); \ + } while (0) + +/* Disable the break/watchpoint in the I'th debug register. */ +#define X86_DR_DISABLE(state, i) \ + do { \ + (state)->dr_control_mirror &= \ + ~(3 << (DR_ENABLE_SIZE * (i))); \ + } while (0) + +/* Set in DR7 the RW and LEN fields for the I'th debug register. */ +#define X86_DR_SET_RW_LEN(state, i, rwlen) \ + do { \ + (state)->dr_control_mirror &= \ + ~(0x0f << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \ + (state)->dr_control_mirror |= \ + ((rwlen) << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))); \ + } while (0) + +/* Get from DR7 the RW and LEN fields for the I'th debug register. */ +#define X86_DR_GET_RW_LEN(dr7, i) \ + (((dr7) \ + >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f) + +/* Did the watchpoint whose address is in the I'th register break? */ +#define X86_DR_WATCH_HIT(dr6, i) ((dr6) & (1 << (i))) + +/* Types of operations supported by x86_handle_nonaligned_watchpoint. */ +typedef enum { WP_INSERT, WP_REMOVE, WP_COUNT } x86_wp_op_t; + +/* Print the values of the mirrored debug registers. */ + +static void +x86_show_dr (struct x86_debug_reg_state *state, + const char *func, CORE_ADDR addr, + int len, enum target_hw_bp_type type) +{ + int i; + + debug_printf ("%s", func); + if (addr || len) + debug_printf (" (addr=%s, len=%d, type=%s)", + phex (addr, 8), len, + type == hw_write ? "data-write" + : (type == hw_read ? "data-read" + : (type == hw_access ? "data-read/write" + : (type == hw_execute ? "instruction-execute" + /* FIXME: if/when I/O read/write + watchpoints are supported, add them + here. */ + : "??unknown??")))); + debug_printf (":\n"); + debug_printf ("\tCONTROL (DR7): %s STATUS (DR6): %s\n", + phex (state->dr_control_mirror, 8), + phex (state->dr_status_mirror, 8)); + ALL_DEBUG_REGISTERS (i) + { + debug_printf ("\ +\tDR%d: addr=0x%s, ref.count=%d DR%d: addr=0x%s, ref.count=%d\n", + i, phex (state->dr_mirror[i], + x86_get_debug_register_length ()), + state->dr_ref_count[i], + i + 1, phex (state->dr_mirror[i + 1], + x86_get_debug_register_length ()), + state->dr_ref_count[i + 1]); + i++; + } +} + +/* Return the value of a 4-bit field for DR7 suitable for watching a + region of LEN bytes for accesses of type TYPE. LEN is assumed to + have the value of 1, 2, or 4. */ + +static unsigned +x86_length_and_rw_bits (int len, enum target_hw_bp_type type) +{ + unsigned rw; + + switch (type) + { + case hw_execute: + rw = DR_RW_EXECUTE; + break; + case hw_write: + rw = DR_RW_WRITE; + break; + case hw_read: + internal_error (__FILE__, __LINE__, + _("The i386 doesn't support " + "data-read watchpoints.\n")); + case hw_access: + rw = DR_RW_READ; + break; +#if 0 + /* Not yet supported. */ + case hw_io_access: + rw = DR_RW_IORW; + break; +#endif + default: + internal_error (__FILE__, __LINE__, _("\ +Invalid hardware breakpoint type %d in x86_length_and_rw_bits.\n"), + (int) type); + } + + switch (len) + { + case 1: + return (DR_LEN_1 | rw); + case 2: + return (DR_LEN_2 | rw); + case 4: + return (DR_LEN_4 | rw); + case 8: + if (TARGET_HAS_DR_LEN_8) + return (DR_LEN_8 | rw); + /* ELSE FALL THROUGH */ + default: + internal_error (__FILE__, __LINE__, _("\ +Invalid hardware breakpoint length %d in x86_length_and_rw_bits.\n"), len); + } +} + +/* Insert a watchpoint at address ADDR, which is assumed to be aligned + according to the length of the region to watch. LEN_RW_BITS is the + value of the bits from DR7 which describes the length and access + type of the region to be watched by this watchpoint. Return 0 on + success, -1 on failure. */ + +static int +x86_insert_aligned_watchpoint (struct x86_debug_reg_state *state, + CORE_ADDR addr, unsigned len_rw_bits) +{ + int i; + + if (!x86_dr_low_can_set_addr () || !x86_dr_low_can_set_control ()) + return -1; + + /* First, look for an occupied debug register with the same address + and the same RW and LEN definitions. If we find one, we can + reuse it for this watchpoint as well (and save a register). */ + ALL_DEBUG_REGISTERS (i) + { + if (!X86_DR_VACANT (state, i) + && state->dr_mirror[i] == addr + && X86_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits) + { + state->dr_ref_count[i]++; + return 0; + } + } + + /* Next, look for a vacant debug register. */ + ALL_DEBUG_REGISTERS (i) + { + if (X86_DR_VACANT (state, i)) + break; + } + + /* No more debug registers! */ + if (i >= DR_NADDR) + return -1; + + /* Now set up the register I to watch our region. */ + + /* Record the info in our local mirrored array. */ + state->dr_mirror[i] = addr; + state->dr_ref_count[i] = 1; + X86_DR_SET_RW_LEN (state, i, len_rw_bits); + /* Note: we only enable the watchpoint locally, i.e. in the current + task. Currently, no x86 target allows or supports global + watchpoints; however, if any target would want that in the + future, GDB should probably provide a command to control whether + to enable watchpoints globally or locally, and the code below + should use global or local enable and slow-down flags as + appropriate. */ + X86_DR_LOCAL_ENABLE (state, i); + state->dr_control_mirror |= DR_LOCAL_SLOWDOWN; + state->dr_control_mirror &= X86_DR_CONTROL_MASK; + + return 0; +} + +/* Remove a watchpoint at address ADDR, which is assumed to be aligned + according to the length of the region to watch. LEN_RW_BITS is the + value of the bits from DR7 which describes the length and access + type of the region watched by this watchpoint. Return 0 on + success, -1 on failure. */ + +static int +x86_remove_aligned_watchpoint (struct x86_debug_reg_state *state, + CORE_ADDR addr, unsigned len_rw_bits) +{ + int i, retval = -1; + int all_vacant = 1; + + ALL_DEBUG_REGISTERS (i) + { + if (!X86_DR_VACANT (state, i) + && state->dr_mirror[i] == addr + && X86_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits) + { + if (--state->dr_ref_count[i] == 0) /* No longer in use? */ + { + /* Reset our mirror. */ + state->dr_mirror[i] = 0; + X86_DR_DISABLE (state, i); + /* Even though not strictly necessary, clear out all + bits in DR_CONTROL related to this debug register. + Debug output is clearer when we don't have stale bits + in place. This also allows the assertion below. */ + X86_DR_SET_RW_LEN (state, i, 0); + } + retval = 0; + } + + if (!X86_DR_VACANT (state, i)) + all_vacant = 0; + } + + if (all_vacant) + { + /* Even though not strictly necessary, clear out all of + DR_CONTROL, so that when we have no debug registers in use, + we end up with DR_CONTROL == 0. The Linux support relies on + this for an optimization. Plus, it makes for clearer debug + output. */ + state->dr_control_mirror &= ~DR_LOCAL_SLOWDOWN; + + gdb_assert (state->dr_control_mirror == 0); + } + return retval; +} + +/* Insert or remove a (possibly non-aligned) watchpoint, or count the + number of debug registers required to watch a region at address + ADDR whose length is LEN for accesses of type TYPE. Return 0 on + successful insertion or removal, a positive number when queried + about the number of registers, or -1 on failure. If WHAT is not a + valid value, bombs through internal_error. */ + +static int +x86_handle_nonaligned_watchpoint (struct x86_debug_reg_state *state, + x86_wp_op_t what, CORE_ADDR addr, int len, + enum target_hw_bp_type type) +{ + int retval = 0; + int max_wp_len = TARGET_HAS_DR_LEN_8 ? 8 : 4; + + static const int size_try_array[8][8] = + { + {1, 1, 1, 1, 1, 1, 1, 1}, /* Trying size one. */ + {2, 1, 2, 1, 2, 1, 2, 1}, /* Trying size two. */ + {2, 1, 2, 1, 2, 1, 2, 1}, /* Trying size three. */ + {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size four. */ + {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size five. */ + {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size six. */ + {4, 1, 2, 1, 4, 1, 2, 1}, /* Trying size seven. */ + {8, 1, 2, 1, 4, 1, 2, 1}, /* Trying size eight. */ + }; + + while (len > 0) + { + int align = addr % max_wp_len; + /* Four (eight on AMD64) is the maximum length a debug register + can watch. */ + int try = (len > max_wp_len ? (max_wp_len - 1) : len - 1); + int size = size_try_array[try][align]; + + if (what == WP_COUNT) + { + /* size_try_array[] is defined such that each iteration + through the loop is guaranteed to produce an address and a + size that can be watched with a single debug register. + Thus, for counting the registers required to watch a + region, we simply need to increment the count on each + iteration. */ + retval++; + } + else + { + unsigned len_rw = x86_length_and_rw_bits (size, type); + + if (what == WP_INSERT) + retval = x86_insert_aligned_watchpoint (state, addr, len_rw); + else if (what == WP_REMOVE) + retval = x86_remove_aligned_watchpoint (state, addr, len_rw); + else + internal_error (__FILE__, __LINE__, _("\ +Invalid value %d of operation in x86_handle_nonaligned_watchpoint.\n"), + (int) what); + if (retval) + break; + } + + addr += size; + len -= size; + } + + return retval; +} + +/* Update the inferior debug registers state, in STATE, with the + new debug registers state, in NEW_STATE. */ + +static void +x86_update_inferior_debug_regs (struct x86_debug_reg_state *state, + struct x86_debug_reg_state *new_state) +{ + int i; + + ALL_DEBUG_REGISTERS (i) + { + if (X86_DR_VACANT (new_state, i) != X86_DR_VACANT (state, i)) + x86_dr_low_set_addr (new_state, i); + else + gdb_assert (new_state->dr_mirror[i] == state->dr_mirror[i]); + } + + if (new_state->dr_control_mirror != state->dr_control_mirror) + x86_dr_low_set_control (new_state); + + *state = *new_state; +} + +/* Insert a watchpoint to watch a memory region which starts at + address ADDR and whose length is LEN bytes. Watch memory accesses + of the type TYPE. Return 0 on success, -1 on failure. */ + +int +x86_dr_insert_watchpoint (struct x86_debug_reg_state *state, + enum target_hw_bp_type type, + CORE_ADDR addr, int len) +{ + int retval; + /* Work on a local copy of the debug registers, and on success, + commit the change back to the inferior. */ + struct x86_debug_reg_state local_state = *state; + + if (type == hw_read) + return 1; /* unsupported */ + + if (((len != 1 && len != 2 && len != 4) + && !(TARGET_HAS_DR_LEN_8 && len == 8)) + || addr % len != 0) + { + retval = x86_handle_nonaligned_watchpoint (&local_state, + WP_INSERT, + addr, len, type); + } + else + { + unsigned len_rw = x86_length_and_rw_bits (len, type); + + retval = x86_insert_aligned_watchpoint (&local_state, + addr, len_rw); + } + + if (retval == 0) + x86_update_inferior_debug_regs (state, &local_state); + + if (show_debug_regs) + x86_show_dr (state, "insert_watchpoint", addr, len, type); + + return retval; +} + +/* Remove a watchpoint that watched the memory region which starts at + address ADDR, whose length is LEN bytes, and for accesses of the + type TYPE. Return 0 on success, -1 on failure. */ + +int +x86_dr_remove_watchpoint (struct x86_debug_reg_state *state, + enum target_hw_bp_type type, + CORE_ADDR addr, int len) +{ + int retval; + /* Work on a local copy of the debug registers, and on success, + commit the change back to the inferior. */ + struct x86_debug_reg_state local_state = *state; + + if (((len != 1 && len != 2 && len != 4) + && !(TARGET_HAS_DR_LEN_8 && len == 8)) + || addr % len != 0) + { + retval = x86_handle_nonaligned_watchpoint (&local_state, + WP_REMOVE, + addr, len, type); + } + else + { + unsigned len_rw = x86_length_and_rw_bits (len, type); + + retval = x86_remove_aligned_watchpoint (&local_state, + addr, len_rw); + } + + if (retval == 0) + x86_update_inferior_debug_regs (state, &local_state); + + if (show_debug_regs) + x86_show_dr (state, "remove_watchpoint", addr, len, type); + + return retval; +} + +/* Return non-zero if we can watch a memory region that starts at + address ADDR and whose length is LEN bytes. */ + +int +x86_dr_region_ok_for_watchpoint (struct x86_debug_reg_state *state, + CORE_ADDR addr, int len) +{ + int nregs; + + /* Compute how many aligned watchpoints we would need to cover this + region. */ + nregs = x86_handle_nonaligned_watchpoint (state, WP_COUNT, + addr, len, hw_write); + return nregs <= DR_NADDR ? 1 : 0; +} + +/* If the inferior has some break/watchpoint that triggered, set the + address associated with that break/watchpoint and return non-zero. + Otherwise, return zero. */ + +int +x86_dr_stopped_data_address (struct x86_debug_reg_state *state, + CORE_ADDR *addr_p) +{ + CORE_ADDR addr = 0; + int i; + int rc = 0; + /* The current thread's DR_STATUS. We always need to read this to + check whether some watchpoint caused the trap. */ + unsigned status; + /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a + data breakpoint trap. Only fetch it when necessary, to avoid an + unnecessary extra syscall when no watchpoint triggered. */ + int control_p = 0; + unsigned control = 0; + + /* In non-stop/async, threads can be running while we change the + global dr_mirror (and friends). Say, we set a watchpoint, and + let threads resume. Now, say you delete the watchpoint, or + add/remove watchpoints such that dr_mirror changes while threads + are running. On targets that support non-stop, + inserting/deleting watchpoints updates the global dr_mirror only. + It does not update the real thread's debug registers; that's only + done prior to resume. Instead, if threads are running when the + mirror changes, a temporary and transparent stop on all threads + is forced so they can get their copy of the debug registers + updated on re-resume. Now, say, a thread hit a watchpoint before + having been updated with the new dr_mirror contents, and we + haven't yet handled the corresponding SIGTRAP. If we trusted + dr_mirror below, we'd mistake the real trapped address (from the + last time we had updated debug registers in the thread) with + whatever was currently in dr_mirror. So to fix this, dr_mirror + always represents intention, what we _want_ threads to have in + debug registers. To get at the address and cause of the trap, we + need to read the state the thread still has in its debug + registers. + + In sum, always get the current debug register values the current + thread has, instead of trusting the global mirror. If the thread + was running when we last changed watchpoints, the mirror no + longer represents what was set in this thread's debug + registers. */ + status = x86_dr_low_get_status (); + + ALL_DEBUG_REGISTERS (i) + { + if (!X86_DR_WATCH_HIT (status, i)) + continue; + + if (!control_p) + { + control = x86_dr_low_get_control (); + control_p = 1; + } + + /* This second condition makes sure DRi is set up for a data + watchpoint, not a hardware breakpoint. The reason is that + GDB doesn't call the target_stopped_data_address method + except for data watchpoints. In other words, I'm being + paranoiac. */ + if (X86_DR_GET_RW_LEN (control, i) != 0) + { + addr = x86_dr_low_get_addr (i); + rc = 1; + if (show_debug_regs) + x86_show_dr (state, "watchpoint_hit", addr, -1, hw_write); + } + } + + if (show_debug_regs && addr == 0) + x86_show_dr (state, "stopped_data_addr", 0, 0, hw_write); + + if (rc) + *addr_p = addr; + return rc; +} + +/* Return non-zero if the inferior has some watchpoint that triggered. + Otherwise return zero. */ + +int +x86_dr_stopped_by_watchpoint (struct x86_debug_reg_state *state) +{ + CORE_ADDR addr = 0; + return x86_dr_stopped_data_address (state, &addr); +} diff --git a/gdb/nat/x86-dregs.h b/gdb/nat/x86-dregs.h new file mode 100644 index 0000000..fb179a5 --- /dev/null +++ b/gdb/nat/x86-dregs.h @@ -0,0 +1,126 @@ +/* Debug register code for x86 (i386 and x86-64). + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +/* Support for hardware watchpoints and breakpoints using the x86 + debug registers. + + This provides several functions for inserting and removing + hardware-assisted breakpoints and watchpoints, testing if one or + more of the watchpoints triggered and at what address, checking + whether a given region can be watched, etc. + + The functions below implement debug registers sharing by reference + counts, and allow to watch regions up to 16 bytes long + (32 bytes on 64 bit hosts). */ + +#ifndef X86_DREGS_H +#define X86_DREGS_H 1 + +/* Forward declaration. */ +enum target_hw_bp_type; + +/* Low-level function vector. */ + +struct x86_dr_low_type + { + /* Set the debug control (DR7) register to a given value for + all LWPs. May be NULL if the debug control register cannot + be set. */ + void (*set_control) (unsigned long); + + /* Put an address into one debug register for all LWPs. May + be NULL if debug registers cannot be set*/ + void (*set_addr) (int, CORE_ADDR); + + /* Return the address in a given debug register of the current + LWP. */ + CORE_ADDR (*get_addr) (int); + + /* Return the value of the debug status (DR6) register for + current LWP. */ + unsigned long (*get_status) (void); + + /* Return the value of the debug control (DR7) register for + current LWP. */ + unsigned long (*get_control) (void); + + /* Number of bytes used for debug registers (4 or 8). */ + int debug_register_length; + }; + +extern struct x86_dr_low_type x86_dr_low; + +/* Debug registers' indices. */ +#define DR_FIRSTADDR 0 +#define DR_LASTADDR 3 +#define DR_NADDR 4 /* The number of debug address registers. */ +#define DR_STATUS 6 /* Index of debug status register (DR6). */ +#define DR_CONTROL 7 /* Index of debug control register (DR7). */ + +/* Global state needed to track h/w watchpoints. */ + +struct x86_debug_reg_state +{ + /* Mirror the inferior's DRi registers. We keep the status and + control registers separated because they don't hold addresses. + Note that since we can change these mirrors while threads are + running, we never trust them to explain a cause of a trap. + For that, we need to peek directly in the inferior registers. */ + CORE_ADDR dr_mirror[DR_NADDR]; + unsigned dr_status_mirror, dr_control_mirror; + + /* Reference counts for each debug register. */ + int dr_ref_count[DR_NADDR]; +}; + +/* A macro to loop over all debug registers. */ +#define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++) + +/* Insert a watchpoint to watch a memory region which starts at + address ADDR and whose length is LEN bytes. Watch memory accesses + of the type TYPE. Return 0 on success, -1 on failure. */ +extern int x86_dr_insert_watchpoint (struct x86_debug_reg_state *state, + enum target_hw_bp_type type, + CORE_ADDR addr, + int len); + +/* Remove a watchpoint that watched the memory region which starts at + address ADDR, whose length is LEN bytes, and for accesses of the + type TYPE. Return 0 on success, -1 on failure. */ +extern int x86_dr_remove_watchpoint (struct x86_debug_reg_state *state, + enum target_hw_bp_type type, + CORE_ADDR addr, + int len); + +/* Return non-zero if we can watch a memory region that starts at + address ADDR and whose length is LEN bytes. */ +extern int x86_dr_region_ok_for_watchpoint (struct x86_debug_reg_state *state, + CORE_ADDR addr, int len); + +/* If the inferior has some break/watchpoint that triggered, set the + address associated with that break/watchpoint and return true. + Otherwise, return false. */ +extern int x86_dr_stopped_data_address (struct x86_debug_reg_state *state, + CORE_ADDR *addr_p); + +/* Return true if the inferior has some watchpoint that triggered. + Otherwise return false. */ +extern int x86_dr_stopped_by_watchpoint (struct x86_debug_reg_state *state); + +#endif /* X86_DREGS_H */ diff --git a/gdb/nat/x86-gcc-cpuid.h b/gdb/nat/x86-gcc-cpuid.h new file mode 100644 index 0000000..18763ad --- /dev/null +++ b/gdb/nat/x86-gcc-cpuid.h @@ -0,0 +1,278 @@ +/* + * Helper cpuid.h file copied from gcc-4.8.0. Code in gdb should not + * include this directly, but pull in x86-cpuid.h and use that func. + */ +/* + * Copyright (C) 2007-2014 Free Software Foundation, Inc. + * + * This file 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, or (at your option) any + * later version. + * + * This file 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. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * . + */ + +/* %ecx */ +#define bit_SSE3 (1 << 0) +#define bit_PCLMUL (1 << 1) +#define bit_LZCNT (1 << 5) +#define bit_SSSE3 (1 << 9) +#define bit_FMA (1 << 12) +#define bit_CMPXCHG16B (1 << 13) +#define bit_SSE4_1 (1 << 19) +#define bit_SSE4_2 (1 << 20) +#define bit_MOVBE (1 << 22) +#define bit_POPCNT (1 << 23) +#define bit_AES (1 << 25) +#define bit_XSAVE (1 << 26) +#define bit_OSXSAVE (1 << 27) +#define bit_AVX (1 << 28) +#define bit_F16C (1 << 29) +#define bit_RDRND (1 << 30) + +/* %edx */ +#define bit_CMPXCHG8B (1 << 8) +#define bit_CMOV (1 << 15) +#define bit_MMX (1 << 23) +#define bit_FXSAVE (1 << 24) +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +/* Extended Features */ +/* %ecx */ +#define bit_LAHF_LM (1 << 0) +#define bit_ABM (1 << 5) +#define bit_SSE4a (1 << 6) +#define bit_PRFCHW (1 << 8) +#define bit_XOP (1 << 11) +#define bit_LWP (1 << 15) +#define bit_FMA4 (1 << 16) +#define bit_TBM (1 << 21) + +/* %edx */ +#define bit_MMXEXT (1 << 22) +#define bit_LM (1 << 29) +#define bit_3DNOWP (1 << 30) +#define bit_3DNOW (1 << 31) + +/* Extended Features (%eax == 7) */ +#define bit_FSGSBASE (1 << 0) +#define bit_BMI (1 << 3) +#define bit_HLE (1 << 4) +#define bit_AVX2 (1 << 5) +#define bit_BMI2 (1 << 8) +#define bit_RTM (1 << 11) +#define bit_AVX512F (1 << 16) +#define bit_MPX (1 << 14) +#define bit_RDSEED (1 << 18) +#define bit_ADX (1 << 19) +#define bit_AVX512PF (1 << 26) +#define bit_AVX512ER (1 << 27) +#define bit_AVX512CD (1 << 28) +#define bit_SHA (1 << 29) + +/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */ +#define bit_XSAVEOPT (1 << 0) + +/* Signatures for different CPU implementations as returned in uses + of cpuid with level 0. */ +#define signature_AMD_ebx 0x68747541 +#define signature_AMD_ecx 0x444d4163 +#define signature_AMD_edx 0x69746e65 + +#define signature_CENTAUR_ebx 0x746e6543 +#define signature_CENTAUR_ecx 0x736c7561 +#define signature_CENTAUR_edx 0x48727561 + +#define signature_CYRIX_ebx 0x69727943 +#define signature_CYRIX_ecx 0x64616574 +#define signature_CYRIX_edx 0x736e4978 + +#define signature_INTEL_ebx 0x756e6547 +#define signature_INTEL_ecx 0x6c65746e +#define signature_INTEL_edx 0x49656e69 + +#define signature_TM1_ebx 0x6e617254 +#define signature_TM1_ecx 0x55504361 +#define signature_TM1_edx 0x74656d73 + +#define signature_TM2_ebx 0x756e6547 +#define signature_TM2_ecx 0x3638784d +#define signature_TM2_edx 0x54656e69 + +#define signature_NSC_ebx 0x646f6547 +#define signature_NSC_ecx 0x43534e20 +#define signature_NSC_edx 0x79622065 + +#define signature_NEXGEN_ebx 0x4778654e +#define signature_NEXGEN_ecx 0x6e657669 +#define signature_NEXGEN_edx 0x72446e65 + +#define signature_RISE_ebx 0x65736952 +#define signature_RISE_ecx 0x65736952 +#define signature_RISE_edx 0x65736952 + +#define signature_SIS_ebx 0x20536953 +#define signature_SIS_ecx 0x20536953 +#define signature_SIS_edx 0x20536953 + +#define signature_UMC_ebx 0x20434d55 +#define signature_UMC_ecx 0x20434d55 +#define signature_UMC_edx 0x20434d55 + +#define signature_VIA_ebx 0x20414956 +#define signature_VIA_ecx 0x20414956 +#define signature_VIA_edx 0x20414956 + +#define signature_VORTEX_ebx 0x74726f56 +#define signature_VORTEX_ecx 0x436f5320 +#define signature_VORTEX_edx 0x36387865 + +#if defined(__i386__) && defined(__PIC__) +/* %ebx may be the PIC register. */ +#if __GNUC__ >= 3 +#define __cpuid(level, a, b, c, d) \ + __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \ + "cpuid\n\t" \ + "xchg{l}\t{%%}ebx, %k1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \ + "cpuid\n\t" \ + "xchg{l}\t{%%}ebx, %k1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#else +/* Host GCCs older than 3.0 weren't supporting Intel asm syntax + nor alternatives in i386 code. */ +#define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %k1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %k1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %k1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %k1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#endif +#elif defined(__x86_64__) && (defined(__code_model_medium__) || defined(__code_model_large__)) && defined(__PIC__) +/* %rbx may be the PIC register. */ +#define __cpuid(level, a, b, c, d) \ + __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \ + "cpuid\n\t" \ + "xchg{q}\t{%%}rbx, %q1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \ + "cpuid\n\t" \ + "xchg{q}\t{%%}rbx, %q1\n\t" \ + : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#else +#define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#endif + +/* Return highest supported input value for cpuid instruction. ext can + be either 0x0 or 0x8000000 to return highest supported value for + basic or extended cpuid information. Function returns 0 if cpuid + is not supported or whatever cpuid returns in eax register. If sig + pointer is non-null, then first four bytes of the signature + (as found in ebx register) are returned in location pointed by sig. */ + +static __inline unsigned int +__get_cpuid_max (unsigned int __ext, unsigned int *__sig) +{ + unsigned int __eax, __ebx, __ecx, __edx; + +#ifndef __x86_64__ + /* See if we can use cpuid. On AMD64 we always can. */ +#if __GNUC__ >= 3 + __asm__ ("pushf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "mov{l}\t{%0, %1|%1, %0}\n\t" + "xor{l}\t{%2, %0|%0, %2}\n\t" + "push{l}\t%0\n\t" + "popf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "popf{l|d}\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#else +/* Host GCCs older than 3.0 weren't supporting Intel asm syntax + nor alternatives in i386 code. */ + __asm__ ("pushfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "movl\t%0, %1\n\t" + "xorl\t%2, %0\n\t" + "pushl\t%0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "popfl\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#endif + + if (!((__eax ^ __ebx) & 0x00200000)) + return 0; +#endif + + /* Host supports cpuid. Return highest supported cpuid input value. */ + __cpuid (__ext, __eax, __ebx, __ecx, __edx); + + if (__sig) + *__sig = __ebx; + + return __eax; +} + +/* Return cpuid data for requested cpuid level, as found in returned + eax, ebx, ecx and edx registers. The function checks if cpuid is + supported and returns 1 for valid cpuid information or 0 for + unsupported cpuid level. All pointers are required to be non-null. */ + +static __inline int +__get_cpuid (unsigned int __level, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __ext = __level & 0x80000000; + + if (__get_cpuid_max (__ext, 0) < __level) + return 0; + + __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} diff --git a/gdb/testsuite/gdb.arch/i386-avx.c b/gdb/testsuite/gdb.arch/i386-avx.c index 791ead0..94f8052 100644 --- a/gdb/testsuite/gdb.arch/i386-avx.c +++ b/gdb/testsuite/gdb.arch/i386-avx.c @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include -#include "nat/i386-cpuid.h" +#include "nat/x86-cpuid.h" typedef struct { float f[8]; @@ -53,7 +53,7 @@ have_avx (void) { unsigned int eax, ebx, ecx, edx; - if (!i386_cpuid (1, &eax, &ebx, &ecx, &edx)) + if (!x86_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; if ((ecx & (bit_AVX | bit_OSXSAVE)) == (bit_AVX | bit_OSXSAVE)) diff --git a/gdb/testsuite/gdb.arch/i386-avx512.c b/gdb/testsuite/gdb.arch/i386-avx512.c index cb08536..77fc347 100644 --- a/gdb/testsuite/gdb.arch/i386-avx512.c +++ b/gdb/testsuite/gdb.arch/i386-avx512.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "nat/i386-cpuid.h" +#include "nat/x86-cpuid.h" typedef struct { diff --git a/gdb/testsuite/gdb.arch/i386-mpx.c b/gdb/testsuite/gdb.arch/i386-mpx.c index 4c9fa33..8e5096d 100644 --- a/gdb/testsuite/gdb.arch/i386-mpx.c +++ b/gdb/testsuite/gdb.arch/i386-mpx.c @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include -#include "nat/i386-cpuid.h" +#include "nat/x86-cpuid.h" #ifndef NOINLINE #define NOINLINE __attribute__ ((noinline)) diff --git a/gdb/testsuite/gdb.arch/i386-sse.c b/gdb/testsuite/gdb.arch/i386-sse.c index f079980..e7360ca 100644 --- a/gdb/testsuite/gdb.arch/i386-sse.c +++ b/gdb/testsuite/gdb.arch/i386-sse.c @@ -18,7 +18,7 @@ along with this program. If not, see . */ #include -#include "nat/i386-cpuid.h" +#include "nat/x86-cpuid.h" typedef struct { float f[4]; @@ -53,7 +53,7 @@ have_sse (void) { int edx; - if (!i386_cpuid (1, NULL, NULL, NULL, &edx)) + if (!x86_cpuid (1, NULL, NULL, NULL, &edx)) return 0; if (edx & bit_SSE) diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 73665e5..6f24e9c 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -63,7 +63,7 @@ #include "windows-tdep.h" #include "windows-nat.h" -#include "i386-nat.h" +#include "x86-nat.h" #include "complaints.h" #include "inf-child.h" @@ -1910,7 +1910,7 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty) gdb_flush (gdb_stdout); } - i386_cleanup_dregs (); + x86_cleanup_dregs (); inferior_ptid = null_ptid; detach_inferior (current_event.dwProcessId); @@ -2361,7 +2361,7 @@ static void windows_mourn_inferior (struct target_ops *ops) { (void) windows_continue (DBG_CONTINUE, -1, 0); - i386_cleanup_dregs(); + x86_cleanup_dregs(); if (open_process_used) { CHECK (CloseHandle (current_process_handle)); @@ -2593,16 +2593,16 @@ _initialize_windows_nat (void) t = windows_target (); - i386_use_watchpoints (t); + x86_use_watchpoints (t); - i386_dr_low.set_control = cygwin_set_dr7; - i386_dr_low.set_addr = cygwin_set_dr; - i386_dr_low.get_addr = cygwin_get_dr; - i386_dr_low.get_status = cygwin_get_dr6; - i386_dr_low.get_control = cygwin_get_dr7; + x86_dr_low.set_control = cygwin_set_dr7; + x86_dr_low.set_addr = cygwin_set_dr; + x86_dr_low.get_addr = cygwin_get_dr; + x86_dr_low.get_status = cygwin_get_dr6; + x86_dr_low.get_control = cygwin_get_dr7; - /* i386_dr_low.debug_register_length field is set by - calling i386_set_debug_register_length function + /* x86_dr_low.debug_register_length field is set by + calling x86_set_debug_register_length function in processor windows specific native file. */ add_target (t); diff --git a/gdb/x86-linux-nat.c b/gdb/x86-linux-nat.c index 7527370..5340dfe 100644 --- a/gdb/x86-linux-nat.c +++ b/gdb/x86-linux-nat.c @@ -25,7 +25,7 @@ #include #include -#include "i386-nat.h" +#include "x86-nat.h" #include "linux-nat.h" #ifndef __x86_64__ #include "i386-linux-nat.h" @@ -35,7 +35,7 @@ #ifdef __x86_64__ #include "amd64-linux-tdep.h" #endif -#include "i386-xstate.h" +#include "x86-xstate.h" #include "nat/linux-btrace.h" /* Per-thread arch-specific data we want to keep. */ @@ -179,8 +179,8 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp) if (lwp->arch_private->debug_registers_changed) { - struct i386_debug_reg_state *state - = i386_debug_reg_state (ptid_get_pid (lwp->ptid)); + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (lwp->ptid)); int i; /* On Linux kernel before 2.6.33 commit @@ -202,7 +202,7 @@ x86_linux_prepare_to_resume (struct lwp_info *lwp) /* If we're setting a watchpoint, any change the inferior had done itself to the debug registers needs to be - discarded, otherwise, i386_stopped_data_address can get + discarded, otherwise, x86_stopped_data_address can get confused. */ clear_status = 1; } @@ -236,8 +236,8 @@ static void x86_linux_new_fork (struct lwp_info *parent, pid_t child_pid) { pid_t parent_pid; - struct i386_debug_reg_state *parent_state; - struct i386_debug_reg_state *child_state; + struct x86_debug_reg_state *parent_state; + struct x86_debug_reg_state *child_state; /* NULL means no watchpoint has ever been set in the parent. In that case, there's nothing to do. */ @@ -259,8 +259,8 @@ x86_linux_new_fork (struct lwp_info *parent, pid_t child_pid) this compatible with older Linux kernels too. */ parent_pid = ptid_get_pid (parent->ptid); - parent_state = i386_debug_reg_state (parent_pid); - child_state = i386_debug_reg_state (child_pid); + parent_state = x86_debug_reg_state (parent_pid); + child_state = x86_debug_reg_state (child_pid); *child_state = *parent_state; } @@ -271,7 +271,7 @@ static void (*super_post_startup_inferior) (struct target_ops *self, static void x86_linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid) { - i386_cleanup_dregs (); + x86_cleanup_dregs (); super_post_startup_inferior (self, ptid); } @@ -347,7 +347,7 @@ x86_linux_read_description (struct target_ops *ops) if (have_ptrace_getregset == -1) { - uint64_t xstateregs[(I386_XSTATE_SSE_SIZE / sizeof (uint64_t))]; + uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))]; struct iovec iov; iov.iov_base = xstateregs; @@ -372,7 +372,7 @@ x86_linux_read_description (struct target_ops *ops) zero so that the "no-features" descriptions are returned by the switches below. */ if (have_ptrace_getregset) - xcr0_features_bits = xcr0 & I386_XSTATE_ALL_MASK; + xcr0_features_bits = xcr0 & X86_XSTATE_ALL_MASK; else xcr0_features_bits = 0; @@ -381,18 +381,18 @@ x86_linux_read_description (struct target_ops *ops) #ifdef __x86_64__ switch (xcr0_features_bits) { - case I386_XSTATE_MPX_AVX512_MASK: - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_MPX_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: if (is_x32) return tdesc_x32_avx512_linux; else return tdesc_amd64_avx512_linux; - case I386_XSTATE_MPX_MASK: + case X86_XSTATE_MPX_MASK: if (is_x32) return tdesc_x32_avx_linux; /* No MPX on x32 using AVX. */ else return tdesc_amd64_mpx_linux; - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_AVX_MASK: if (is_x32) return tdesc_x32_avx_linux; else @@ -409,12 +409,12 @@ x86_linux_read_description (struct target_ops *ops) { switch (xcr0_features_bits) { - case I386_XSTATE_MPX_AVX512_MASK: - case I386_XSTATE_AVX512_MASK: + case X86_XSTATE_MPX_AVX512_MASK: + case X86_XSTATE_AVX512_MASK: return tdesc_i386_avx512_linux; - case I386_XSTATE_MPX_MASK: + case X86_XSTATE_MPX_MASK: return tdesc_i386_mpx_linux; - case I386_XSTATE_AVX_MASK: + case X86_XSTATE_AVX_MASK: return tdesc_i386_avx_linux; default: return tdesc_i386_linux; @@ -530,13 +530,13 @@ x86_linux_create_target (void) struct target_ops *t = linux_target (); /* Initialize the debug register function vectors. */ - i386_use_watchpoints (t); - i386_dr_low.set_control = x86_linux_dr_set_control; - i386_dr_low.set_addr = x86_linux_dr_set_addr; - i386_dr_low.get_addr = x86_linux_dr_get_addr; - i386_dr_low.get_status = x86_linux_dr_get_status; - i386_dr_low.get_control = x86_linux_dr_get_control; - i386_set_debug_register_length (sizeof (void *)); + x86_use_watchpoints (t); + x86_dr_low.set_control = x86_linux_dr_set_control; + x86_dr_low.set_addr = x86_linux_dr_set_addr; + x86_dr_low.get_addr = x86_linux_dr_get_addr; + x86_dr_low.get_status = x86_linux_dr_get_status; + x86_dr_low.get_control = x86_linux_dr_get_control; + x86_set_debug_register_length (sizeof (void *)); /* Override the GNU/Linux inferior startup hook. */ super_post_startup_inferior = t->to_post_startup_inferior; @@ -563,6 +563,6 @@ x86_linux_add_target (struct target_ops *t) linux_nat_add_target (t); linux_nat_set_new_thread (t, x86_linux_new_thread); linux_nat_set_new_fork (t, x86_linux_new_fork); - linux_nat_set_forget_process (t, i386_forget_process); + linux_nat_set_forget_process (t, x86_forget_process); linux_nat_set_prepare_to_resume (t, x86_linux_prepare_to_resume); } diff --git a/gdb/x86-nat.c b/gdb/x86-nat.c new file mode 100644 index 0000000..a016e60 --- /dev/null +++ b/gdb/x86-nat.c @@ -0,0 +1,313 @@ +/* Native-dependent code for x86 (i386 and x86-64). + + Copyright (C) 2001-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "x86-nat.h" +#include "gdbcmd.h" +#include "inferior.h" + +/* Support for hardware watchpoints and breakpoints using the x86 + debug registers. + + This provides several functions for inserting and removing + hardware-assisted breakpoints and watchpoints, testing if one or + more of the watchpoints triggered and at what address, checking + whether a given region can be watched, etc. + + The functions below implement debug registers sharing by reference + counts, and allow to watch regions up to 16 bytes long. */ + +/* Low-level function vector. */ +struct x86_dr_low_type x86_dr_low; + +/* Per-process data. We don't bind this to a per-inferior registry + because of targets like x86 GNU/Linux that need to keep track of + processes that aren't bound to any inferior (e.g., fork children, + checkpoints). */ + +struct x86_process_info +{ + /* Linked list. */ + struct x86_process_info *next; + + /* The process identifier. */ + pid_t pid; + + /* Copy of x86 hardware debug registers. */ + struct x86_debug_reg_state state; +}; + +static struct x86_process_info *x86_process_list = NULL; + +/* Find process data for process PID. */ + +static struct x86_process_info * +x86_find_process_pid (pid_t pid) +{ + struct x86_process_info *proc; + + for (proc = x86_process_list; proc; proc = proc->next) + if (proc->pid == pid) + return proc; + + return NULL; +} + +/* Add process data for process PID. Returns newly allocated info + object. */ + +static struct x86_process_info * +x86_add_process (pid_t pid) +{ + struct x86_process_info *proc; + + proc = xcalloc (1, sizeof (*proc)); + proc->pid = pid; + + proc->next = x86_process_list; + x86_process_list = proc; + + return proc; +} + +/* Get data specific info for process PID, creating it if necessary. + Never returns NULL. */ + +static struct x86_process_info * +x86_process_info_get (pid_t pid) +{ + struct x86_process_info *proc; + + proc = x86_find_process_pid (pid); + if (proc == NULL) + proc = x86_add_process (pid); + + return proc; +} + +/* Get debug registers state for process PID. */ + +struct x86_debug_reg_state * +x86_debug_reg_state (pid_t pid) +{ + return &x86_process_info_get (pid)->state; +} + +/* See declaration in i386-nat.h. */ + +void +x86_forget_process (pid_t pid) +{ + struct x86_process_info *proc, **proc_link; + + proc = x86_process_list; + proc_link = &x86_process_list; + + while (proc != NULL) + { + if (proc->pid == pid) + { + *proc_link = proc->next; + + xfree (proc); + return; + } + + proc_link = &proc->next; + proc = *proc_link; + } +} + +/* Clear the reference counts and forget everything we knew about the + debug registers. */ + +void +x86_cleanup_dregs (void) +{ + /* Starting from scratch has the same effect. */ + x86_forget_process (ptid_get_pid (inferior_ptid)); +} + +/* Insert a watchpoint to watch a memory region which starts at + address ADDR and whose length is LEN bytes. Watch memory accesses + of the type TYPE. Return 0 on success, -1 on failure. */ + +static int +x86_insert_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len, int type, + struct expression *cond) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_insert_watchpoint (state, type, addr, len); +} + +/* Remove a watchpoint that watched the memory region which starts at + address ADDR, whose length is LEN bytes, and for accesses of the + type TYPE. Return 0 on success, -1 on failure. */ +static int +x86_remove_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len, int type, + struct expression *cond) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_remove_watchpoint (state, type, addr, len); +} + +/* Return non-zero if we can watch a memory region that starts at + address ADDR and whose length is LEN bytes. */ + +static int +x86_region_ok_for_watchpoint (struct target_ops *self, + CORE_ADDR addr, int len) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_region_ok_for_watchpoint (state, addr, len); +} + +/* If the inferior has some break/watchpoint that triggered, set the + address associated with that break/watchpoint and return non-zero. + Otherwise, return zero. */ + +static int +x86_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_stopped_data_address (state, addr_p); +} + +/* Return non-zero if the inferior has some watchpoint that triggered. + Otherwise return zero. */ + +static int +x86_stopped_by_watchpoint (struct target_ops *ops) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_stopped_by_watchpoint (state); +} + +/* Insert a hardware-assisted breakpoint at BP_TGT->placed_address. + Return 0 on success, EBUSY on failure. */ + +static int +x86_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_insert_watchpoint (state, hw_execute, + bp_tgt->placed_address, 1) ? EBUSY : 0; +} + +/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address. + Return 0 on success, -1 on failure. */ + +static int +x86_remove_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) +{ + struct x86_debug_reg_state *state + = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); + + return x86_dr_remove_watchpoint (state, hw_execute, + bp_tgt->placed_address, 1); +} + +/* Returns the number of hardware watchpoints of type TYPE that we can + set. Value is positive if we can set CNT watchpoints, zero if + setting watchpoints of type TYPE is not supported, and negative if + CNT is more than the maximum number of watchpoints of type TYPE + that we can support. TYPE is one of bp_hardware_watchpoint, + bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_breakpoint. + CNT is the number of such watchpoints used so far (including this + one). OTHERTYPE is non-zero if other types of watchpoints are + currently enabled. + + We always return 1 here because we don't have enough information + about possible overlap of addresses that they want to watch. As an + extreme example, consider the case where all the watchpoints watch + the same address and the same region length: then we can handle a + virtually unlimited number of watchpoints, due to debug register + sharing implemented via reference counts in i386-nat.c. */ + +static int +x86_can_use_hw_breakpoint (struct target_ops *self, + int type, int cnt, int othertype) +{ + return 1; +} + +static void +add_show_debug_regs_command (void) +{ + /* A maintenance command to enable printing the internal DRi mirror + variables. */ + add_setshow_boolean_cmd ("show-debug-regs", class_maintenance, + &show_debug_regs, _("\ +Set whether to show variables that mirror the x86 debug registers."), _("\ +Show whether to show variables that mirror the x86 debug registers."), _("\ +Use \"on\" to enable, \"off\" to disable.\n\ +If enabled, the debug registers values are shown when GDB inserts\n\ +or removes a hardware breakpoint or watchpoint, and when the inferior\n\ +triggers a breakpoint or watchpoint."), + NULL, + NULL, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); +} + +/* There are only two global functions left. */ + +void +x86_use_watchpoints (struct target_ops *t) +{ + /* After a watchpoint trap, the PC points to the instruction after the + one that caused the trap. Therefore we don't need to step over it. + But we do need to reset the status register to avoid another trap. */ + t->to_have_continuable_watchpoint = 1; + + t->to_can_use_hw_breakpoint = x86_can_use_hw_breakpoint; + t->to_region_ok_for_hw_watchpoint = x86_region_ok_for_watchpoint; + t->to_stopped_by_watchpoint = x86_stopped_by_watchpoint; + t->to_stopped_data_address = x86_stopped_data_address; + t->to_insert_watchpoint = x86_insert_watchpoint; + t->to_remove_watchpoint = x86_remove_watchpoint; + t->to_insert_hw_breakpoint = x86_insert_hw_breakpoint; + t->to_remove_hw_breakpoint = x86_remove_hw_breakpoint; +} + +void +x86_set_debug_register_length (int len) +{ + /* This function should be called only once for each native target. */ + gdb_assert (x86_dr_low.debug_register_length == 0); + gdb_assert (len == 4 || len == 8); + x86_dr_low.debug_register_length = len; + add_show_debug_regs_command (); +} diff --git a/gdb/x86-nat.h b/gdb/x86-nat.h new file mode 100644 index 0000000..df5e9f2 --- /dev/null +++ b/gdb/x86-nat.h @@ -0,0 +1,57 @@ +/* Native-dependent code for x86 (i386 and x86-64). + + Low level functions to implement Oeprating System specific + code to manipulate x86 debug registers. + + Copyright (C) 2009-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifndef X86_NAT_H +#define X86_NAT_H 1 + +#include "nat/x86-dregs.h" + +/* Hardware-assisted breakpoints and watchpoints. */ + +/* Add watchpoint methods to the provided target_ops. + Targets using x86 family debug registers for watchpoints should call + this. */ +struct target_ops; +extern void x86_use_watchpoints (struct target_ops *); + +/* Use this function to set x86_dr_low debug_register_length field + rather than setting it directly to check that the length is only + set once. It also enables the 'maint set/show show-debug-regs' + command. */ + +extern void x86_set_debug_register_length (int len); + +/* Use this function to reset the x86-nat.c debug register state. */ + +extern void x86_cleanup_dregs (void); + +/* Return a pointer to the local mirror of the debug registers of + process PID. */ + +extern struct x86_debug_reg_state *x86_debug_reg_state (pid_t pid); + +/* Called whenever GDB is no longer debugging process PID. It deletes + data structures that keep track of debug register state. */ + +extern void x86_forget_process (pid_t pid); + +#endif /* X86_NAT_H */