blob: e2197caf02466fd729469b04fe1220908e1fd3bc [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;
250 return module_filespec;
251}
252
253void *
254Host::DynamicLibraryOpen(const FileSpec &file_spec, uint32_t options, Error &error)
255{
256 error.SetErrorString("not implemented");
257 return NULL;
258}
259
260Error
261Host::DynamicLibraryClose (void *opaque)
262{
263 Error error;
264 error.SetErrorString("not implemented");
265 return error;
266}
267
268void *
269Host::DynamicLibraryGetSymbol(void *opaque, const char *symbol_name, Error &error)
270{
271 error.SetErrorString("not implemented");
272 return NULL;
273}
274
275const char *
276Host::GetUserName (uint32_t uid, std::string &user_name)
277{
278 return NULL;
279}
280
281const char *
282Host::GetGroupName (uint32_t gid, std::string &group_name)
283{
Zachary Turner310035a2014-07-08 04:52:15 +0000284 llvm_unreachable("Windows does not support group name");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000285 return NULL;
286}
287
288uint32_t
289Host::GetUserID ()
290{
Zachary Turner310035a2014-07-08 04:52:15 +0000291 llvm_unreachable("Windows does not support uid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000292}
293
294uint32_t
295Host::GetGroupID ()
296{
Zachary Turner310035a2014-07-08 04:52:15 +0000297 llvm_unreachable("Windows does not support gid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000298 return 0;
299}
300
301uint32_t
302Host::GetEffectiveUserID ()
303{
Zachary Turner310035a2014-07-08 04:52:15 +0000304 llvm_unreachable("Windows does not support euid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000305 return 0;
306}
307
308uint32_t
309Host::GetEffectiveGroupID ()
310{
Zachary Turner310035a2014-07-08 04:52:15 +0000311 llvm_unreachable("Windows does not support egid");
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000312 return 0;
313}
314
Zachary Turner310035a2014-07-08 04:52:15 +0000315uint32_t
316Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
317{
318 process_infos.Clear();
319
320 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
321 if (!snapshot.IsValid())
322 return 0;
323
324 PROCESSENTRY32 pe = {0};
325 pe.dwSize = sizeof(PROCESSENTRY32);
326 if (Process32First(snapshot.get(), &pe))
327 {
328 do
329 {
330 AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
331
332 ProcessInstanceInfo process;
333 process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
334 process.SetProcessID(pe.th32ProcessID);
335 process.SetParentProcessID(pe.th32ParentProcessID);
336 GetProcessExecutableAndTriple(handle, process);
337
338 if (match_info.MatchAllProcesses() || match_info.Matches(process))
339 process_infos.Append(process);
340 } while (Process32Next(snapshot.get(), &pe));
341 }
342 return process_infos.GetSize();
343}
344
345bool
346Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
347{
348 process_info.Clear();
349
350 AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
351 nullptr);
352 if (!handle.IsValid())
353 return false;
354
355 process_info.SetProcessID(pid);
356 GetProcessExecutableAndTriple(handle, process_info);
357
358 // Need to read the PEB to get parent process and command line arguments.
359 return true;
360}
361
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000362lldb::thread_t
363Host::StartMonitoringChildProcess
364(
365 Host::MonitorChildProcessCallback callback,
366 void *callback_baton,
367 lldb::pid_t pid,
368 bool monitor_signals
369)
370{
371 return LLDB_INVALID_HOST_THREAD;
372}