blob: 9fa265200e4b381493845ec573c368e83d467576 [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
11#include <stdio.h>
12#include "lldb/Host/windows/windows.h"
Zachary Turner310035a2014-07-08 04:52:15 +000013#include "lldb/Host/windows/AutoHandle.h"
Virgile Bellob2f1fb22013-08-23 12:44:05 +000014
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/Error.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Target/Process.h"
21
22#include "lldb/Host/Host.h"
23#include "lldb/Core/DataBufferHeap.h"
24#include "lldb/Core/DataExtractor.h"
Zachary Turner310035a2014-07-08 04:52:15 +000025#include "lldb/Core/StreamFile.h"
26
27// Windows includes
28#include <TlHelp32.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000029
30using namespace lldb;
31using namespace lldb_private;
32
Zachary Turner310035a2014-07-08 04:52:15 +000033namespace
34{
35 bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple)
36 {
37 // Open the PE File as a binary file, and parse just enough information to determine the
38 // machine type.
39 File imageBinary(
40 executable.GetPath().c_str(),
41 File::eOpenOptionRead,
42 lldb::eFilePermissionsUserRead);
43 imageBinary.SeekFromStart(0x3c);
44 int32_t peOffset = 0;
45 uint32_t peHead = 0;
46 uint16_t machineType = 0;
47 size_t readSize = sizeof(peOffset);
48 imageBinary.Read(&peOffset, readSize);
49 imageBinary.SeekFromStart(peOffset);
50 imageBinary.Read(&peHead, readSize);
51 if (peHead != 0x00004550) // "PE\0\0", little-endian
52 return false; // Error: Can't find PE header
53 readSize = 2;
54 imageBinary.Read(&machineType, readSize);
55 triple.setVendor(llvm::Triple::PC);
56 triple.setOS(llvm::Triple::Win32);
57 triple.setArch(llvm::Triple::UnknownArch);
58 if (machineType == 0x8664)
59 triple.setArch(llvm::Triple::x86_64);
60 else if (machineType == 0x14c)
61 triple.setArch(llvm::Triple::x86);
62
63 return true;
64 }
65
66 bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
67 {
68 // Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB.
69 std::vector<char> buffer(32768);
70 DWORD dwSize = buffer.size();
71 if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize))
72 return false;
73 path.assign(&buffer[0]);
74 return true;
75 }
76
77 void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
78 {
79 // We may not have permissions to read the path from the process. So start off by
80 // setting the executable file to whatever Toolhelp32 gives us, and then try 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 {
89 FileSpec executableFile(executable.c_str(), false);
90 process.SetExecutableFile(executableFile, true);
91 GetTripleForProcess(executableFile, triple);
92 }
93 process.SetArchitecture(ArchSpec(triple));
94
95 // TODO(zturner): Add the ability to get the process user name.
96 }
97}
98
Virgile Bellob2f1fb22013-08-23 12:44:05 +000099bool
100Host::GetOSVersion(uint32_t &major,
101 uint32_t &minor,
102 uint32_t &update)
103{
104 OSVERSIONINFOEX info;
105
106 ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
107 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
Todd Fiala4dc62522014-06-02 17:30:22 +0000108#pragma warning(push)
109#pragma warning(disable: 4996)
110 // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in favor of the
111 // new Windows Version Helper APIs. Since we don't specify a minimum SDK version, it's easier
112 // to simply disable the warning rather than try to support both APIs.
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000113 if (GetVersionEx((LPOSVERSIONINFO) &info) == 0) {
114 return false;
115 }
Todd Fiala4dc62522014-06-02 17:30:22 +0000116#pragma warning(pop)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000117
118 major = (uint32_t) info.dwMajorVersion;
119 minor = (uint32_t) info.dwMinorVersion;
120 update = (uint32_t) info.wServicePackMajor;
121
122 return true;
123}
124
125Error
126Host::LaunchProcess (ProcessLaunchInfo &launch_info)
127{
128 Error error;
129 assert(!"Not implemented yet!!!");
130 return error;
131}
132
133lldb::DataBufferSP
134Host::GetAuxvData(lldb_private::Process *process)
135{
136 return 0;
137}
138
139std::string
140Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
141{
142 return std::string();
143}
144
145lldb::tid_t
146Host::GetCurrentThreadID()
147{
148 return lldb::tid_t(::GetCurrentThreadId());
149}
150
151lldb::thread_t
152Host::GetCurrentThread ()
153{
154 return lldb::thread_t(::GetCurrentThread());
155}
156
157bool
158Host::ThreadCancel (lldb::thread_t thread, Error *error)
159{
160 int err = ::TerminateThread((HANDLE)thread, 0);
161 return err == 0;
162}
163
164bool
165Host::ThreadDetach (lldb::thread_t thread, Error *error)
166{
167 return ThreadCancel(thread, error);
168}
169
170bool
171Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error)
172{
173 WaitForSingleObject((HANDLE) thread, INFINITE);
174 return true;
175}
176
177lldb::thread_key_t
178Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
179{
180 return TlsAlloc();
181}
182
183void*
184Host::ThreadLocalStorageGet(lldb::thread_key_t key)
185{
186 return ::TlsGetValue (key);
187}
188
189void
190Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
191{
192 ::TlsSetValue (key, value);
193}
194
195bool
196Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
197{
198 return false;
199}
200
201bool
202Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid,
203 const char *thread_name, size_t len)
204{
205 return false;
206}
207
208void
209Host::Kill(lldb::pid_t pid, int signo)
210{
211 TerminateProcess((HANDLE) pid, 1);
212}
213
214uint32_t
215Host::GetNumberCPUS()
216{
217 static uint32_t g_num_cores = UINT32_MAX;
218 if (g_num_cores == UINT32_MAX)
219 {
220 SYSTEM_INFO system_info;
221 ::GetSystemInfo(&system_info);
222 g_num_cores = system_info.dwNumberOfProcessors;
223 }
224 return g_num_cores;
225}
226
227size_t
228Host::GetPageSize()
229{
230 static long g_pagesize = 0;
231 if (!g_pagesize)
232 {
233 SYSTEM_INFO systemInfo;
234 GetNativeSystemInfo(&systemInfo);
235 g_pagesize = systemInfo.dwPageSize;
236 }
237 return g_pagesize;
238}
239
240const char *
241Host::GetSignalAsCString(int signo)
242{
243 return NULL;
244}
245
246FileSpec
247Host::GetModuleFileSpecForHostAddress (const void *host_addr)
248{
249 FileSpec module_filespec;
Zachary Turnerc9bf0c72014-07-18 20:36:08 +0000250
251 HMODULE hmodule = NULL;
252 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
253 return module_filespec;
254
255 std::vector<char> buffer(MAX_PATH);
256 DWORD chars_copied = 0;
257 do {
258 chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
259 if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
260 buffer.resize(buffer.size() * 2);
261 } while (chars_copied >= buffer.size());
262
263 module_filespec.SetFile(&buffer[0], false);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000264 return module_filespec;
265}
266
267void *
268Host::DynamicLibraryOpen(const FileSpec &file_spec, uint32_t options, Error &error)
269{
270 error.SetErrorString("not implemented");
271 return NULL;
272}
273
274Error
275Host::DynamicLibraryClose (void *opaque)
276{
277 Error error;
278 error.SetErrorString("not implemented");
279 return error;
280}
281
282void *
283Host::DynamicLibraryGetSymbol(void *opaque, const char *symbol_name, Error &error)
284{
285 error.SetErrorString("not implemented");
286 return NULL;
287}
288
289const char *
290Host::GetUserName (uint32_t uid, std::string &user_name)
291{
292 return NULL;
293}
294
295const char *
296Host::GetGroupName (uint32_t gid, std::string &group_name)
297{
Zachary Turner310035a2014-07-08 04:52:15 +0000298 llvm_unreachable("Windows does not support group name");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000299 return NULL;
300}
301
302uint32_t
303Host::GetUserID ()
304{
Zachary Turner310035a2014-07-08 04:52:15 +0000305 llvm_unreachable("Windows does not support uid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000306}
307
308uint32_t
309Host::GetGroupID ()
310{
Zachary Turner310035a2014-07-08 04:52:15 +0000311 llvm_unreachable("Windows does not support gid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000312 return 0;
313}
314
315uint32_t
316Host::GetEffectiveUserID ()
317{
Zachary Turner310035a2014-07-08 04:52:15 +0000318 llvm_unreachable("Windows does not support euid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000319 return 0;
320}
321
322uint32_t
323Host::GetEffectiveGroupID ()
324{
Zachary Turner310035a2014-07-08 04:52:15 +0000325 llvm_unreachable("Windows does not support egid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000326 return 0;
327}
328
Zachary Turner310035a2014-07-08 04:52:15 +0000329uint32_t
330Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
331{
332 process_infos.Clear();
333
334 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
335 if (!snapshot.IsValid())
336 return 0;
337
338 PROCESSENTRY32 pe = {0};
339 pe.dwSize = sizeof(PROCESSENTRY32);
340 if (Process32First(snapshot.get(), &pe))
341 {
342 do
343 {
344 AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
345
346 ProcessInstanceInfo process;
347 process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
348 process.SetProcessID(pe.th32ProcessID);
349 process.SetParentProcessID(pe.th32ParentProcessID);
350 GetProcessExecutableAndTriple(handle, process);
351
352 if (match_info.MatchAllProcesses() || match_info.Matches(process))
353 process_infos.Append(process);
354 } while (Process32Next(snapshot.get(), &pe));
355 }
356 return process_infos.GetSize();
357}
358
359bool
360Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
361{
362 process_info.Clear();
363
364 AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
365 nullptr);
366 if (!handle.IsValid())
367 return false;
368
369 process_info.SetProcessID(pid);
370 GetProcessExecutableAndTriple(handle, process_info);
371
372 // Need to read the PEB to get parent process and command line arguments.
373 return true;
374}
375
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000376lldb::thread_t
377Host::StartMonitoringChildProcess
378(
379 Host::MonitorChildProcessCallback callback,
380 void *callback_baton,
381 lldb::pid_t pid,
382 bool monitor_signals
383)
384{
385 return LLDB_INVALID_HOST_THREAD;
386}