mib created this revision.
mib added a reviewer: JDevlieghere.
mib added a project: LLDB.
mib requested review of this revision.
Herald added a subscriber: lldb-commits.

This patch changes the ScriptedProcess test to use a stack-only skinny
corefile as a backing store.

The corefile is saved as a temporary file at the beginning of the test,
and a second target is created for the ScriptedProcess. To do so, we use
the SBAPI from the ScriptedProcess' python script to interact with the
corefile process.

This patch also makes some small adjustments to the other ScriptedProcess
scripts to resolve some inconsistencies and removes the raw memory dump
that was previously checked in.

Signed-off-by: Med Ismail Bennani <medismail.benn...@gmail.com>


Repository:
  rG LLVM Github Monorepo

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)
@@ -89,8 +90,19 @@
         for idx, reg in enumerate(registers, start=1):
             self.assertEqual(idx, int(reg.value, 16))
 
-    @skipIfDarwin
-    @skipUnlessDarwin
+    def create_stack_skinny_corefile(self):
+        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.
+        stack_core = tempfile.NamedTemporaryFile()
+        self.runCmd("process save-core -s stack  " + stack_core.name)
+        self.assertTrue(os.path.exists(stack_core.name), "No stack-only corefile found.")
+        self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target")
+        print(stack_core.name)
+        target = self.dbg.CreateTarget(None)
+        return target.LoadCore(self.getBuildArtifact(stack_core.name))
+
     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,24 +113,38 @@
         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"))
 
-        process = target.GetProcess()
+        corefile_process = self.create_stack_skinny_corefile()
+        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)
+
+        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)
         frame = thread.GetSelectedFrame()
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,129 @@
+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:
+        error = lldb.SBError()
+        data = self.corefile_process.ReadMemory(addr, size, error)
+        if error.Fail():
+            return None
+        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)
+        import pdb
+        pdb.set_trace()
+        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 = lldbutil.get_GPRs(frame)
+
+        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
@@ -210,7 +210,7 @@
         self.state = None
         self.stop_reason = None
         self.register_info = None
-        self.register_ctx = []
+        self.register_ctx = {}
         self.frames = []
 
     @abstractmethod
@@ -293,7 +293,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
@@ -115,7 +115,7 @@
 
 
 class MyScriptedThread(ScriptedThread):
-    registers = {
+    register_ctx = {
         "rax":0x00000000000006e4,
         "rbx":0x00000001040b6060,
         "rcx":0x00000001040b2e00,
@@ -169,7 +169,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