forked from OSchip/llvm-project
Implment "platform process list" for Windows.
This patch implements basic functionality of the "platform process list" command for Windows. Currently this has the following limitations. * Certain types of filtering are not enabled (e.g. filtering by architecture with -a), although most filters work. * The username of the process is not yet obtained. * Using -v to list verbose information generates an error. * The architecture column displays the entire triple, leading to misaligned formatting of the printed table. Reviewed by: Greg Clayton Differential Revision: http://reviews.llvm.org/D4413 llvm-svn: 212510
This commit is contained in:
parent
24f3dee6ca
commit
310035a4f9
|
@ -0,0 +1,40 @@
|
|||
//===-- AutoHandle.h --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_lldb_Host_windows_AutoHandle_h_
|
||||
#define LLDB_lldb_Host_windows_AutoHandle_h_
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class AutoHandle {
|
||||
public:
|
||||
AutoHandle(HANDLE handle, HANDLE invalid_value = INVALID_HANDLE_VALUE)
|
||||
: m_handle(handle)
|
||||
, m_invalid_value(invalid_value)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoHandle()
|
||||
{
|
||||
if (m_handle != m_invalid_value)
|
||||
::CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
bool IsValid() const { return m_handle != m_invalid_value; }
|
||||
|
||||
HANDLE get() const { return m_handle; }
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
HANDLE m_invalid_value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1443,7 +1443,8 @@ Host::GetOSKernelDescription (std::string &s)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined(__linux__)
|
||||
#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) \
|
||||
&& !defined(__linux__) && !defined(_WIN32)
|
||||
uint32_t
|
||||
Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// C Includes
|
||||
#include <stdio.h>
|
||||
#include "lldb/Host/windows/windows.h"
|
||||
#include "lldb/Host/windows/AutoHandle.h"
|
||||
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
|
@ -21,10 +22,80 @@
|
|||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Core/DataBufferHeap.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
|
||||
// Windows includes
|
||||
#include <TlHelp32.h>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple)
|
||||
{
|
||||
// Open the PE File as a binary file, and parse just enough information to determine the
|
||||
// machine type.
|
||||
File imageBinary(
|
||||
executable.GetPath().c_str(),
|
||||
File::eOpenOptionRead,
|
||||
lldb::eFilePermissionsUserRead);
|
||||
imageBinary.SeekFromStart(0x3c);
|
||||
int32_t peOffset = 0;
|
||||
uint32_t peHead = 0;
|
||||
uint16_t machineType = 0;
|
||||
size_t readSize = sizeof(peOffset);
|
||||
imageBinary.Read(&peOffset, readSize);
|
||||
imageBinary.SeekFromStart(peOffset);
|
||||
imageBinary.Read(&peHead, readSize);
|
||||
if (peHead != 0x00004550) // "PE\0\0", little-endian
|
||||
return false; // Error: Can't find PE header
|
||||
readSize = 2;
|
||||
imageBinary.Read(&machineType, readSize);
|
||||
triple.setVendor(llvm::Triple::PC);
|
||||
triple.setOS(llvm::Triple::Win32);
|
||||
triple.setArch(llvm::Triple::UnknownArch);
|
||||
if (machineType == 0x8664)
|
||||
triple.setArch(llvm::Triple::x86_64);
|
||||
else if (machineType == 0x14c)
|
||||
triple.setArch(llvm::Triple::x86);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
|
||||
{
|
||||
// Get the process image path. MAX_PATH isn't long enough, paths can actually be up to 32KB.
|
||||
std::vector<char> buffer(32768);
|
||||
DWORD dwSize = buffer.size();
|
||||
if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize))
|
||||
return false;
|
||||
path.assign(&buffer[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
|
||||
{
|
||||
// We may not have permissions to read the path from the process. So start off by
|
||||
// setting the executable file to whatever Toolhelp32 gives us, and then try to
|
||||
// enhance this with more detailed information, but fail gracefully.
|
||||
std::string executable;
|
||||
llvm::Triple triple;
|
||||
triple.setVendor(llvm::Triple::PC);
|
||||
triple.setOS(llvm::Triple::Win32);
|
||||
triple.setArch(llvm::Triple::UnknownArch);
|
||||
if (GetExecutableForProcess(handle, executable))
|
||||
{
|
||||
FileSpec executableFile(executable.c_str(), false);
|
||||
process.SetExecutableFile(executableFile, true);
|
||||
GetTripleForProcess(executableFile, triple);
|
||||
}
|
||||
process.SetArchitecture(ArchSpec(triple));
|
||||
|
||||
// TODO(zturner): Add the ability to get the process user name.
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Host::GetOSVersion(uint32_t &major,
|
||||
uint32_t &minor,
|
||||
|
@ -210,33 +281,84 @@ Host::GetUserName (uint32_t uid, std::string &user_name)
|
|||
const char *
|
||||
Host::GetGroupName (uint32_t gid, std::string &group_name)
|
||||
{
|
||||
llvm_unreachable("Windows does not support group name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::GetUserID ()
|
||||
{
|
||||
return 0;
|
||||
llvm_unreachable("Windows does not support uid");
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::GetGroupID ()
|
||||
{
|
||||
llvm_unreachable("Windows does not support gid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::GetEffectiveUserID ()
|
||||
{
|
||||
llvm_unreachable("Windows does not support euid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::GetEffectiveGroupID ()
|
||||
{
|
||||
llvm_unreachable("Windows does not support egid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
|
||||
{
|
||||
process_infos.Clear();
|
||||
|
||||
AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
|
||||
if (!snapshot.IsValid())
|
||||
return 0;
|
||||
|
||||
PROCESSENTRY32 pe = {0};
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(snapshot.get(), &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
|
||||
|
||||
ProcessInstanceInfo process;
|
||||
process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
|
||||
process.SetProcessID(pe.th32ProcessID);
|
||||
process.SetParentProcessID(pe.th32ParentProcessID);
|
||||
GetProcessExecutableAndTriple(handle, process);
|
||||
|
||||
if (match_info.MatchAllProcesses() || match_info.Matches(process))
|
||||
process_infos.Append(process);
|
||||
} while (Process32Next(snapshot.get(), &pe));
|
||||
}
|
||||
return process_infos.GetSize();
|
||||
}
|
||||
|
||||
bool
|
||||
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
|
||||
{
|
||||
process_info.Clear();
|
||||
|
||||
AutoHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid),
|
||||
nullptr);
|
||||
if (!handle.IsValid())
|
||||
return false;
|
||||
|
||||
process_info.SetProcessID(pid);
|
||||
GetProcessExecutableAndTriple(handle, process_info);
|
||||
|
||||
// Need to read the PEB to get parent process and command line arguments.
|
||||
return true;
|
||||
}
|
||||
|
||||
lldb::thread_t
|
||||
Host::StartMonitoringChildProcess
|
||||
(
|
||||
|
|
Loading…
Reference in New Issue