xref: /llvm-project/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp (revision 6f9e690199edd68b20bac92983a216459bc568ed)
1 //===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/State.h"
11 #include "lldb/Host/HostInfo.h"
12 #include "lldb/Host/HostNativeThreadBase.h"
13 #include "lldb/Host/windows/HostThreadWindows.h"
14 #include "lldb/Host/windows/windows.h"
15 #include "lldb/Target/RegisterContext.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Logging.h"
18 
19 #include "ProcessWindows.h"
20 #include "ProcessWindowsLog.h"
21 #include "TargetThreadWindows.h"
22 #include "UnwindLLDB.h"
23 
24 #if defined(_WIN64)
25 #include "x64/RegisterContextWindows_x64.h"
26 #else
27 #include "x86/RegisterContextWindows_x86.h"
28 #endif
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
34                                          const HostThread &thread)
35     : Thread(process, thread.GetNativeThread().GetThreadId()),
36       m_host_thread(thread) {}
37 
38 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
39 
40 void TargetThreadWindows::RefreshStateAfterStop() {
41   ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
42   SetState(eStateStopped);
43   GetRegisterContext()->InvalidateIfNeeded(false);
44 }
45 
46 void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
47 
48 void TargetThreadWindows::DidStop() {}
49 
50 RegisterContextSP TargetThreadWindows::GetRegisterContext() {
51   if (!m_reg_context_sp)
52     m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
53 
54   return m_reg_context_sp;
55 }
56 
57 RegisterContextSP
58 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
59   return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
60 }
61 
62 RegisterContextSP
63 TargetThreadWindows::CreateRegisterContextForFrameIndex(uint32_t idx) {
64   if (!m_reg_context_sp) {
65     ArchSpec arch = HostInfo::GetArchitecture();
66     switch (arch.GetMachine()) {
67     case llvm::Triple::x86:
68 #if defined(_WIN64)
69 // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
70 #else
71       m_reg_context_sp.reset(new RegisterContextWindows_x86(*this, idx));
72 #endif
73       break;
74     case llvm::Triple::x86_64:
75 #if defined(_WIN64)
76       m_reg_context_sp.reset(new RegisterContextWindows_x64(*this, idx));
77 #else
78 // LLDB is 32-bit, but the target process is 64-bit.  We probably can't debug
79 // this.
80 #endif
81     default:
82       break;
83     }
84   }
85   return m_reg_context_sp;
86 }
87 
88 bool TargetThreadWindows::CalculateStopInfo() {
89   SetStopInfo(m_stop_info_sp);
90   return true;
91 }
92 
93 Unwind *TargetThreadWindows::GetUnwinder() {
94   // FIXME: Implement an unwinder based on the Windows unwinder exposed through
95   // DIA SDK.
96   if (m_unwinder_ap.get() == NULL)
97     m_unwinder_ap.reset(new UnwindLLDB(*this));
98   return m_unwinder_ap.get();
99 }
100 
101 bool TargetThreadWindows::DoResume() {
102   StateType resume_state = GetTemporaryResumeState();
103   StateType current_state = GetState();
104   if (resume_state == current_state)
105     return true;
106 
107   if (resume_state == eStateStepping) {
108     uint32_t flags_index =
109         GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
110             eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
111     uint64_t flags_value =
112         GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
113     flags_value |= 0x100; // Set the trap flag on the CPU
114     GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
115   }
116 
117   if (resume_state == eStateStepping || resume_state == eStateRunning) {
118     DWORD previous_suspend_count = 0;
119     HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
120     do {
121       previous_suspend_count = ::ResumeThread(thread_handle);
122     } while (previous_suspend_count > 0);
123   }
124   return true;
125 }
126