//===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Windows includes #include "lldb/Host/windows/windows.h" // C++ Includes // Other libraries and framework includes #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Target.h" #include "ProcessWindows.h" using namespace lldb; using namespace lldb_private; namespace { HANDLE GetStdioHandle(ProcessLaunchInfo &launch_info, int fd) { const ProcessLaunchInfo::FileAction *action = launch_info.GetFileActionForFD(fd); if (action == nullptr) return NULL; SECURITY_ATTRIBUTES secattr = {0}; secattr.nLength = sizeof(SECURITY_ATTRIBUTES); secattr.bInheritHandle = TRUE; const char *path = action->GetPath(); DWORD access = 0; DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD create = 0; DWORD flags = 0; if (fd == STDIN_FILENO) { access = GENERIC_READ; create = OPEN_EXISTING; flags = FILE_ATTRIBUTE_READONLY; } if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { access = GENERIC_WRITE; create = CREATE_ALWAYS; if (fd == STDERR_FILENO) flags = FILE_FLAG_WRITE_THROUGH; } HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL); return (result == INVALID_HANDLE_VALUE) ? NULL : result; } } //------------------------------------------------------------------------------ // Static functions. ProcessSP ProcessWindows::CreateInstance(Target &target, Listener &listener, const FileSpec *) { return ProcessSP(new ProcessWindows(target, listener)); } void ProcessWindows::Initialize() { static bool g_initialized = false; if (!g_initialized) { g_initialized = true; PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); } } //------------------------------------------------------------------------------ // Constructors and destructors. ProcessWindows::ProcessWindows(Target& target, Listener &listener) : lldb_private::Process(target, listener) { } void ProcessWindows::Terminate() { } lldb_private::ConstString ProcessWindows::GetPluginNameStatic() { static ConstString g_name("windows"); return g_name; } const char * ProcessWindows::GetPluginDescriptionStatic() { return "Process plugin for Windows"; } bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { new_thread_list = old_thread_list; return new_thread_list.GetSize(false) > 0; } Error ProcessWindows::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { std::string executable; std::string commandLine; std::vector environment; STARTUPINFO startupinfo = {0}; PROCESS_INFORMATION pi = {0}; HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO); HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO); HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO); startupinfo.cb = sizeof(startupinfo); startupinfo.dwFlags |= STARTF_USESTDHANDLES; startupinfo.hStdError = stderr_handle; startupinfo.hStdInput = stdin_handle; startupinfo.hStdOutput = stdout_handle; executable = launch_info.GetExecutableFile().GetPath(); launch_info.GetArguments().GetQuotedCommandString(commandLine); BOOL result = ::CreateProcessA(executable.c_str(), const_cast(commandLine.c_str()), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, launch_info.GetWorkingDirectory(), &startupinfo, &pi); if (result) { ::CloseHandle(pi.hProcess); ::CloseHandle(pi.hThread); } if (stdin_handle) ::CloseHandle(stdin_handle); if (stdout_handle) ::CloseHandle(stdout_handle); if (stderr_handle) ::CloseHandle(stderr_handle); Error error; if (!result) error.SetErrorToErrno(); return error; } Error ProcessWindows::DoResume() { Error error; return error; } //------------------------------------------------------------------------------ // ProcessInterface protocol. lldb_private::ConstString ProcessWindows::GetPluginName() { return GetPluginNameStatic(); } uint32_t ProcessWindows::GetPluginVersion() { return 1; } void ProcessWindows::GetPluginCommandHelp(const char *command, Stream *strm) { } Error ProcessWindows::ExecutePluginCommand(Args &command, Stream *strm) { return Error(1, eErrorTypeGeneric); } Log * ProcessWindows::EnablePluginLogging(Stream *strm, Args &command) { return NULL; } Error ProcessWindows::DoDetach(bool keep_stopped) { Error error; error.SetErrorString("Detaching from processes is not currently supported on Windows."); return error; } Error ProcessWindows::DoDestroy() { Error error; error.SetErrorString("Destroying processes is not currently supported on Windows."); return error; } void ProcessWindows::RefreshStateAfterStop() { } bool ProcessWindows::IsAlive() { return false; } size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Error &error) { return 0; } bool ProcessWindows::CanDebug(Target &target, bool plugin_specified_by_name) { if (plugin_specified_by_name) return true; // For now we are just making sure the file exists for a given module ModuleSP exe_module_sp(target.GetExecutableModule()); if (exe_module_sp.get()) return exe_module_sp->GetFileSpec().Exists(); return false; }