1 //===-- 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"
13 #include "lldb/Host/windows/AutoHandle.h"
14 
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"
25 #include "lldb/Core/StreamFile.h"
26 
27 // Windows includes
28 #include <TlHelp32.h>
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 namespace
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 
99 lldb::DataBufferSP
100 Host::GetAuxvData(lldb_private::Process *process)
101 {
102     return 0;
103 }
104 
105 lldb::tid_t
106 Host::GetCurrentThreadID()
107 {
108     return lldb::tid_t(::GetCurrentThreadId());
109 }
110 
111 lldb::thread_t
112 Host::GetCurrentThread ()
113 {
114     return lldb::thread_t(::GetCurrentThread());
115 }
116 
117 lldb::thread_key_t
118 Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback)
119 {
120     return TlsAlloc();
121 }
122 
123 void*
124 Host::ThreadLocalStorageGet(lldb::thread_key_t key)
125 {
126     return ::TlsGetValue (key);
127 }
128 
129 void
130 Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value)
131 {
132    ::TlsSetValue (key, value);
133 }
134 
135 void
136 Host::Kill(lldb::pid_t pid, int signo)
137 {
138     TerminateProcess((HANDLE) pid, 1);
139 }
140 
141 
142 const char *
143 Host::GetSignalAsCString(int signo)
144 {
145     return NULL;
146 }
147 
148 FileSpec
149 Host::GetModuleFileSpecForHostAddress (const void *host_addr)
150 {
151     FileSpec module_filespec;
152 
153     HMODULE hmodule = NULL;
154     if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
155         return module_filespec;
156 
157     std::vector<char> buffer(MAX_PATH);
158     DWORD chars_copied = 0;
159     do {
160         chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
161         if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
162             buffer.resize(buffer.size() * 2);
163     } while (chars_copied >= buffer.size());
164 
165     module_filespec.SetFile(&buffer[0], false);
166     return module_filespec;
167 }
168 
169 uint32_t
170 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
171 {
172     process_infos.Clear();
173 
174     AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
175     if (!snapshot.IsValid())
176         return 0;
177 
178     PROCESSENTRY32 pe = {0};
179     pe.dwSize = sizeof(PROCESSENTRY32);
180     if (Process32First(snapshot.get(), &pe))
181     {
182         do
183         {
184             AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
185 
186             ProcessInstanceInfo process;
187             process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
188             process.SetProcessID(pe.th32ProcessID);
189             process.SetParentProcessID(pe.th32ParentProcessID);
190             GetProcessExecutableAndTriple(handle, process);
191 
192             if (match_info.MatchAllProcesses() || match_info.Matches(process))
193                 process_infos.Append(process);
194         } while (Process32Next(snapshot.get(), &pe));
195     }
196     return process_infos.GetSize();
197 }
198 
199 bool
200 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
201 {
202     process_info.Clear();
203 
204     AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
205                       nullptr);
206     if (!handle.IsValid())
207         return false;
208 
209     process_info.SetProcessID(pid);
210     GetProcessExecutableAndTriple(handle, process_info);
211 
212     // Need to read the PEB to get parent process and command line arguments.
213     return true;
214 }
215 
216 HostThread
217 Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals)
218 {
219     return HostThread();
220 }