mib updated this revision to Diff 413079.
mib added a comment.

Address @JDevlieghere comments:

- Fix error message
- Use corefile module load address for scripted process module


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

https://reviews.llvm.org/D120969

Files:
  lldb/examples/python/scripted_process/scripted_process.py
  lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
  lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
  lldb/source/Plugins/Process/scripted/ScriptedProcess.h
  
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
  lldb/test/API/functionalities/scripted_process/Makefile
  lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
  lldb/test/API/functionalities/scripted_process/baz.c
  lldb/test/API/functionalities/scripted_process/baz.h
  lldb/test/API/functionalities/scripted_process/main.cpp
  lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py

Index: lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
+++ lldb/test/API/functionalities/scripted_process/stack_core_scripted_process.py
@@ -7,13 +7,19 @@
 from lldb.plugins.scripted_process import ScriptedThread
 
 class StackCoreScriptedProcess(ScriptedProcess):
+    def get_module_with_name(self, target, name):
+        for module in target.modules:
+            if name in module.GetFileSpec().GetFilename():
+                return module
+        return None
+
     def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
         super().__init__(target, args)
 
-        self.backing_target_idx = args.GetValueForKey("backing_target_idx")
-
         self.corefile_target = None
         self.corefile_process = None
+
+        self.backing_target_idx = args.GetValueForKey("backing_target_idx")
         if (self.backing_target_idx and self.backing_target_idx.IsValid()):
             if self.backing_target_idx.GetType() == lldb.eStructuredDataTypeInteger:
                 idx = self.backing_target_idx.GetIntegerValue(42)
@@ -30,9 +36,22 @@
 
                 self.threads[corefile_thread.GetThreadID()] = StackCoreScriptedThread(self, structured_data)
 
-        if len(self.threads) == 3:
+        if len(self.threads) == 2:
             self.threads[len(self.threads) - 1].is_stopped = True
 
+        corefile_module = self.get_module_with_name(self.corefile_target,
+                                                    "libbaz.dylib")
+        if not corefile_module or not corefile_module.IsValid():
+            return
+        module_path = os.path.join(corefile_module.GetFileSpec().GetDirectory(),
+                                   corefile_module.GetFileSpec().GetFilename())
+        if not os.path.exists(module_path):
+            return
+        module_load_addr = corefile_module.GetObjectFileHeaderAddress().GetLoadAddress(self.corefile_target)
+
+        self.loaded_images.append({"path": module_path,
+                                   "load_addr": module_load_addr})
+
     def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
         mem_region = lldb.SBMemoryRegionInfo()
         error = self.corefile_process.GetMemoryRegionInfo(addr, mem_region)
@@ -61,8 +80,6 @@
         return data
 
     def get_loaded_images(self):
-        # TODO: Iterate over corefile_target modules and build a data structure
-        # from it.
         return self.loaded_images
 
     def get_process_id(self) -> int:
Index: lldb/test/API/functionalities/scripted_process/main.cpp
===================================================================
--- lldb/test/API/functionalities/scripted_process/main.cpp
+++ lldb/test/API/functionalities/scripted_process/main.cpp
@@ -2,16 +2,20 @@
 #include <mutex>
 #include <thread>
 
+extern "C" {
+int baz(int);
+}
+
 int bar(int i) {
   int j = i * i;
-  return j; // break here
+  return j;
 }
 
 int foo(int i) { return bar(i); }
 
 void call_and_wait(int &n) {
   std::cout << "waiting for computation!" << std::endl;
-  while (n != 42 * 42)
+  while (baz(n) != 42)
     ;
   std::cout << "finished computation!" << std::endl;
 }
Index: lldb/test/API/functionalities/scripted_process/baz.h
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/scripted_process/baz.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int baz(int j);
Index: lldb/test/API/functionalities/scripted_process/baz.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/scripted_process/baz.c
@@ -0,0 +1,8 @@
+#include "baz.h"
+
+#include <math.h>
+
+int baz(int j) {
+  int k = sqrt(j);
+  return k; // break here
+}
Index: lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
+++ lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py
@@ -25,13 +25,19 @@
     def create_stack_skinny_corefile(self, file):
         self.build()
         target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here",
-                                                                       lldb.SBFileSpec("main.cpp"))
+                                                                       lldb.SBFileSpec("baz.c"))
         self.assertTrue(process.IsValid(), "Process is invalid.")
         # FIXME: Use SBAPI to save the process corefile.
         self.runCmd("process save-core -s stack  " + file)
         self.assertTrue(os.path.exists(file), "No stack-only corefile found.")
         self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target")
 
+    def get_module_with_name(self, target, name):
+        for module in target.modules:
+            if name in module.GetFileSpec().GetFilename():
+                return module
+        return None
+
     @skipUnlessDarwin
     @skipIfOutOfTreeDebugserver
     def test_launch_scripted_process_stack_frames(self):
@@ -41,15 +47,15 @@
         target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
         self.assertTrue(target, VALID_TARGET)
 
-        for module in target.modules:
-            if 'a.out' in module.GetFileSpec().GetFilename():
-                main_module = module
-                break
-
+        main_module = self.get_module_with_name(target, 'a.out')
         self.assertTrue(main_module, "Invalid main module.")
         error = target.SetModuleLoadAddress(main_module, 0)
         self.assertSuccess(error, "Reloading main module at offset 0 failed.")
 
+        scripted_dylib = self.get_module_with_name(target, 'libbaz.dylib')
+        self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.")
+        self.assertEqual(scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 0xffffffffffffffff)
+
         os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
         def cleanup():
           del os.environ["SKIP_SCRIPTED_PROCESS_LAUNCH"]
@@ -68,7 +74,8 @@
 
         structured_data = lldb.SBStructuredData()
         structured_data.SetFromJSON(json.dumps({
-            "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget())
+            "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget()),
+            "libbaz_path" : self.getBuildArtifact("libbaz.dylib")
         }))
         launch_info = lldb.SBLaunchInfo(None)
         launch_info.SetProcessPluginName("ScriptedProcess")
@@ -81,10 +88,10 @@
         self.assertTrue(process, PROCESS_IS_VALID)
         self.assertEqual(process.GetProcessID(), 42)
 
-        self.assertEqual(process.GetNumThreads(), 3)
+        self.assertEqual(process.GetNumThreads(), 2)
         thread = process.GetSelectedThread()
         self.assertTrue(thread, "Invalid thread.")
-        self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-2")
+        self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1")
 
         self.assertTrue(target.triple, "Invalid target triple")
         arch = target.triple.split('-')[0]
@@ -102,9 +109,17 @@
         else:
             self.assertTrue(thread.GetStopReason(), lldb.eStopReasonSignal)
 
-        self.assertEqual(thread.GetNumFrames(), 6)
+        self.assertEqual(thread.GetNumFrames(), 5)
         frame = thread.GetSelectedFrame()
         self.assertTrue(frame, "Invalid frame.")
-        self.assertIn("bar", frame.GetFunctionName())
-        self.assertEqual(int(frame.FindValue("i", lldb.eValueTypeVariableArgument).GetValue()), 42)
-        self.assertEqual(int(frame.FindValue("j", lldb.eValueTypeVariableLocal).GetValue()), 42 * 42)
+        func = frame.GetFunction()
+        self.assertTrue(func, "Invalid function.")
+
+        self.assertIn("baz", frame.GetFunctionName())
+        self.assertEqual(frame.vars.GetSize(), 2)
+        self.assertEqual(int(frame.vars.GetFirstValueByName('j').GetValue()), 42 * 42)
+        self.assertEqual(int(frame.vars.GetFirstValueByName('k').GetValue()), 42)
+
+        scripted_dylib = self.get_module_with_name(target, 'libbaz.dylib')
+        self.assertTrue(scripted_dylib, "Dynamic library libbaz.dylib not found.")
+        self.assertEqual(scripted_dylib.GetObjectFileHeaderAddress().GetLoadAddress(target), 0x1001e0000)
Index: lldb/test/API/functionalities/scripted_process/Makefile
===================================================================
--- lldb/test/API/functionalities/scripted_process/Makefile
+++ lldb/test/API/functionalities/scripted_process/Makefile
@@ -1,4 +1,13 @@
 CXX_SOURCES := main.cpp
 ENABLE_THREADS := YES
-include Makefile.rules
+LD_EXTRAS := -L. -lbaz -I.
+
+override ARCH := $(shell uname -m)
+
+all: libbaz.dylib a.out
 
+libbaz.dylib: baz.c
+	$(MAKE) -f $(MAKEFILE_RULES) ARCH=$(ARCH) \
+		DYLIB_ONLY=YES DYLIB_NAME=baz DYLIB_C_SOURCES=baz.c
+
+include Makefile.rules
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
@@ -49,7 +49,7 @@
   lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size,
                                             Status &error) override;
 
-  StructuredData::DictionarySP GetLoadedImages() override;
+  StructuredData::ArraySP GetLoadedImages() override;
 
   lldb::pid_t GetProcessID() override;
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -124,9 +124,21 @@
                                          address, size);
 }
 
-StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
-  // TODO: Implement
-  return {};
+StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
+  Status error;
+  StructuredData::ArraySP array =
+      Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
+
+  if (!array || !array->IsValid() || error.Fail()) {
+    return ScriptedInterface::ErrorWithMessage<StructuredData::ArraySP>(
+        LLVM_PRETTY_FUNCTION,
+        llvm::Twine("Null or invalid object (" +
+                    llvm::Twine(error.AsCString()) + llvm::Twine(")."))
+            .str(),
+        error);
+  }
+
+  return array;
 }
 
 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.h
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.h
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -89,6 +89,9 @@
 
   bool GetProcessInfo(ProcessInstanceInfo &info) override;
 
+  lldb_private::StructuredData::ObjectSP
+  GetLoadedDynamicLibrariesInfos() override;
+
 protected:
   Status DoStop();
 
Index: lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
===================================================================
--- lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
+++ lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -170,6 +170,7 @@
 void ScriptedProcess::DidLaunch() {
   CheckInterpreterAndScriptObject();
   m_pid = GetInterface().GetProcessID();
+  GetLoadedDynamicLibrariesInfos();
 }
 
 Status ScriptedProcess::DoResume() {
@@ -378,6 +379,93 @@
   return true;
 }
 
+lldb_private::StructuredData::ObjectSP
+ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
+  CheckInterpreterAndScriptObject();
+
+  Status error;
+  auto error_with_message = [&error](llvm::StringRef message) {
+    return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
+                                                     message.data(), error);
+  };
+
+  StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
+
+  if (!loaded_images_sp || !loaded_images_sp->GetSize())
+    return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>(
+        LLVM_PRETTY_FUNCTION, "No loaded images.", error);
+
+  ModuleList module_list;
+  Target &target = GetTarget();
+
+  auto reload_image = [&target, &module_list, &error_with_message](
+                          StructuredData::Object *obj) -> bool {
+    StructuredData::Dictionary *dict = obj->GetAsDictionary();
+
+    if (!dict)
+      return error_with_message("Couldn't cast image object into dictionary.");
+
+    ModuleSpec module_spec;
+    llvm::StringRef value;
+
+    bool has_path = dict->HasKey("path");
+    bool has_uuid = dict->HasKey("uuid");
+    if (!has_path && !has_uuid)
+      return error_with_message("Dictionary should have key 'path' or 'uuid'");
+    if (!dict->HasKey("load_addr"))
+      return error_with_message("Dictionary is missing key 'load_addr'");
+
+    if (has_path) {
+      dict->GetValueForKeyAsString("path", value);
+      module_spec.GetFileSpec().SetPath(value);
+    }
+
+    if (has_uuid) {
+      dict->GetValueForKeyAsString("uuid", value);
+      module_spec.GetUUID().SetFromStringRef(value);
+    }
+    module_spec.GetArchitecture() = target.GetArchitecture();
+
+    ModuleSP module_sp =
+        target.GetOrCreateModule(module_spec, true /* notify */);
+
+    if (!module_sp)
+      return error_with_message("Couldn't create or get module.");
+
+    lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+    lldb::addr_t slide = LLDB_INVALID_OFFSET;
+    dict->GetValueForKeyAsInteger("load_addr", load_addr);
+    dict->GetValueForKeyAsInteger("slide", slide);
+    if (load_addr == LLDB_INVALID_ADDRESS)
+      return error_with_message(
+          "Couldn't get valid load address or slide offset.");
+
+    if (slide != LLDB_INVALID_OFFSET)
+      load_addr += slide;
+
+    bool changed = false;
+    module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
+                              changed);
+
+    if (!changed && !module_sp->GetObjectFile())
+      return error_with_message("Couldn't set the load address for module.");
+
+    dict->GetValueForKeyAsString("path", value);
+    FileSpec objfile(value);
+    module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
+
+    return module_list.AppendIfNeeded(module_sp);
+  };
+
+  if (!loaded_images_sp->ForEach(reload_image))
+    return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>(
+        LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
+
+  target.ModulesDidLoad(module_list);
+
+  return loaded_images_sp;
+}
+
 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
   return m_interpreter->GetScriptedProcessInterface();
 }
Index: lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
+++ lldb/include/lldb/Interpreter/ScriptedProcessInterface.h
@@ -57,7 +57,7 @@
     return nullptr;
   }
 
-  virtual StructuredData::DictionarySP GetLoadedImages() { return nullptr; }
+  virtual StructuredData::ArraySP GetLoadedImages() { return nullptr; }
 
   virtual lldb::pid_t GetProcessID() { return LLDB_INVALID_PROCESS_ID; }
 
Index: lldb/examples/python/scripted_process/scripted_process.py
===================================================================
--- lldb/examples/python/scripted_process/scripted_process.py
+++ lldb/examples/python/scripted_process/scripted_process.py
@@ -19,7 +19,7 @@
     memory_regions = None
     stack_memory_dump = None
     loaded_images = None
-    threads = {}
+    threads = None
 
     @abstractmethod
     def __init__(self, target, args):
@@ -41,6 +41,8 @@
             self.dbg = target.GetDebugger()
         if isinstance(args, lldb.SBStructuredData) and args.IsValid():
             self.args = args
+        self.threads = {}
+        self.loaded_images = []
 
     @abstractmethod
     def get_memory_region_containing_address(self, addr):
@@ -116,8 +118,7 @@
 
         ```
         class ScriptedProcessImage:
-            def __init__(name, file_spec, uuid, load_address):
-              self.name = name
+            def __init__(file_spec, uuid, load_address):
               self.file_spec = file_spec
               self.uuid = uuid
               self.load_address = load_address
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to