[windows] LLDB shows the wrong values when register read is executed at a frame other than zero

Summary:
This is a clean version of the change suggested here: https://bugs.llvm.org/show_bug.cgi?id=37495

The main change is to follow the same pattern as non-windows targets and use an unwinder object to retrieve the register context. I also changed a couple of the comments to actually log, so that issues with unsupported scenarios can be tracked down more easily. Lastly, ClearStackFrames is implemented in the base class, so individual thread implementations don't have to override it.

Reviewers: asmith, zturner, aleksandr.urakov

Reviewed By: aleksandr.urakov

Subscribers: emaste, stella.stamenova, tatyana-krasnukha, llvm-commits

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

llvm-svn: 336732
diff --git a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
index 154c8a4..3903280 100644
--- a/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
@@ -16,10 +16,10 @@
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/Logging.h"
 
+#include "Plugins/Process/Utility/UnwindLLDB.h"
 #include "ProcessWindows.h"
 #include "ProcessWindowsLog.h"
 #include "TargetThreadWindows.h"
-#include "Plugins/Process/Utility/UnwindLLDB.h"
 
 #if defined(_WIN64)
 #include "x64/RegisterContextWindows_x64.h"
@@ -33,7 +33,7 @@
 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
                                          const HostThread &thread)
     : Thread(process, thread.GetNativeThread().GetThreadId()),
-      m_host_thread(thread) {}
+      m_thread_reg_ctx_sp(), m_host_thread(thread) {}
 
 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
 
@@ -49,40 +49,53 @@
 
 RegisterContextSP TargetThreadWindows::GetRegisterContext() {
   if (!m_reg_context_sp)
-    m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
+    m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
 
   return m_reg_context_sp;
 }
 
 RegisterContextSP
 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
-  return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
-}
+  RegisterContextSP reg_ctx_sp;
+  uint32_t concrete_frame_idx = 0;
+  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 
-RegisterContextSP
-TargetThreadWindows::CreateRegisterContextForFrameIndex(uint32_t idx) {
-  if (!m_reg_context_sp) {
-    ArchSpec arch = HostInfo::GetArchitecture();
-    switch (arch.GetMachine()) {
-    case llvm::Triple::x86:
+  if (frame)
+    concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+  if (concrete_frame_idx == 0) {
+    if (!m_thread_reg_ctx_sp) {
+      ArchSpec arch = HostInfo::GetArchitecture();
+      switch (arch.GetMachine()) {
+      case llvm::Triple::x86:
 #if defined(_WIN64)
-// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
+        // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
+        LLDB_LOG(log, "This is a Wow64 process, we should create a "
+                      "RegisterContextWindows_Wow64, but we don't.");
 #else
-      m_reg_context_sp.reset(new RegisterContextWindows_x86(*this, idx));
+        m_thread_reg_ctx_sp.reset(
+            new RegisterContextWindows_x86(*this, concrete_frame_idx));
 #endif
-      break;
-    case llvm::Triple::x86_64:
+        break;
+      case llvm::Triple::x86_64:
 #if defined(_WIN64)
-      m_reg_context_sp.reset(new RegisterContextWindows_x64(*this, idx));
+        m_thread_reg_ctx_sp.reset(
+            new RegisterContextWindows_x64(*this, concrete_frame_idx));
 #else
-// LLDB is 32-bit, but the target process is 64-bit.  We probably can't debug
-// this.
+        LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit.");
 #endif
-    default:
-      break;
+      default:
+        break;
+      }
     }
+    reg_ctx_sp = m_thread_reg_ctx_sp;
+  } else {
+    Unwind *unwinder = GetUnwinder();
+    if (unwinder != nullptr)
+      reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
   }
-  return m_reg_context_sp;
+
+  return reg_ctx_sp;
 }
 
 bool TargetThreadWindows::CalculateStopInfo() {
@@ -93,7 +106,7 @@
 Unwind *TargetThreadWindows::GetUnwinder() {
   // FIXME: Implement an unwinder based on the Windows unwinder exposed through
   // DIA SDK.
-  if (m_unwinder_ap.get() == NULL)
+  if (!m_unwinder_ap)
     m_unwinder_ap.reset(new UnwindLLDB(*this));
   return m_unwinder_ap.get();
 }
@@ -118,9 +131,10 @@
     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.
+      // 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)