180814287SRaphael Isemann //===-- ProcessWindows.cpp ------------------------------------------------===//
218a9135dSAdrian McCarthy //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618a9135dSAdrian McCarthy //
718a9135dSAdrian McCarthy //===----------------------------------------------------------------------===//
818a9135dSAdrian McCarthy
918a9135dSAdrian McCarthy #include "ProcessWindows.h"
1018a9135dSAdrian McCarthy
114ad5def9SAdrian McCarthy // Windows includes
124ad5def9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
134ad5def9SAdrian McCarthy #include <psapi.h>
144ad5def9SAdrian McCarthy
156179c0ebSAleksandr Urakov #include "lldb/Breakpoint/Watchpoint.h"
1618a9135dSAdrian McCarthy #include "lldb/Core/Module.h"
1718a9135dSAdrian McCarthy #include "lldb/Core/ModuleSpec.h"
1818a9135dSAdrian McCarthy #include "lldb/Core/PluginManager.h"
1918a9135dSAdrian McCarthy #include "lldb/Core/Section.h"
2060cf3f82SJonas Devlieghere #include "lldb/Host/FileSystem.h"
21*a6eeffa1SJonas Devlieghere #include "lldb/Host/HostInfo.h"
224ad5def9SAdrian McCarthy #include "lldb/Host/HostNativeProcessBase.h"
234ad5def9SAdrian McCarthy #include "lldb/Host/HostProcess.h"
244ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h"
250c35cde9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
262f3df613SZachary Turner #include "lldb/Symbol/ObjectFile.h"
2718a9135dSAdrian McCarthy #include "lldb/Target/DynamicLoader.h"
2818a9135dSAdrian McCarthy #include "lldb/Target/MemoryRegionInfo.h"
294ad5def9SAdrian McCarthy #include "lldb/Target/StopInfo.h"
3018a9135dSAdrian McCarthy #include "lldb/Target/Target.h"
31d821c997SPavel Labath #include "lldb/Utility/State.h"
3218a9135dSAdrian McCarthy
334ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h"
344ad5def9SAdrian McCarthy #include "llvm/Support/Format.h"
35c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h"
364ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h"
374ad5def9SAdrian McCarthy
384ad5def9SAdrian McCarthy #include "DebuggerThread.h"
394ad5def9SAdrian McCarthy #include "ExceptionRecord.h"
404ad5def9SAdrian McCarthy #include "ForwardDecl.h"
414ad5def9SAdrian McCarthy #include "LocalDebugDelegate.h"
424ad5def9SAdrian McCarthy #include "ProcessWindowsLog.h"
434ad5def9SAdrian McCarthy #include "TargetThreadWindows.h"
444ad5def9SAdrian McCarthy
4518a9135dSAdrian McCarthy using namespace lldb;
4618a9135dSAdrian McCarthy using namespace lldb_private;
4718a9135dSAdrian McCarthy
48ccad1948SJonas Devlieghere LLDB_PLUGIN_DEFINE_ADV(ProcessWindows, ProcessWindowsCommon)
49fbb4d1e4SJonas Devlieghere
504ad5def9SAdrian McCarthy namespace {
GetProcessExecutableName(HANDLE process_handle)514ad5def9SAdrian McCarthy std::string GetProcessExecutableName(HANDLE process_handle) {
524ad5def9SAdrian McCarthy std::vector<wchar_t> file_name;
534ad5def9SAdrian McCarthy DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
544ad5def9SAdrian McCarthy DWORD copied = 0;
554ad5def9SAdrian McCarthy do {
564ad5def9SAdrian McCarthy file_name_size *= 2;
574ad5def9SAdrian McCarthy file_name.resize(file_name_size);
584ad5def9SAdrian McCarthy copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
594ad5def9SAdrian McCarthy file_name_size);
604ad5def9SAdrian McCarthy } while (copied >= file_name_size);
614ad5def9SAdrian McCarthy file_name.resize(copied);
624ad5def9SAdrian McCarthy std::string result;
634ad5def9SAdrian McCarthy llvm::convertWideToUTF8(file_name.data(), result);
644ad5def9SAdrian McCarthy return result;
654ad5def9SAdrian McCarthy }
664ad5def9SAdrian McCarthy
GetProcessExecutableName(DWORD pid)674ad5def9SAdrian McCarthy std::string GetProcessExecutableName(DWORD pid) {
684ad5def9SAdrian McCarthy std::string file_name;
694ad5def9SAdrian McCarthy HANDLE process_handle =
704ad5def9SAdrian McCarthy ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
714ad5def9SAdrian McCarthy if (process_handle != NULL) {
724ad5def9SAdrian McCarthy file_name = GetProcessExecutableName(process_handle);
734ad5def9SAdrian McCarthy ::CloseHandle(process_handle);
744ad5def9SAdrian McCarthy }
754ad5def9SAdrian McCarthy return file_name;
764ad5def9SAdrian McCarthy }
774ad5def9SAdrian McCarthy } // anonymous namespace
784ad5def9SAdrian McCarthy
79b9c1b51eSKate Stone namespace lldb_private {
8018a9135dSAdrian McCarthy
CreateInstance(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const FileSpec *,bool can_connect)814ad5def9SAdrian McCarthy ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,
824ad5def9SAdrian McCarthy lldb::ListenerSP listener_sp,
8318e4272aSMichał Górny const FileSpec *,
8418e4272aSMichał Górny bool can_connect) {
854ad5def9SAdrian McCarthy return ProcessSP(new ProcessWindows(target_sp, listener_sp));
864ad5def9SAdrian McCarthy }
874ad5def9SAdrian McCarthy
ShouldUseLLDBServer()8808913665SAleksandr Urakov static bool ShouldUseLLDBServer() {
8908913665SAleksandr Urakov llvm::StringRef use_lldb_server = ::getenv("LLDB_USE_LLDB_SERVER");
90e50f9c41SMartin Storsjö return use_lldb_server.equals_insensitive("on") ||
91e50f9c41SMartin Storsjö use_lldb_server.equals_insensitive("yes") ||
92e50f9c41SMartin Storsjö use_lldb_server.equals_insensitive("1") ||
93e50f9c41SMartin Storsjö use_lldb_server.equals_insensitive("true");
9408913665SAleksandr Urakov }
9508913665SAleksandr Urakov
Initialize()964ad5def9SAdrian McCarthy void ProcessWindows::Initialize() {
9708913665SAleksandr Urakov if (!ShouldUseLLDBServer()) {
98c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag;
994ad5def9SAdrian McCarthy
100c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() {
1014ad5def9SAdrian McCarthy PluginManager::RegisterPlugin(GetPluginNameStatic(),
10208913665SAleksandr Urakov GetPluginDescriptionStatic(),
10308913665SAleksandr Urakov CreateInstance);
1044ad5def9SAdrian McCarthy });
1054ad5def9SAdrian McCarthy }
10608913665SAleksandr Urakov }
1074ad5def9SAdrian McCarthy
Terminate()1084ad5def9SAdrian McCarthy void ProcessWindows::Terminate() {}
1094ad5def9SAdrian McCarthy
GetPluginDescriptionStatic()1105f4980f0SPavel Labath llvm::StringRef ProcessWindows::GetPluginDescriptionStatic() {
1114ad5def9SAdrian McCarthy return "Process plugin for Windows";
1124ad5def9SAdrian McCarthy }
1134ad5def9SAdrian McCarthy
11418a9135dSAdrian McCarthy // Constructors and destructors.
11518a9135dSAdrian McCarthy
ProcessWindows(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp)116b9c1b51eSKate Stone ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
117b9c1b51eSKate Stone lldb::ListenerSP listener_sp)
1186179c0ebSAleksandr Urakov : lldb_private::Process(target_sp, listener_sp),
1196179c0ebSAleksandr Urakov m_watchpoint_ids(
1206179c0ebSAleksandr Urakov RegisterContextWindows::GetNumHardwareBreakpointSlots(),
1216179c0ebSAleksandr Urakov LLDB_INVALID_BREAK_ID) {}
12218a9135dSAdrian McCarthy
~ProcessWindows()123b9c1b51eSKate Stone ProcessWindows::~ProcessWindows() {}
12418a9135dSAdrian McCarthy
GetSTDOUT(char * buf,size_t buf_size,Status & error)12597206d57SZachary Turner size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) {
12618a9135dSAdrian McCarthy error.SetErrorString("GetSTDOUT unsupported on Windows");
12718a9135dSAdrian McCarthy return 0;
12818a9135dSAdrian McCarthy }
12918a9135dSAdrian McCarthy
GetSTDERR(char * buf,size_t buf_size,Status & error)13097206d57SZachary Turner size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) {
13118a9135dSAdrian McCarthy error.SetErrorString("GetSTDERR unsupported on Windows");
13218a9135dSAdrian McCarthy return 0;
13318a9135dSAdrian McCarthy }
13418a9135dSAdrian McCarthy
PutSTDIN(const char * buf,size_t buf_size,Status & error)135b9c1b51eSKate Stone size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
13697206d57SZachary Turner Status &error) {
13718a9135dSAdrian McCarthy error.SetErrorString("PutSTDIN unsupported on Windows");
13818a9135dSAdrian McCarthy return 0;
13918a9135dSAdrian McCarthy }
14018a9135dSAdrian McCarthy
EnableBreakpointSite(BreakpointSite * bp_site)14197206d57SZachary Turner Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
142b352e62fSTatyana Krasnukha if (bp_site->HardwareRequired())
143b352e62fSTatyana Krasnukha return Status("Hardware breakpoints are not supported.");
144b352e62fSTatyana Krasnukha
1456730df47SPavel Labath Log *log = GetLog(WindowsLog::Breakpoints);
146a385d2c1SPavel Labath LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
147a385d2c1SPavel Labath bp_site->GetID(), bp_site->GetLoadAddress());
1484ad5def9SAdrian McCarthy
14997206d57SZachary Turner Status error = EnableSoftwareBreakpoint(bp_site);
150a385d2c1SPavel Labath if (!error.Success())
151a385d2c1SPavel Labath LLDB_LOG(log, "error: {0}", error);
1524ad5def9SAdrian McCarthy return error;
1534ad5def9SAdrian McCarthy }
1544ad5def9SAdrian McCarthy
DisableBreakpointSite(BreakpointSite * bp_site)15597206d57SZachary Turner Status ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {
1566730df47SPavel Labath Log *log = GetLog(WindowsLog::Breakpoints);
157a385d2c1SPavel Labath LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
158a385d2c1SPavel Labath bp_site->GetID(), bp_site->GetLoadAddress());
1594ad5def9SAdrian McCarthy
16097206d57SZachary Turner Status error = DisableSoftwareBreakpoint(bp_site);
1614ad5def9SAdrian McCarthy
162a385d2c1SPavel Labath if (!error.Success())
163a385d2c1SPavel Labath LLDB_LOG(log, "error: {0}", error);
1644ad5def9SAdrian McCarthy return error;
1654ad5def9SAdrian McCarthy }
1664ad5def9SAdrian McCarthy
DoDetach(bool keep_stopped)16797206d57SZachary Turner Status ProcessWindows::DoDetach(bool keep_stopped) {
168ed499a36SStella Stamenova Status error;
1696730df47SPavel Labath Log *log = GetLog(WindowsLog::Process);
170053eb356SAaron Smith StateType private_state = GetPrivateState();
171ed499a36SStella Stamenova if (private_state != eStateExited && private_state != eStateDetached) {
172053eb356SAaron Smith error = DetachProcess();
173053eb356SAaron Smith if (error.Success())
174ed499a36SStella Stamenova SetPrivateState(eStateDetached);
175053eb356SAaron Smith else
176053eb356SAaron Smith LLDB_LOG(log, "Detaching process error: {0}", error);
177ed499a36SStella Stamenova } else {
178ed78dc8eSMartin Storsjo error.SetErrorStringWithFormatv("error: process {0} in state = {1}, but "
179053eb356SAaron Smith "cannot detach it in this state.",
180053eb356SAaron Smith GetID(), private_state);
181053eb356SAaron Smith LLDB_LOG(log, "error: {0}", error);
182ed499a36SStella Stamenova }
1834ad5def9SAdrian McCarthy return error;
1844ad5def9SAdrian McCarthy }
1854ad5def9SAdrian McCarthy
DoLaunch(Module * exe_module,ProcessLaunchInfo & launch_info)18697206d57SZachary Turner Status ProcessWindows::DoLaunch(Module *exe_module,
1874ad5def9SAdrian McCarthy ProcessLaunchInfo &launch_info) {
188053eb356SAaron Smith Status error;
1894ad5def9SAdrian McCarthy DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
190053eb356SAaron Smith error = LaunchProcess(launch_info, delegate);
191053eb356SAaron Smith if (error.Success())
192053eb356SAaron Smith SetID(launch_info.GetProcessID());
1934ad5def9SAdrian McCarthy return error;
1944ad5def9SAdrian McCarthy }
1954ad5def9SAdrian McCarthy
19697206d57SZachary Turner Status
DoAttachToProcessWithID(lldb::pid_t pid,const ProcessAttachInfo & attach_info)19797206d57SZachary Turner ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,
19897206d57SZachary Turner const ProcessAttachInfo &attach_info) {
1994ad5def9SAdrian McCarthy DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
200053eb356SAaron Smith Status error = AttachProcess(pid, attach_info, delegate);
201053eb356SAaron Smith if (error.Success())
202053eb356SAaron Smith SetID(GetDebuggedProcessId());
2034ad5def9SAdrian McCarthy return error;
2044ad5def9SAdrian McCarthy }
2054ad5def9SAdrian McCarthy
DoResume()20697206d57SZachary Turner Status ProcessWindows::DoResume() {
2076730df47SPavel Labath Log *log = GetLog(WindowsLog::Process);
2084ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
20997206d57SZachary Turner Status error;
2104ad5def9SAdrian McCarthy
2114ad5def9SAdrian McCarthy StateType private_state = GetPrivateState();
2124ad5def9SAdrian McCarthy if (private_state == eStateStopped || private_state == eStateCrashed) {
213a385d2c1SPavel Labath LLDB_LOG(log, "process {0} is in state {1}. Resuming...",
2144ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(),
2154ad5def9SAdrian McCarthy GetPrivateState());
2164ad5def9SAdrian McCarthy
217a385d2c1SPavel Labath LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());
2184ad5def9SAdrian McCarthy
2190fd67b53SStella Stamenova bool failed = false;
2204ad5def9SAdrian McCarthy for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
2214ad5def9SAdrian McCarthy auto thread = std::static_pointer_cast<TargetThreadWindows>(
2224ad5def9SAdrian McCarthy m_thread_list.GetThreadAtIndex(i));
2230fd67b53SStella Stamenova Status result = thread->DoResume();
2240fd67b53SStella Stamenova if (result.Fail()) {
2250fd67b53SStella Stamenova failed = true;
22662c76db4SStella Stamenova LLDB_LOG(
22762c76db4SStella Stamenova log,
22862c76db4SStella Stamenova "Trying to resume thread at index {0}, but failed with error {1}.",
22962c76db4SStella Stamenova i, result);
2300fd67b53SStella Stamenova }
2314ad5def9SAdrian McCarthy }
2324ad5def9SAdrian McCarthy
2330fd67b53SStella Stamenova if (failed) {
2340fd67b53SStella Stamenova error.SetErrorString("ProcessWindows::DoResume failed");
2350fd67b53SStella Stamenova } else {
2364ad5def9SAdrian McCarthy SetPrivateState(eStateRunning);
2370fd67b53SStella Stamenova }
2383f062102SAdrian McCarthy
2393f062102SAdrian McCarthy ExceptionRecordSP active_exception =
2403f062102SAdrian McCarthy m_session_data->m_debugger->GetActiveException().lock();
2413f062102SAdrian McCarthy if (active_exception) {
2423f062102SAdrian McCarthy // Resume the process and continue processing debug events. Mask the
2433f062102SAdrian McCarthy // exception so that from the process's view, there is no indication that
2443f062102SAdrian McCarthy // anything happened.
2453f062102SAdrian McCarthy m_session_data->m_debugger->ContinueAsyncException(
2463f062102SAdrian McCarthy ExceptionResult::MaskException);
2473f062102SAdrian McCarthy }
2484ad5def9SAdrian McCarthy } else {
249c28daec5SAaron Smith LLDB_LOG(log, "error: process {0} is in state {1}. Returning...",
2504ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(),
2514ad5def9SAdrian McCarthy GetPrivateState());
2524ad5def9SAdrian McCarthy }
2534ad5def9SAdrian McCarthy return error;
2544ad5def9SAdrian McCarthy }
2554ad5def9SAdrian McCarthy
DoDestroy()25697206d57SZachary Turner Status ProcessWindows::DoDestroy() {
257053eb356SAaron Smith StateType private_state = GetPrivateState();
258053eb356SAaron Smith return DestroyProcess(private_state);
2594ad5def9SAdrian McCarthy }
2604ad5def9SAdrian McCarthy
DoHalt(bool & caused_stop)26197206d57SZachary Turner Status ProcessWindows::DoHalt(bool &caused_stop) {
2624ad5def9SAdrian McCarthy StateType state = GetPrivateState();
263053eb356SAaron Smith if (state != eStateStopped)
264053eb356SAaron Smith return HaltProcess(caused_stop);
2654ad5def9SAdrian McCarthy caused_stop = false;
266053eb356SAaron Smith return Status();
2674ad5def9SAdrian McCarthy }
2684ad5def9SAdrian McCarthy
DidLaunch()2694ad5def9SAdrian McCarthy void ProcessWindows::DidLaunch() {
2704ad5def9SAdrian McCarthy ArchSpec arch_spec;
2714ad5def9SAdrian McCarthy DidAttach(arch_spec);
2724ad5def9SAdrian McCarthy }
2734ad5def9SAdrian McCarthy
DidAttach(ArchSpec & arch_spec)2744ad5def9SAdrian McCarthy void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
2754ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
2764ad5def9SAdrian McCarthy
2774ad5def9SAdrian McCarthy // The initial stop won't broadcast the state change event, so account for
2784ad5def9SAdrian McCarthy // that here.
2794ad5def9SAdrian McCarthy if (m_session_data && GetPrivateState() == eStateStopped &&
2804ad5def9SAdrian McCarthy m_session_data->m_stop_at_entry)
2814ad5def9SAdrian McCarthy RefreshStateAfterStop();
2824ad5def9SAdrian McCarthy }
2834ad5def9SAdrian McCarthy
28426366c3eSAleksandr Urakov static void
DumpAdditionalExceptionInformation(llvm::raw_ostream & stream,const ExceptionRecordSP & exception)28526366c3eSAleksandr Urakov DumpAdditionalExceptionInformation(llvm::raw_ostream &stream,
28626366c3eSAleksandr Urakov const ExceptionRecordSP &exception) {
28726366c3eSAleksandr Urakov // Decode additional exception information for specific exception types based
28826366c3eSAleksandr Urakov // on
28926366c3eSAleksandr Urakov // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record
29026366c3eSAleksandr Urakov
29126366c3eSAleksandr Urakov const int addr_min_width = 2 + 8; // "0x" + 4 address bytes
29226366c3eSAleksandr Urakov
29326366c3eSAleksandr Urakov const std::vector<ULONG_PTR> &args = exception->GetExceptionArguments();
29426366c3eSAleksandr Urakov switch (exception->GetExceptionCode()) {
29526366c3eSAleksandr Urakov case EXCEPTION_ACCESS_VIOLATION: {
29626366c3eSAleksandr Urakov if (args.size() < 2)
29726366c3eSAleksandr Urakov break;
29826366c3eSAleksandr Urakov
29926366c3eSAleksandr Urakov stream << ": ";
30026366c3eSAleksandr Urakov const int access_violation_code = args[0];
30126366c3eSAleksandr Urakov const lldb::addr_t access_violation_address = args[1];
30226366c3eSAleksandr Urakov switch (access_violation_code) {
30326366c3eSAleksandr Urakov case 0:
30426366c3eSAleksandr Urakov stream << "Access violation reading";
30526366c3eSAleksandr Urakov break;
30626366c3eSAleksandr Urakov case 1:
30726366c3eSAleksandr Urakov stream << "Access violation writing";
30826366c3eSAleksandr Urakov break;
30926366c3eSAleksandr Urakov case 8:
31026366c3eSAleksandr Urakov stream << "User-mode data execution prevention (DEP) violation at";
31126366c3eSAleksandr Urakov break;
31226366c3eSAleksandr Urakov default:
31326366c3eSAleksandr Urakov stream << "Unknown access violation (code " << access_violation_code
31426366c3eSAleksandr Urakov << ") at";
31526366c3eSAleksandr Urakov break;
31626366c3eSAleksandr Urakov }
31726366c3eSAleksandr Urakov stream << " location "
31826366c3eSAleksandr Urakov << llvm::format_hex(access_violation_address, addr_min_width);
31926366c3eSAleksandr Urakov break;
32026366c3eSAleksandr Urakov }
32126366c3eSAleksandr Urakov case EXCEPTION_IN_PAGE_ERROR: {
32226366c3eSAleksandr Urakov if (args.size() < 3)
32326366c3eSAleksandr Urakov break;
32426366c3eSAleksandr Urakov
32526366c3eSAleksandr Urakov stream << ": ";
32626366c3eSAleksandr Urakov const int page_load_error_code = args[0];
32726366c3eSAleksandr Urakov const lldb::addr_t page_load_error_address = args[1];
32826366c3eSAleksandr Urakov const DWORD underlying_code = args[2];
32926366c3eSAleksandr Urakov switch (page_load_error_code) {
33026366c3eSAleksandr Urakov case 0:
33126366c3eSAleksandr Urakov stream << "In page error reading";
33226366c3eSAleksandr Urakov break;
33326366c3eSAleksandr Urakov case 1:
33426366c3eSAleksandr Urakov stream << "In page error writing";
33526366c3eSAleksandr Urakov break;
33626366c3eSAleksandr Urakov case 8:
33726366c3eSAleksandr Urakov stream << "User-mode data execution prevention (DEP) violation at";
33826366c3eSAleksandr Urakov break;
33926366c3eSAleksandr Urakov default:
34026366c3eSAleksandr Urakov stream << "Unknown page loading error (code " << page_load_error_code
34126366c3eSAleksandr Urakov << ") at";
34226366c3eSAleksandr Urakov break;
34326366c3eSAleksandr Urakov }
34426366c3eSAleksandr Urakov stream << " location "
34526366c3eSAleksandr Urakov << llvm::format_hex(page_load_error_address, addr_min_width)
34626366c3eSAleksandr Urakov << " (status code " << llvm::format_hex(underlying_code, 8) << ")";
34726366c3eSAleksandr Urakov break;
34826366c3eSAleksandr Urakov }
34926366c3eSAleksandr Urakov }
35026366c3eSAleksandr Urakov }
35126366c3eSAleksandr Urakov
RefreshStateAfterStop()3524ad5def9SAdrian McCarthy void ProcessWindows::RefreshStateAfterStop() {
3536730df47SPavel Labath Log *log = GetLog(WindowsLog::Exception);
3544ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
3554ad5def9SAdrian McCarthy
3564ad5def9SAdrian McCarthy if (!m_session_data) {
357a385d2c1SPavel Labath LLDB_LOG(log, "no active session. Returning...");
3584ad5def9SAdrian McCarthy return;
3594ad5def9SAdrian McCarthy }
3604ad5def9SAdrian McCarthy
3614ad5def9SAdrian McCarthy m_thread_list.RefreshStateAfterStop();
3624ad5def9SAdrian McCarthy
3634ad5def9SAdrian McCarthy std::weak_ptr<ExceptionRecord> exception_record =
3644ad5def9SAdrian McCarthy m_session_data->m_debugger->GetActiveException();
3654ad5def9SAdrian McCarthy ExceptionRecordSP active_exception = exception_record.lock();
3664ad5def9SAdrian McCarthy if (!active_exception) {
36762c76db4SStella Stamenova LLDB_LOG(log,
36862c76db4SStella Stamenova "there is no active exception in process {0}. Why is the "
369a385d2c1SPavel Labath "process stopped?",
3704ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId());
3714ad5def9SAdrian McCarthy return;
3724ad5def9SAdrian McCarthy }
3734ad5def9SAdrian McCarthy
3744ad5def9SAdrian McCarthy StopInfoSP stop_info;
3754ad5def9SAdrian McCarthy m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
3764ad5def9SAdrian McCarthy ThreadSP stop_thread = m_thread_list.GetSelectedThread();
3774ad5def9SAdrian McCarthy if (!stop_thread)
3784ad5def9SAdrian McCarthy return;
3794ad5def9SAdrian McCarthy
3804ad5def9SAdrian McCarthy switch (active_exception->GetExceptionCode()) {
3814ad5def9SAdrian McCarthy case EXCEPTION_SINGLE_STEP: {
3824ad5def9SAdrian McCarthy RegisterContextSP register_context = stop_thread->GetRegisterContext();
3834ad5def9SAdrian McCarthy const uint64_t pc = register_context->GetPC();
3844ad5def9SAdrian McCarthy BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
385479c3577SJim Ingham if (site && site->ValidForThisThread(*stop_thread)) {
38662c76db4SStella Stamenova LLDB_LOG(log,
38762c76db4SStella Stamenova "Single-stepped onto a breakpoint in process {0} at "
388a385d2c1SPavel Labath "address {1:x} with breakpoint site {2}",
3894ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
3904ad5def9SAdrian McCarthy site->GetID());
3914ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
3924ad5def9SAdrian McCarthy site->GetID());
3934ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info);
3946179c0ebSAleksandr Urakov
3956179c0ebSAleksandr Urakov return;
3966179c0ebSAleksandr Urakov }
3976179c0ebSAleksandr Urakov
3986179c0ebSAleksandr Urakov auto *reg_ctx = static_cast<RegisterContextWindows *>(
3996179c0ebSAleksandr Urakov stop_thread->GetRegisterContext().get());
4006179c0ebSAleksandr Urakov uint32_t slot_id = reg_ctx->GetTriggeredHardwareBreakpointSlotId();
4016179c0ebSAleksandr Urakov if (slot_id != LLDB_INVALID_INDEX32) {
4026179c0ebSAleksandr Urakov int id = m_watchpoint_ids[slot_id];
4036179c0ebSAleksandr Urakov LLDB_LOG(log,
4046179c0ebSAleksandr Urakov "Single-stepped onto a watchpoint in process {0} at address "
4056179c0ebSAleksandr Urakov "{1:x} with watchpoint {2}",
4066179c0ebSAleksandr Urakov m_session_data->m_debugger->GetProcess().GetProcessId(), pc, id);
4076179c0ebSAleksandr Urakov
4086179c0ebSAleksandr Urakov if (lldb::WatchpointSP wp_sp =
4096179c0ebSAleksandr Urakov GetTarget().GetWatchpointList().FindByID(id))
4106179c0ebSAleksandr Urakov wp_sp->SetHardwareIndex(slot_id);
4116179c0ebSAleksandr Urakov
4126179c0ebSAleksandr Urakov stop_info = StopInfo::CreateStopReasonWithWatchpointID(
4136179c0ebSAleksandr Urakov *stop_thread, id, m_watchpoints[id].address);
4146179c0ebSAleksandr Urakov stop_thread->SetStopInfo(stop_info);
4156179c0ebSAleksandr Urakov
4166179c0ebSAleksandr Urakov return;
4176179c0ebSAleksandr Urakov }
4186179c0ebSAleksandr Urakov
419a385d2c1SPavel Labath LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());
4204ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
4214ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info);
4226179c0ebSAleksandr Urakov
4234ad5def9SAdrian McCarthy return;
4244ad5def9SAdrian McCarthy }
4254ad5def9SAdrian McCarthy
4264ad5def9SAdrian McCarthy case EXCEPTION_BREAKPOINT: {
4274ad5def9SAdrian McCarthy RegisterContextSP register_context = stop_thread->GetRegisterContext();
4284ad5def9SAdrian McCarthy
4299f34f75fSMartin Storsjö int breakpoint_size = 1;
4309f34f75fSMartin Storsjö switch (GetTarget().GetArchitecture().GetMachine()) {
4319f34f75fSMartin Storsjö case llvm::Triple::aarch64:
4329f34f75fSMartin Storsjö breakpoint_size = 4;
4339f34f75fSMartin Storsjö break;
4349f34f75fSMartin Storsjö
4359f34f75fSMartin Storsjö case llvm::Triple::arm:
4369f34f75fSMartin Storsjö case llvm::Triple::thumb:
4379f34f75fSMartin Storsjö breakpoint_size = 2;
4389f34f75fSMartin Storsjö break;
4399f34f75fSMartin Storsjö
4409f34f75fSMartin Storsjö case llvm::Triple::x86:
4419f34f75fSMartin Storsjö case llvm::Triple::x86_64:
4429f34f75fSMartin Storsjö breakpoint_size = 1;
4439f34f75fSMartin Storsjö break;
4449f34f75fSMartin Storsjö
4459f34f75fSMartin Storsjö default:
4469f34f75fSMartin Storsjö LLDB_LOG(log, "Unknown breakpoint size for architecture");
4479f34f75fSMartin Storsjö break;
4489f34f75fSMartin Storsjö }
4499f34f75fSMartin Storsjö
4509f34f75fSMartin Storsjö // The current PC is AFTER the BP opcode, on all architectures.
4519f34f75fSMartin Storsjö uint64_t pc = register_context->GetPC() - breakpoint_size;
4524ad5def9SAdrian McCarthy
4534ad5def9SAdrian McCarthy BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
4544ad5def9SAdrian McCarthy if (site) {
45562c76db4SStella Stamenova LLDB_LOG(log,
45662c76db4SStella Stamenova "detected breakpoint in process {0} at address {1:x} with "
457a385d2c1SPavel Labath "breakpoint site {2}",
4584ad5def9SAdrian McCarthy m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
4594ad5def9SAdrian McCarthy site->GetID());
4604ad5def9SAdrian McCarthy
461479c3577SJim Ingham if (site->ValidForThisThread(*stop_thread)) {
46262c76db4SStella Stamenova LLDB_LOG(log,
46362c76db4SStella Stamenova "Breakpoint site {0} is valid for this thread ({1:x}), "
4644ad5def9SAdrian McCarthy "creating stop info.",
4654ad5def9SAdrian McCarthy site->GetID(), stop_thread->GetID());
4664ad5def9SAdrian McCarthy
4674ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
4684ad5def9SAdrian McCarthy *stop_thread, site->GetID());
4694ad5def9SAdrian McCarthy register_context->SetPC(pc);
4704ad5def9SAdrian McCarthy } else {
47162c76db4SStella Stamenova LLDB_LOG(log,
47262c76db4SStella Stamenova "Breakpoint site {0} is not valid for this thread, "
4734ad5def9SAdrian McCarthy "creating empty stop info.",
4744ad5def9SAdrian McCarthy site->GetID());
4754ad5def9SAdrian McCarthy }
4764ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info);
4774ad5def9SAdrian McCarthy return;
4784ad5def9SAdrian McCarthy } else {
4794ad5def9SAdrian McCarthy // The thread hit a hard-coded breakpoint like an `int 3` or
4804ad5def9SAdrian McCarthy // `__debugbreak()`.
481a385d2c1SPavel Labath LLDB_LOG(log,
4824ad5def9SAdrian McCarthy "No breakpoint site matches for this thread. __debugbreak()? "
4834ad5def9SAdrian McCarthy "Creating stop info with the exception.");
4844ad5def9SAdrian McCarthy // FALLTHROUGH: We'll treat this as a generic exception record in the
4854ad5def9SAdrian McCarthy // default case.
486b0717666SAlexandre Ganea LLVM_FALLTHROUGH;
4874ad5def9SAdrian McCarthy }
4884ad5def9SAdrian McCarthy }
4894ad5def9SAdrian McCarthy
4904ad5def9SAdrian McCarthy default: {
4914ad5def9SAdrian McCarthy std::string desc;
4924ad5def9SAdrian McCarthy llvm::raw_string_ostream desc_stream(desc);
4934ad5def9SAdrian McCarthy desc_stream << "Exception "
4944ad5def9SAdrian McCarthy << llvm::format_hex(active_exception->GetExceptionCode(), 8)
4954ad5def9SAdrian McCarthy << " encountered at address "
4964ad5def9SAdrian McCarthy << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
49726366c3eSAleksandr Urakov DumpAdditionalExceptionInformation(desc_stream, active_exception);
49826366c3eSAleksandr Urakov
4994ad5def9SAdrian McCarthy stop_info = StopInfo::CreateStopReasonWithException(
5004ad5def9SAdrian McCarthy *stop_thread, desc_stream.str().c_str());
5014ad5def9SAdrian McCarthy stop_thread->SetStopInfo(stop_info);
502a385d2c1SPavel Labath LLDB_LOG(log, "{0}", desc_stream.str());
5034ad5def9SAdrian McCarthy return;
5044ad5def9SAdrian McCarthy }
5054ad5def9SAdrian McCarthy }
5064ad5def9SAdrian McCarthy }
5074ad5def9SAdrian McCarthy
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)5084ad5def9SAdrian McCarthy bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
5094ad5def9SAdrian McCarthy bool plugin_specified_by_name) {
5104ad5def9SAdrian McCarthy if (plugin_specified_by_name)
5114ad5def9SAdrian McCarthy return true;
5124ad5def9SAdrian McCarthy
5134ad5def9SAdrian McCarthy // For now we are just making sure the file exists for a given module
5144ad5def9SAdrian McCarthy ModuleSP exe_module_sp(target_sp->GetExecutableModule());
5154ad5def9SAdrian McCarthy if (exe_module_sp.get())
51660cf3f82SJonas Devlieghere return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
51705097246SAdrian Prantl // However, if there is no executable module, we return true since we might
51805097246SAdrian Prantl // be preparing to attach.
5194ad5def9SAdrian McCarthy return true;
5204ad5def9SAdrian McCarthy }
5214ad5def9SAdrian McCarthy
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)5224bb62448SWalter Erquinigo bool ProcessWindows::DoUpdateThreadList(ThreadList &old_thread_list,
5234ad5def9SAdrian McCarthy ThreadList &new_thread_list) {
5246730df47SPavel Labath Log *log = GetLog(WindowsLog::Thread);
5254ad5def9SAdrian McCarthy // Add all the threads that were previously running and for which we did not
5264ad5def9SAdrian McCarthy // detect a thread exited event.
5274ad5def9SAdrian McCarthy int new_size = 0;
5284ad5def9SAdrian McCarthy int continued_threads = 0;
5294ad5def9SAdrian McCarthy int exited_threads = 0;
5304ad5def9SAdrian McCarthy int new_threads = 0;
5314ad5def9SAdrian McCarthy
5324ad5def9SAdrian McCarthy for (ThreadSP old_thread : old_thread_list.Threads()) {
5334ad5def9SAdrian McCarthy lldb::tid_t old_thread_id = old_thread->GetID();
5344ad5def9SAdrian McCarthy auto exited_thread_iter =
5354ad5def9SAdrian McCarthy m_session_data->m_exited_threads.find(old_thread_id);
5364ad5def9SAdrian McCarthy if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
5374ad5def9SAdrian McCarthy new_thread_list.AddThread(old_thread);
5384ad5def9SAdrian McCarthy ++new_size;
5394ad5def9SAdrian McCarthy ++continued_threads;
540a385d2c1SPavel Labath LLDB_LOGV(log, "Thread {0} was running and is still running.",
5414ad5def9SAdrian McCarthy old_thread_id);
5424ad5def9SAdrian McCarthy } else {
543a385d2c1SPavel Labath LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id);
5444ad5def9SAdrian McCarthy ++exited_threads;
5454ad5def9SAdrian McCarthy }
5464ad5def9SAdrian McCarthy }
5474ad5def9SAdrian McCarthy
54805097246SAdrian Prantl // Also add all the threads that are new since the last time we broke into
54905097246SAdrian Prantl // the debugger.
5504ad5def9SAdrian McCarthy for (const auto &thread_info : m_session_data->m_new_threads) {
5516179c0ebSAleksandr Urakov new_thread_list.AddThread(thread_info.second);
5524ad5def9SAdrian McCarthy ++new_size;
5534ad5def9SAdrian McCarthy ++new_threads;
554a385d2c1SPavel Labath LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first);
5554ad5def9SAdrian McCarthy }
5564ad5def9SAdrian McCarthy
557a385d2c1SPavel Labath LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.",
5584ad5def9SAdrian McCarthy new_threads, continued_threads, exited_threads);
5594ad5def9SAdrian McCarthy
5604ad5def9SAdrian McCarthy m_session_data->m_new_threads.clear();
5614ad5def9SAdrian McCarthy m_session_data->m_exited_threads.clear();
5624ad5def9SAdrian McCarthy
5634ad5def9SAdrian McCarthy return new_size > 0;
5644ad5def9SAdrian McCarthy }
5654ad5def9SAdrian McCarthy
IsAlive()5664ad5def9SAdrian McCarthy bool ProcessWindows::IsAlive() {
5674ad5def9SAdrian McCarthy StateType state = GetPrivateState();
5684ad5def9SAdrian McCarthy switch (state) {
5694ad5def9SAdrian McCarthy case eStateCrashed:
5704ad5def9SAdrian McCarthy case eStateDetached:
5714ad5def9SAdrian McCarthy case eStateUnloaded:
5724ad5def9SAdrian McCarthy case eStateExited:
5734ad5def9SAdrian McCarthy case eStateInvalid:
5744ad5def9SAdrian McCarthy return false;
5754ad5def9SAdrian McCarthy default:
5764ad5def9SAdrian McCarthy return true;
5774ad5def9SAdrian McCarthy }
5784ad5def9SAdrian McCarthy }
5794ad5def9SAdrian McCarthy
GetSystemArchitecture()58068099b1dSJonas Devlieghere ArchSpec ProcessWindows::GetSystemArchitecture() {
58168099b1dSJonas Devlieghere return HostInfo::GetArchitecture();
58268099b1dSJonas Devlieghere }
58368099b1dSJonas Devlieghere
DoReadMemory(lldb::addr_t vm_addr,void * buf,size_t size,Status & error)5844ad5def9SAdrian McCarthy size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
58597206d57SZachary Turner size_t size, Status &error) {
586053eb356SAaron Smith size_t bytes_read = 0;
587053eb356SAaron Smith error = ProcessDebugger::ReadMemory(vm_addr, buf, size, bytes_read);
5884ad5def9SAdrian McCarthy return bytes_read;
5894ad5def9SAdrian McCarthy }
5904ad5def9SAdrian McCarthy
DoWriteMemory(lldb::addr_t vm_addr,const void * buf,size_t size,Status & error)5914ad5def9SAdrian McCarthy size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
59297206d57SZachary Turner size_t size, Status &error) {
593053eb356SAaron Smith size_t bytes_written = 0;
594053eb356SAaron Smith error = ProcessDebugger::WriteMemory(vm_addr, buf, size, bytes_written);
5954ad5def9SAdrian McCarthy return bytes_written;
5964ad5def9SAdrian McCarthy }
5974ad5def9SAdrian McCarthy
DoAllocateMemory(size_t size,uint32_t permissions,Status & error)5989d5b2d4aSAleksandr Urakov lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions,
5999d5b2d4aSAleksandr Urakov Status &error) {
600053eb356SAaron Smith lldb::addr_t vm_addr = LLDB_INVALID_ADDRESS;
601053eb356SAaron Smith error = ProcessDebugger::AllocateMemory(size, permissions, vm_addr);
602053eb356SAaron Smith return vm_addr;
6039d5b2d4aSAleksandr Urakov }
6049d5b2d4aSAleksandr Urakov
DoDeallocateMemory(lldb::addr_t ptr)6059d5b2d4aSAleksandr Urakov Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) {
606053eb356SAaron Smith return ProcessDebugger::DeallocateMemory(ptr);
6079d5b2d4aSAleksandr Urakov }
6089d5b2d4aSAleksandr Urakov
DoGetMemoryRegionInfo(lldb::addr_t vm_addr,MemoryRegionInfo & info)6092937b282SDavid Spickett Status ProcessWindows::DoGetMemoryRegionInfo(lldb::addr_t vm_addr,
6104ad5def9SAdrian McCarthy MemoryRegionInfo &info) {
6115fbcf677SDavid Spickett return ProcessDebugger::GetMemoryRegionInfo(vm_addr, info);
6124ad5def9SAdrian McCarthy }
6134ad5def9SAdrian McCarthy
GetImageInfoAddress()614b9c1b51eSKate Stone lldb::addr_t ProcessWindows::GetImageInfoAddress() {
61518a9135dSAdrian McCarthy Target &target = GetTarget();
61618a9135dSAdrian McCarthy ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
61718a9135dSAdrian McCarthy Address addr = obj_file->GetImageInfoAddress(&target);
61818a9135dSAdrian McCarthy if (addr.IsValid())
61918a9135dSAdrian McCarthy return addr.GetLoadAddress(&target);
62018a9135dSAdrian McCarthy else
62118a9135dSAdrian McCarthy return LLDB_INVALID_ADDRESS;
62218a9135dSAdrian McCarthy }
62318a9135dSAdrian McCarthy
GetDynamicLoader()624eb6671e7SAaron Smith DynamicLoaderWindowsDYLD *ProcessWindows::GetDynamicLoader() {
62596b82107SAaron Smith if (m_dyld_up.get() == NULL)
62696b82107SAaron Smith m_dyld_up.reset(DynamicLoader::FindPlugin(
6271397c56dSPavel Labath this, DynamicLoaderWindowsDYLD::GetPluginNameStatic()));
62896b82107SAaron Smith return static_cast<DynamicLoaderWindowsDYLD *>(m_dyld_up.get());
629eb6671e7SAaron Smith }
630eb6671e7SAaron Smith
OnExitProcess(uint32_t exit_code)6314ad5def9SAdrian McCarthy void ProcessWindows::OnExitProcess(uint32_t exit_code) {
6324ad5def9SAdrian McCarthy // No need to acquire the lock since m_session_data isn't accessed.
6336730df47SPavel Labath Log *log = GetLog(WindowsLog::Process);
634a385d2c1SPavel Labath LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
6354ad5def9SAdrian McCarthy
636d7e126c4SJim Ingham TargetSP target = CalculateTarget();
6374ad5def9SAdrian McCarthy if (target) {
6384ad5def9SAdrian McCarthy ModuleSP executable_module = target->GetExecutableModule();
6394ad5def9SAdrian McCarthy ModuleList unloaded_modules;
6404ad5def9SAdrian McCarthy unloaded_modules.Append(executable_module);
6414ad5def9SAdrian McCarthy target->ModulesDidUnload(unloaded_modules, true);
6424ad5def9SAdrian McCarthy }
6434ad5def9SAdrian McCarthy
6444ad5def9SAdrian McCarthy SetProcessExitStatus(GetID(), true, 0, exit_code);
6454ad5def9SAdrian McCarthy SetPrivateState(eStateExited);
646e3037904SAaron Smith
647403cd574SMartin Storsjö ProcessDebugger::OnExitProcess(exit_code);
6484ad5def9SAdrian McCarthy }
6494ad5def9SAdrian McCarthy
OnDebuggerConnected(lldb::addr_t image_base)6504ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
6514ad5def9SAdrian McCarthy DebuggerThreadSP debugger = m_session_data->m_debugger;
6526730df47SPavel Labath Log *log = GetLog(WindowsLog::Process);
653a385d2c1SPavel Labath LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
6544ad5def9SAdrian McCarthy debugger->GetProcess().GetProcessId(), image_base);
6554ad5def9SAdrian McCarthy
6564ad5def9SAdrian McCarthy ModuleSP module = GetTarget().GetExecutableModule();
6574ad5def9SAdrian McCarthy if (!module) {
6584ad5def9SAdrian McCarthy // During attach, we won't have the executable module, so find it now.
6594ad5def9SAdrian McCarthy const DWORD pid = debugger->GetProcess().GetProcessId();
6604ad5def9SAdrian McCarthy const std::string file_name = GetProcessExecutableName(pid);
6614ad5def9SAdrian McCarthy if (file_name.empty()) {
6624ad5def9SAdrian McCarthy return;
6634ad5def9SAdrian McCarthy }
6644ad5def9SAdrian McCarthy
66554bb3161SAleksandr Urakov FileSpec executable_file(file_name);
66654bb3161SAleksandr Urakov FileSystem::Instance().Resolve(executable_file);
6674ad5def9SAdrian McCarthy ModuleSpec module_spec(executable_file);
66897206d57SZachary Turner Status error;
6696179c0ebSAleksandr Urakov module =
6706179c0ebSAleksandr Urakov GetTarget().GetOrCreateModule(module_spec, true /* notify */, &error);
6714ad5def9SAdrian McCarthy if (!module) {
6724ad5def9SAdrian McCarthy return;
6734ad5def9SAdrian McCarthy }
6744ad5def9SAdrian McCarthy
675d54ee88aSTatyana Krasnukha GetTarget().SetExecutableModule(module, eLoadDependentsNo);
6764ad5def9SAdrian McCarthy }
6774ad5def9SAdrian McCarthy
678eb6671e7SAaron Smith if (auto dyld = GetDynamicLoader())
679a2d9fdf5SStella Stamenova dyld->OnLoadModule(module, ModuleSpec(), image_base);
6804ad5def9SAdrian McCarthy
6814ad5def9SAdrian McCarthy // Add the main executable module to the list of pending module loads. We
68205097246SAdrian Prantl // can't call GetTarget().ModulesDidLoad() here because we still haven't
68305097246SAdrian Prantl // returned from DoLaunch() / DoAttach() yet so the target may not have set
68405097246SAdrian Prantl // the process instance to `this` yet.
6854ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
6866179c0ebSAleksandr Urakov
6876179c0ebSAleksandr Urakov const HostThread &host_main_thread = debugger->GetMainThread();
6886179c0ebSAleksandr Urakov ThreadSP main_thread =
6896179c0ebSAleksandr Urakov std::make_shared<TargetThreadWindows>(*this, host_main_thread);
6906179c0ebSAleksandr Urakov
6916179c0ebSAleksandr Urakov tid_t id = host_main_thread.GetNativeThread().GetThreadId();
6926179c0ebSAleksandr Urakov main_thread->SetID(id);
6936179c0ebSAleksandr Urakov
6946179c0ebSAleksandr Urakov m_session_data->m_new_threads[id] = main_thread;
6954ad5def9SAdrian McCarthy }
6964ad5def9SAdrian McCarthy
6974ad5def9SAdrian McCarthy ExceptionResult
OnDebugException(bool first_chance,const ExceptionRecord & record)6984ad5def9SAdrian McCarthy ProcessWindows::OnDebugException(bool first_chance,
6994ad5def9SAdrian McCarthy const ExceptionRecord &record) {
7006730df47SPavel Labath Log *log = GetLog(WindowsLog::Exception);
7014ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
7024ad5def9SAdrian McCarthy
7034ad5def9SAdrian McCarthy // FIXME: Without this check, occasionally when running the test suite there
7044ad5def9SAdrian McCarthy // is
7054ad5def9SAdrian McCarthy // an issue where m_session_data can be null. It's not clear how this could
70605097246SAdrian Prantl // happen but it only surfaces while running the test suite. In order to
70705097246SAdrian Prantl // properly diagnose this, we probably need to first figure allow the test
70805097246SAdrian Prantl // suite to print out full lldb logs, and then add logging to the process
70905097246SAdrian Prantl // plugin.
7104ad5def9SAdrian McCarthy if (!m_session_data) {
71162c76db4SStella Stamenova LLDB_LOG(log,
71262c76db4SStella Stamenova "Debugger thread reported exception {0:x} at address {1:x}, "
713a385d2c1SPavel Labath "but there is no session.",
7144ad5def9SAdrian McCarthy record.GetExceptionCode(), record.GetExceptionAddress());
7154ad5def9SAdrian McCarthy return ExceptionResult::SendToApplication;
7164ad5def9SAdrian McCarthy }
7174ad5def9SAdrian McCarthy
7184ad5def9SAdrian McCarthy if (!first_chance) {
719a5235af9SAleksandr Urakov // Not any second chance exception is an application crash by definition.
720a5235af9SAleksandr Urakov // It may be an expression evaluation crash.
721a5235af9SAleksandr Urakov SetPrivateState(eStateStopped);
7224ad5def9SAdrian McCarthy }
7234ad5def9SAdrian McCarthy
7244ad5def9SAdrian McCarthy ExceptionResult result = ExceptionResult::SendToApplication;
7254ad5def9SAdrian McCarthy switch (record.GetExceptionCode()) {
7264ad5def9SAdrian McCarthy case EXCEPTION_BREAKPOINT:
7274ad5def9SAdrian McCarthy // Handle breakpoints at the first chance.
7284ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger;
7294ad5def9SAdrian McCarthy
7304ad5def9SAdrian McCarthy if (!m_session_data->m_initial_stop_received) {
731a385d2c1SPavel Labath LLDB_LOG(
732a385d2c1SPavel Labath log,
733a385d2c1SPavel Labath "Hit loader breakpoint at address {0:x}, setting initial stop event.",
7344ad5def9SAdrian McCarthy record.GetExceptionAddress());
7354ad5def9SAdrian McCarthy m_session_data->m_initial_stop_received = true;
7364ad5def9SAdrian McCarthy ::SetEvent(m_session_data->m_initial_stop_event);
7374ad5def9SAdrian McCarthy } else {
738a385d2c1SPavel Labath LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
7394ad5def9SAdrian McCarthy record.GetExceptionAddress());
7404ad5def9SAdrian McCarthy }
7414ad5def9SAdrian McCarthy SetPrivateState(eStateStopped);
7424ad5def9SAdrian McCarthy break;
7434ad5def9SAdrian McCarthy case EXCEPTION_SINGLE_STEP:
7444ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger;
7454ad5def9SAdrian McCarthy SetPrivateState(eStateStopped);
7464ad5def9SAdrian McCarthy break;
7474ad5def9SAdrian McCarthy default:
74862c76db4SStella Stamenova LLDB_LOG(log,
74962c76db4SStella Stamenova "Debugger thread reported exception {0:x} at address {1:x} "
750a385d2c1SPavel Labath "(first_chance={2})",
7514ad5def9SAdrian McCarthy record.GetExceptionCode(), record.GetExceptionAddress(),
752a385d2c1SPavel Labath first_chance);
7534ad5def9SAdrian McCarthy // For non-breakpoints, give the application a chance to handle the
7544ad5def9SAdrian McCarthy // exception first.
7554ad5def9SAdrian McCarthy if (first_chance)
7564ad5def9SAdrian McCarthy result = ExceptionResult::SendToApplication;
7574ad5def9SAdrian McCarthy else
7584ad5def9SAdrian McCarthy result = ExceptionResult::BreakInDebugger;
7594ad5def9SAdrian McCarthy }
7604ad5def9SAdrian McCarthy
7614ad5def9SAdrian McCarthy return result;
7624ad5def9SAdrian McCarthy }
7634ad5def9SAdrian McCarthy
OnCreateThread(const HostThread & new_thread)7644ad5def9SAdrian McCarthy void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
7654ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
7666179c0ebSAleksandr Urakov
7676179c0ebSAleksandr Urakov ThreadSP thread = std::make_shared<TargetThreadWindows>(*this, new_thread);
7686179c0ebSAleksandr Urakov
7696179c0ebSAleksandr Urakov const HostNativeThread &native_new_thread = new_thread.GetNativeThread();
7706179c0ebSAleksandr Urakov tid_t id = native_new_thread.GetThreadId();
7716179c0ebSAleksandr Urakov thread->SetID(id);
7726179c0ebSAleksandr Urakov
7736179c0ebSAleksandr Urakov m_session_data->m_new_threads[id] = thread;
7746179c0ebSAleksandr Urakov
7756179c0ebSAleksandr Urakov for (const std::map<int, WatchpointInfo>::value_type &p : m_watchpoints) {
7766179c0ebSAleksandr Urakov auto *reg_ctx = static_cast<RegisterContextWindows *>(
7776179c0ebSAleksandr Urakov thread->GetRegisterContext().get());
7786179c0ebSAleksandr Urakov reg_ctx->AddHardwareBreakpoint(p.second.slot_id, p.second.address,
7796179c0ebSAleksandr Urakov p.second.size, p.second.read,
7806179c0ebSAleksandr Urakov p.second.write);
7816179c0ebSAleksandr Urakov }
7824ad5def9SAdrian McCarthy }
7834ad5def9SAdrian McCarthy
OnExitThread(lldb::tid_t thread_id,uint32_t exit_code)7844ad5def9SAdrian McCarthy void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
7854ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
7864ad5def9SAdrian McCarthy
7874ad5def9SAdrian McCarthy // On a forced termination, we may get exit thread events after the session
7884ad5def9SAdrian McCarthy // data has been cleaned up.
7894ad5def9SAdrian McCarthy if (!m_session_data)
7904ad5def9SAdrian McCarthy return;
7914ad5def9SAdrian McCarthy
7924ad5def9SAdrian McCarthy // A thread may have started and exited before the debugger stopped allowing a
7934ad5def9SAdrian McCarthy // refresh.
7944ad5def9SAdrian McCarthy // Just remove it from the new threads list in that case.
7954ad5def9SAdrian McCarthy auto iter = m_session_data->m_new_threads.find(thread_id);
7964ad5def9SAdrian McCarthy if (iter != m_session_data->m_new_threads.end())
7974ad5def9SAdrian McCarthy m_session_data->m_new_threads.erase(iter);
7984ad5def9SAdrian McCarthy else
7994ad5def9SAdrian McCarthy m_session_data->m_exited_threads.insert(thread_id);
8004ad5def9SAdrian McCarthy }
8014ad5def9SAdrian McCarthy
OnLoadDll(const ModuleSpec & module_spec,lldb::addr_t module_addr)8024ad5def9SAdrian McCarthy void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
8034ad5def9SAdrian McCarthy lldb::addr_t module_addr) {
804eb6671e7SAaron Smith if (auto dyld = GetDynamicLoader())
805a2d9fdf5SStella Stamenova dyld->OnLoadModule(nullptr, module_spec, module_addr);
8064ad5def9SAdrian McCarthy }
8074ad5def9SAdrian McCarthy
OnUnloadDll(lldb::addr_t module_addr)8084ad5def9SAdrian McCarthy void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
809eb6671e7SAaron Smith if (auto dyld = GetDynamicLoader())
810eb6671e7SAaron Smith dyld->OnUnloadModule(module_addr);
8114ad5def9SAdrian McCarthy }
8124ad5def9SAdrian McCarthy
OnDebugString(const std::string & string)8134ad5def9SAdrian McCarthy void ProcessWindows::OnDebugString(const std::string &string) {}
8144ad5def9SAdrian McCarthy
OnDebuggerError(const Status & error,uint32_t type)81597206d57SZachary Turner void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {
8164ad5def9SAdrian McCarthy llvm::sys::ScopedLock lock(m_mutex);
8176730df47SPavel Labath Log *log = GetLog(WindowsLog::Process);
8184ad5def9SAdrian McCarthy
8194ad5def9SAdrian McCarthy if (m_session_data->m_initial_stop_received) {
82005097246SAdrian Prantl // This happened while debugging. Do we shutdown the debugging session,
82105097246SAdrian Prantl // try to continue, or do something else?
82262c76db4SStella Stamenova LLDB_LOG(log,
82362c76db4SStella Stamenova "Error {0} occurred during debugging. Unexpected behavior "
824a385d2c1SPavel Labath "may result. {1}",
825a385d2c1SPavel Labath error.GetError(), error);
8264ad5def9SAdrian McCarthy } else {
8274ad5def9SAdrian McCarthy // If we haven't actually launched the process yet, this was an error
82805097246SAdrian Prantl // launching the process. Set the internal error and signal the initial
82905097246SAdrian Prantl // stop event so that the DoLaunch method wakes up and returns a failure.
8304ad5def9SAdrian McCarthy m_session_data->m_launch_error = error;
8314ad5def9SAdrian McCarthy ::SetEvent(m_session_data->m_initial_stop_event);
832a385d2c1SPavel Labath LLDB_LOG(
833a385d2c1SPavel Labath log,
834a385d2c1SPavel Labath "Error {0} occurred launching the process before the initial stop. {1}",
835a385d2c1SPavel Labath error.GetError(), error);
8364ad5def9SAdrian McCarthy return;
8374ad5def9SAdrian McCarthy }
8384ad5def9SAdrian McCarthy }
8396179c0ebSAleksandr Urakov
GetWatchpointSupportInfo(uint32_t & num)8406179c0ebSAleksandr Urakov Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num) {
8416179c0ebSAleksandr Urakov num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
8426179c0ebSAleksandr Urakov return {};
8436179c0ebSAleksandr Urakov }
8446179c0ebSAleksandr Urakov
GetWatchpointSupportInfo(uint32_t & num,bool & after)8456179c0ebSAleksandr Urakov Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
8466179c0ebSAleksandr Urakov num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
8476179c0ebSAleksandr Urakov after = RegisterContextWindows::DoHardwareBreakpointsTriggerAfter();
8486179c0ebSAleksandr Urakov return {};
8496179c0ebSAleksandr Urakov }
8506179c0ebSAleksandr Urakov
EnableWatchpoint(Watchpoint * wp,bool notify)8516179c0ebSAleksandr Urakov Status ProcessWindows::EnableWatchpoint(Watchpoint *wp, bool notify) {
8526179c0ebSAleksandr Urakov Status error;
8536179c0ebSAleksandr Urakov
8546179c0ebSAleksandr Urakov if (wp->IsEnabled()) {
8556179c0ebSAleksandr Urakov wp->SetEnabled(true, notify);
8566179c0ebSAleksandr Urakov return error;
8576179c0ebSAleksandr Urakov }
8586179c0ebSAleksandr Urakov
8596179c0ebSAleksandr Urakov WatchpointInfo info;
8606179c0ebSAleksandr Urakov for (info.slot_id = 0;
8616179c0ebSAleksandr Urakov info.slot_id < RegisterContextWindows::GetNumHardwareBreakpointSlots();
8626179c0ebSAleksandr Urakov info.slot_id++)
8636179c0ebSAleksandr Urakov if (m_watchpoint_ids[info.slot_id] == LLDB_INVALID_BREAK_ID)
8646179c0ebSAleksandr Urakov break;
8656179c0ebSAleksandr Urakov if (info.slot_id == RegisterContextWindows::GetNumHardwareBreakpointSlots()) {
8666179c0ebSAleksandr Urakov error.SetErrorStringWithFormat("Can't find free slot for watchpoint %i",
8676179c0ebSAleksandr Urakov wp->GetID());
8686179c0ebSAleksandr Urakov return error;
8696179c0ebSAleksandr Urakov }
8706179c0ebSAleksandr Urakov info.address = wp->GetLoadAddress();
8716179c0ebSAleksandr Urakov info.size = wp->GetByteSize();
8726179c0ebSAleksandr Urakov info.read = wp->WatchpointRead();
8736179c0ebSAleksandr Urakov info.write = wp->WatchpointWrite();
8746179c0ebSAleksandr Urakov
8756179c0ebSAleksandr Urakov for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
8766179c0ebSAleksandr Urakov Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
8776179c0ebSAleksandr Urakov auto *reg_ctx = static_cast<RegisterContextWindows *>(
8786179c0ebSAleksandr Urakov thread->GetRegisterContext().get());
8796179c0ebSAleksandr Urakov if (!reg_ctx->AddHardwareBreakpoint(info.slot_id, info.address, info.size,
8806179c0ebSAleksandr Urakov info.read, info.write)) {
8816179c0ebSAleksandr Urakov error.SetErrorStringWithFormat(
8826179c0ebSAleksandr Urakov "Can't enable watchpoint %i on thread 0x%llx", wp->GetID(),
8836179c0ebSAleksandr Urakov thread->GetID());
8846179c0ebSAleksandr Urakov break;
8856179c0ebSAleksandr Urakov }
8866179c0ebSAleksandr Urakov }
8876179c0ebSAleksandr Urakov if (error.Fail()) {
8886179c0ebSAleksandr Urakov for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
8896179c0ebSAleksandr Urakov Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
8906179c0ebSAleksandr Urakov auto *reg_ctx = static_cast<RegisterContextWindows *>(
8916179c0ebSAleksandr Urakov thread->GetRegisterContext().get());
8926179c0ebSAleksandr Urakov reg_ctx->RemoveHardwareBreakpoint(info.slot_id);
8936179c0ebSAleksandr Urakov }
8946179c0ebSAleksandr Urakov return error;
8956179c0ebSAleksandr Urakov }
8966179c0ebSAleksandr Urakov
8976179c0ebSAleksandr Urakov m_watchpoints[wp->GetID()] = info;
8986179c0ebSAleksandr Urakov m_watchpoint_ids[info.slot_id] = wp->GetID();
8996179c0ebSAleksandr Urakov
9006179c0ebSAleksandr Urakov wp->SetEnabled(true, notify);
9016179c0ebSAleksandr Urakov
9026179c0ebSAleksandr Urakov return error;
9036179c0ebSAleksandr Urakov }
9046179c0ebSAleksandr Urakov
DisableWatchpoint(Watchpoint * wp,bool notify)9056179c0ebSAleksandr Urakov Status ProcessWindows::DisableWatchpoint(Watchpoint *wp, bool notify) {
9066179c0ebSAleksandr Urakov Status error;
9076179c0ebSAleksandr Urakov
9086179c0ebSAleksandr Urakov if (!wp->IsEnabled()) {
9096179c0ebSAleksandr Urakov wp->SetEnabled(false, notify);
9106179c0ebSAleksandr Urakov return error;
9116179c0ebSAleksandr Urakov }
9126179c0ebSAleksandr Urakov
9136179c0ebSAleksandr Urakov auto it = m_watchpoints.find(wp->GetID());
9146179c0ebSAleksandr Urakov if (it == m_watchpoints.end()) {
9156179c0ebSAleksandr Urakov error.SetErrorStringWithFormat("Info about watchpoint %i is not found",
9166179c0ebSAleksandr Urakov wp->GetID());
9176179c0ebSAleksandr Urakov return error;
9186179c0ebSAleksandr Urakov }
9196179c0ebSAleksandr Urakov
9206179c0ebSAleksandr Urakov for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
9216179c0ebSAleksandr Urakov Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
9226179c0ebSAleksandr Urakov auto *reg_ctx = static_cast<RegisterContextWindows *>(
9236179c0ebSAleksandr Urakov thread->GetRegisterContext().get());
9246179c0ebSAleksandr Urakov if (!reg_ctx->RemoveHardwareBreakpoint(it->second.slot_id)) {
9256179c0ebSAleksandr Urakov error.SetErrorStringWithFormat(
9266179c0ebSAleksandr Urakov "Can't disable watchpoint %i on thread 0x%llx", wp->GetID(),
9276179c0ebSAleksandr Urakov thread->GetID());
9286179c0ebSAleksandr Urakov break;
9296179c0ebSAleksandr Urakov }
9306179c0ebSAleksandr Urakov }
9316179c0ebSAleksandr Urakov if (error.Fail())
9326179c0ebSAleksandr Urakov return error;
9336179c0ebSAleksandr Urakov
9346179c0ebSAleksandr Urakov m_watchpoint_ids[it->second.slot_id] = LLDB_INVALID_BREAK_ID;
9356179c0ebSAleksandr Urakov m_watchpoints.erase(it);
9366179c0ebSAleksandr Urakov
9376179c0ebSAleksandr Urakov wp->SetEnabled(false, notify);
9386179c0ebSAleksandr Urakov
9396179c0ebSAleksandr Urakov return error;
9406179c0ebSAleksandr Urakov }
9414ad5def9SAdrian McCarthy } // namespace lldb_private
942