blob: be5846d0b03423056c3d11d13930537f9c14bfda [file] [log] [blame]
Zachary Turner119767d2014-11-17 17:46:43 +00001//===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Zachary Turner119767d2014-11-17 17:46:43 +00006//
7//===----------------------------------------------------------------------===//
8
Zachary Turner17f383d2014-11-20 22:47:32 +00009#include "lldb/Host/HostInfo.h"
Zachary Turner119767d2014-11-17 17:46:43 +000010#include "lldb/Host/HostNativeThreadBase.h"
11#include "lldb/Host/windows/HostThreadWindows.h"
12#include "lldb/Host/windows/windows.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000013#include "lldb/Target/RegisterContext.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000014#include "lldb/Utility/Log.h"
15#include "lldb/Utility/Logging.h"
Pavel Labathd821c992018-08-07 11:07:21 +000016#include "lldb/Utility/State.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000017
Stella Stamenova45d81342018-07-10 22:05:33 +000018#include "Plugins/Process/Utility/UnwindLLDB.h"
Zachary Turner17f383d2014-11-20 22:47:32 +000019#include "ProcessWindows.h"
Adrian McCarthy3ae74922015-06-01 21:51:50 +000020#include "ProcessWindowsLog.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000021#include "TargetThreadWindows.h"
Zachary Turner119767d2014-11-17 17:46:43 +000022
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000023#if defined(_WIN64)
Hafiz Abid Qadeer65abfb12016-11-29 09:31:57 +000024#include "x64/RegisterContextWindows_x64.h"
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000025#else
26#include "x86/RegisterContextWindows_x86.h"
27#endif
28
Zachary Turner119767d2014-11-17 17:46:43 +000029using namespace lldb;
30using namespace lldb_private;
31
Kate Stoneb9c1b512016-09-06 20:57:50 +000032TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
33 const HostThread &thread)
34 : Thread(process, thread.GetNativeThread().GetThreadId()),
Stella Stamenova45d81342018-07-10 22:05:33 +000035 m_thread_reg_ctx_sp(), m_host_thread(thread) {}
Kate Stoneb9c1b512016-09-06 20:57:50 +000036
37TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
38
39void TargetThreadWindows::RefreshStateAfterStop() {
40 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
41 SetState(eStateStopped);
42 GetRegisterContext()->InvalidateIfNeeded(false);
Zachary Turner119767d2014-11-17 17:46:43 +000043}
44
Kate Stoneb9c1b512016-09-06 20:57:50 +000045void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
46
47void TargetThreadWindows::DidStop() {}
48
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000049RegisterContextSP TargetThreadWindows::GetRegisterContext() {
50 if (!m_reg_context_sp)
Stella Stamenova45d81342018-07-10 22:05:33 +000051 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000052
53 return m_reg_context_sp;
54}
55
56RegisterContextSP
57TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
Stella Stamenova45d81342018-07-10 22:05:33 +000058 RegisterContextSP reg_ctx_sp;
59 uint32_t concrete_frame_idx = 0;
60 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000061
Stella Stamenova45d81342018-07-10 22:05:33 +000062 if (frame)
63 concrete_frame_idx = frame->GetConcreteFrameIndex();
64
65 if (concrete_frame_idx == 0) {
66 if (!m_thread_reg_ctx_sp) {
67 ArchSpec arch = HostInfo::GetArchitecture();
68 switch (arch.GetMachine()) {
69 case llvm::Triple::x86:
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000070#if defined(_WIN64)
Stella Stamenova45d81342018-07-10 22:05:33 +000071 // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
72 LLDB_LOG(log, "This is a Wow64 process, we should create a "
73 "RegisterContextWindows_Wow64, but we don't.");
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000074#else
Stella Stamenova45d81342018-07-10 22:05:33 +000075 m_thread_reg_ctx_sp.reset(
76 new RegisterContextWindows_x86(*this, concrete_frame_idx));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000077#endif
Stella Stamenova45d81342018-07-10 22:05:33 +000078 break;
79 case llvm::Triple::x86_64:
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000080#if defined(_WIN64)
Stella Stamenova45d81342018-07-10 22:05:33 +000081 m_thread_reg_ctx_sp.reset(
82 new RegisterContextWindows_x64(*this, concrete_frame_idx));
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000083#else
Stella Stamenova45d81342018-07-10 22:05:33 +000084 LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit.");
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000085#endif
Stella Stamenova45d81342018-07-10 22:05:33 +000086 default:
87 break;
88 }
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000089 }
Stella Stamenova45d81342018-07-10 22:05:33 +000090 reg_ctx_sp = m_thread_reg_ctx_sp;
91 } else {
92 Unwind *unwinder = GetUnwinder();
93 if (unwinder != nullptr)
94 reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000095 }
Stella Stamenova45d81342018-07-10 22:05:33 +000096
97 return reg_ctx_sp;
Adrian McCarthy4ad5def2016-11-23 16:26:37 +000098}
99
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100bool TargetThreadWindows::CalculateStopInfo() {
101 SetStopInfo(m_stop_info_sp);
102 return true;
Zachary Turner119767d2014-11-17 17:46:43 +0000103}
104
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105Unwind *TargetThreadWindows::GetUnwinder() {
106 // FIXME: Implement an unwinder based on the Windows unwinder exposed through
107 // DIA SDK.
Stella Stamenova45d81342018-07-10 22:05:33 +0000108 if (!m_unwinder_ap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 m_unwinder_ap.reset(new UnwindLLDB(*this));
110 return m_unwinder_ap.get();
Zachary Turner119767d2014-11-17 17:46:43 +0000111}
112
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000113Status TargetThreadWindows::DoResume() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114 StateType resume_state = GetTemporaryResumeState();
115 StateType current_state = GetState();
116 if (resume_state == current_state)
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000117 return Status();
Zachary Turner17f383d2014-11-20 22:47:32 +0000118
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 if (resume_state == eStateStepping) {
120 uint32_t flags_index =
121 GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
122 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
123 uint64_t flags_value =
124 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
125 flags_value |= 0x100; // Set the trap flag on the CPU
126 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
127 }
Zachary Turner119767d2014-11-17 17:46:43 +0000128
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129 if (resume_state == eStateStepping || resume_state == eStateRunning) {
130 DWORD previous_suspend_count = 0;
131 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
132 do {
Stella Stamenova45d81342018-07-10 22:05:33 +0000133 // ResumeThread returns -1 on error, or the thread's *previous* suspend
134 // count on success. This means that the return value is 1 when the thread
135 // was restarted. Note that DWORD is an unsigned int, so we need to
136 // explicitly compare with -1.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 previous_suspend_count = ::ResumeThread(thread_handle);
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000138
139 if (previous_suspend_count == (DWORD)-1)
140 return Status(::GetLastError(), eErrorTypeWin32);
141
142 } while (previous_suspend_count > 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 }
Stella Stamenova0fd67b52018-05-17 21:34:24 +0000144
145 return Status();
Zachary Turner119767d2014-11-17 17:46:43 +0000146}