118a9135dSAdrian McCarthy //===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===//
218a9135dSAdrian McCarthy //
318a9135dSAdrian McCarthy //                     The LLVM Compiler Infrastructure
418a9135dSAdrian McCarthy //
518a9135dSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
618a9135dSAdrian McCarthy // License. See LICENSE.TXT for details.
718a9135dSAdrian McCarthy //
818a9135dSAdrian McCarthy //===----------------------------------------------------------------------===//
918a9135dSAdrian McCarthy 
1018a9135dSAdrian McCarthy #include "lldb/Core/Log.h"
1118a9135dSAdrian McCarthy #include "lldb/Core/Logging.h"
1218a9135dSAdrian McCarthy #include "lldb/Core/State.h"
1318a9135dSAdrian McCarthy #include "lldb/Host/HostInfo.h"
1418a9135dSAdrian McCarthy #include "lldb/Host/HostNativeThreadBase.h"
1518a9135dSAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h"
1618a9135dSAdrian McCarthy #include "lldb/Host/windows/windows.h"
1718a9135dSAdrian McCarthy #include "lldb/Target/RegisterContext.h"
1818a9135dSAdrian McCarthy 
1918a9135dSAdrian McCarthy #include "ProcessWindows.h"
2018a9135dSAdrian McCarthy #include "ProcessWindowsLog.h"
21b9c1b51eSKate Stone #include "TargetThreadWindows.h"
2218a9135dSAdrian McCarthy #include "UnwindLLDB.h"
2318a9135dSAdrian McCarthy 
24*4ad5def9SAdrian McCarthy #if defined(_WIN64)
25*4ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x64.h"
26*4ad5def9SAdrian McCarthy #else
27*4ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x86.h"
28*4ad5def9SAdrian McCarthy #endif
29*4ad5def9SAdrian McCarthy 
3018a9135dSAdrian McCarthy using namespace lldb;
3118a9135dSAdrian McCarthy using namespace lldb_private;
3218a9135dSAdrian McCarthy 
33b9c1b51eSKate Stone TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
34b9c1b51eSKate Stone                                          const HostThread &thread)
35b9c1b51eSKate Stone     : Thread(process, thread.GetNativeThread().GetThreadId()),
36b9c1b51eSKate Stone       m_host_thread(thread) {}
3718a9135dSAdrian McCarthy 
38b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
3918a9135dSAdrian McCarthy 
40b9c1b51eSKate Stone void TargetThreadWindows::RefreshStateAfterStop() {
4118a9135dSAdrian McCarthy   ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
4218a9135dSAdrian McCarthy   SetState(eStateStopped);
4318a9135dSAdrian McCarthy   GetRegisterContext()->InvalidateIfNeeded(false);
4418a9135dSAdrian McCarthy }
4518a9135dSAdrian McCarthy 
46b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
4718a9135dSAdrian McCarthy 
48b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {}
4918a9135dSAdrian McCarthy 
50*4ad5def9SAdrian McCarthy RegisterContextSP TargetThreadWindows::GetRegisterContext() {
51*4ad5def9SAdrian McCarthy   if (!m_reg_context_sp)
52*4ad5def9SAdrian McCarthy     m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
53*4ad5def9SAdrian McCarthy 
54*4ad5def9SAdrian McCarthy   return m_reg_context_sp;
55*4ad5def9SAdrian McCarthy }
56*4ad5def9SAdrian McCarthy 
57*4ad5def9SAdrian McCarthy RegisterContextSP
58*4ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
59*4ad5def9SAdrian McCarthy   return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
60*4ad5def9SAdrian McCarthy }
61*4ad5def9SAdrian McCarthy 
62*4ad5def9SAdrian McCarthy RegisterContextSP
63*4ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrameIndex(uint32_t idx) {
64*4ad5def9SAdrian McCarthy   if (!m_reg_context_sp) {
65*4ad5def9SAdrian McCarthy     ArchSpec arch = HostInfo::GetArchitecture();
66*4ad5def9SAdrian McCarthy     switch (arch.GetMachine()) {
67*4ad5def9SAdrian McCarthy     case llvm::Triple::x86:
68*4ad5def9SAdrian McCarthy #if defined(_WIN64)
69*4ad5def9SAdrian McCarthy // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
70*4ad5def9SAdrian McCarthy #else
71*4ad5def9SAdrian McCarthy       m_reg_context_sp.reset(new RegisterContextWindows_x86(*this, idx));
72*4ad5def9SAdrian McCarthy #endif
73*4ad5def9SAdrian McCarthy       break;
74*4ad5def9SAdrian McCarthy     case llvm::Triple::x86_64:
75*4ad5def9SAdrian McCarthy #if defined(_WIN64)
76*4ad5def9SAdrian McCarthy       m_reg_context_sp.reset(new RegisterContextWindows_x64(*this, idx));
77*4ad5def9SAdrian McCarthy #else
78*4ad5def9SAdrian McCarthy // LLDB is 32-bit, but the target process is 64-bit.  We probably can't debug
79*4ad5def9SAdrian McCarthy // this.
80*4ad5def9SAdrian McCarthy #endif
81*4ad5def9SAdrian McCarthy     default:
82*4ad5def9SAdrian McCarthy       break;
83*4ad5def9SAdrian McCarthy     }
84*4ad5def9SAdrian McCarthy   }
85*4ad5def9SAdrian McCarthy   return m_reg_context_sp;
86*4ad5def9SAdrian McCarthy }
87*4ad5def9SAdrian McCarthy 
88b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() {
8918a9135dSAdrian McCarthy   SetStopInfo(m_stop_info_sp);
9018a9135dSAdrian McCarthy   return true;
9118a9135dSAdrian McCarthy }
9218a9135dSAdrian McCarthy 
93b9c1b51eSKate Stone Unwind *TargetThreadWindows::GetUnwinder() {
94b9c1b51eSKate Stone   // FIXME: Implement an unwinder based on the Windows unwinder exposed through
95b9c1b51eSKate Stone   // DIA SDK.
9618a9135dSAdrian McCarthy   if (m_unwinder_ap.get() == NULL)
9718a9135dSAdrian McCarthy     m_unwinder_ap.reset(new UnwindLLDB(*this));
9818a9135dSAdrian McCarthy   return m_unwinder_ap.get();
9918a9135dSAdrian McCarthy }
10018a9135dSAdrian McCarthy 
101b9c1b51eSKate Stone bool TargetThreadWindows::DoResume() {
10218a9135dSAdrian McCarthy   StateType resume_state = GetTemporaryResumeState();
10318a9135dSAdrian McCarthy   StateType current_state = GetState();
10418a9135dSAdrian McCarthy   if (resume_state == current_state)
10518a9135dSAdrian McCarthy     return true;
10618a9135dSAdrian McCarthy 
107b9c1b51eSKate Stone   if (resume_state == eStateStepping) {
108b9c1b51eSKate Stone     uint32_t flags_index =
109b9c1b51eSKate Stone         GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
110b9c1b51eSKate Stone             eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
111b9c1b51eSKate Stone     uint64_t flags_value =
112b9c1b51eSKate Stone         GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
11318a9135dSAdrian McCarthy     flags_value |= 0x100; // Set the trap flag on the CPU
11418a9135dSAdrian McCarthy     GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
11518a9135dSAdrian McCarthy   }
11618a9135dSAdrian McCarthy 
117b9c1b51eSKate Stone   if (resume_state == eStateStepping || resume_state == eStateRunning) {
11818a9135dSAdrian McCarthy     DWORD previous_suspend_count = 0;
11918a9135dSAdrian McCarthy     HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
120b9c1b51eSKate Stone     do {
12118a9135dSAdrian McCarthy       previous_suspend_count = ::ResumeThread(thread_handle);
12218a9135dSAdrian McCarthy     } while (previous_suspend_count > 0);
12318a9135dSAdrian McCarthy   }
12418a9135dSAdrian McCarthy   return true;
12518a9135dSAdrian McCarthy }
126