blob: 538348224047a99e3c4e55f1180fd7a06774cfa4 [file] [log] [blame]
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001//===-- source/Host/windows/Host.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// C Includes
Zachary Turner310035a2014-07-08 04:52:15 +000011#include "lldb/Host/windows/AutoHandle.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000012#include "lldb/Host/windows/windows.h"
13#include <stdio.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000014
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "lldb/Host/Host.h"
19#include "lldb/Host/HostInfo.h"
Pavel Labathf1fb38b2017-06-30 11:31:13 +000020#include "lldb/Target/Process.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000021#include "lldb/Utility/DataBufferHeap.h"
22#include "lldb/Utility/DataExtractor.h"
Pavel Labathf1fb38b2017-06-30 11:31:13 +000023#include "lldb/Utility/Log.h"
24#include "lldb/Utility/Status.h"
Pavel Labathf2a8bcc2017-06-27 10:45:31 +000025#include "lldb/Utility/StructuredData.h"
Zachary Turner310035a2014-07-08 04:52:15 +000026
Zachary Turner190fadc2016-03-22 17:58:09 +000027#include "llvm/Support/ConvertUTF.h"
28
Zachary Turner310035a2014-07-08 04:52:15 +000029// Windows includes
Hafiz Abid Qadeerf6ee79c2016-12-15 15:00:41 +000030#include <tlhelp32.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Kate Stoneb9c1b512016-09-06 20:57:50 +000035namespace {
36bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) {
37 // Open the PE File as a binary file, and parse just enough information to
38 // determine the
39 // machine type.
40 File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead,
41 lldb::eFilePermissionsUserRead);
42 imageBinary.SeekFromStart(0x3c);
43 int32_t peOffset = 0;
44 uint32_t peHead = 0;
45 uint16_t machineType = 0;
46 size_t readSize = sizeof(peOffset);
47 imageBinary.Read(&peOffset, readSize);
48 imageBinary.SeekFromStart(peOffset);
49 imageBinary.Read(&peHead, readSize);
50 if (peHead != 0x00004550) // "PE\0\0", little-endian
Zachary Turner97206d52017-05-12 04:51:55 +000051 return false; // Status: Can't find PE header
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 readSize = 2;
53 imageBinary.Read(&machineType, readSize);
54 triple.setVendor(llvm::Triple::PC);
55 triple.setOS(llvm::Triple::Win32);
56 triple.setArch(llvm::Triple::UnknownArch);
57 if (machineType == 0x8664)
58 triple.setArch(llvm::Triple::x86_64);
59 else if (machineType == 0x14c)
60 triple.setArch(llvm::Triple::x86);
Zachary Turner310035a2014-07-08 04:52:15 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 return true;
Zachary Turner310035a2014-07-08 04:52:15 +000063}
64
Kate Stoneb9c1b512016-09-06 20:57:50 +000065bool GetExecutableForProcess(const AutoHandle &handle, std::string &path) {
66 // Get the process image path. MAX_PATH isn't long enough, paths can actually
67 // be up to 32KB.
68 std::vector<wchar_t> buffer(PATH_MAX);
69 DWORD dwSize = buffer.size();
70 if (!::QueryFullProcessImageNameW(handle.get(), 0, &buffer[0], &dwSize))
71 return false;
72 return llvm::convertWideToUTF8(buffer.data(), path);
Virgile Bellob2f1fb22013-08-23 12:44:05 +000073}
74
Kate Stoneb9c1b512016-09-06 20:57:50 +000075void GetProcessExecutableAndTriple(const AutoHandle &handle,
76 ProcessInstanceInfo &process) {
77 // We may not have permissions to read the path from the process. So start
78 // off by
79 // setting the executable file to whatever Toolhelp32 gives us, and then try
80 // to
81 // enhance this with more detailed information, but fail gracefully.
82 std::string executable;
83 llvm::Triple triple;
84 triple.setVendor(llvm::Triple::PC);
85 triple.setOS(llvm::Triple::Win32);
86 triple.setArch(llvm::Triple::UnknownArch);
87 if (GetExecutableForProcess(handle, executable)) {
88 FileSpec executableFile(executable.c_str(), false);
89 process.SetExecutableFile(executableFile, true);
90 GetTripleForProcess(executableFile, triple);
91 }
92 process.SetArchitecture(ArchSpec(triple));
93
94 // TODO(zturner): Add the ability to get the process user name.
95}
Virgile Bellob2f1fb22013-08-23 12:44:05 +000096}
97
Kate Stoneb9c1b512016-09-06 20:57:50 +000098lldb::thread_t Host::GetCurrentThread() {
99 return lldb::thread_t(::GetCurrentThread());
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000100}
101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102void Host::Kill(lldb::pid_t pid, int signo) {
103 TerminateProcess((HANDLE)pid, 1);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000104}
105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106const char *Host::GetSignalAsCString(int signo) { return NULL; }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
109 FileSpec module_filespec;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000110
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111 HMODULE hmodule = NULL;
112 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
113 (LPCTSTR)host_addr, &hmodule))
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000114 return module_filespec;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115
116 std::vector<wchar_t> buffer(PATH_MAX);
117 DWORD chars_copied = 0;
118 do {
119 chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
120 if (chars_copied == buffer.size() &&
121 ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
122 buffer.resize(buffer.size() * 2);
123 } while (chars_copied >= buffer.size());
124 std::string path;
125 if (!llvm::convertWideToUTF8(buffer.data(), path))
126 return module_filespec;
127 module_filespec.SetFile(path, false);
128 return module_filespec;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000129}
130
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
132 ProcessInstanceInfoList &process_infos) {
133 process_infos.Clear();
Zachary Turner310035a2014-07-08 04:52:15 +0000134
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
136 if (!snapshot.IsValid())
137 return 0;
Zachary Turner310035a2014-07-08 04:52:15 +0000138
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000139 PROCESSENTRY32W pe = {};
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 pe.dwSize = sizeof(PROCESSENTRY32W);
141 if (Process32FirstW(snapshot.get(), &pe)) {
142 do {
143 AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE,
144 pe.th32ProcessID),
145 nullptr);
Zachary Turner310035a2014-07-08 04:52:15 +0000146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 ProcessInstanceInfo process;
148 std::string exeFile;
149 llvm::convertWideToUTF8(pe.szExeFile, exeFile);
150 process.SetExecutableFile(FileSpec(exeFile, false), true);
151 process.SetProcessID(pe.th32ProcessID);
152 process.SetParentProcessID(pe.th32ParentProcessID);
153 GetProcessExecutableAndTriple(handle, process);
Zachary Turner310035a2014-07-08 04:52:15 +0000154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 if (match_info.MatchAllProcesses() || match_info.Matches(process))
156 process_infos.Append(process);
157 } while (Process32NextW(snapshot.get(), &pe));
158 }
159 return process_infos.GetSize();
160}
161
162bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
163 process_info.Clear();
164
165 AutoHandle handle(
166 ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
167 nullptr);
168 if (!handle.IsValid())
169 return false;
170
171 process_info.SetProcessID(pid);
172 GetProcessExecutableAndTriple(handle, process_info);
173
174 // Need to read the PEB to get parent process and command line arguments.
175 return true;
176}
177
178HostThread Host::StartMonitoringChildProcess(
179 const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid,
180 bool monitor_signals) {
181 return HostThread();
182}
183
Zachary Turner97206d52017-05-12 04:51:55 +0000184Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
185 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
187 FileSpec expand_tool_spec;
188 if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir,
189 expand_tool_spec)) {
190 error.SetErrorString("could not find support executable directory for "
191 "the lldb-argdumper tool");
192 return error;
Zachary Turner310035a2014-07-08 04:52:15 +0000193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194 expand_tool_spec.AppendPathComponent("lldb-argdumper.exe");
195 if (!expand_tool_spec.Exists()) {
196 error.SetErrorString("could not find the lldb-argdumper tool");
197 return error;
Enrico Granata83a14372015-02-20 21:48:38 +0000198 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199
200 std::string quoted_cmd_string;
201 launch_info.GetArguments().GetQuotedCommandString(quoted_cmd_string);
202 std::replace(quoted_cmd_string.begin(), quoted_cmd_string.end(), '\\', '/');
203 StreamString expand_command;
204
205 expand_command.Printf("\"%s\" %s", expand_tool_spec.GetPath().c_str(),
206 quoted_cmd_string.c_str());
207
208 int status;
209 std::string output;
Zachary Turnerc1564272016-11-16 21:15:24 +0000210 std::string command = expand_command.GetString();
211 RunShellCommand(command.c_str(), launch_info.GetWorkingDirectory(), &status,
212 nullptr, &output, 10);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213
214 if (status != 0) {
215 error.SetErrorStringWithFormat("lldb-argdumper exited with error %d",
216 status);
217 return error;
218 }
219
220 auto data_sp = StructuredData::ParseJSON(output);
221 if (!data_sp) {
222 error.SetErrorString("invalid JSON");
223 return error;
224 }
225
226 auto dict_sp = data_sp->GetAsDictionary();
227 if (!data_sp) {
228 error.SetErrorString("invalid JSON");
229 return error;
230 }
231
232 auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments");
233 if (!args_sp) {
234 error.SetErrorString("invalid JSON");
235 return error;
236 }
237
238 auto args_array_sp = args_sp->GetAsArray();
239 if (!args_array_sp) {
240 error.SetErrorString("invalid JSON");
241 return error;
242 }
243
244 launch_info.GetArguments().Clear();
245
246 for (size_t i = 0; i < args_array_sp->GetSize(); i++) {
247 auto item_sp = args_array_sp->GetItemAtIndex(i);
248 if (!item_sp)
249 continue;
250 auto str_sp = item_sp->GetAsString();
251 if (!str_sp)
252 continue;
253
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000254 launch_info.GetArguments().AppendArgument(str_sp->GetValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255 }
256 }
257
258 return error;
Enrico Granata83a14372015-02-20 21:48:38 +0000259}
Zachary Turner279a2b72015-05-22 19:34:17 +0000260
Pavel Labath62930e52018-01-10 11:57:31 +0000261Environment Host::GetEnvironment() {
262 Environment env;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263 // The environment block on Windows is a contiguous buffer of NULL terminated
Pavel Labath62930e52018-01-10 11:57:31 +0000264 // strings, where the end of the environment block is indicated by two
265 // consecutive NULLs.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 LPWCH environment_block = ::GetEnvironmentStringsW();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 while (*environment_block != L'\0') {
268 std::string current_var;
269 auto current_var_size = wcslen(environment_block) + 1;
270 if (!llvm::convertWideToUTF8(environment_block, current_var)) {
271 environment_block += current_var_size;
272 continue;
Zachary Turner279a2b72015-05-22 19:34:17 +0000273 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 if (current_var[0] != '=')
Pavel Labath62930e52018-01-10 11:57:31 +0000275 env.insert(current_var);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276
277 environment_block += current_var_size;
278 }
Pavel Labath62930e52018-01-10 11:57:31 +0000279 return env;
Zachary Turner279a2b72015-05-22 19:34:17 +0000280}