blob: 4542025f6eec258669a770f005cc596ad404ef3d [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 +000099Error
100Host::LaunchProcess (ProcessLaunchInfo &launch_info)
101{
102 Error error;
103 assert(!"Not implemented yet!!!");
104 return error;
105}
106
107lldb::DataBufferSP
108Host::GetAuxvData(lldb_private::Process *process)
109{
110 return 0;
111}
112
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000113lldb::tid_t
114Host::GetCurrentThreadID()
115{
116 return lldb::tid_t(::GetCurrentThreadId());
117}
118
119lldb::thread_t
120Host::GetCurrentThread ()
121{
122 return lldb::thread_t(::GetCurrentThread());
123}
124
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000125lldb::thread_key_t
126Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
127{
128 return TlsAlloc();
129}
130
131void*
132Host::ThreadLocalStorageGet(lldb::thread_key_t key)
133{
134 return ::TlsGetValue (key);
135}
136
137void
138Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
139{
140 ::TlsSetValue (key, value);
141}
142
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000143void
144Host::Kill(lldb::pid_t pid, int signo)
145{
146 TerminateProcess((HANDLE) pid, 1);
147}
148
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000149
150const char *
151Host::GetSignalAsCString(int signo)
152{
153 return NULL;
154}
155
156FileSpec
157Host::GetModuleFileSpecForHostAddress (const void *host_addr)
158{
159 FileSpec module_filespec;
Zachary Turnerc9bf0c72014-07-18 20:36:08 +0000160
161 HMODULE hmodule = NULL;
162 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
163 return module_filespec;
164
165 std::vector<char> buffer(MAX_PATH);
166 DWORD chars_copied = 0;
167 do {
168 chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
169 if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
170 buffer.resize(buffer.size() * 2);
171 } while (chars_copied >= buffer.size());
172
173 module_filespec.SetFile(&buffer[0], false);
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000174 return module_filespec;
175}
176
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000177uint32_t
Zachary Turner310035a2014-07-08 04:52:15 +0000178Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
179{
180 process_infos.Clear();
181
182 AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
183 if (!snapshot.IsValid())
184 return 0;
185
186 PROCESSENTRY32 pe = {0};
187 pe.dwSize = sizeof(PROCESSENTRY32);
188 if (Process32First(snapshot.get(), &pe))
189 {
190 do
191 {
192 AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
193
194 ProcessInstanceInfo process;
195 process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
196 process.SetProcessID(pe.th32ProcessID);
197 process.SetParentProcessID(pe.th32ParentProcessID);
198 GetProcessExecutableAndTriple(handle, process);
199
200 if (match_info.MatchAllProcesses() || match_info.Matches(process))
201 process_infos.Append(process);
202 } while (Process32Next(snapshot.get(), &pe));
203 }
204 return process_infos.GetSize();
205}
206
207bool
208Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
209{
210 process_info.Clear();
211
212 AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
213 nullptr);
214 if (!handle.IsValid())
215 return false;
216
217 process_info.SetProcessID(pid);
218 GetProcessExecutableAndTriple(handle, process_info);
219
220 // Need to read the PEB to get parent process and command line arguments.
221 return true;
222}
223
Zachary Turner39de3112014-09-09 20:54:56 +0000224HostThread
225Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000226{
Zachary Turner39de3112014-09-09 20:54:56 +0000227 return HostThread();
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000228}