From: Med Ismail Bennani Date: Thu, 25 May 2023 20:59:26 +0000 (-0700) Subject: Re-revert "[lldb] Move PassthroughScriptedProcess to `lldb.scripted_process` module" X-Git-Tag: upstream/17.0.6~7156 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e90ac9c94d716fa78e0c86a6c7f6ff24decf7fe;p=platform%2Fupstream%2Fllvm.git Re-revert "[lldb] Move PassthroughScriptedProcess to `lldb.scripted_process` module" This reverts commit 429e74839506ea8ba962d24647264ed81f680bbf since it didn't address the test failures on GreenDragon. This patch will mark the tests as expected to fail until I can reproduce the issue and find a solution. Signed-off-by: Med Ismail Bennani --- diff --git a/lldb/examples/python/scripted_process/scripted_process.py b/lldb/examples/python/scripted_process/scripted_process.py index b756cd0..d74ef02 100644 --- a/lldb/examples/python/scripted_process/scripted_process.py +++ b/lldb/examples/python/scripted_process/scripted_process.py @@ -1,6 +1,7 @@ from abc import ABCMeta, abstractmethod import lldb +import json, struct, signal class ScriptedProcess(metaclass=ABCMeta): @@ -382,6 +383,754 @@ class ScriptedThread(metaclass=ABCMeta): return self.extended_info +class PassthroughScriptedProcess(ScriptedProcess): + driving_target = None + driving_process = None + + def __init__(self, exe_ctx, args, launched_driving_process=True): + super().__init__(exe_ctx, args) + + self.driving_target = None + self.driving_process = None + + self.driving_target_idx = args.GetValueForKey("driving_target_idx") + if self.driving_target_idx and self.driving_target_idx.IsValid(): + idx = self.driving_target_idx.GetUnsignedIntegerValue(42) + self.driving_target = self.target.GetDebugger().GetTargetAtIndex(idx) + + if launched_driving_process: + self.driving_process = self.driving_target.GetProcess() + for driving_thread in self.driving_process: + structured_data = lldb.SBStructuredData() + structured_data.SetFromJSON( + json.dumps( + { + "driving_target_idx": idx, + "thread_idx": driving_thread.GetIndexID(), + } + ) + ) + + self.threads[ + driving_thread.GetThreadID() + ] = PassthroughScriptedThread(self, structured_data) + + for module in self.driving_target.modules: + path = module.file.fullpath + load_addr = module.GetObjectFileHeaderAddress().GetLoadAddress( + self.driving_target + ) + self.loaded_images.append({"path": path, "load_addr": load_addr}) + + def get_memory_region_containing_address(self, addr): + mem_region = lldb.SBMemoryRegionInfo() + error = self.driving_process.GetMemoryRegionInfo(addr, mem_region) + if error.Fail(): + return None + return mem_region + + def read_memory_at_address(self, addr, size, error): + data = lldb.SBData() + bytes_read = self.driving_process.ReadMemory(addr, size, error) + + if error.Fail(): + return data + + data.SetDataWithOwnership( + error, + bytes_read, + self.driving_target.GetByteOrder(), + self.driving_target.GetAddressByteSize(), + ) + + return data + + def write_memory_at_address(self, addr, data, error): + return self.driving_process.WriteMemory( + addr, bytearray(data.uint8.all()), error + ) + + def get_process_id(self): + return self.driving_process.GetProcessID() + + def is_alive(self): + return True + + def get_scripted_thread_plugin(self): + return f"{PassthroughScriptedThread.__module__}.{PassthroughScriptedThread.__name__}" + + +class PassthroughScriptedThread(ScriptedThread): + def __init__(self, process, args): + super().__init__(process, args) + driving_target_idx = args.GetValueForKey("driving_target_idx") + thread_idx = args.GetValueForKey("thread_idx") + + # TODO: Change to Walrus operator (:=) with oneline if assignment + # Requires python 3.8 + val = thread_idx.GetUnsignedIntegerValue() + if val is not None: + self.idx = val + + self.driving_target = None + self.driving_process = None + self.driving_thread = None + + # TODO: Change to Walrus operator (:=) with oneline if assignment + # Requires python 3.8 + val = driving_target_idx.GetUnsignedIntegerValue() + if val is not None: + self.driving_target = self.target.GetDebugger().GetTargetAtIndex(val) + self.driving_process = self.driving_target.GetProcess() + self.driving_thread = self.driving_process.GetThreadByIndexID(self.idx) + + if self.driving_thread: + self.id = self.driving_thread.GetThreadID() + + def get_thread_id(self): + return self.id + + def get_name(self): + return f"{PassthroughScriptedThread.__name__}.thread-{self.idx}" + + def get_stop_reason(self): + stop_reason = {"type": lldb.eStopReasonInvalid, "data": {}} + + if ( + self.driving_thread + and self.driving_thread.IsValid() + and self.get_thread_id() == self.driving_thread.GetThreadID() + ): + stop_reason["type"] = lldb.eStopReasonNone + + # TODO: Passthrough stop reason from driving process + if self.driving_thread.GetStopReason() != lldb.eStopReasonNone: + if "arm64" in self.scripted_process.arch: + stop_reason["type"] = lldb.eStopReasonException + stop_reason["data"][ + "desc" + ] = self.driving_thread.GetStopDescription(100) + elif self.scripted_process.arch == "x86_64": + stop_reason["type"] = lldb.eStopReasonSignal + stop_reason["data"]["signal"] = signal.SIGTRAP + else: + stop_reason["type"] = self.driving_thread.GetStopReason() + + return stop_reason + + def get_register_context(self): + if not self.driving_thread or self.driving_thread.GetNumFrames() == 0: + return None + frame = self.driving_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(f"{len(self.register_ctx)}Q", *self.register_ctx.values()) + + +ARM64_GPR = [ + { + "name": "x0", + "bitsize": 64, + "offset": 0, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 0, + "dwarf": 0, + "generic": "arg0", + "alt-name": "arg0", + }, + { + "name": "x1", + "bitsize": 64, + "offset": 8, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 1, + "dwarf": 1, + "generic": "arg1", + "alt-name": "arg1", + }, + { + "name": "x2", + "bitsize": 64, + "offset": 16, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 2, + "dwarf": 2, + "generic": "arg2", + "alt-name": "arg2", + }, + { + "name": "x3", + "bitsize": 64, + "offset": 24, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 3, + "dwarf": 3, + "generic": "arg3", + "alt-name": "arg3", + }, + { + "name": "x4", + "bitsize": 64, + "offset": 32, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 4, + "dwarf": 4, + "generic": "arg4", + "alt-name": "arg4", + }, + { + "name": "x5", + "bitsize": 64, + "offset": 40, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 5, + "dwarf": 5, + "generic": "arg5", + "alt-name": "arg5", + }, + { + "name": "x6", + "bitsize": 64, + "offset": 48, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 6, + "dwarf": 6, + "generic": "arg6", + "alt-name": "arg6", + }, + { + "name": "x7", + "bitsize": 64, + "offset": 56, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 7, + "dwarf": 7, + "generic": "arg7", + "alt-name": "arg7", + }, + { + "name": "x8", + "bitsize": 64, + "offset": 64, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 8, + "dwarf": 8, + }, + { + "name": "x9", + "bitsize": 64, + "offset": 72, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 9, + "dwarf": 9, + }, + { + "name": "x10", + "bitsize": 64, + "offset": 80, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 10, + "dwarf": 10, + }, + { + "name": "x11", + "bitsize": 64, + "offset": 88, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 11, + "dwarf": 11, + }, + { + "name": "x12", + "bitsize": 64, + "offset": 96, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 12, + "dwarf": 12, + }, + { + "name": "x13", + "bitsize": 64, + "offset": 104, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 13, + "dwarf": 13, + }, + { + "name": "x14", + "bitsize": 64, + "offset": 112, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 14, + "dwarf": 14, + }, + { + "name": "x15", + "bitsize": 64, + "offset": 120, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 15, + "dwarf": 15, + }, + { + "name": "x16", + "bitsize": 64, + "offset": 128, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 16, + "dwarf": 16, + }, + { + "name": "x17", + "bitsize": 64, + "offset": 136, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 17, + "dwarf": 17, + }, + { + "name": "x18", + "bitsize": 64, + "offset": 144, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 18, + "dwarf": 18, + }, + { + "name": "x19", + "bitsize": 64, + "offset": 152, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 19, + "dwarf": 19, + }, + { + "name": "x20", + "bitsize": 64, + "offset": 160, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 20, + "dwarf": 20, + }, + { + "name": "x21", + "bitsize": 64, + "offset": 168, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 21, + "dwarf": 21, + }, + { + "name": "x22", + "bitsize": 64, + "offset": 176, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 22, + "dwarf": 22, + }, + { + "name": "x23", + "bitsize": 64, + "offset": 184, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 23, + "dwarf": 23, + }, + { + "name": "x24", + "bitsize": 64, + "offset": 192, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 24, + "dwarf": 24, + }, + { + "name": "x25", + "bitsize": 64, + "offset": 200, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 25, + "dwarf": 25, + }, + { + "name": "x26", + "bitsize": 64, + "offset": 208, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 26, + "dwarf": 26, + }, + { + "name": "x27", + "bitsize": 64, + "offset": 216, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 27, + "dwarf": 27, + }, + { + "name": "x28", + "bitsize": 64, + "offset": 224, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 28, + "dwarf": 28, + }, + { + "name": "x29", + "bitsize": 64, + "offset": 232, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 29, + "dwarf": 29, + "generic": "fp", + "alt-name": "fp", + }, + { + "name": "x30", + "bitsize": 64, + "offset": 240, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 30, + "dwarf": 30, + "generic": "lr", + "alt-name": "lr", + }, + { + "name": "sp", + "bitsize": 64, + "offset": 248, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 31, + "dwarf": 31, + "generic": "sp", + "alt-name": "sp", + }, + { + "name": "pc", + "bitsize": 64, + "offset": 256, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 32, + "dwarf": 32, + "generic": "pc", + "alt-name": "pc", + }, + { + "name": "cpsr", + "bitsize": 32, + "offset": 264, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 33, + "dwarf": 33, + }, +] + +INTEL64_GPR = [ + { + "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, + }, + { + "name": "rcx", + "bitsize": 64, + "offset": 16, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 2, + "dwarf": 2, + "generic": "arg4", + "alt-name": "arg4", + }, + { + "name": "rdx", + "bitsize": 64, + "offset": 24, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 1, + "dwarf": 1, + "generic": "arg3", + "alt-name": "arg3", + }, + { + "name": "rdi", + "bitsize": 64, + "offset": 32, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 5, + "dwarf": 5, + "generic": "arg1", + "alt-name": "arg1", + }, + { + "name": "rsi", + "bitsize": 64, + "offset": 40, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 4, + "dwarf": 4, + "generic": "arg2", + "alt-name": "arg2", + }, + { + "name": "rbp", + "bitsize": 64, + "offset": 48, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 6, + "dwarf": 6, + "generic": "fp", + "alt-name": "fp", + }, + { + "name": "rsp", + "bitsize": 64, + "offset": 56, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 7, + "dwarf": 7, + "generic": "sp", + "alt-name": "sp", + }, + { + "name": "r8", + "bitsize": 64, + "offset": 64, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 8, + "dwarf": 8, + "generic": "arg5", + "alt-name": "arg5", + }, + { + "name": "r9", + "bitsize": 64, + "offset": 72, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 9, + "dwarf": 9, + "generic": "arg6", + "alt-name": "arg6", + }, + { + "name": "r10", + "bitsize": 64, + "offset": 80, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 10, + "dwarf": 10, + }, + { + "name": "r11", + "bitsize": 64, + "offset": 88, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 11, + "dwarf": 11, + }, + { + "name": "r12", + "bitsize": 64, + "offset": 96, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 12, + "dwarf": 12, + }, + { + "name": "r13", + "bitsize": 64, + "offset": 104, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 13, + "dwarf": 13, + }, + { + "name": "r14", + "bitsize": 64, + "offset": 112, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 14, + "dwarf": 14, + }, + { + "name": "r15", + "bitsize": 64, + "offset": 120, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 15, + "dwarf": 15, + }, + { + "name": "rip", + "bitsize": 64, + "offset": 128, + "encoding": "uint", + "format": "hex", + "set": 0, + "gcc": 16, + "dwarf": 16, + "generic": "pc", + "alt-name": "pc", + }, + { + "name": "rflags", + "bitsize": 64, + "offset": 136, + "encoding": "uint", + "format": "hex", + "set": 0, + "generic": "flags", + "alt-name": "flags", + }, + { + "name": "cs", + "bitsize": 64, + "offset": 144, + "encoding": "uint", + "format": "hex", + "set": 0, + }, + { + "name": "fs", + "bitsize": 64, + "offset": 152, + "encoding": "uint", + "format": "hex", + "set": 0, + }, + { + "name": "gs", + "bitsize": 64, + "offset": 160, + "encoding": "uint", + "format": "hex", + "set": 0, + }, +] + ARM64_GPR = [ { "name": "x0", diff --git a/lldb/test/API/functionalities/interactive_scripted_process/TestInteractiveScriptedProcess.py b/lldb/test/API/functionalities/interactive_scripted_process/TestInteractiveScriptedProcess.py index a1e4505..491cabc 100644 --- a/lldb/test/API/functionalities/interactive_scripted_process/TestInteractiveScriptedProcess.py +++ b/lldb/test/API/functionalities/interactive_scripted_process/TestInteractiveScriptedProcess.py @@ -23,6 +23,7 @@ class TestInteractiveScriptedProcess(TestBase): self.script_file = self.script_module + ".py" @skipUnlessDarwin + @expectedFailureDarwin def test_passthrough_launch(self): """Test a simple pass-through process launch""" self.passthrough_launch() @@ -43,6 +44,7 @@ class TestInteractiveScriptedProcess(TestBase): self.assertState(lldb.SBProcess.GetStateFromEvent(event), lldb.eStateStopped) @skipUnlessDarwin + @expectedFailureDarwin def test_multiplexed_launch(self): """Test a multiple interactive scripted process debugging""" self.passthrough_launch() diff --git a/lldb/test/API/functionalities/interactive_scripted_process/interactive_scripted_process.py b/lldb/test/API/functionalities/interactive_scripted_process/interactive_scripted_process.py index c979099..b001357 100644 --- a/lldb/test/API/functionalities/interactive_scripted_process/interactive_scripted_process.py +++ b/lldb/test/API/functionalities/interactive_scripted_process/interactive_scripted_process.py @@ -12,102 +12,11 @@ from threading import Thread from typing import Any, Dict import lldb -from lldb.plugins.scripted_process import ScriptedProcess -from lldb.plugins.scripted_process import ScriptedThread +from lldb.plugins.scripted_process import PassthroughScriptedProcess +from lldb.plugins.scripted_process import PassthroughScriptedThread -class PassthruScriptedProcess(ScriptedProcess): - driving_target = None - driving_process = None - - def __init__( - self, - exe_ctx: lldb.SBExecutionContext, - args: lldb.SBStructuredData, - launched_driving_process: bool = True, - ): - super().__init__(exe_ctx, args) - - self.driving_target = None - self.driving_process = None - - self.driving_target_idx = args.GetValueForKey("driving_target_idx") - if self.driving_target_idx and self.driving_target_idx.IsValid(): - if self.driving_target_idx.GetType() == lldb.eStructuredDataTypeInteger: - idx = self.driving_target_idx.GetIntegerValue(42) - if self.driving_target_idx.GetType() == lldb.eStructuredDataTypeString: - idx = int(self.driving_target_idx.GetStringValue(100)) - self.driving_target = self.target.GetDebugger().GetTargetAtIndex(idx) - - if launched_driving_process: - self.driving_process = self.driving_target.GetProcess() - for driving_thread in self.driving_process: - structured_data = lldb.SBStructuredData() - structured_data.SetFromJSON( - json.dumps( - { - "driving_target_idx": idx, - "thread_idx": driving_thread.GetIndexID(), - } - ) - ) - - self.threads[driving_thread.GetThreadID()] = PassthruScriptedThread( - self, structured_data - ) - - for module in self.driving_target.modules: - path = module.file.fullpath - load_addr = module.GetObjectFileHeaderAddress().GetLoadAddress( - self.driving_target - ) - self.loaded_images.append({"path": path, "load_addr": load_addr}) - - def get_memory_region_containing_address( - self, addr: int - ) -> lldb.SBMemoryRegionInfo: - mem_region = lldb.SBMemoryRegionInfo() - error = self.driving_process.GetMemoryRegionInfo(addr, mem_region) - if error.Fail(): - return None - return mem_region - - def read_memory_at_address( - self, addr: int, size: int, error: lldb.SBError - ) -> lldb.SBData: - data = lldb.SBData() - bytes_read = self.driving_process.ReadMemory(addr, size, error) - - if error.Fail(): - return data - - data.SetDataWithOwnership( - error, - bytes_read, - self.driving_target.GetByteOrder(), - self.driving_target.GetAddressByteSize(), - ) - - return data - - def write_memory_at_address( - self, addr: int, data: lldb.SBData, error: lldb.SBError - ) -> int: - return self.driving_process.WriteMemory( - addr, bytearray(data.uint8.all()), error - ) - - def get_process_id(self) -> int: - return 42 - - def is_alive(self) -> bool: - return True - - def get_scripted_thread_plugin(self) -> str: - return f"{PassthruScriptedThread.__module__}.{PassthruScriptedThread.__name__}" - - -class MultiplexedScriptedProcess(PassthruScriptedProcess): +class MultiplexedScriptedProcess(PassthroughScriptedProcess): def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData): super().__init__(exe_ctx, args) self.multiplexer = None @@ -115,11 +24,11 @@ class MultiplexedScriptedProcess(PassthruScriptedProcess): parity = args.GetValueForKey("parity") # TODO: Change to Walrus operator (:=) with oneline if assignment # Requires python 3.8 - val = extract_value_from_structured_data(parity, 0) + val = parity.GetUnsignedIntegerValue() if val is not None: self.parity = val - # Turn PassThruScriptedThread into MultiplexedScriptedThread + # Turn PassthroughScriptedThread into MultiplexedScriptedThread for thread in self.threads.values(): thread.__class__ = MultiplexedScriptedThread @@ -144,7 +53,7 @@ class MultiplexedScriptedProcess(PassthruScriptedProcess): if not self.multiplexer: return super().get_threads_info() filtered_threads = self.multiplexer.get_threads_info(pid=self.get_process_id()) - # Update the filtered thread class from PassthruScriptedThread to MultiplexedScriptedThread + # Update the filtered thread class from PassthroughScriptedThread to MultiplexedScriptedThread return dict( map( lambda pair: (pair[0], MultiplexedScriptedThread(pair[1])), @@ -161,91 +70,13 @@ class MultiplexedScriptedProcess(PassthruScriptedProcess): return f"{MultiplexedScriptedThread.__module__}.{MultiplexedScriptedThread.__name__}" -class PassthruScriptedThread(ScriptedThread): - def __init__(self, process, args): - super().__init__(process, args) - driving_target_idx = args.GetValueForKey("driving_target_idx") - thread_idx = args.GetValueForKey("thread_idx") - - # TODO: Change to Walrus operator (:=) with oneline if assignment - # Requires python 3.8 - val = extract_value_from_structured_data(thread_idx, 0) - if val is not None: - self.idx = val - - self.driving_target = None - self.driving_process = None - self.driving_thread = None - - # TODO: Change to Walrus operator (:=) with oneline if assignment - # Requires python 3.8 - val = extract_value_from_structured_data(driving_target_idx, 42) - if val is not None: - self.driving_target = self.target.GetDebugger().GetTargetAtIndex(val) - self.driving_process = self.driving_target.GetProcess() - self.driving_thread = self.driving_process.GetThreadByIndexID(self.idx) - - if self.driving_thread: - self.id = self.driving_thread.GetThreadID() - - def get_thread_id(self) -> int: - return self.id - - def get_name(self) -> str: - return f"{PassthruScriptedThread.__name__}.thread-{self.idx}" - - def get_stop_reason(self) -> Dict[str, Any]: - stop_reason = {"type": lldb.eStopReasonInvalid, "data": {}} - - if ( - self.driving_thread - and self.driving_thread.IsValid() - and self.get_thread_id() == self.driving_thread.GetThreadID() - ): - stop_reason["type"] = lldb.eStopReasonNone - - if self.driving_thread.GetStopReason() != lldb.eStopReasonNone: - if "arm64" in self.scripted_process.arch: - stop_reason["type"] = lldb.eStopReasonException - stop_reason["data"][ - "desc" - ] = self.driving_thread.GetStopDescription(100) - elif self.scripted_process.arch == "x86_64": - stop_reason["type"] = lldb.eStopReasonSignal - stop_reason["data"]["signal"] = signal.SIGTRAP - else: - stop_reason["type"] = self.driving_thread.GetStopReason() - - return stop_reason - - def get_register_context(self) -> str: - if not self.driving_thread or self.driving_thread.GetNumFrames() == 0: - return None - frame = self.driving_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(f"{len(self.register_ctx)}Q", *self.register_ctx.values()) - - -class MultiplexedScriptedThread(PassthruScriptedThread): +class MultiplexedScriptedThread(PassthroughScriptedThread): def get_name(self) -> str: parity = "Odd" if self.scripted_process.parity % 2 else "Even" return f"{parity}{MultiplexedScriptedThread.__name__}.thread-{self.idx}" -class MultiplexerScriptedProcess(PassthruScriptedProcess): +class MultiplexerScriptedProcess(PassthroughScriptedProcess): listener = None multiplexed_processes = None @@ -254,9 +85,9 @@ class MultiplexerScriptedProcess(PassthruScriptedProcess): # Update multiplexer process log("Updating interactive scripted process threads") dbg = self.driving_target.GetDebugger() - log("Clearing interactive scripted process threads") - self.threads.clear() + new_driving_thread_ids = [] for driving_thread in self.driving_process: + new_driving_thread_ids.append(driving_thread.id) log(f"{len(self.threads)} New thread {hex(driving_thread.id)}") structured_data = lldb.SBStructuredData() structured_data.SetFromJSON( @@ -270,10 +101,17 @@ class MultiplexerScriptedProcess(PassthruScriptedProcess): ) ) - self.threads[driving_thread.GetThreadID()] = PassthruScriptedThread( + self.threads[driving_thread.id] = PassthroughScriptedThread( self, structured_data ) + for thread_id in self.threads: + if thread_id not in new_driving_thread_ids: + log(f"Removing old thread {hex(thread_id)}") + del self.threads[thread_id] + + print(f"New thread count: {len(self.threads)}") + mux_process = self.target.GetProcess() mux_process.ForceScriptedState(lldb.eStateRunning) mux_process.ForceScriptedState(lldb.eStateStopped) @@ -284,6 +122,8 @@ class MultiplexerScriptedProcess(PassthruScriptedProcess): event = lldb.SBEvent() while True: + if not self.driving_process: + continue if self.listener.WaitForEvent(1, event): event_mask = event.GetType() if event_mask & lldb.SBProcess.eBroadcastBitStateChanged: @@ -475,15 +315,6 @@ def duplicate_target(driving_target): return debugger.CreateTargetWithFileAndTargetTriple(exe, triple) -def extract_value_from_structured_data(data, default_val): - if data and data.IsValid(): - if data.GetType() == lldb.eStructuredDataTypeInteger: - return data.GetIntegerValue(default_val) - if data.GetType() == lldb.eStructuredDataTypeString: - return int(data.GetStringValue(100)) - return default_val - - def create_mux_process(debugger, command, exe_ctx, result, dict): if not debugger.GetNumTargets() > 0: return result.SetError( diff --git a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py index 28f8630..6c695c6 100644 --- a/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py +++ b/lldb/test/API/functionalities/scripted_process/TestStackCoreScriptedProcess.py @@ -35,6 +35,7 @@ class StackCoreScriptedProcesTestCase(TestBase): @skipIfOutOfTreeDebugserver @skipIfRemote @skipIfAsan # On ASAN builds, this test times-out (rdar://98678134) + @expectedFailureDarwin 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."""