blob: b121dc7bf15ea86eec96502deecbf8c9dff763ce [file] [log] [blame]
Zachary Turner119767d2014-11-17 17:46:43 +00001//===-- 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
Zachary Turner17f383d2014-11-20 22:47:32 +000010#include "lldb/Host/HostInfo.h"
Zachary Turner119767d2014-11-17 17:46:43 +000011#include "lldb/Host/HostNativeThreadBase.h"
12#include "lldb/Host/windows/HostThreadWindows.h"
13#include "lldb/Host/windows/windows.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000014#include "lldb/Target/RegisterContext.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000015#include "lldb/Utility/Log.h"
16#include "lldb/Utility/Logging.h"
Pavel Labathd821c992018-08-07 11:07:21 +000017#include "lldb/Utility/State.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000018
Stella Stamenova45d81342018-07-10 22:05:33 +000019#include "Plugins/Process/Utility/UnwindLLDB.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000020#include "ProcessWindows.h"
Adrian McCarthy3ae74922015-06-01 21:51:50 +000021#include "ProcessWindowsLog.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "TargetThreadWindows.h"
Zachary Turner119767d2014-11-17 17:46:43 +000023
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000024#if defined(_WIN64)
Hafiz Abid Qadeer65abfb12016-11-29 09:31:57 +000025#include "x64/RegisterContextWindows_x64.h"
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000026#else
27#include "x86/RegisterContextWindows_x86.h"
28#endif
29
Zachary Turner119767d2014-11-17 17:46:43 +000030using namespace lldb;
31using namespace lldb_private;
32
Kate Stoneb9c1b512016-09-06 20:57:50 +000033TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
34 const HostThread &thread)
35 : Thread(process, thread.GetNativeThread().GetThreadId()),
Stella Stamenova45d81342018-07-10 22:05:33 +000036 m_thread_reg_ctx_sp(), m_host_thread(thread) {}
Kate Stoneb9c1b512016-09-06 20:57:50 +000037
38TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
39
40void TargetThreadWindows::RefreshStateAfterStop() {
41 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
42 SetState(eStateStopped);
43 GetRegisterContext()->InvalidateIfNeeded(false);
Zachary Turner119767d2014-11-17 17:46:43 +000044}
45
Kate Stoneb9c1b512016-09-06 20:57:50 +000046void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
47
48void TargetThreadWindows::DidStop() {}
49
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000050RegisterContextSP TargetThreadWindows::GetRegisterContext() {
51 if (!m_reg_context_sp)
Stella Stamenova45d81342018-07-10 22:05:33 +000052 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000053
54 return m_reg_context_sp;
55}
56
57RegisterContextSP
58TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
Stella Stamenova45d81342018-07-10 22:05:33 +000059 RegisterContextSP reg_ctx_sp;
60 uint32_t concrete_frame_idx = 0;
61 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000062
Stella Stamenova45d81342018-07-10 22:05:33 +000063 if (frame)
64 concrete_frame_idx = frame->GetConcreteFrameIndex();
65
66 if (concrete_frame_idx == 0) {
67 if (!m_thread_reg_ctx_sp) {
68 ArchSpec arch = HostInfo::GetArchitecture();
69 switch (arch.GetMachine()) {
70 case llvm::Triple::x86:
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000071#if defined(_WIN64)
Stella Stamenova45d81342018-07-10 22:05:33 +000072 // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
73 LLDB_LOG(log, "This is a Wow64 process, we should create a "
74 "RegisterContextWindows_Wow64, but we don't.");
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000075#else
Stella Stamenova45d81342018-07-10 22:05:33 +000076 m_thread_reg_ctx_sp.reset(
77 new RegisterContextWindows_x86(*this, concrete_frame_idx));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000078#endif
Stella Stamenova45d81342018-07-10 22:05:33 +000079 break;
80 case llvm::Triple::x86_64:
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000081#if defined(_WIN64)
Stella Stamenova45d81342018-07-10 22:05:33 +000082 m_thread_reg_ctx_sp.reset(
83 new RegisterContextWindows_x64(*this, concrete_frame_idx));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000084#else
Stella Stamenova45d81342018-07-10 22:05:33 +000085 LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit.");
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000086#endif
Stella Stamenova45d81342018-07-10 22:05:33 +000087 default:
88 break;
89 }
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000090 }
Stella Stamenova45d81342018-07-10 22:05:33 +000091 reg_ctx_sp = m_thread_reg_ctx_sp;
92 } else {
93 Unwind *unwinder = GetUnwinder();
94 if (unwinder != nullptr)
95 reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000096 }
Stella Stamenova45d81342018-07-10 22:05:33 +000097
98 return reg_ctx_sp;
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000099}
100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101bool TargetThreadWindows::CalculateStopInfo() {
102 SetStopInfo(m_stop_info_sp);
103 return true;
Zachary Turner119767d2014-11-17 17:46:43 +0000104}
105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106Unwind *TargetThreadWindows::GetUnwinder() {
107 // FIXME: Implement an unwinder based on the Windows unwinder exposed through
108 // DIA SDK.
Stella Stamenova45d81342018-07-10 22:05:33 +0000109 if (!m_unwinder_ap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 m_unwinder_ap.reset(new UnwindLLDB(*this));
111 return m_unwinder_ap.get();
Zachary Turner119767d2014-11-17 17:46:43 +0000112}
113
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000114Status TargetThreadWindows::DoResume() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115 StateType resume_state = GetTemporaryResumeState();
116 StateType current_state = GetState();
117 if (resume_state == current_state)
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000118 return Status();
Zachary Turner17f383d2014-11-20 22:47:32 +0000119
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 if (resume_state == eStateStepping) {
121 uint32_t flags_index =
122 GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
123 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
124 uint64_t flags_value =
125 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
126 flags_value |= 0x100; // Set the trap flag on the CPU
127 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
128 }
Zachary Turner119767d2014-11-17 17:46:43 +0000129
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130 if (resume_state == eStateStepping || resume_state == eStateRunning) {
131 DWORD previous_suspend_count = 0;
132 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
133 do {
Stella Stamenova45d81342018-07-10 22:05:33 +0000134 // ResumeThread returns -1 on error, or the thread's *previous* suspend
135 // count on success. This means that the return value is 1 when the thread
136 // was restarted. Note that DWORD is an unsigned int, so we need to
137 // explicitly compare with -1.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 previous_suspend_count = ::ResumeThread(thread_handle);
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000139
140 if (previous_suspend_count == (DWORD)-1)
141 return Status(::GetLastError(), eErrorTypeWin32);
142
143 } while (previous_suspend_count > 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 }
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000145
146 return Status();
Zachary Turner119767d2014-11-17 17:46:43 +0000147}