[Lldb-commits] [lldb] r323637 - Remove ObjectFile usage from HostLinux::GetProcessInfo

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Jan 29 02:46:00 PST 2018


Author: labath
Date: Mon Jan 29 02:46:00 2018
New Revision: 323637

URL: http://llvm.org/viewvc/llvm-project?rev=323637&view=rev
Log:
Remove ObjectFile usage from HostLinux::GetProcessInfo

Summary:
The ObjectFile class was used to determine the architecture of a running
process by inspecting it's main executable. There were two issues with
this:
- it's in the wrong layer
- the call can be very expensive (it can end up computing the crc of the
  whole file).

Since the process is running on the host, ideally we would be able to
just query the data straight from the OS like darwin does, but there
doesn't seem to be a reasonable way to do that. So, this fixes the
layering issue by using the llvm object library to inspect the file.
Since we know the process is already running on the host, we just need
to peek at a few bytes of the elf header to determine whether it's 32-
or 64-bit (which should make this faster as well).

Pretty much the same logic was implemented in
NativeProcessProtocol::ResolveProcessArchitecture, so I delete this
logic and replace calls with GetProcessInfo.

Reviewers: eugene, krytarowski

Subscribers: mgorny, hintonda, lldb-commits

Differential Revision: https://reviews.llvm.org/D42488

Modified:
    lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
    lldb/trunk/include/lldb/Utility/ArchSpec.h
    lldb/trunk/source/Host/CMakeLists.txt
    lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
    lldb/trunk/source/Host/linux/Host.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
    lldb/trunk/source/Utility/ArchSpec.cpp
    lldb/trunk/unittests/Host/linux/HostTest.cpp

Modified: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h Mon Jan 29 02:46:00 2018
@@ -466,11 +466,6 @@ protected:
 
   NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
 
-  // -----------------------------------------------------------
-  // Static helper methods for derived classes.
-  // -----------------------------------------------------------
-  static Status ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch);
-
 private:
   void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
 };

Modified: lldb/trunk/include/lldb/Utility/ArchSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/ArchSpec.h?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Utility/ArchSpec.h (original)
+++ lldb/trunk/include/lldb/Utility/ArchSpec.h Mon Jan 29 02:46:00 2018
@@ -617,6 +617,7 @@ protected:
 /// @return true if \a lhs is less than \a rhs
 //------------------------------------------------------------------
 bool operator<(const ArchSpec &lhs, const ArchSpec &rhs);
+bool operator==(const ArchSpec &lhs, const ArchSpec &rhs);
 
 bool ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, ArchSpec &arch);
 

Modified: lldb/trunk/source/Host/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/CMakeLists.txt?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Host/CMakeLists.txt (original)
+++ lldb/trunk/source/Host/CMakeLists.txt Mon Jan 29 02:46:00 2018
@@ -188,5 +188,6 @@ add_lldb_library(lldbHost
     ${EXTRA_LIBS}
   
   LINK_COMPONENTS
+    Object
     Support
   )

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Mon Jan 29 02:46:00 2018
@@ -8,13 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/common/NativeRegisterContext.h"
 #include "lldb/Host/common/NativeThreadProtocol.h"
 #include "lldb/Host/common/SoftwareBreakpoint.h"
-#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/Log.h"
@@ -431,26 +429,4 @@ void NativeProcessProtocol::DoStopIDBump
   // Default implementation does nothing.
 }
 
-Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid,
-                                                         ArchSpec &arch) {
-  // Grab process info for the running process.
-  ProcessInstanceInfo process_info;
-  if (!Host::GetProcessInfo(pid, process_info))
-    return Status("failed to get process info");
-
-  // Resolve the executable module.
-  ModuleSpecList module_specs;
-  if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0,
-                                           0, module_specs))
-    return Status("failed to get module specifications");
-  lldbassert(module_specs.GetSize() == 1);
-
-  arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture();
-  if (arch.IsValid())
-    return Status();
-  else
-    return Status(
-        "failed to retrieve a valid architecture from the exe module");
-}
-
 NativeProcessProtocol::Factory::~Factory() = default;

Modified: lldb/trunk/source/Host/linux/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/linux/Host.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Host/linux/Host.cpp (original)
+++ lldb/trunk/source/Host/linux/Host.cpp Mon Jan 29 02:46:00 2018
@@ -20,7 +20,9 @@
 
 // C++ Includes
 // Other libraries and framework includes
+#include "llvm/Object/ELF.h"
 #include "llvm/Support/ScopedPrinter.h"
+
 // Project includes
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/Log.h"
@@ -29,12 +31,9 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/linux/Support.h"
-#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataBufferLLVM.h"
 #include "lldb/Utility/DataExtractor.h"
 
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Symbol/ObjectFile.h"
-
 using namespace lldb;
 using namespace lldb_private;
 
@@ -123,28 +122,27 @@ static bool IsDirNumeric(const char *dna
   return true;
 }
 
-static bool GetELFProcessCPUType(llvm::StringRef exe_path,
-                                 ProcessInstanceInfo &process_info) {
-  // Clear the architecture.
-  process_info.GetArchitecture().Clear();
-
-  ModuleSpecList specs;
-  FileSpec filespec(exe_path, false);
-  const size_t num_specs =
-      ObjectFile::GetModuleSpecifications(filespec, 0, 0, specs);
-  // GetModuleSpecifications() could fail if the executable has been deleted or
-  // is locked.
-  // But it shouldn't return more than 1 architecture.
-  assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
-  if (num_specs == 1) {
-    ModuleSpec module_spec;
-    if (specs.GetModuleSpecAtIndex(0, module_spec) &&
-        module_spec.GetArchitecture().IsValid()) {
-      process_info.GetArchitecture() = module_spec.GetArchitecture();
-      return true;
-    }
+static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) {
+  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+
+  auto buffer_sp = DataBufferLLVM::CreateSliceFromPath(exe_path, 0x20, 0);
+  if (!buffer_sp)
+    return ArchSpec();
+
+  uint8_t exe_class =
+      llvm::object::getElfArchType(
+          {buffer_sp->GetChars(), size_t(buffer_sp->GetByteSize())})
+          .first;
+
+  switch (exe_class) {
+  case llvm::ELF::ELFCLASS32:
+    return HostInfo::GetArchitecture(HostInfo::eArchKind32);
+  case llvm::ELF::ELFCLASS64:
+    return HostInfo::GetArchitecture(HostInfo::eArchKind64);
+  default:
+    LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class, exe_path);
+    return ArchSpec();
   }
-  return false;
 }
 
 static bool GetProcessAndStatInfo(::pid_t pid,
@@ -173,7 +171,7 @@ static bool GetProcessAndStatInfo(::pid_
   llvm::StringRef PathRef = ExePath;
   PathRef.consume_back(" (deleted)");
 
-  GetELFProcessCPUType(PathRef, process_info);
+  process_info.SetArchitecture(GetELFProcessCPUType(PathRef));
 
   // Get the process environment.
   auto BufferOrError = getProcFile(pid, "environ");
@@ -193,7 +191,6 @@ static bool GetProcessAndStatInfo(::pid_
 
   process_info.SetProcessID(pid);
   process_info.GetExecutableFile().SetFile(PathRef, false);
-  process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture());
 
   llvm::StringRef Rest = Environ->getBuffer();
   while (!Rest.empty()) {

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Mon Jan 29 02:46:00 2018
@@ -245,13 +245,15 @@ NativeProcessLinux::Factory::Launch(Proc
   }
   LLDB_LOG(log, "inferior started, now in stopped state");
 
-  ArchSpec arch;
-  if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
-    return status.ToError();
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::make_error<StringError>("Cannot get process architecture",
+                                         llvm::inconvertibleErrorCode());
+  }
 
   // Set the architecture to the exe architecture.
   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
-           arch.GetArchitectureName());
+           Info.GetArchitecture().GetArchitectureName());
 
   status = SetDefaultPtraceOpts(pid);
   if (status.Fail()) {
@@ -261,7 +263,7 @@ NativeProcessLinux::Factory::Launch(Proc
 
   return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
       pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
-      arch, mainloop, {pid}));
+      Info.GetArchitecture(), mainloop, {pid}));
 }
 
 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
@@ -272,17 +274,18 @@ NativeProcessLinux::Factory::Attach(
   LLDB_LOG(log, "pid = {0:x}", pid);
 
   // Retrieve the architecture for the running process.
-  ArchSpec arch;
-  Status status = ResolveProcessArchitecture(pid, arch);
-  if (!status.Success())
-    return status.ToError();
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::make_error<StringError>("Cannot get process architecture",
+                                         llvm::inconvertibleErrorCode());
+  }
 
   auto tids_or = NativeProcessLinux::Attach(pid);
   if (!tids_or)
     return tids_or.takeError();
 
   return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
-      pid, -1, native_delegate, arch, mainloop, *tids_or));
+      pid, -1, native_delegate, Info.GetArchitecture(), mainloop, *tids_or));
 }
 
 // -----------------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp Mon Jan 29 02:46:00 2018
@@ -93,17 +93,19 @@ NativeProcessNetBSD::Factory::Launch(Pro
   }
   LLDB_LOG(log, "inferior started, now in stopped state");
 
-  ArchSpec arch;
-  if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
-    return status.ToError();
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::make_error<StringError>("Cannot get process architecture",
+                                         llvm::inconvertibleErrorCode());
+  }
 
   // Set the architecture to the exe architecture.
   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
-           arch.GetArchitectureName());
+           Info.GetArchitecture().GetArchitectureName());
 
   std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
       pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
-      arch, mainloop));
+      Info.GetArchitecture(), mainloop));
 
   status = process_up->ReinitializeThreads();
   if (status.Fail())
@@ -124,13 +126,14 @@ NativeProcessNetBSD::Factory::Attach(
   LLDB_LOG(log, "pid = {0:x}", pid);
 
   // Retrieve the architecture for the running process.
-  ArchSpec arch;
-  Status status = ResolveProcessArchitecture(pid, arch);
-  if (!status.Success())
-    return status.ToError();
+  ProcessInstanceInfo Info;
+  if (!Host::GetProcessInfo(pid, Info)) {
+    return llvm::make_error<StringError>("Cannot get process architecture",
+                                         llvm::inconvertibleErrorCode());
+  }
 
-  std::unique_ptr<NativeProcessNetBSD> process_up(
-      new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop));
+  std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
+      pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
 
   status = process_up->Attach();
   if (!status.Success())

Modified: lldb/trunk/source/Utility/ArchSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/ArchSpec.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/source/Utility/ArchSpec.cpp (original)
+++ lldb/trunk/source/Utility/ArchSpec.cpp Mon Jan 29 02:46:00 2018
@@ -1416,6 +1416,11 @@ bool lldb_private::operator<(const ArchS
   return lhs_core < rhs_core;
 }
 
+
+bool lldb_private::operator==(const ArchSpec &lhs, const ArchSpec &rhs) {
+  return lhs.GetCore() == rhs.GetCore();
+}
+
 bool ArchSpec::IsFullySpecifiedTriple() const {
   const auto &user_specified_triple = GetTriple();
 

Modified: lldb/trunk/unittests/Host/linux/HostTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Host/linux/HostTest.cpp?rev=323637&r1=323636&r2=323637&view=diff
==============================================================================
--- lldb/trunk/unittests/Host/linux/HostTest.cpp (original)
+++ lldb/trunk/unittests/Host/linux/HostTest.cpp Mon Jan 29 02:46:00 2018
@@ -45,4 +45,8 @@ TEST_F(HostTest, GetProcessInfo) {
 
   ASSERT_TRUE(Info.GroupIDIsValid());
   EXPECT_EQ(getegid(), Info.GetGroupID());
+
+  EXPECT_TRUE(Info.GetArchitecture().IsValid());
+  EXPECT_EQ(HostInfo::GetArchitecture(HostInfo::eArchKindDefault),
+            Info.GetArchitecture());
 }




More information about the lldb-commits mailing list