compnerd updated this revision to Diff 254883.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77287/new/

https://reviews.llvm.org/D77287

Files:
  lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
  lldb/source/Plugins/Platform/Windows/PlatformWindows.h
  lldb/test/Shell/Process/Windows/process_load.cpp

Index: lldb/test/Shell/Process/Windows/process_load.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/Process/Windows/process_load.cpp
@@ -0,0 +1,12 @@
+// clang-format off
+
+// REQUIRES: system-windows
+// RUN: %build --compiler=clang-cl -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -o "b main" -o "process launch" -o "process load kernel32.dll" | FileCheck %s
+
+int main(int argc, char *argv[]) {
+  return 0;
+}
+
+// CHECK: "Loading "kernel32.dll"...ok{{.*}}
+// CHECK: Image 0 loaded.
Index: lldb/source/Plugins/Platform/Windows/PlatformWindows.h
===================================================================
--- lldb/source/Plugins/Platform/Windows/PlatformWindows.h
+++ lldb/source/Plugins/Platform/Windows/PlatformWindows.h
@@ -49,6 +49,15 @@
 
   lldb_private::Status DisconnectRemote() override;
 
+  uint32_t DoLoadImage(lldb_private::Process *process,
+                       const lldb_private::FileSpec &remote_file,
+                       const std::vector<std::string> *paths,
+                       lldb_private::Status &error,
+                       lldb_private::FileSpec *loaded_path) override;
+
+  lldb_private::Status UnloadImage(lldb_private::Process *process,
+                                   uint32_t image_token) override;
+
   lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info,
                                lldb_private::Debugger &debugger,
                                lldb_private::Target *target,
@@ -73,6 +82,10 @@
 
 private:
   DISALLOW_COPY_AND_ASSIGN(PlatformWindows);
+
+  lldb_private::Status EvaluateLoaderExpression(lldb_private::Process *process,
+                                                const char *expression,
+                                                lldb::ValueObjectSP &value);
 };
 
 } // namespace lldb_private
Index: lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
===================================================================
--- lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -20,7 +20,10 @@
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/UserExpression.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/Status.h"
 
@@ -306,6 +309,111 @@
   return error;
 }
 
+Status PlatformWindows::EvaluateLoaderExpression(Process *process,
+                                                 const char *expression,
+                                                 ValueObjectSP &value) {
+  // FIXME(compnerd) `-fdeclspec` is not passed to the clang instance?
+  static const char kLoaderDecls[] =
+      R"(
+          // libloaderapi.h
+
+          // WINBASEAPI BOOL WINAPI FreeModule(HMODULE);
+          extern "C" /* __declspec(dllimport) */ BOOL __stdcall FreeModule(void *hLibModule);
+
+          // WINBASEAPI HMODULE WINAPI LoadLibraryA(LPCSTR);
+          extern "C" /* __declspec(dllimport) */ void * __stdcall LoadLibraryA(const char *);
+        )";
+
+  if (DynamicLoader *loader = process->GetDynamicLoader()) {
+    Status result = loader->CanLoadImage();
+    if (result.Fail())
+      return result;
+  }
+
+  ThreadSP thread = process->GetThreadList().GetExpressionExecutionThread();
+  if (!thread)
+    return Status("selected thread is invalid");
+
+  StackFrameSP frame = thread->GetStackFrameAtIndex(0);
+  if (!frame)
+    return Status("frame 0 is invalid");
+
+  ExecutionContext context;
+  frame->CalculateExecutionContext(context);
+
+  EvaluateExpressionOptions options;
+  options.SetUnwindOnError(true);
+  options.SetIgnoreBreakpoints(true);
+  options.SetExecutionPolicy(eExecutionPolicyAlways);
+  options.SetLanguage(eLanguageTypeC_plus_plus);
+  // LoadLibrary{A,W}/FreeLibrary cannot raise exceptions which we can handle.
+  // They may potentially throw SEH exceptions which we do not know how to
+  // handle currently.
+  options.SetTrapExceptions(false);
+  options.SetTimeout(process->GetUtilityExpressionTimeout());
+
+  Status error;
+  ExpressionResults result = UserExpression::Evaluate(
+      context, options, expression, kLoaderDecls, value, error);
+  if (result != eExpressionCompleted)
+    return error;
+
+  if (value->GetError().Fail())
+    return value->GetError();
+
+  return Status();
+}
+
+uint32_t PlatformWindows::DoLoadImage(Process *process,
+                                      const FileSpec &remote_file,
+                                      const std::vector<std::string> *paths,
+                                      Status &error, FileSpec *loaded_path) {
+  if (loaded_path)
+    loaded_path->Clear();
+
+  StreamString expression;
+  expression.Printf("LoadLibraryA(\"%s\")", remote_file.GetPath().c_str());
+
+  ValueObjectSP value;
+  Status result =
+      EvaluateLoaderExpression(process, expression.GetData(), value);
+  if (result.Fail())
+    return LLDB_INVALID_IMAGE_TOKEN;
+
+  Scalar scalar;
+  if (value->ResolveValue(scalar)) {
+    lldb::addr_t address = scalar.ULongLong();
+    if (address == 0)
+      return LLDB_INVALID_IMAGE_TOKEN;
+    return process->AddImageToken(address);
+  }
+  return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+Status PlatformWindows::UnloadImage(Process *process, uint32_t image_token) {
+  const addr_t address = process->GetImagePtrFromToken(image_token);
+  if (address == LLDB_INVALID_ADDRESS)
+    return Status("invalid image token");
+
+  StreamString expression;
+  expression.Printf("FreeLibrary((HMODULE)0x%" PRIx64 ")", address);
+
+  ValueObjectSP value;
+  Status result =
+      EvaluateLoaderExpression(process, expression.GetData(), value);
+  if (result.Fail())
+    return result;
+
+  Scalar scalar;
+  if (value->ResolveValue(scalar)) {
+    if (scalar.UInt(1))
+      return Status("expression failed: \"%s\"", expression.GetData());
+    process->ResetImageToken(image_token);
+  }
+
+  return Status();
+}
+
 ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
                                         Debugger &debugger, Target *target,
                                         Status &error) {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to