[Lldb-commits] [lldb] r212510 - Implment "platform process list" for Windows.

Zachary Turner zturner at google.com
Mon Jul 7 21:52:15 PDT 2014


Author: zturner
Date: Mon Jul  7 23:52:15 2014
New Revision: 212510

URL: http://llvm.org/viewvc/llvm-project?rev=212510&view=rev
Log:
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

Added:
    lldb/trunk/include/lldb/Host/windows/AutoHandle.h
Modified:
    lldb/trunk/source/Host/common/Host.cpp
    lldb/trunk/source/Host/windows/Host.cpp

Added: lldb/trunk/include/lldb/Host/windows/AutoHandle.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/windows/AutoHandle.h?rev=212510&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Host/windows/AutoHandle.h (added)
+++ lldb/trunk/include/lldb/Host/windows/AutoHandle.h Mon Jul  7 23:52:15 2014
@@ -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
+

Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=212510&r1=212509&r2=212510&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Mon Jul  7 23:52:15 2014
@@ -1443,7 +1443,8 @@ Host::GetOSKernelDescription (std::strin
 }
 #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)
 {

Modified: lldb/trunk/source/Host/windows/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/Host.cpp?rev=212510&r1=212509&r2=212510&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/Host.cpp (original)
+++ lldb/trunk/source/Host/windows/Host.cpp Mon Jul  7 23:52:15 2014
@@ -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::st
 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
 (





More information about the lldb-commits mailing list