[Lldb-commits] [lldb] r368759 - Initial support for native debugging of x86/x64 Windows processes

Aaron Smith via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 13 15:18:01 PDT 2019


Author: asmith
Date: Tue Aug 13 15:18:01 2019
New Revision: 368759

URL: http://llvm.org/viewvc/llvm-project?rev=368759&view=rev
Log:
Initial support for native debugging of x86/x64 Windows processes

Summary: Thanks to Hui Huang and the reviewers for all the help with this patch.

Reviewers: labath, Hui, jfb, clayborg, amccarth

Reviewed By: labath

Subscribers: amccarth, compnerd, dexonsmith, mgorny, jfb, teemperor, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D63165

Added:
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.h
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
Modified:
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp
    lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/Windows/Common/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
    lldb/trunk/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
    lldb/trunk/third_party/Python/module/unittest2/unittest2/case.py
    lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp
    lldb/trunk/unittests/tools/lldb-server/tests/TestBase.h
    lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/register-reading/main.cpp Tue Aug 13 15:18:01 2019
@@ -1,10 +1,10 @@
 #include <cstdint>
 
-struct alignas(16) xmm_t {
-  uint64_t a, b;
-};
-
 int main() {
+#if defined(__x86_64__)
+  struct alignas(16) xmm_t {
+    uint64_t a, b;
+  };
   uint64_t r8 = 0x0102030405060708;
   uint64_t r9 = 0x1112131415161718;
   uint64_t r10 = 0x2122232425262728;
@@ -49,6 +49,6 @@ int main() {
                : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
                  "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
                  "%xmm14", "%xmm15");
-
+#endif
   return 0;
 }

Modified: lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt Tue Aug 13 15:18:01 2019
@@ -43,6 +43,8 @@ add_lldb_library(lldbPluginProcessUtilit
   RegisterContextPOSIX_s390x.cpp
   RegisterContextPOSIX_x86.cpp
   RegisterContextThreadMemory.cpp
+  RegisterContextWindows_i386.cpp
+  RegisterContextWindows_x86_64.cpp
   RegisterInfoPOSIX_arm.cpp
   RegisterInfoPOSIX_arm64.cpp
   RegisterInfoPOSIX_ppc64le.cpp

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,89 @@
+//===-- RegisterContextWindows_i386.cpp -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextWindows_i386.h"
+#include "RegisterContext_x86.h"
+#include "lldb-x86-register-enums.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace {
+// Declare our g_register_infos structure.
+typedef struct _GPR {
+  uint32_t eax;
+  uint32_t ebx;
+  uint32_t ecx;
+  uint32_t edx;
+  uint32_t edi;
+  uint32_t esi;
+  uint32_t ebp;
+  uint32_t esp;
+  uint32_t eip;
+  uint32_t eflags;
+  uint32_t cs;
+  uint32_t fs;
+  uint32_t gs;
+  uint32_t ss;
+  uint32_t ds;
+  uint32_t es;
+} GPR;
+
+#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
+
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)                       \
+  {                                                                            \
+#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint,  \
+        eFormatHex,                                                            \
+        {kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, nullptr, nullptr,    \
+         nullptr, 0                                                            \
+  }
+
+// clang-format off
+static RegisterInfo g_register_infos_i386[] = {
+// General purpose registers     EH_Frame              DWARF                 Generic                     Process Plugin
+//  ===========================  ==================    ================      =========================   ====================
+    DEFINE_GPR(eax,   nullptr,   ehframe_eax_i386,     dwarf_eax_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ebx,   nullptr,   ehframe_ebx_i386,     dwarf_ebx_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ecx,   nullptr,   ehframe_ecx_i386,     dwarf_ecx_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(edx,   nullptr,   ehframe_edx_i386,     dwarf_edx_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(edi,   nullptr,   ehframe_edi_i386,     dwarf_edi_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(esi,   nullptr,   ehframe_esi_i386,     dwarf_esi_i386,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ebp,   "fp",      ehframe_ebp_i386,     dwarf_ebp_i386,       LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(esp,   "sp",      ehframe_esp_i386,     dwarf_esp_i386,       LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(eip,   "pc",      ehframe_eip_i386,     dwarf_eip_i386,       LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(eflags, "flags",  ehframe_eflags_i386,  dwarf_eflags_i386,    LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM),
+    DEFINE_GPR(cs,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_cs_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(fs,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_fs_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(gs,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_gs_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ss,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_ss_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ds,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_ds_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(es,     nullptr,  LLDB_INVALID_REGNUM,  dwarf_es_i386,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+};
+// clang-format on
+} // namespace
+
+RegisterContextWindows_i386::RegisterContextWindows_i386(
+    const ArchSpec &target_arch)
+    : lldb_private::RegisterInfoInterface(target_arch) {
+  assert(target_arch.GetMachine() == llvm::Triple::x86);
+}
+
+const RegisterInfo *RegisterContextWindows_i386::GetRegisterInfo() const {
+  return g_register_infos_i386;
+}
+
+uint32_t RegisterContextWindows_i386::GetRegisterCount() const {
+  return llvm::array_lengthof(g_register_infos_i386);
+}
+
+uint32_t RegisterContextWindows_i386::GetUserRegisterCount() const {
+  return llvm::array_lengthof(g_register_infos_i386);
+}
+
+size_t RegisterContextWindows_i386::GetGPRSize() const { return sizeof(GPR); }

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_i386.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,27 @@
+//===-- RegisterContextWindows_i386.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextWindows_i386_H_
+#define liblldb_RegisterContextWindows_i386_H_
+
+#include "RegisterInfoInterface.h"
+
+class RegisterContextWindows_i386 : public lldb_private::RegisterInfoInterface {
+public:
+  RegisterContextWindows_i386(const lldb_private::ArchSpec &target_arch);
+
+  size_t GetGPRSize() const override;
+
+  const lldb_private::RegisterInfo *GetRegisterInfo() const override;
+
+  uint32_t GetRegisterCount() const override;
+
+  uint32_t GetUserRegisterCount() const override;
+};
+
+#endif

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,150 @@
+//===-- RegisterContextWindows_x86_64.cpp -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextWindows_x86_64.h"
+#include "RegisterContext_x86.h"
+#include "lldb-x86-register-enums.h"
+
+#include <vector>
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace {
+typedef struct _GPR {
+  uint64_t rax;
+  uint64_t rcx;
+  uint64_t rdx;
+  uint64_t rbx;
+  uint64_t rsp;
+  uint64_t rbp;
+  uint64_t rsi;
+  uint64_t rdi;
+  uint64_t r8;
+  uint64_t r9;
+  uint64_t r10;
+  uint64_t r11;
+  uint64_t r12;
+  uint64_t r13;
+  uint64_t r14;
+  uint64_t r15;
+  uint64_t rip;
+  uint64_t rflags;
+  uint16_t cs;
+  uint16_t fs;
+  uint16_t gs;
+  uint16_t ss;
+  uint16_t ds;
+  uint16_t es;
+} GPR;
+
+#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)                       \
+  {                                                                            \
+#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint,  \
+        eFormatHex,                                                            \
+        {kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, nullptr, nullptr,  \
+         nullptr, 0                                                            \
+  }
+
+typedef struct _FPReg {
+  XMMReg xmm0;
+  XMMReg xmm1;
+  XMMReg xmm2;
+  XMMReg xmm3;
+  XMMReg xmm4;
+  XMMReg xmm5;
+  XMMReg xmm6;
+  XMMReg xmm7;
+  XMMReg xmm8;
+  XMMReg xmm9;
+  XMMReg xmm10;
+  XMMReg xmm11;
+  XMMReg xmm12;
+  XMMReg xmm13;
+  XMMReg xmm14;
+  XMMReg xmm15;
+} FPReg;
+
+#define FPR_OFFSET(regname)                                                    \
+  (sizeof(GPR) + LLVM_EXTENSION offsetof(FPReg, regname))
+
+#define DEFINE_XMM(reg)                                                        \
+#reg, NULL, sizeof(((FPReg *)nullptr)->reg), FPR_OFFSET(reg), eEncodingUint, \
+      eFormatVectorOfUInt64,                                                   \
+      {dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM,        \
+       LLDB_INVALID_REGNUM, lldb_##reg##_x86_64 },                             \
+       nullptr, nullptr, nullptr, 0
+
+// clang-format off
+static RegisterInfo g_register_infos_x86_64[] = {
+// General purpose registers     EH_Frame              DWARF                 Generic                     Process Plugin
+//  ===========================  ==================    ================      =========================   ====================
+    DEFINE_GPR(rax,    nullptr,  dwarf_rax_x86_64,     dwarf_rax_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rbx,    nullptr,  dwarf_rbx_x86_64,     dwarf_rbx_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rcx,    "arg4",   dwarf_rcx_x86_64,     dwarf_rcx_x86_64,     LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rdx,    "arg3",   dwarf_rdx_x86_64,     dwarf_rdx_x86_64,     LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rdi,    "arg1",   dwarf_rdi_x86_64,     dwarf_rdi_x86_64,     LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rsi,    "arg2",   dwarf_rsi_x86_64,     dwarf_rsi_x86_64,     LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rbp,    "fp",     dwarf_rbp_x86_64,     dwarf_rbp_x86_64,     LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rsp,    "sp",     dwarf_rsp_x86_64,     dwarf_rsp_x86_64,     LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r8,     "arg5",   dwarf_r8_x86_64,      dwarf_r8_x86_64,      LLDB_REGNUM_GENERIC_ARG5,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r9,     "arg6",   dwarf_r9_x86_64,      dwarf_r9_x86_64,      LLDB_REGNUM_GENERIC_ARG6,   LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r10,    nullptr,  dwarf_r10_x86_64,     dwarf_r10_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r11,    nullptr,  dwarf_r11_x86_64,     dwarf_r11_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r12,    nullptr,  dwarf_r12_x86_64,     dwarf_r12_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r13,    nullptr,  dwarf_r13_x86_64,     dwarf_r13_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r14,    nullptr,  dwarf_r14_x86_64,     dwarf_r14_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r15,    nullptr,  dwarf_r15_x86_64,     dwarf_r15_x86_64,     LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rip,    "pc",     dwarf_rip_x86_64,     dwarf_rip_x86_64,     LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM),
+    DEFINE_GPR(rflags, "flags",  dwarf_rflags_x86_64,  dwarf_rflags_x86_64,  LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM),
+    DEFINE_GPR(cs,     nullptr,  dwarf_cs_x86_64,      dwarf_cs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(fs,     nullptr,  dwarf_fs_x86_64,      dwarf_fs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(gs,     nullptr,  dwarf_gs_x86_64,      dwarf_gs_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ss,     nullptr,  dwarf_ss_x86_64,      dwarf_ss_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(ds,     nullptr,  dwarf_ds_x86_64,      dwarf_ds_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_GPR(es,     nullptr,  dwarf_es_x86_64,      dwarf_es_x86_64,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM),
+    DEFINE_XMM(xmm0),
+    DEFINE_XMM(xmm1),
+    DEFINE_XMM(xmm2),
+    DEFINE_XMM(xmm3),
+    DEFINE_XMM(xmm4),
+    DEFINE_XMM(xmm5),
+    DEFINE_XMM(xmm6),
+    DEFINE_XMM(xmm7),
+    DEFINE_XMM(xmm8),
+    DEFINE_XMM(xmm9),
+    DEFINE_XMM(xmm10),
+    DEFINE_XMM(xmm11),
+    DEFINE_XMM(xmm12),
+    DEFINE_XMM(xmm13),
+    DEFINE_XMM(xmm14),
+    DEFINE_XMM(xmm15)
+};
+// clang-format on
+} // namespace
+
+RegisterContextWindows_x86_64::RegisterContextWindows_x86_64(
+    const ArchSpec &target_arch)
+    : lldb_private::RegisterInfoInterface(target_arch) {
+  assert(target_arch.GetMachine() == llvm::Triple::x86_64);
+}
+
+const RegisterInfo *RegisterContextWindows_x86_64::GetRegisterInfo() const {
+  return g_register_infos_x86_64;
+}
+
+uint32_t RegisterContextWindows_x86_64::GetRegisterCount() const {
+  return llvm::array_lengthof(g_register_infos_x86_64);
+}
+
+uint32_t RegisterContextWindows_x86_64::GetUserRegisterCount() const {
+  return llvm::array_lengthof(g_register_infos_x86_64);
+}
+
+size_t RegisterContextWindows_x86_64::GetGPRSize() const { return sizeof(GPR); }

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,28 @@
+//===-- RegisterContextWindows_x86_64.h --- ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextWindows_x86_64_H_
+#define liblldb_RegisterContextWindows_x86_64_H_
+
+#include "RegisterInfoInterface.h"
+
+class RegisterContextWindows_x86_64
+    : public lldb_private::RegisterInfoInterface {
+public:
+  RegisterContextWindows_x86_64(const lldb_private::ArchSpec &target_arch);
+
+  size_t GetGPRSize() const override;
+
+  const lldb_private::RegisterInfo *GetRegisterInfo() const override;
+
+  uint32_t GetRegisterCount() const override;
+
+  uint32_t GetUserRegisterCount() const override;
+};
+
+#endif

Modified: lldb/trunk/source/Plugins/Process/Windows/Common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/CMakeLists.txt?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/CMakeLists.txt Tue Aug 13 15:18:01 2019
@@ -2,6 +2,12 @@
 add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
   DebuggerThread.cpp
   LocalDebugDelegate.cpp
+  NativeProcessWindows.cpp
+  NativeRegisterContextWindows.cpp
+  NativeRegisterContextWindows_i386.cpp
+  NativeRegisterContextWindows_WoW64.cpp
+  NativeRegisterContextWindows_x86_64.cpp
+  NativeThreadWindows.cpp
   ProcessDebugger.cpp
   ProcessWindows.cpp
   ProcessWindowsLog.cpp

Modified: lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp Tue Aug 13 15:18:01 2019
@@ -29,6 +29,10 @@
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/raw_ostream.h"
 
+#ifndef STATUS_WX86_BREAKPOINT
+#define STATUS_WX86_BREAKPOINT 0x4000001FL // For WOW64 
+#endif
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -350,7 +354,8 @@ DebuggerThread::HandleExceptionEvent(con
     // we use simply to wake up the DebuggerThread so that we can close out the
     // debug loop.
     if (m_pid_to_detach != 0 &&
-        info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) {
+        (info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT ||
+         info.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) {
       LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}",
                m_pid_to_detach.load());
       ::DebugActiveProcessStop(m_pid_to_detach);

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,573 @@
+//===-- NativeProcessWindows.cpp --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/windows/windows.h"
+#include <psapi.h>
+
+#include "NativeProcessWindows.h"
+#include "NativeThreadWindows.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostNativeProcessBase.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Host/windows/AutoHandle.h"
+#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/State.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "DebuggerThread.h"
+#include "ExceptionRecord.h"
+#include "ProcessWindowsLog.h"
+
+#include <tlhelp32.h>
+
+#pragma warning(disable : 4005)
+#include "winternl.h"
+#include <ntstatus.h>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+namespace lldb_private {
+
+NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
+                                           NativeDelegate &delegate,
+                                           llvm::Error &E)
+    : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,
+                            launch_info.GetPTY().ReleaseMasterFileDescriptor(),
+                            delegate),
+      ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {
+  ErrorAsOutParameter EOut(&E);
+  DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
+  E = LaunchProcess(launch_info, delegate_sp).ToError();
+  if (E)
+    return;
+
+  SetID(GetDebuggedProcessId());
+}
+
+NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
+                                           NativeDelegate &delegate,
+                                           llvm::Error &E)
+    : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger() {
+  ErrorAsOutParameter EOut(&E);
+  DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
+  ProcessAttachInfo attach_info;
+  attach_info.SetProcessID(pid);
+  E = AttachProcess(pid, attach_info, delegate_sp).ToError();
+  if (E)
+    return;
+
+  SetID(GetDebuggedProcessId());
+
+  ProcessInstanceInfo info;
+  if (!Host::GetProcessInfo(pid, info)) {
+    E = createStringError(inconvertibleErrorCode(),
+                          "Cannot get process information");
+    return;
+  }
+  m_arch = info.GetArchitecture();
+}
+
+Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
+  Status error;
+  llvm::sys::ScopedLock lock(m_mutex);
+
+  StateType state = GetState();
+  if (state == eStateStopped || state == eStateCrashed) {
+    LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
+             GetDebuggedProcessId(), state);
+    LLDB_LOG(log, "resuming {0} threads.", m_threads.size());
+
+    bool failed = false;
+    for (uint32_t i = 0; i < m_threads.size(); ++i) {
+      auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());
+      const ResumeAction *const action =
+          resume_actions.GetActionForThread(thread->GetID(), true);
+      if (action == nullptr)
+        continue;
+
+      switch (action->state) {
+      case eStateRunning:
+      case eStateStepping: {
+        Status result = thread->DoResume(action->state);
+        if (result.Fail()) {
+          failed = true;
+          LLDB_LOG(log,
+                   "Trying to resume thread at index {0}, but failed with "
+                   "error {1}.",
+                   i, result);
+        }
+        break;
+      }
+      case eStateSuspended:
+      case eStateStopped:
+        llvm_unreachable("Unexpected state");
+
+      default:
+        return Status(
+            "NativeProcessWindows::%s (): unexpected state %s specified "
+            "for pid %" PRIu64 ", tid %" PRIu64,
+            __FUNCTION__, StateAsCString(action->state), GetID(),
+            thread->GetID());
+      }
+    }
+
+    if (failed) {
+      error.SetErrorString("NativeProcessWindows::DoResume failed");
+    } else {
+      SetState(eStateRunning);
+    }
+
+    // Resume the debug loop.
+    ExceptionRecordSP active_exception =
+        m_session_data->m_debugger->GetActiveException().lock();
+    if (active_exception) {
+      // Resume the process and continue processing debug events.  Mask the
+      // exception so that from the process's view, there is no indication that
+      // anything happened.
+      m_session_data->m_debugger->ContinueAsyncException(
+          ExceptionResult::MaskException);
+    }
+  } else {
+    LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
+             GetDebuggedProcessId(), GetState());
+  }
+
+  return error;
+}
+
+NativeThreadWindows *
+NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {
+  return static_cast<NativeThreadWindows *>(
+      NativeProcessProtocol::GetThreadByID(thread_id));
+}
+
+Status NativeProcessWindows::Halt() {
+  bool caused_stop = false;
+  StateType state = GetState();
+  if (state != eStateStopped)
+    return HaltProcess(caused_stop);
+  return Status();
+}
+
+Status NativeProcessWindows::Detach() {
+  Status error;
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
+  StateType state = GetState();
+  if (state != eStateExited && state != eStateDetached) {
+    error = DetachProcess();
+    if (error.Success())
+      SetState(eStateDetached);
+    else
+      LLDB_LOG(log, "Detaching process error: {0}", error);
+  } else {
+    error.SetErrorStringWithFormat("error: process {0} in state = {1}, but "
+                                   "cannot detach it in this state.",
+                                   GetID(), state);
+    LLDB_LOG(log, "error: {0}", error);
+  }
+  return error;
+}
+
+Status NativeProcessWindows::Signal(int signo) {
+  Status error;
+  error.SetErrorString("Windows does not support sending signals to processes");
+  return error;
+}
+
+Status NativeProcessWindows::Interrupt() { return Halt(); }
+
+Status NativeProcessWindows::Kill() {
+  StateType state = GetState();
+  return DestroyProcess(state);
+}
+
+Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {
+  return Status();
+}
+
+Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr,
+                                                 MemoryRegionInfo &range_info) {
+  return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info);
+}
+
+Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf,
+                                        size_t size, size_t &bytes_read) {
+  return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);
+}
+
+Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf,
+                                         size_t size, size_t &bytes_written) {
+  return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);
+}
+
+Status NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions,
+                                            lldb::addr_t &addr) {
+  return ProcessDebugger::AllocateMemory(size, permissions, addr);
+}
+
+Status NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) {
+  return ProcessDebugger::DeallocateMemory(addr);
+}
+
+lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; }
+
+bool NativeProcessWindows::IsAlive() const {
+  StateType state = GetState();
+  switch (state) {
+  case eStateCrashed:
+  case eStateDetached:
+  case eStateExited:
+  case eStateInvalid:
+  case eStateUnloaded:
+    return false;
+  default:
+    return true;
+  }
+}
+
+void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread,
+                                                  lldb::StopReason reason,
+                                                  std::string description) {
+  SetCurrentThreadID(thread.GetID());
+
+  ThreadStopInfo stop_info;
+  stop_info.reason = reason;
+
+  // No signal support on Windows but required to provide a 'valid' signum.
+  if (reason == StopReason::eStopReasonException) {
+    stop_info.details.exception.type = 0;
+    stop_info.details.exception.data_count = 0;
+  } else {
+    stop_info.details.signal.signo = SIGTRAP;
+  }
+
+  thread.SetStopReason(stop_info, description);
+}
+
+void NativeProcessWindows::StopThread(lldb::tid_t thread_id,
+                                      lldb::StopReason reason,
+                                      std::string description) {
+  NativeThreadWindows *thread = GetThreadByID(thread_id);
+  if (!thread)
+    return;
+
+  for (uint32_t i = 0; i < m_threads.size(); ++i) {
+    auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
+    Status error = t->DoStop();
+    if (error.Fail())
+      exit(1);
+  }
+  SetStopReasonForThread(*thread, reason, description);
+}
+
+size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); }
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+NativeProcessWindows::GetAuxvData() const {
+  // Not available on this target.
+  return llvm::errc::not_supported;
+}
+
+bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {
+  auto it = m_software_breakpoints.find(addr);
+  if (it == m_software_breakpoints.end())
+    return false;
+  return true;
+}
+
+Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size,
+                                           bool hardware) {
+  if (hardware)
+    return SetHardwareBreakpoint(addr, size);
+  return SetSoftwareBreakpoint(addr, size);
+}
+
+Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,
+                                              bool hardware) {
+  if (hardware)
+    return RemoveHardwareBreakpoint(addr);
+  return RemoveSoftwareBreakpoint(addr);
+}
+
+Status NativeProcessWindows::CacheLoadedModules() {
+  Status error;
+  if (!m_loaded_modules.empty())
+    return Status();
+
+  // Retrieve loaded modules by a Target/Module free implemenation.
+  AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
+  if (snapshot.IsValid()) {
+    MODULEENTRY32W me;
+    me.dwSize = sizeof(MODULEENTRY32W);
+    if (Module32FirstW(snapshot.get(), &me)) {
+      do {
+        std::string path;
+        if (!llvm::convertWideToUTF8(me.szExePath, path))
+          continue;
+
+        FileSpec file_spec(path);
+        FileSystem::Instance().Resolve(file_spec);
+        m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr;
+      } while (Module32Next(snapshot.get(), &me));
+    }
+
+    if (!m_loaded_modules.empty())
+      return Status();
+  }
+
+  error.SetError(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
+  return error;
+}
+
+Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path,
+                                                     FileSpec &file_spec) {
+  Status error = CacheLoadedModules();
+  if (error.Fail())
+    return error;
+
+  FileSpec module_file_spec(module_path);
+  FileSystem::Instance().Resolve(module_file_spec);
+  for (auto &it : m_loaded_modules) {
+    if (it.first == module_file_spec) {
+      file_spec = it.first;
+      return Status();
+    }
+  }
+  return Status("Module (%s) not found in process %" PRIu64 "!",
+                module_file_spec.GetCString(), GetID());
+}
+
+Status
+NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,
+                                         lldb::addr_t &load_addr) {
+  Status error = CacheLoadedModules();
+  if (error.Fail())
+    return error;
+
+  load_addr = LLDB_INVALID_ADDRESS;
+  FileSpec file_spec(file_name);
+  FileSystem::Instance().Resolve(file_spec);
+  for (auto &it : m_loaded_modules) {
+    if (it.first == file_spec) {
+      load_addr = it.second;
+      return Status();
+    }
+  }
+  return Status("Can't get loaded address of file (%s) in process %" PRIu64 "!",
+                file_spec.GetCString(), GetID());
+}
+
+void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
+  LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
+
+  ProcessDebugger::OnExitProcess(exit_code);
+
+  // No signal involved.  It is just an exit event.
+  WaitStatus wait_status(WaitStatus::Exit, exit_code);
+  SetExitStatus(wait_status, true);
+
+  // Notify the native delegate.
+  SetState(eStateExited, true);
+}
+
+void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
+  LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
+           GetDebuggedProcessId(), image_base);
+
+  // This is the earliest chance we can resolve the process ID and
+  // architecutre if we don't know them yet.
+  if (GetID() == LLDB_INVALID_PROCESS_ID)
+    SetID(GetDebuggedProcessId());
+
+  if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {
+    ProcessInstanceInfo process_info;
+    if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) {
+      LLDB_LOG(log, "Cannot get process information during debugger connecting "
+                    "to process");
+      return;
+    }
+    SetArchitecture(process_info.GetArchitecture());
+  }
+
+  // The very first one shall always be the main thread.
+  assert(m_threads.empty());
+  m_threads.push_back(llvm::make_unique<NativeThreadWindows>(
+      *this, m_session_data->m_debugger->GetMainThread()));
+}
+
+ExceptionResult
+NativeProcessWindows::OnDebugException(bool first_chance,
+                                       const ExceptionRecord &record) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
+  llvm::sys::ScopedLock lock(m_mutex);
+
+  // Let the debugger establish the internal status.
+  ProcessDebugger::OnDebugException(first_chance, record);
+
+  static bool initial_stop = false;
+  if (!first_chance) {
+    SetState(eStateStopped, false);
+  }
+
+  ExceptionResult result = ExceptionResult::SendToApplication;
+  switch (record.GetExceptionCode()) {
+  case STATUS_SINGLE_STEP:
+  case STATUS_WX86_SINGLE_STEP:
+    StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);
+    SetState(eStateStopped, true);
+
+    // Continue the debugger.
+    return ExceptionResult::MaskException;
+
+  case STATUS_BREAKPOINT:
+  case STATUS_WX86_BREAKPOINT:
+    if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
+      LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
+               record.GetExceptionAddress());
+
+      StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
+
+      if (NativeThreadWindows *stop_thread =
+              GetThreadByID(record.GetThreadID())) {
+        auto &register_context = stop_thread->GetRegisterContext();
+        // The current EIP is AFTER the BP opcode, which is one byte '0xCC'
+        uint64_t pc = register_context.GetPC() - 1;
+        register_context.SetPC(pc);
+      }
+
+      SetState(eStateStopped, true);
+      return ExceptionResult::MaskException;
+    }
+
+    if (!initial_stop) {
+      initial_stop = true;
+      LLDB_LOG(log,
+               "Hit loader breakpoint at address {0:x}, setting initial stop "
+               "event.",
+               record.GetExceptionAddress());
+
+      // We are required to report the reason for the first stop after
+      // launching or being attached.
+      if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID()))
+        SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint);
+
+      // Do not notify the native delegate (e.g. llgs) since at this moment
+      // the program hasn't returned from Factory::Launch() and the delegate
+      // might not have an valid native process to operate on.
+      SetState(eStateStopped, false);
+
+      // Hit the initial stop. Continue the application.
+      return ExceptionResult::BreakInDebugger;
+    }
+
+    // Fall through
+  default:
+    LLDB_LOG(log,
+             "Debugger thread reported exception {0:x} at address {1:x} "
+             "(first_chance={2})",
+             record.GetExceptionCode(), record.GetExceptionAddress(),
+             first_chance);
+
+    {
+      std::string desc;
+      llvm::raw_string_ostream desc_stream(desc);
+      desc_stream << "Exception "
+                  << llvm::format_hex(record.GetExceptionCode(), 8)
+                  << " encountered at address "
+                  << llvm::format_hex(record.GetExceptionAddress(), 8);
+      StopThread(record.GetThreadID(), StopReason::eStopReasonException,
+                 desc_stream.str().c_str());
+
+      SetState(eStateStopped, true);
+    }
+
+    // For non-breakpoints, give the application a chance to handle the
+    // exception first.
+    if (first_chance)
+      result = ExceptionResult::SendToApplication;
+    else
+      result = ExceptionResult::BreakInDebugger;
+  }
+
+  return result;
+}
+
+void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) {
+  llvm::sys::ScopedLock lock(m_mutex);
+  m_threads.push_back(
+      llvm::make_unique<NativeThreadWindows>(*this, new_thread));
+}
+
+void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,
+                                        uint32_t exit_code) {
+  llvm::sys::ScopedLock lock(m_mutex);
+  NativeThreadWindows *thread = GetThreadByID(thread_id);
+  if (!thread)
+    return;
+
+  for (auto t = m_threads.begin(); t != m_threads.end();) {
+    if ((*t)->GetID() == thread_id) {
+      t = m_threads.erase(t);
+    } else {
+      ++t;
+    }
+  }
+}
+
+void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
+                                     lldb::addr_t module_addr) {
+  // Simply invalidate the cached loaded modules.
+  if (!m_loaded_modules.empty())
+    m_loaded_modules.clear();
+}
+
+void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
+  if (!m_loaded_modules.empty())
+    m_loaded_modules.clear();
+}
+
+llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+NativeProcessWindows::Factory::Launch(
+    ProcessLaunchInfo &launch_info,
+    NativeProcessProtocol::NativeDelegate &native_delegate,
+    MainLoop &mainloop) const {
+  Error E = Error::success();
+  auto process_up = std::unique_ptr<NativeProcessWindows>(
+      new NativeProcessWindows(launch_info, native_delegate, E));
+  if (E)
+    return std::move(E);
+  return std::move(process_up);
+}
+
+llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+NativeProcessWindows::Factory::Attach(
+    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
+    MainLoop &mainloop) const {
+  Error E = Error::success();
+  // Set pty master fd invalid since it is not available.
+  auto process_up = std::unique_ptr<NativeProcessWindows>(
+      new NativeProcessWindows(pid, -1, native_delegate, E));
+  if (E)
+    return std::move(E);
+  return std::move(process_up);
+}
+} // namespace lldb_private

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeProcessWindows.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,182 @@
+//===-- NativeProcessWindows.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NativeProcessWindows_h_
+#define liblldb_NativeProcessWindows_h_
+
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/lldb-forward.h"
+
+#include "IDebugDelegate.h"
+#include "ProcessDebugger.h"
+
+namespace lldb_private {
+
+class HostProcess;
+class NativeProcessWindows;
+class NativeThreadWindows;
+class NativeDebugDelegate;
+
+typedef std::shared_ptr<NativeDebugDelegate> NativeDebugDelegateSP;
+
+//------------------------------------------------------------------
+// NativeProcessWindows
+//------------------------------------------------------------------
+class NativeProcessWindows : public NativeProcessProtocol,
+                             public ProcessDebugger {
+
+public:
+  class Factory : public NativeProcessProtocol::Factory {
+  public:
+    llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+    Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+           MainLoop &mainloop) const override;
+
+    llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+    Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
+           MainLoop &mainloop) const override;
+  };
+
+  Status Resume(const ResumeActionList &resume_actions) override;
+
+  Status Halt() override;
+
+  Status Detach() override;
+
+  Status Signal(int signo) override;
+
+  Status Interrupt() override;
+
+  Status Kill() override;
+
+  Status IgnoreSignals(llvm::ArrayRef<int> signals) override;
+
+  Status GetMemoryRegionInfo(lldb::addr_t load_addr,
+                             MemoryRegionInfo &range_info) override;
+
+  Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+                    size_t &bytes_read) override;
+
+  Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
+                     size_t &bytes_written) override;
+
+  Status AllocateMemory(size_t size, uint32_t permissions,
+                        lldb::addr_t &addr) override;
+
+  Status DeallocateMemory(lldb::addr_t addr) override;
+
+  lldb::addr_t GetSharedLibraryInfoAddress() override;
+
+  bool IsAlive() const override;
+
+  size_t UpdateThreads() override;
+
+  const ArchSpec &GetArchitecture() const override { return m_arch; }
+
+  void SetArchitecture(const ArchSpec &arch_spec) { m_arch = arch_spec; }
+
+  Status SetBreakpoint(lldb::addr_t addr, uint32_t size,
+                       bool hardware) override;
+
+  Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override;
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+  GetAuxvData() const override;
+
+  Status GetLoadedModuleFileSpec(const char *module_path,
+                                 FileSpec &file_spec) override;
+
+  Status GetFileLoadAddress(const llvm::StringRef &file_name,
+                            lldb::addr_t &load_addr) override;
+
+  // ProcessDebugger Overrides
+  void OnExitProcess(uint32_t exit_code) override;
+  void OnDebuggerConnected(lldb::addr_t image_base) override;
+  ExceptionResult OnDebugException(bool first_chance,
+                                   const ExceptionRecord &record) override;
+  void OnCreateThread(const HostThread &thread) override;
+  void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override;
+  void OnLoadDll(const ModuleSpec &module_spec,
+                 lldb::addr_t module_addr) override;
+  void OnUnloadDll(lldb::addr_t module_addr) override;
+
+protected:
+  NativeThreadWindows *GetThreadByID(lldb::tid_t thread_id);
+
+  bool FindSoftwareBreakpoint(lldb::addr_t addr);
+
+  void StopThread(lldb::tid_t thread_id, lldb::StopReason reason,
+                  std::string description = "");
+
+  void SetStopReasonForThread(NativeThreadWindows &thread,
+                              lldb::StopReason reason,
+                              std::string description = "");
+
+private:
+  ArchSpec m_arch;
+
+  NativeProcessWindows(ProcessLaunchInfo &launch_info, NativeDelegate &delegate,
+                       llvm::Error &E);
+
+  NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
+                       NativeDelegate &delegate, llvm::Error &E);
+
+  Status CacheLoadedModules();
+  std::map<lldb_private::FileSpec, lldb::addr_t> m_loaded_modules;
+};
+
+//------------------------------------------------------------------
+// NativeDebugDelegate
+//------------------------------------------------------------------
+class NativeDebugDelegate : public IDebugDelegate {
+public:
+  NativeDebugDelegate(NativeProcessWindows &process) : m_process(process) {}
+
+  void OnExitProcess(uint32_t exit_code) { m_process.OnExitProcess(exit_code); }
+
+  void OnDebuggerConnected(lldb::addr_t image_base) {
+    m_process.OnDebuggerConnected(image_base);
+  }
+
+  ExceptionResult OnDebugException(bool first_chance,
+                                   const ExceptionRecord &record) {
+    return m_process.OnDebugException(first_chance, record);
+  }
+
+  void OnCreateThread(const HostThread &thread) {
+    m_process.OnCreateThread(thread);
+  }
+
+  void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
+    m_process.OnExitThread(thread_id, exit_code);
+  }
+
+  void OnLoadDll(const lldb_private::ModuleSpec &module_spec,
+                 lldb::addr_t module_addr) {
+    m_process.OnLoadDll(module_spec, module_addr);
+  }
+
+  void OnUnloadDll(lldb::addr_t module_addr) {
+    m_process.OnUnloadDll(module_addr);
+  }
+
+  void OnDebugString(const std::string &string) {
+    m_process.OnDebugString(string);
+  }
+
+  void OnDebuggerError(const Status &error, uint32_t type) {
+    return m_process.OnDebuggerError(error, type);
+  }
+
+private:
+  NativeProcessWindows &m_process;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_NativeProcessWindows_h_

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,28 @@
+//===-- NativeRegisterContextWindows.cpp ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Log.h"
+
+#include "NativeRegisterContextWindows.h"
+#include "NativeThreadWindows.h"
+#include "ProcessWindowsLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+NativeRegisterContextWindows::NativeRegisterContextWindows(
+    NativeThreadProtocol &thread, RegisterInfoInterface *reg_info_interface_p)
+    : NativeRegisterContextRegisterInfo(thread, reg_info_interface_p) {}
+
+lldb::thread_t NativeRegisterContextWindows::GetThreadHandle() const {
+  auto wthread = static_cast<NativeThreadWindows *>(&m_thread);
+  return wthread->GetHostThread().GetNativeThread().GetSystemHandle();
+}

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,36 @@
+//===-- NativeRegisterContextWindows.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NativeRegisterContextWindows_h_
+#define liblldb_NativeRegisterContextWindows_h_
+
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+namespace lldb_private {
+
+class NativeThreadWindows;
+
+class NativeRegisterContextWindows : public NativeRegisterContextRegisterInfo {
+public:
+  NativeRegisterContextWindows::NativeRegisterContextWindows(
+      NativeThreadProtocol &native_thread,
+      RegisterInfoInterface *reg_info_interface_p);
+
+  static std::unique_ptr<NativeRegisterContextWindows>
+  CreateHostNativeRegisterContextWindows(const ArchSpec &target_arch,
+                                         NativeThreadProtocol &native_thread);
+
+protected:
+  lldb::thread_t GetThreadHandle() const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NativeRegisterContextWindows_h_

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,362 @@
+//===-- NativeRegisterContextWindows_WoW64.cpp ----- ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN64)
+
+#include "NativeRegisterContextWindows_WoW64.h"
+
+#include "NativeThreadWindows.h"
+#include "Plugins/Process/Utility/RegisterContextWindows_i386.h"
+#include "ProcessWindowsLog.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define REG_CONTEXT_SIZE sizeof(::WOW64_CONTEXT)
+
+namespace {
+static const uint32_t g_gpr_regnums_WoW64[] = {
+    lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
+    lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
+    lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
+    lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
+    LLDB_INVALID_REGNUM // Register set must be terminated with this flag.
+};
+
+static const RegisterSet g_reg_sets_WoW64[] = {
+    {"General Purpose Registers", "gpr",
+     llvm::array_lengthof(g_gpr_regnums_WoW64) - 1, g_gpr_regnums_WoW64},
+};
+enum { k_num_register_sets = 1 };
+
+static const DWORD kWoW64ContextFlags =
+    WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS;
+
+} // namespace
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+  // i686 32bit instruction set.
+  assert((target_arch.GetAddressByteSize() == 4 &&
+          HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+         "Register setting path assumes this is a 64-bit host");
+  return new RegisterContextWindows_i386(target_arch);
+}
+
+static Status GetWoW64ThreadContextHelper(lldb::thread_t thread_handle,
+                                          PWOW64_CONTEXT context_ptr) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+  memset(context_ptr, 0, sizeof(::WOW64_CONTEXT));
+  context_ptr->ContextFlags = kWoW64ContextFlags;
+  if (!::Wow64GetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} Wow64GetThreadContext failed with error {1}",
+             __FUNCTION__, error);
+    return error;
+  }
+  return Status();
+}
+
+static Status SetWoW64ThreadContextHelper(lldb::thread_t thread_handle,
+                                          PWOW64_CONTEXT context_ptr) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+  if (!::Wow64SetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} Wow64SetThreadContext failed with error {1}",
+             __FUNCTION__, error);
+    return error;
+  }
+  return Status();
+}
+
+NativeRegisterContextWindows_WoW64::NativeRegisterContextWindows_WoW64(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextWindows(native_thread,
+                                   CreateRegisterInfoInterface(target_arch)) {}
+
+bool NativeRegisterContextWindows_WoW64::IsGPR(uint32_t reg_index) const {
+  return (reg_index >= k_first_gpr_i386 && reg_index < k_first_alias_i386);
+}
+
+uint32_t NativeRegisterContextWindows_WoW64::GetRegisterSetCount() const {
+  return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextWindows_WoW64::GetRegisterSet(uint32_t set_index) const {
+  if (set_index >= k_num_register_sets)
+    return nullptr;
+  return &g_reg_sets_WoW64[set_index];
+}
+
+Status NativeRegisterContextWindows_WoW64::GPRRead(const uint32_t reg,
+                                                   RegisterValue &reg_value) {
+  ::WOW64_CONTEXT tls_context;
+  Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_eax_i386:
+    reg_value.SetUInt32(tls_context.Eax);
+    break;
+  case lldb_ebx_i386:
+    reg_value.SetUInt32(tls_context.Ebx);
+    break;
+  case lldb_ecx_i386:
+    reg_value.SetUInt32(tls_context.Ecx);
+    break;
+  case lldb_edx_i386:
+    reg_value.SetUInt32(tls_context.Edx);
+    break;
+  case lldb_edi_i386:
+    reg_value.SetUInt32(tls_context.Edi);
+    break;
+  case lldb_esi_i386:
+    reg_value.SetUInt32(tls_context.Esi);
+    break;
+  case lldb_ebp_i386:
+    reg_value.SetUInt32(tls_context.Ebp);
+    break;
+  case lldb_esp_i386:
+    reg_value.SetUInt32(tls_context.Esp);
+    break;
+  case lldb_eip_i386:
+    reg_value.SetUInt32(tls_context.Eip);
+    break;
+  case lldb_eflags_i386:
+    reg_value.SetUInt32(tls_context.EFlags);
+    break;
+  case lldb_cs_i386:
+    reg_value.SetUInt32(tls_context.SegCs);
+    break;
+  case lldb_fs_i386:
+    reg_value.SetUInt32(tls_context.SegFs);
+    break;
+  case lldb_gs_i386:
+    reg_value.SetUInt32(tls_context.SegGs);
+    break;
+  case lldb_ss_i386:
+    reg_value.SetUInt32(tls_context.SegSs);
+    break;
+  case lldb_ds_i386:
+    reg_value.SetUInt32(tls_context.SegDs);
+    break;
+  case lldb_es_i386:
+    reg_value.SetUInt32(tls_context.SegEs);
+    break;
+  }
+
+  return error;
+}
+
+Status
+NativeRegisterContextWindows_WoW64::GPRWrite(const uint32_t reg,
+                                             const RegisterValue &reg_value) {
+  ::WOW64_CONTEXT tls_context;
+  auto thread_handle = GetThreadHandle();
+  Status error = GetWoW64ThreadContextHelper(thread_handle, &tls_context);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_eax_i386:
+    tls_context.Eax = reg_value.GetAsUInt32();
+    break;
+  case lldb_ebx_i386:
+    tls_context.Ebx = reg_value.GetAsUInt32();
+    break;
+  case lldb_ecx_i386:
+    tls_context.Ecx = reg_value.GetAsUInt32();
+    break;
+  case lldb_edx_i386:
+    tls_context.Edx = reg_value.GetAsUInt32();
+    break;
+  case lldb_edi_i386:
+    tls_context.Edi = reg_value.GetAsUInt32();
+    break;
+  case lldb_esi_i386:
+    tls_context.Esi = reg_value.GetAsUInt32();
+    break;
+  case lldb_ebp_i386:
+    tls_context.Ebp = reg_value.GetAsUInt32();
+    break;
+  case lldb_esp_i386:
+    tls_context.Esp = reg_value.GetAsUInt32();
+    break;
+  case lldb_eip_i386:
+    tls_context.Eip = reg_value.GetAsUInt32();
+    break;
+  case lldb_eflags_i386:
+    tls_context.EFlags = reg_value.GetAsUInt32();
+    break;
+  case lldb_cs_i386:
+    tls_context.SegCs = reg_value.GetAsUInt32();
+    break;
+  case lldb_fs_i386:
+    tls_context.SegFs = reg_value.GetAsUInt32();
+    break;
+  case lldb_gs_i386:
+    tls_context.SegGs = reg_value.GetAsUInt32();
+    break;
+  case lldb_ss_i386:
+    tls_context.SegSs = reg_value.GetAsUInt32();
+    break;
+  case lldb_ds_i386:
+    tls_context.SegDs = reg_value.GetAsUInt32();
+    break;
+  case lldb_es_i386:
+    tls_context.SegEs = reg_value.GetAsUInt32();
+    break;
+  }
+
+  return SetWoW64ThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status
+NativeRegisterContextWindows_WoW64::ReadRegister(const RegisterInfo *reg_info,
+                                                 RegisterValue &reg_value) {
+  Status error;
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRRead(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_WoW64::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRWrite(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_WoW64::ReadAllRegisterValues(
+    lldb::DataBufferSP &data_sp) {
+  const size_t data_size = REG_CONTEXT_SIZE;
+  data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
+  ::WOW64_CONTEXT tls_context;
+  Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
+  if (error.Fail())
+    return error;
+
+  uint8_t *dst = data_sp->GetBytes();
+  ::memcpy(dst, &tls_context, data_size);
+  return error;
+}
+
+Status NativeRegisterContextWindows_WoW64::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+  const size_t data_size = REG_CONTEXT_SIZE;
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextWindows_WoW64::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != data_size) {
+    error.SetErrorStringWithFormatv(
+        "data_sp contained mismatched data size, expected {0}, actual {1}",
+        data_size, data_sp->GetByteSize());
+    return error;
+  }
+
+  ::WOW64_CONTEXT tls_context;
+  memcpy(&tls_context, data_sp->GetBytes(), data_size);
+  return SetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
+}
+
+Status NativeRegisterContextWindows_WoW64::IsWatchpointHit(uint32_t wp_index,
+                                                           bool &is_hit) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_WoW64::GetWatchpointHitIndex(
+    uint32_t &wp_index, lldb::addr_t trap_addr) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_WoW64::IsWatchpointVacant(uint32_t wp_index,
+                                                              bool &is_vacant) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_WoW64::SetHardwareWatchpointWithIndex(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+  return Status("unimplemented");
+}
+
+bool NativeRegisterContextWindows_WoW64::ClearHardwareWatchpoint(
+    uint32_t wp_index) {
+  return false;
+}
+
+Status NativeRegisterContextWindows_WoW64::ClearAllHardwareWatchpoints() {
+  return Status("unimplemented");
+}
+
+uint32_t NativeRegisterContextWindows_WoW64::SetHardwareWatchpoint(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+  return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextWindows_WoW64::GetWatchpointAddress(uint32_t wp_index) {
+  return LLDB_INVALID_ADDRESS;
+}
+
+uint32_t NativeRegisterContextWindows_WoW64::NumSupportedHardwareWatchpoints() {
+  // Not implemented
+  return 0;
+}
+
+#endif // defined(_WIN64)

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,74 @@
+//===-- NativeRegisterContextWindows_WoW64.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN64)
+#ifndef liblldb_NativeRegisterContextWindows_WoW64_h_
+#define liblldb_NativeRegisterContextWindows_WoW64_h_
+
+#include "Plugins/Process/Utility/RegisterContext_x86.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+#include "NativeRegisterContextWindows.h"
+
+namespace lldb_private {
+
+class NativeThreadWindows;
+
+class NativeRegisterContextWindows_WoW64 : public NativeRegisterContextWindows {
+public:
+  NativeRegisterContextWindows_WoW64(const ArchSpec &target_arch,
+                                     NativeThreadProtocol &native_thread);
+
+  uint32_t GetRegisterSetCount() const override;
+
+  const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+  Status ReadRegister(const RegisterInfo *reg_info,
+                      RegisterValue &reg_value) override;
+
+  Status WriteRegister(const RegisterInfo *reg_info,
+                       const RegisterValue &reg_value) override;
+
+  Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+  Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+  Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+  Status GetWatchpointHitIndex(uint32_t &wp_index,
+                               lldb::addr_t trap_addr) override;
+
+  Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+  Status ClearAllHardwareWatchpoints() override;
+
+  Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+                                        uint32_t watch_flags,
+                                        uint32_t wp_index);
+
+  uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+                                 uint32_t watch_flags) override;
+
+  lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+  uint32_t NumSupportedHardwareWatchpoints() override;
+
+protected:
+  Status GPRRead(const uint32_t reg, RegisterValue &reg_value);
+  Status GPRWrite(const uint32_t reg, const RegisterValue &reg_value);
+
+private:
+  bool IsGPR(uint32_t reg_index) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NativeRegisterContextWindows_WoW64_h_
+#endif // defined(_WIN64)

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,376 @@
+//===-- NativeRegisterContextWindows_i386.cpp -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN32) && !defined(_WIN64)
+
+#include "NativeRegisterContextWindows_i386.h"
+
+#include "NativeThreadWindows.h"
+#include "Plugins/Process/Utility/RegisterContextWindows_i386.h"
+#include "ProcessWindowsLog.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
+
+namespace {
+static const uint32_t g_gpr_regnums_i386[] = {
+    lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
+    lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
+    lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
+    lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
+    LLDB_INVALID_REGNUM // Register sets must be terminated with this flag.
+};
+
+static const RegisterSet g_reg_sets_i386[] = {
+    {"General Purpose Registers", "gpr",
+     llvm::array_lengthof(g_gpr_regnums_i386) - 1, g_gpr_regnums_i386},
+};
+
+enum { k_num_register_sets = 1 };
+
+} // namespace
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+  assert((HostInfo::GetArchitecture().GetAddressByteSize() == 4) &&
+         "Register setting path assumes this is a 32-bit host");
+  return new RegisterContextWindows_i386(target_arch);
+}
+
+static Status GetThreadContextHelper(lldb::thread_t thread_handle,
+                                     PCONTEXT context_ptr,
+                                     const DWORD control_flag) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+
+  memset(context_ptr, 0, sizeof(::CONTEXT));
+  context_ptr->ContextFlags = control_flag;
+  if (!::GetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__,
+             error);
+    return error;
+  }
+  return Status();
+}
+
+static Status SetThreadContextHelper(lldb::thread_t thread_handle,
+                                     PCONTEXT context_ptr) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+
+  if (!::SetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__,
+             error);
+    return error;
+  }
+  return Status();
+}
+
+std::unique_ptr<NativeRegisterContextWindows>
+NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+  return llvm::make_unique<NativeRegisterContextWindows_i386>(target_arch,
+                                                              native_thread);
+}
+
+NativeRegisterContextWindows_i386::NativeRegisterContextWindows_i386(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextWindows(native_thread,
+                                   CreateRegisterInfoInterface(target_arch)) {}
+
+bool NativeRegisterContextWindows_i386::IsGPR(uint32_t reg_index) const {
+  return (reg_index < k_first_alias_i386);
+}
+
+uint32_t NativeRegisterContextWindows_i386::GetRegisterSetCount() const {
+  return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextWindows_i386::GetRegisterSet(uint32_t set_index) const {
+  if (set_index >= k_num_register_sets)
+    return nullptr;
+  return &g_reg_sets_i386[set_index];
+}
+
+Status NativeRegisterContextWindows_i386::GPRRead(const uint32_t reg,
+                                                  RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
+  Status error =
+      GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_eax_i386:
+    reg_value.SetUInt32(tls_context.Eax);
+    break;
+  case lldb_ebx_i386:
+    reg_value.SetUInt32(tls_context.Ebx);
+    break;
+  case lldb_ecx_i386:
+    reg_value.SetUInt32(tls_context.Ecx);
+    break;
+  case lldb_edx_i386:
+    reg_value.SetUInt32(tls_context.Edx);
+    break;
+  case lldb_edi_i386:
+    reg_value.SetUInt32(tls_context.Edi);
+    break;
+  case lldb_esi_i386:
+    reg_value.SetUInt32(tls_context.Esi);
+    break;
+  case lldb_ebp_i386:
+    reg_value.SetUInt32(tls_context.Ebp);
+    break;
+  case lldb_esp_i386:
+    reg_value.SetUInt32(tls_context.Esp);
+    break;
+  case lldb_eip_i386:
+    reg_value.SetUInt32(tls_context.Eip);
+    break;
+  case lldb_eflags_i386:
+    reg_value.SetUInt32(tls_context.EFlags);
+    break;
+  case lldb_cs_i386:
+    reg_value.SetUInt32(tls_context.SegCs);
+    break;
+  case lldb_fs_i386:
+    reg_value.SetUInt32(tls_context.SegFs);
+    break;
+  case lldb_gs_i386:
+    reg_value.SetUInt32(tls_context.SegGs);
+    break;
+  case lldb_ss_i386:
+    reg_value.SetUInt32(tls_context.SegSs);
+    break;
+  case lldb_ds_i386:
+    reg_value.SetUInt32(tls_context.SegDs);
+    break;
+  case lldb_es_i386:
+    reg_value.SetUInt32(tls_context.SegEs);
+    break;
+  }
+
+  return error;
+}
+
+Status
+NativeRegisterContextWindows_i386::GPRWrite(const uint32_t reg,
+                                            const RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
+  auto thread_handle = GetThreadHandle();
+  Status error =
+      GetThreadContextHelper(thread_handle, &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_eax_i386:
+    tls_context.Eax = reg_value.GetAsUInt32();
+    break;
+  case lldb_ebx_i386:
+    tls_context.Ebx = reg_value.GetAsUInt32();
+    break;
+  case lldb_ecx_i386:
+    tls_context.Ecx = reg_value.GetAsUInt32();
+    break;
+  case lldb_edx_i386:
+    tls_context.Edx = reg_value.GetAsUInt32();
+    break;
+  case lldb_edi_i386:
+    tls_context.Edi = reg_value.GetAsUInt32();
+    break;
+  case lldb_esi_i386:
+    tls_context.Esi = reg_value.GetAsUInt32();
+    break;
+  case lldb_ebp_i386:
+    tls_context.Ebp = reg_value.GetAsUInt32();
+    break;
+  case lldb_esp_i386:
+    tls_context.Esp = reg_value.GetAsUInt32();
+    break;
+  case lldb_eip_i386:
+    tls_context.Eip = reg_value.GetAsUInt32();
+    break;
+  case lldb_eflags_i386:
+    tls_context.EFlags = reg_value.GetAsUInt32();
+    break;
+  case lldb_cs_i386:
+    tls_context.SegCs = reg_value.GetAsUInt32();
+    break;
+  case lldb_fs_i386:
+    tls_context.SegFs = reg_value.GetAsUInt32();
+    break;
+  case lldb_gs_i386:
+    tls_context.SegGs = reg_value.GetAsUInt32();
+    break;
+  case lldb_ss_i386:
+    tls_context.SegSs = reg_value.GetAsUInt32();
+    break;
+  case lldb_ds_i386:
+    tls_context.SegDs = reg_value.GetAsUInt32();
+    break;
+  case lldb_es_i386:
+    tls_context.SegEs = reg_value.GetAsUInt32();
+    break;
+  }
+
+  return SetThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status
+NativeRegisterContextWindows_i386::ReadRegister(const RegisterInfo *reg_info,
+                                                RegisterValue &reg_value) {
+  Status error;
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRRead(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_i386::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRRead(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_x86_64::ReadAllRegisterValues(
+    lldb::DataBufferSP &data_sp) {
+  const size_t data_size = REG_CONTEXT_SIZE;
+  data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
+  ::CONTEXT tls_context;
+  Status error =
+      GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
+  if (error.Fail())
+    return error;
+
+  uint8_t *dst = data_sp->GetBytes();
+  ::memcpy(dst, &tls_context, data_size);
+  return error;
+}
+
+Status NativeRegisterContextWindows_i386::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+  const size_t data_size = REG_CONTEXT_SIZE;
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextWindows_i386::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != data_size) {
+    error.SetErrorStringWithFormatv(
+        "data_sp contained mismatched data size, expected {0}, actual {1}",
+        data_size, data_sp->GetByteSize());
+    return error;
+  }
+
+  ::CONTEXT tls_context;
+  memcpy(&tls_context, data_sp->GetBytes(), data_size);
+  return SetThreadContextHelper(GetThreadHandle(), &tls_context);
+}
+
+Status NativeRegisterContextWindows_i386::IsWatchpointHit(uint32_t wp_index,
+                                                          bool &is_hit) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_i386::GetWatchpointHitIndex(
+    uint32_t &wp_index, lldb::addr_t trap_addr) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_i386::IsWatchpointVacant(uint32_t wp_index,
+                                                             bool &is_vacant) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_i386::SetHardwareWatchpointWithIndex(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+  return Status("unimplemented");
+}
+
+bool NativeRegisterContextWindows_i386::ClearHardwareWatchpoint(
+    uint32_t wp_index) {
+  return false;
+}
+
+Status NativeRegisterContextWindows_i386::ClearAllHardwareWatchpoints() {
+  return Status("unimplemented");
+}
+
+uint32_t NativeRegisterContextWindows_i386::SetHardwareWatchpoint(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+  return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextWindows_i386::GetWatchpointAddress(uint32_t wp_index) {
+  return LLDB_INVALID_ADDRESS;
+}
+
+uint32_t NativeRegisterContextWindows_i386::NumSupportedHardwareWatchpoints() {
+  // Not implemented
+  return 0;
+}
+
+#endif

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,74 @@
+//===-- NativeRegisterContextWindows_i386.h ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN64)
+#ifndef liblldb_NativeRegisterContextWindows_i386_h_
+#define liblldb_NativeRegisterContextWindows_i386_h_
+
+#include "Plugins/Process/Utility/RegisterContext_x86.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+#include "NativeRegisterContextWindows.h"
+
+namespace lldb_private {
+
+class NativeThreadWindows;
+
+class NativeRegisterContextWindows_i386 : public NativeRegisterContextWindows {
+public:
+  NativeRegisterContextWindows_i386(const ArchSpec &target_arch,
+                                    NativeThreadProtocol &native_thread);
+
+  uint32_t GetRegisterSetCount() const override;
+
+  const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+  Status ReadRegister(const RegisterInfo *reg_info,
+                      RegisterValue &reg_value) override;
+
+  Status WriteRegister(const RegisterInfo *reg_info,
+                       const RegisterValue &reg_value) override;
+
+  Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+  Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+  Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+  Status GetWatchpointHitIndex(uint32_t &wp_index,
+                               lldb::addr_t trap_addr) override;
+
+  Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+  Status ClearAllHardwareWatchpoints() override;
+
+  Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+                                        uint32_t watch_flags,
+                                        uint32_t wp_index);
+
+  uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+                                 uint32_t watch_flags) override;
+
+  lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+  uint32_t NumSupportedHardwareWatchpoints() override;
+
+protected:
+  Status GPRRead(const uint32_t reg, RegisterValue &reg_value);
+  Status GPRWrite(const uint32_t reg, const RegisterValue &reg_value);
+
+private:
+  bool IsGPR(uint32_t reg_index) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NativeRegisterContextWindows_i386_h_
+#endif // defined(_WIN64)

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,579 @@
+//===-- NativeRegisterContextWindows_x86_64.cpp -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN64)
+
+#include "NativeRegisterContextWindows_x86_64.h"
+#include "NativeRegisterContextWindows_WoW64.h"
+#include "NativeThreadWindows.h"
+#include "Plugins/Process/Utility/RegisterContextWindows_i386.h"
+#include "Plugins/Process/Utility/RegisterContextWindows_x86_64.h"
+#include "ProcessWindowsLog.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
+
+namespace {
+static const uint32_t g_gpr_regnums_x86_64[] = {
+    lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
+    lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
+    lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
+    lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
+    lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
+    lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
+    LLDB_INVALID_REGNUM // Register set must be terminated with this flag
+};
+
+static const uint32_t g_fpr_regnums_x86_64[] = {
+    lldb_xmm0_x86_64,   lldb_xmm1_x86_64,  lldb_xmm2_x86_64,  lldb_xmm3_x86_64,
+    lldb_xmm4_x86_64,   lldb_xmm5_x86_64,  lldb_xmm6_x86_64,  lldb_xmm7_x86_64,
+    lldb_xmm8_x86_64,   lldb_xmm9_x86_64,  lldb_xmm10_x86_64, lldb_xmm11_x86_64,
+    lldb_xmm12_x86_64,  lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64,
+    LLDB_INVALID_REGNUM // Register set must be terminated with this flag
+};
+
+static const RegisterSet g_reg_sets_x86_64[] = {
+    {"General Purpose Registers", "gpr",
+     llvm::array_lengthof(g_gpr_regnums_x86_64) - 1, g_gpr_regnums_x86_64},
+    {"Floating Point Registers", "fpr",
+     llvm::array_lengthof(g_fpr_regnums_x86_64) - 1, g_fpr_regnums_x86_64}};
+
+enum { k_num_register_sets = 2 };
+
+} // namespace
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+  assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+         "Register setting path assumes this is a 64-bit host");
+  return new RegisterContextWindows_x86_64(target_arch);
+}
+
+static Status GetThreadContextHelper(lldb::thread_t thread_handle,
+                                     PCONTEXT context_ptr,
+                                     const DWORD control_flag) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+
+  memset(context_ptr, 0, sizeof(::CONTEXT));
+  context_ptr->ContextFlags = control_flag;
+  if (!::GetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__,
+             error);
+    return error;
+  }
+  return Status();
+}
+
+static Status SetThreadContextHelper(lldb::thread_t thread_handle,
+                                     PCONTEXT context_ptr) {
+  Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
+  Status error;
+  // It's assumed that the thread has stopped.
+  if (!::SetThreadContext(thread_handle, context_ptr)) {
+    error.SetError(GetLastError(), eErrorTypeWin32);
+    LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__,
+             error);
+    return error;
+  }
+  return Status();
+}
+
+std::unique_ptr<NativeRegisterContextWindows>
+NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+  // Register context for a WoW64 application.
+  if (target_arch.GetAddressByteSize() == 4)
+    return llvm::make_unique<NativeRegisterContextWindows_WoW64>(target_arch,
+                                                                 native_thread);
+
+  // Register context for a native 64-bit application.
+  return llvm::make_unique<NativeRegisterContextWindows_x86_64>(target_arch,
+                                                                native_thread);
+}
+
+NativeRegisterContextWindows_x86_64::NativeRegisterContextWindows_x86_64(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextWindows(native_thread,
+                                   CreateRegisterInfoInterface(target_arch)) {}
+
+bool NativeRegisterContextWindows_x86_64::IsGPR(uint32_t reg_index) const {
+  return (reg_index >= k_first_gpr_x86_64 && reg_index < k_first_alias_x86_64);
+}
+
+bool NativeRegisterContextWindows_x86_64::IsFPR(uint32_t reg_index) const {
+  return (reg_index >= lldb_xmm0_x86_64 && reg_index <= k_last_fpr_x86_64);
+}
+
+uint32_t NativeRegisterContextWindows_x86_64::GetRegisterSetCount() const {
+  return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextWindows_x86_64::GetRegisterSet(uint32_t set_index) const {
+  if (set_index >= k_num_register_sets)
+    return nullptr;
+  return &g_reg_sets_x86_64[set_index];
+}
+
+Status NativeRegisterContextWindows_x86_64::GPRRead(const uint32_t reg,
+                                                    RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
+  Status error =
+      GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_rax_x86_64:
+    reg_value.SetUInt64(tls_context.Rax);
+    break;
+  case lldb_rbx_x86_64:
+    reg_value.SetUInt64(tls_context.Rbx);
+    break;
+  case lldb_rcx_x86_64:
+    reg_value.SetUInt64(tls_context.Rcx);
+    break;
+  case lldb_rdx_x86_64:
+    reg_value.SetUInt64(tls_context.Rdx);
+    break;
+  case lldb_rdi_x86_64:
+    reg_value.SetUInt64(tls_context.Rdi);
+    break;
+  case lldb_rsi_x86_64:
+    reg_value.SetUInt64(tls_context.Rsi);
+    break;
+  case lldb_rbp_x86_64:
+    reg_value.SetUInt64(tls_context.Rbp);
+    break;
+  case lldb_rsp_x86_64:
+    reg_value.SetUInt64(tls_context.Rsp);
+    break;
+  case lldb_r8_x86_64:
+    reg_value.SetUInt64(tls_context.R8);
+    break;
+  case lldb_r9_x86_64:
+    reg_value.SetUInt64(tls_context.R9);
+    break;
+  case lldb_r10_x86_64:
+    reg_value.SetUInt64(tls_context.R10);
+    break;
+  case lldb_r11_x86_64:
+    reg_value.SetUInt64(tls_context.R11);
+    break;
+  case lldb_r12_x86_64:
+    reg_value.SetUInt64(tls_context.R12);
+    break;
+  case lldb_r13_x86_64:
+    reg_value.SetUInt64(tls_context.R13);
+    break;
+  case lldb_r14_x86_64:
+    reg_value.SetUInt64(tls_context.R14);
+    break;
+  case lldb_r15_x86_64:
+    reg_value.SetUInt64(tls_context.R15);
+    break;
+  case lldb_rip_x86_64:
+    reg_value.SetUInt64(tls_context.Rip);
+    break;
+  case lldb_rflags_x86_64:
+    reg_value.SetUInt64(tls_context.EFlags | 0x2); // Bit #1 always 1
+    break;
+  case lldb_cs_x86_64:
+    reg_value.SetUInt16(tls_context.SegCs);
+    break;
+  case lldb_fs_x86_64:
+    reg_value.SetUInt16(tls_context.SegFs);
+    break;
+  case lldb_gs_x86_64:
+    reg_value.SetUInt16(tls_context.SegGs);
+    break;
+  case lldb_ss_x86_64:
+    reg_value.SetUInt16(tls_context.SegSs);
+    break;
+  case lldb_ds_x86_64:
+    reg_value.SetUInt16(tls_context.SegDs);
+    break;
+  case lldb_es_x86_64:
+    reg_value.SetUInt16(tls_context.SegEs);
+    break;
+  }
+
+  return error;
+}
+
+Status
+NativeRegisterContextWindows_x86_64::GPRWrite(const uint32_t reg,
+                                              const RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
+  auto thread_handle = GetThreadHandle();
+  Status error =
+      GetThreadContextHelper(thread_handle, &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_rax_x86_64:
+    tls_context.Rax = reg_value.GetAsUInt64();
+    break;
+  case lldb_rbx_x86_64:
+    tls_context.Rbx = reg_value.GetAsUInt64();
+    break;
+  case lldb_rcx_x86_64:
+    tls_context.Rcx = reg_value.GetAsUInt64();
+    break;
+  case lldb_rdx_x86_64:
+    tls_context.Rdx = reg_value.GetAsUInt64();
+    break;
+  case lldb_rdi_x86_64:
+    tls_context.Rdi = reg_value.GetAsUInt64();
+    break;
+  case lldb_rsi_x86_64:
+    tls_context.Rsi = reg_value.GetAsUInt64();
+    break;
+  case lldb_rbp_x86_64:
+    tls_context.Rbp = reg_value.GetAsUInt64();
+    break;
+  case lldb_rsp_x86_64:
+    tls_context.Rsp = reg_value.GetAsUInt64();
+    break;
+  case lldb_r8_x86_64:
+    tls_context.R8 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r9_x86_64:
+    tls_context.R9 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r10_x86_64:
+    tls_context.R10 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r11_x86_64:
+    tls_context.R11 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r12_x86_64:
+    tls_context.R12 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r13_x86_64:
+    tls_context.R13 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r14_x86_64:
+    tls_context.R14 = reg_value.GetAsUInt64();
+    break;
+  case lldb_r15_x86_64:
+    tls_context.R15 = reg_value.GetAsUInt64();
+    break;
+  case lldb_rip_x86_64:
+    tls_context.Rip = reg_value.GetAsUInt64();
+    break;
+  case lldb_rflags_x86_64:
+    tls_context.EFlags = reg_value.GetAsUInt64();
+    break;
+  case lldb_cs_x86_64:
+    tls_context.SegCs = reg_value.GetAsUInt16();
+    break;
+  case lldb_fs_x86_64:
+    tls_context.SegFs = reg_value.GetAsUInt16();
+    break;
+  case lldb_gs_x86_64:
+    tls_context.SegGs = reg_value.GetAsUInt16();
+    break;
+  case lldb_ss_x86_64:
+    tls_context.SegSs = reg_value.GetAsUInt16();
+    break;
+  case lldb_ds_x86_64:
+    tls_context.SegDs = reg_value.GetAsUInt16();
+    break;
+  case lldb_es_x86_64:
+    tls_context.SegEs = reg_value.GetAsUInt16();
+    break;
+  }
+
+  return SetThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status NativeRegisterContextWindows_x86_64::FPRRead(const uint32_t reg,
+                                                    RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
+  Status error =
+      GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_xmm0_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm0, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm1_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm1, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm2_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm2, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm3_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm3, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm4_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm4, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm5_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm5, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm6_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm6, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm7_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm7, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm8_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm8, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm9_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm9, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm10_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm10, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm11_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm11, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm12_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm12, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm13_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm13, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm14_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm14, 16, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm15_x86_64:
+    reg_value.SetBytes(&tls_context.Xmm15, 16, endian::InlHostByteOrder());
+    break;
+  }
+
+  return error;
+}
+
+Status
+NativeRegisterContextWindows_x86_64::FPRWrite(const uint32_t reg,
+                                              const RegisterValue &reg_value) {
+  ::CONTEXT tls_context;
+  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
+  auto thread_handle = GetThreadHandle();
+  Status error =
+      GetThreadContextHelper(thread_handle, &tls_context, context_flag);
+  if (error.Fail())
+    return error;
+
+  switch (reg) {
+  case lldb_xmm0_x86_64:
+    memcpy(&tls_context.Xmm0, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm1_x86_64:
+    memcpy(&tls_context.Xmm1, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm2_x86_64:
+    memcpy(&tls_context.Xmm2, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm3_x86_64:
+    memcpy(&tls_context.Xmm3, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm4_x86_64:
+    memcpy(&tls_context.Xmm4, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm5_x86_64:
+    memcpy(&tls_context.Xmm5, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm6_x86_64:
+    memcpy(&tls_context.Xmm6, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm7_x86_64:
+    memcpy(&tls_context.Xmm7, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm8_x86_64:
+    memcpy(&tls_context.Xmm8, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm9_x86_64:
+    memcpy(&tls_context.Xmm9, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm10_x86_64:
+    memcpy(&tls_context.Xmm10, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm11_x86_64:
+    memcpy(&tls_context.Xmm11, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm12_x86_64:
+    memcpy(&tls_context.Xmm12, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm13_x86_64:
+    memcpy(&tls_context.Xmm13, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm14_x86_64:
+    memcpy(&tls_context.Xmm14, reg_value.GetBytes(), 16);
+    break;
+  case lldb_xmm15_x86_64:
+    memcpy(&tls_context.Xmm15, reg_value.GetBytes(), 16);
+    break;
+  }
+
+  return SetThreadContextHelper(thread_handle, &tls_context);
+}
+
+Status
+NativeRegisterContextWindows_x86_64::ReadRegister(const RegisterInfo *reg_info,
+                                                  RegisterValue &reg_value) {
+  Status error;
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRRead(reg, reg_value);
+
+  if (IsFPR(reg))
+    return FPRRead(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_x86_64::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (IsGPR(reg))
+    return GPRWrite(reg, reg_value);
+
+  if (IsFPR(reg))
+    return FPRWrite(reg, reg_value);
+
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_x86_64::ReadAllRegisterValues(
+    lldb::DataBufferSP &data_sp) {
+  const size_t data_size = REG_CONTEXT_SIZE;
+  data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
+  ::CONTEXT tls_context;
+  Status error =
+      GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
+  if (error.Fail())
+    return error;
+
+  uint8_t *dst = data_sp->GetBytes();
+  ::memcpy(dst, &tls_context, data_size);
+  return error;
+}
+
+Status NativeRegisterContextWindows_x86_64::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+  const size_t data_size = REG_CONTEXT_SIZE;
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextWindows_x86_64::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != data_size) {
+    error.SetErrorStringWithFormatv(
+        "data_sp contained mismatched data size, expected {0}, actual {1}",
+        data_size, data_sp->GetByteSize());
+    return error;
+  }
+
+  ::CONTEXT tls_context;
+  memcpy(&tls_context, data_sp->GetBytes(), data_size);
+  return SetThreadContextHelper(GetThreadHandle(), &tls_context);
+}
+
+Status NativeRegisterContextWindows_x86_64::IsWatchpointHit(uint32_t wp_index,
+                                                            bool &is_hit) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_x86_64::GetWatchpointHitIndex(
+    uint32_t &wp_index, lldb::addr_t trap_addr) {
+  return Status("unimplemented");
+}
+
+Status
+NativeRegisterContextWindows_x86_64::IsWatchpointVacant(uint32_t wp_index,
+                                                        bool &is_vacant) {
+  return Status("unimplemented");
+}
+
+Status NativeRegisterContextWindows_x86_64::SetHardwareWatchpointWithIndex(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+  return Status("unimplemented");
+}
+
+bool NativeRegisterContextWindows_x86_64::ClearHardwareWatchpoint(
+    uint32_t wp_index) {
+  return false;
+}
+
+Status NativeRegisterContextWindows_x86_64::ClearAllHardwareWatchpoints() {
+  return Status("unimplemented");
+}
+
+uint32_t NativeRegisterContextWindows_x86_64::SetHardwareWatchpoint(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+  return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextWindows_x86_64::GetWatchpointAddress(uint32_t wp_index) {
+  return LLDB_INVALID_ADDRESS;
+}
+
+uint32_t
+NativeRegisterContextWindows_x86_64::NumSupportedHardwareWatchpoints() {
+  // Not implemented
+  return 0;
+}
+
+#endif // defined(_WIN64)

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,82 @@
+//===-- NativeRegisterContextWindows_x86_64.h -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(_WIN64)
+#ifndef liblldb_NativeRegisterContextWindows_x86_64_h_
+#define liblldb_NativeRegisterContextWindows_x86_64_h_
+
+#include "Plugins/Process/Utility/RegisterContext_x86.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+#include "NativeRegisterContextWindows.h"
+
+namespace lldb_private {
+
+class NativeThreadWindows;
+
+class NativeRegisterContextWindows_x86_64
+    : public NativeRegisterContextWindows {
+public:
+  NativeRegisterContextWindows_x86_64(const ArchSpec &target_arch,
+                                      NativeThreadProtocol &native_thread);
+
+  uint32_t GetRegisterSetCount() const override;
+
+  const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+  Status ReadRegister(const RegisterInfo *reg_info,
+                      RegisterValue &reg_value) override;
+
+  Status WriteRegister(const RegisterInfo *reg_info,
+                       const RegisterValue &reg_value) override;
+
+  Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+  Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+  Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+  Status GetWatchpointHitIndex(uint32_t &wp_index,
+                               lldb::addr_t trap_addr) override;
+
+  Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+  Status ClearAllHardwareWatchpoints() override;
+
+  Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+                                        uint32_t watch_flags,
+                                        uint32_t wp_index);
+
+  uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+                                 uint32_t watch_flags) override;
+
+  lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+  uint32_t NumSupportedHardwareWatchpoints() override;
+
+protected:
+  Status GPRRead(const uint32_t reg, RegisterValue &reg_value);
+
+  Status GPRWrite(const uint32_t reg, const RegisterValue &reg_value);
+
+  Status FPRRead(const uint32_t reg, RegisterValue &reg_value);
+
+  Status FPRWrite(const uint32_t reg, const RegisterValue &reg_value);
+
+private:
+  bool IsGPR(uint32_t reg_index) const;
+
+  bool IsFPR(uint32_t reg_index) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NativeRegisterContextWindows_x86_64_h_
+#endif // defined(_WIN64)

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp Tue Aug 13 15:18:01 2019
@@ -0,0 +1,149 @@
+//===-- NativeThreadWindows.cpp ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeThreadWindows.h"
+#include "NativeProcessWindows.h"
+
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Windows/HostThreadWindows.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
+
+#include "lldb/lldb-forward.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process,
+                                         const HostThread &thread)
+    : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()),
+      m_stop_info(), m_stop_description(), m_host_thread(thread) {
+  m_reg_context_up =
+      (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
+          process.GetArchitecture(), *this));
+}
+
+Status NativeThreadWindows::DoStop() {
+  if (m_state != eStateStopped) {
+    DWORD previous_suspend_count =
+        ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
+    if (previous_suspend_count == (DWORD)-1)
+      return Status(::GetLastError(), eErrorTypeWin32);
+
+    m_state = eStateStopped;
+  }
+  return Status();
+}
+
+Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
+  StateType current_state = GetState();
+  if (resume_state == current_state)
+    return Status();
+
+  if (resume_state == eStateStepping) {
+    uint32_t flags_index =
+        GetRegisterContext().ConvertRegisterKindToRegisterNumber(
+            eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+    uint64_t flags_value =
+        GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0);
+    flags_value |= 0x100; // Set the trap flag on the CPU
+    GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
+  }
+
+  if (resume_state == eStateStepping || resume_state == eStateRunning) {
+    DWORD previous_suspend_count = 0;
+    HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
+    do {
+      // ResumeThread returns -1 on error, or the thread's *previous* suspend
+      // count on success. This means that the return value is 1 when the thread
+      // was restarted. Note that DWORD is an unsigned int, so we need to
+      // explicitly compare with -1.
+      previous_suspend_count = ::ResumeThread(thread_handle);
+
+      if (previous_suspend_count == (DWORD)-1)
+        return Status(::GetLastError(), eErrorTypeWin32);
+
+    } while (previous_suspend_count > 1);
+    m_state = eStateRunning;
+  }
+
+  return Status();
+}
+
+std::string NativeThreadWindows::GetName() {
+  if (!m_name.empty())
+    return m_name;
+
+  // Name is not a property of the Windows thread. Create one with the
+  // process's.
+  NativeProcessProtocol &process = GetProcess();
+  ProcessInstanceInfo process_info;
+  if (Host::GetProcessInfo(process.GetID(), process_info)) {
+    std::string process_name(process_info.GetName());
+    m_name = process_name;
+  }
+  return m_name;
+}
+
+void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info,
+                                        std::string description) {
+  m_state = eStateStopped;
+  m_stop_info = stop_info;
+  m_stop_description = description;
+}
+
+bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info,
+                                        std::string &description) {
+  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
+  switch (m_state) {
+  case eStateStopped:
+  case eStateCrashed:
+  case eStateExited:
+  case eStateSuspended:
+  case eStateUnloaded:
+    stop_info = m_stop_info;
+    description = m_stop_description;
+    return true;
+
+  case eStateInvalid:
+  case eStateConnected:
+  case eStateAttaching:
+  case eStateLaunching:
+  case eStateRunning:
+  case eStateStepping:
+  case eStateDetached:
+    if (log) {
+      log->Printf("NativeThreadWindows::%s tid %" PRIu64
+                  " in state %s cannot answer stop reason",
+                  __FUNCTION__, GetID(), StateAsCString(m_state));
+    }
+    return false;
+  }
+  llvm_unreachable("unhandled StateType!");
+}
+
+Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size,
+                                          uint32_t watch_flags, bool hardware) {
+  return Status("unimplemented.");
+}
+
+Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
+  return Status("unimplemented");
+}
+
+Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
+                                                  size_t size) {
+  return Status("unimplemented.");
+}
+
+Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
+  return Status("unimplemented.");
+}

Added: lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.h?rev=368759&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.h (added)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/NativeThreadWindows.h Tue Aug 13 15:18:01 2019
@@ -0,0 +1,70 @@
+//===-- NativeThreadWindows.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NativeThreadWindows_h_
+#define liblldb_NativeThreadWindows_h_
+
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/lldb-private-forward.h"
+
+#include "NativeRegisterContextWindows.h"
+
+namespace lldb_private {
+
+class NativeProcessWindows;
+
+class NativeThreadWindows : public NativeThreadProtocol {
+public:
+  NativeThreadWindows(NativeProcessWindows &process, const HostThread &thread);
+
+  ~NativeThreadWindows() {}
+
+  Status DoStop();
+  Status DoResume(lldb::StateType resume_state);
+
+  std::string GetName() override;
+
+  lldb::StateType GetState() override { return m_state; }
+
+  NativeRegisterContextWindows &GetRegisterContext() override {
+    return *m_reg_context_up;
+  }
+
+  bool GetStopReason(ThreadStopInfo &stop_info,
+                     std::string &description) override;
+
+  Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
+                       bool hardware) override;
+
+  Status RemoveWatchpoint(lldb::addr_t addr) override;
+
+  Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
+
+  Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
+
+  void SetStopReason(ThreadStopInfo stop_info, std::string description);
+
+  const HostThread &GetHostThread() { return m_host_thread; }
+
+protected:
+  lldb::StateType m_state = lldb::StateType::eStateInvalid;
+  std::string m_name;
+  ThreadStopInfo m_stop_info;
+  std::string m_stop_description;
+  std::unique_ptr<NativeRegisterContextWindows> m_reg_context_up;
+  // Cache address and index of the watchpoints and hardware breakpoints since
+  // the register context does not.
+  using IndexMap = std::map<lldb::addr_t, uint32_t>;
+  IndexMap m_watchpoint_index_map;
+  IndexMap m_hw_breakpoint_index_map;
+  HostThread m_host_thread;
+};
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_NativeThreadWindows_h_

Modified: lldb/trunk/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp Tue Aug 13 15:18:01 2019
@@ -123,7 +123,9 @@ bool RegisterContextWindows::CacheAllReg
     return false;
   }
   memcpy(&m_context, tmpContext, sizeof(m_context));
-  if (!::SuspendThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
+  if (::SuspendThread(
+          wthread.GetHostThread().GetNativeThread().GetSystemHandle()) ==
+      (DWORD)-1) {
     return false;
   }
   if (!::GetThreadContext(
@@ -135,7 +137,9 @@ bool RegisterContextWindows::CacheAllReg
         ::GetLastError());
     return false;
   }
-  if (!::ResumeThread(wthread.GetHostThread().GetNativeThread().GetSystemHandle())) {
+  if (::ResumeThread(
+          wthread.GetHostThread().GetNativeThread().GetSystemHandle()) ==
+      (DWORD)-1) {
     return false;
   }
   LLDB_LOG(log, "successfully updated the register values.");

Modified: lldb/trunk/third_party/Python/module/unittest2/unittest2/case.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/third_party/Python/module/unittest2/unittest2/case.py?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/third_party/Python/module/unittest2/unittest2/case.py (original)
+++ lldb/trunk/third_party/Python/module/unittest2/unittest2/case.py Tue Aug 13 15:18:01 2019
@@ -753,7 +753,7 @@ class TestCase(unittest.TestCase):
             elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
             differing = '%ss differ: %s != %s\n' % elements
 
-            for i in xrange(min(len1, len2)):
+            for i in range(min(len1, len2)):
                 try:
                     item1 = seq1[i]
                 except (TypeError, IndexError, NotImplementedError):

Modified: lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp Tue Aug 13 15:18:01 2019
@@ -14,6 +14,10 @@ using namespace llgs_tests;
 using namespace lldb_private;
 using namespace llvm;
 
+#ifdef SendMessage
+#undef SendMessage
+#endif
+
 TEST_F(TestBase, LaunchModePreservesEnvironment) {
   putenv(const_cast<char *>("LLDB_TEST_MAGIC_VARIABLE=LLDB_TEST_MAGIC_VALUE"));
 

Modified: lldb/trunk/unittests/tools/lldb-server/tests/TestBase.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/TestBase.h?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/TestBase.h (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/TestBase.h Tue Aug 13 15:18:01 2019
@@ -12,6 +12,7 @@
 #include "TestClient.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Socket.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
@@ -23,9 +24,11 @@ public:
   static void SetUpTestCase() {
     lldb_private::FileSystem::Initialize();
     lldb_private::HostInfo::Initialize();
+    ASSERT_THAT_ERROR(lldb_private::Socket::Initialize(), llvm::Succeeded());
   }
 
   static void TearDownTestCase() {
+    lldb_private::Socket::Terminate();
     lldb_private::HostInfo::Terminate();
     lldb_private::FileSystem::Terminate();
   }

Modified: lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp?rev=368759&r1=368758&r2=368759&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp Tue Aug 13 15:18:01 2019
@@ -25,6 +25,10 @@ using namespace lldb_private;
 using namespace llvm;
 using namespace llgs_tests;
 
+#ifdef SendMessage
+#undef SendMessage
+#endif
+
 TestClient::TestClient(std::unique_ptr<Connection> Conn) {
   SetConnection(Conn.release());
   SetPacketTimeout(std::chrono::seconds(10));




More information about the lldb-commits mailing list