mib updated this revision to Diff 386021.
mib marked 2 inline comments as done.
mib added a comment.

Address @JDevlieghere comments and skip test for non x86_64 archs


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D112047

Files:
  lldb/examples/python/scripted_process/main.stack-dump
  lldb/examples/python/scripted_process/my_scripted_process.py
  lldb/examples/python/scripted_process/scripted_process.py
  lldb/examples/python/scripted_process/stack_core_scripted_process.py
  lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py

Index: lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
===================================================================
--- lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
+++ lldb/test/API/functionalities/scripted_process/TestScriptedProcess.py
@@ -2,7 +2,7 @@
 Test python scripted process in lldb
 """
 
-import os
+import os, json, tempfile
 
 import lldb
 from lldbsuite.test.decorators import *
@@ -10,14 +10,15 @@
 from lldbsuite.test import lldbutil
 from lldbsuite.test import lldbtest
 
-
 class ScriptedProcesTestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
     def setUp(self):
         TestBase.setUp(self)
-        self.source = "main.c"
+        self.scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process']
+        self.scripted_process_example_abspath = os.path.join(self.getSourceDir(),
+                                                            *self.scripted_process_example_relpath)
 
     def tearDown(self):
         TestBase.tearDown(self)
@@ -43,7 +44,7 @@
         self.expect('script dir(ScriptedProcess)',
                     substrs=["launch"])
 
-    @skipIf(oslist=["linux"], archs=["arm", "aarch64"])
+    @skipIf(archs=no_match(['x86_64']))
     def test_scripted_process_and_scripted_thread(self):
         """Test that we can launch an lldb scripted process using the SBAPI,
         check its process ID, read string from memory, check scripted thread
@@ -78,19 +79,29 @@
         self.assertGreater(thread.GetNumFrames(), 0)
 
         frame = thread.GetFrameAtIndex(0)
+        GPRs = None
         register_set = frame.registers # Returns an SBValueList.
         for regs in register_set:
-            if 'GPR' in regs.name:
-                registers  = regs
+            if 'general purpose' in regs.name.lower():
+                GPRs = regs
                 break
 
-        self.assertTrue(registers, "Invalid General Purpose Registers Set")
-        self.assertEqual(registers.GetNumChildren(), 21)
-        for idx, reg in enumerate(registers, start=1):
+        self.assertTrue(GPRs, "Invalid General Purpose Registers Set")
+        self.assertEqual(GPRs.GetNumChildren(), 21)
+        for idx, reg in enumerate(GPRs, start=1):
             self.assertEqual(idx, int(reg.value, 16))
 
-    @skipIfDarwin
+    def create_stack_skinny_corefile(self, file):
+        self.build()
+        target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.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")
+
     @skipUnlessDarwin
+    @skipIf(archs=no_match(['x86_64']))
     def test_launch_scripted_process_stack_frames(self):
         """Test that we can launch an lldb scripted process from the command
         line, check its process ID and read string from memory."""
@@ -101,26 +112,44 @@
         for module in target.modules:
             if 'a.out' in module.GetFileSpec().GetFilename():
                 main_module = module
+                break
 
         self.assertTrue(main_module, "Invalid main module.")
         error = target.SetModuleLoadAddress(main_module, 0)
         self.assertTrue(error.Success(), "Reloading main module at offset 0 failed.")
 
-        scripted_process_example_relpath = ['..','..','..','..','examples','python','scripted_process','my_scripted_process.py']
-        self.runCmd("command script import " + os.path.join(self.getSourceDir(),
-                                                            *scripted_process_example_relpath))
+        os.environ['SKIP_SCRIPTED_PROCESS_LAUNCH'] = '1'
+        self.runCmd("command script import " + os.path.join(self.scripted_process_example_abspath,
+                                                            "stack_core_scripted_process.py"))
+
+        corefile_process = None
+        with tempfile.NamedTemporaryFile() as file:
+            self.create_stack_skinny_corefile(file.name)
+            corefile_target = self.dbg.CreateTarget(None)
+            corefile_process = corefile_target.LoadCore(self.getBuildArtifact(file.name))
+        self.assertTrue(corefile_process, PROCESS_IS_VALID)
+
+        structured_data = lldb.SBStructuredData()
+        structured_data.SetFromJSON(json.dumps({
+            "backing_target_idx" : self.dbg.GetIndexOfTarget(corefile_process.GetTarget())
+        }))
+        launch_info = lldb.SBLaunchInfo(None)
+        launch_info.SetProcessPluginName("ScriptedProcess")
+        launch_info.SetScriptedProcessClassName("stack_core_scripted_process.StackCoreScriptedProcess")
+        launch_info.SetScriptedProcessDictionary(structured_data)
 
-        process = target.GetProcess()
+        error = lldb.SBError()
+        process = target.Launch(launch_info, error)
+        self.assertTrue(error.Success(), error.GetCString())
         self.assertTrue(process, PROCESS_IS_VALID)
         self.assertEqual(process.GetProcessID(), 42)
-        self.assertEqual(process.GetNumThreads(), 1)
 
+        self.assertEqual(process.GetNumThreads(), 1)
         thread = process.GetSelectedThread()
         self.assertTrue(thread, "Invalid thread.")
-        self.assertEqual(thread.GetThreadID(), 0x19)
-        self.assertEqual(thread.GetName(), "MyScriptedThread.thread-1")
+        self.assertEqual(thread.GetName(), "StackCoreScriptedThread.thread-1")
 
-        self.assertEqual(thread.GetNumFrames(), 4)
+        self.assertEqual(thread.GetNumFrames(), 3)
         frame = thread.GetSelectedFrame()
         self.assertTrue(frame, "Invalid frame.")
         self.assertEqual(frame.GetFunctionName(), "bar")
Index: lldb/examples/python/scripted_process/stack_core_scripted_process.py
===================================================================
--- /dev/null
+++ lldb/examples/python/scripted_process/stack_core_scripted_process.py
@@ -0,0 +1,139 @@
+import os,struct,signal
+
+from typing import Any, Dict
+
+import lldb
+from lldb.plugins.scripted_process import ScriptedProcess
+from lldb.plugins.scripted_process import ScriptedThread
+
+class StackCoreScriptedProcess(ScriptedProcess):
+    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
+        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)
+            if self.backing_target_idx.GetType() == lldb.eStructuredDataTypeString:
+                idx = int(self.backing_target_idx.GetStringValue(100))
+            self.corefile_target = target.GetDebugger().GetTargetAtIndex(idx)
+            self.corefile_process = self.corefile_target.GetProcess()
+
+    def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
+        mem_region = lldb.SBMemoryRegionInfo()
+        error = self.corefile_process.GetMemoryRegionInfo(addr, mem_region)
+        if error.Fail():
+            return None
+        return mem_region
+
+    def get_thread_with_id(self, tid: int):
+        return {}
+
+    def get_registers_for_thread(self, tid: int):
+        return {}
+
+    def read_memory_at_address(self, addr: int, size: int) -> lldb.SBData:
+        data = lldb.SBData()
+        error = lldb.SBError()
+        bytes_read = self.corefile_process.ReadMemory(addr, size, error)
+
+        if error.Fail():
+            return data
+
+        data.SetData(error, bytes_read, self.corefile_target.GetByteOrder(),
+                        self.corefile_target.GetAddressByteSize())
+
+        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:
+        return 42
+
+    def should_stop(self) -> bool:
+        return True
+
+    def is_alive(self) -> bool:
+        return True
+
+    def get_scripted_thread_plugin(self):
+        return StackCoreScriptedThread.__module__ + "." + StackCoreScriptedThread.__name__
+
+
+class StackCoreScriptedThread(ScriptedThread):
+    def __init__(self, process, args):
+        super().__init__(process, args)
+        self.backing_target_idx = args.GetValueForKey("backing_target_idx")
+
+        self.corefile_target = None
+        self.corefile_process = None
+        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)
+            if self.backing_target_idx.GetType() == lldb.eStructuredDataTypeString:
+                idx = int(self.backing_target_idx.GetStringValue(100))
+            self.corefile_target = self.target.GetDebugger().GetTargetAtIndex(idx)
+            self.corefile_process = self.corefile_target.GetProcess()
+
+    def get_thread_id(self) -> int:
+        return 0x19
+
+    def get_name(self) -> str:
+        return StackCoreScriptedThread.__name__ + ".thread-1"
+
+    def get_stop_reason(self) -> Dict[str, Any]:
+        return { "type": lldb.eStopReasonSignal, "data": {
+            "signal": signal.SIGINT
+        } }
+
+    def get_stackframes(self):
+        class ScriptedStackFrame:
+            def __init__(idx, cfa, pc, symbol_ctx):
+                self.idx = idx
+                self.cfa = cfa
+                self.pc = pc
+                self.symbol_ctx = symbol_ctx
+
+
+        symbol_ctx = lldb.SBSymbolContext()
+        frame_zero = ScriptedStackFrame(0, 0x42424242, 0x5000000, symbol_ctx)
+        self.frames.append(frame_zero)
+
+        return self.frame_zero[0:0]
+
+    def get_register_context(self) -> str:
+        thread = self.corefile_process.GetSelectedThread()
+        if not thread or thread.GetNumFrames() == 0:
+            return None
+        frame = thread.GetFrameAtIndex(0)
+
+        GPRs = None
+        registerSet = frame.registers # Returns an SBValueList.
+        for regs in registerSet:
+            if 'general purpose' in regs.name.lower():
+                GPRs = regs
+                break
+
+        if not GPRs:
+            return None
+
+        for reg in GPRs:
+            self.register_ctx[reg.name] = int(reg.value, base=16)
+
+        return struct.pack("{}Q".format(len(self.register_ctx)), *self.register_ctx.values())
+
+
+def __lldb_init_module(debugger, dict):
+    if not 'SKIP_SCRIPTED_PROCESS_LAUNCH' in os.environ:
+        debugger.HandleCommand(
+            "process launch -C %s.%s" % (__name__,
+                                     StackCoreScriptedProcess.__name__))
+    else:
+        print("Name of the class that will manage the scripted process: '%s.%s'"
+                % (__name__, StackCoreScriptedProcess.__name__))
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
@@ -37,7 +37,7 @@
             self.args = args
 
     @abstractmethod
-    def get_memory_region_containing_address(addr):
+    def get_memory_region_containing_address(self, addr):
         """ Get the memory region for the scripted process, containing a
             specific address.
 
@@ -52,7 +52,7 @@
         pass
 
     @abstractmethod
-    def get_thread_with_id(tid):
+    def get_thread_with_id(self, tid):
         """ Get the scripted process thread with a specific ID.
 
         Args:
@@ -66,7 +66,7 @@
         pass
 
     @abstractmethod
-    def get_registers_for_thread(tid):
+    def get_registers_for_thread(self, tid):
         """ Get the register context dictionary for a certain thread of
             the scripted process.
 
@@ -81,7 +81,7 @@
         pass
 
     @abstractmethod
-    def read_memory_at_address(addr, size):
+    def read_memory_at_address(self, addr, size):
         """ Get a memory buffer from the scripted process at a certain address,
             of a certain size.
 
@@ -211,7 +211,7 @@
         self.state = None
         self.stop_reason = None
         self.register_info = None
-        self.register_ctx = []
+        self.register_ctx = {}
         self.frames = []
 
     @abstractmethod
@@ -294,7 +294,7 @@
             if triple:
                 arch = triple.split('-')[0]
                 if arch == 'x86_64':
-                    self.register_info['sets'] = ['GPR', 'FPU', 'EXC']
+                    self.register_info['sets'] = ['General Purpose Registers']
                     self.register_info['registers'] = [
                         {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0},
                         {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3},
Index: lldb/examples/python/scripted_process/my_scripted_process.py
===================================================================
--- lldb/examples/python/scripted_process/my_scripted_process.py
+++ lldb/examples/python/scripted_process/my_scripted_process.py
@@ -69,7 +69,7 @@
 
 
 class MyScriptedThread(ScriptedThread):
-    registers = {
+    register_ctx = {
         "rax":0x00000000000006e4,
         "rbx":0x00000001040b6060,
         "rcx":0x00000001040b2e00,
@@ -123,7 +123,7 @@
         return self.frame_zero[0:0]
 
     def get_register_context(self) -> str:
-        return struct.pack("{}Q".format(len(self.registers)), *self.registers.values())
+        return struct.pack("{}Q".format(len(self.register_ctx)), *self.register_ctx.values())
 
 
 def __lldb_init_module(debugger, dict):
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to