16cf66801SMed Ismail Bennani# Usage: 26cf66801SMed Ismail Bennani# ./bin/lldb $LLVM/lldb/test/API/functionalities/interactive_scripted_process/main \ 36cf66801SMed Ismail Bennani# -o "br set -p 'Break here'" \ 46cf66801SMed Ismail Bennani# -o "command script import $LLVM/lldb/test/API/functionalities/interactive_scripted_process/interactive_scripted_process.py" \ 56cf66801SMed Ismail Bennani# -o "create_mux" \ 66cf66801SMed Ismail Bennani# -o "create_sub" \ 76cf66801SMed Ismail Bennani# -o "br set -p 'also break here'" -o 'continue' 86cf66801SMed Ismail Bennani 9e31d0c20SMed Ismail Bennaniimport os, json, struct, signal, tempfile 106cf66801SMed Ismail Bennani 116cf66801SMed Ismail Bennanifrom threading import Thread 126cf66801SMed Ismail Bennanifrom typing import Any, Dict 136cf66801SMed Ismail Bennani 146cf66801SMed Ismail Bennaniimport lldb 15*0e90ac9cSMed Ismail Bennanifrom lldb.plugins.scripted_process import PassthroughScriptedProcess 16*0e90ac9cSMed Ismail Bennanifrom lldb.plugins.scripted_process import PassthroughScriptedThread 176cf66801SMed Ismail Bennani 18429e7483SMed Ismail Bennani 19*0e90ac9cSMed Ismail Bennaniclass MultiplexedScriptedProcess(PassthroughScriptedProcess): 206cf66801SMed Ismail Bennani def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData): 216cf66801SMed Ismail Bennani super().__init__(exe_ctx, args) 226cf66801SMed Ismail Bennani self.multiplexer = None 236cf66801SMed Ismail Bennani if isinstance(self.driving_process, lldb.SBProcess) and self.driving_process: 246cf66801SMed Ismail Bennani parity = args.GetValueForKey("parity") 256cf66801SMed Ismail Bennani # TODO: Change to Walrus operator (:=) with oneline if assignment 266cf66801SMed Ismail Bennani # Requires python 3.8 27*0e90ac9cSMed Ismail Bennani val = parity.GetUnsignedIntegerValue() 286cf66801SMed Ismail Bennani if val is not None: 296cf66801SMed Ismail Bennani self.parity = val 306cf66801SMed Ismail Bennani 31*0e90ac9cSMed Ismail Bennani # Turn PassthroughScriptedThread into MultiplexedScriptedThread 326cf66801SMed Ismail Bennani for thread in self.threads.values(): 336cf66801SMed Ismail Bennani thread.__class__ = MultiplexedScriptedThread 346cf66801SMed Ismail Bennani 356cf66801SMed Ismail Bennani def get_process_id(self) -> int: 366cf66801SMed Ismail Bennani return self.parity + 420 376cf66801SMed Ismail Bennani 386cf66801SMed Ismail Bennani def launch(self, should_stop: bool = True) -> lldb.SBError: 396cf66801SMed Ismail Bennani self.first_launch = True 406cf66801SMed Ismail Bennani return lldb.SBError() 416cf66801SMed Ismail Bennani 426cf66801SMed Ismail Bennani def resume(self, should_stop: bool) -> lldb.SBError: 436cf66801SMed Ismail Bennani if self.first_launch: 446cf66801SMed Ismail Bennani self.first_launch = False 456cf66801SMed Ismail Bennani return super().resume() 466cf66801SMed Ismail Bennani else: 476cf66801SMed Ismail Bennani if not self.multiplexer: 486cf66801SMed Ismail Bennani error = lldb.SBError("Multiplexer is not set.") 496cf66801SMed Ismail Bennani return error 506cf66801SMed Ismail Bennani return self.multiplexer.resume(should_stop) 516cf66801SMed Ismail Bennani 526cf66801SMed Ismail Bennani def get_threads_info(self) -> Dict[int, Any]: 536cf66801SMed Ismail Bennani if not self.multiplexer: 546cf66801SMed Ismail Bennani return super().get_threads_info() 556cf66801SMed Ismail Bennani filtered_threads = self.multiplexer.get_threads_info(pid=self.get_process_id()) 56*0e90ac9cSMed Ismail Bennani # Update the filtered thread class from PassthroughScriptedThread to MultiplexedScriptedThread 576cf66801SMed Ismail Bennani return dict( 586cf66801SMed Ismail Bennani map( 596cf66801SMed Ismail Bennani lambda pair: (pair[0], MultiplexedScriptedThread(pair[1])), 606cf66801SMed Ismail Bennani filtered_threads.items(), 616cf66801SMed Ismail Bennani ) 626cf66801SMed Ismail Bennani ) 636cf66801SMed Ismail Bennani 64e31d0c20SMed Ismail Bennani def create_breakpoint(self, addr, error, pid=None): 65e31d0c20SMed Ismail Bennani if not self.multiplexer: 66e31d0c20SMed Ismail Bennani error.SetErrorString("Multiplexer is not set.") 67e31d0c20SMed Ismail Bennani return self.multiplexer.create_breakpoint(addr, error, self.get_process_id()) 68e31d0c20SMed Ismail Bennani 696cf66801SMed Ismail Bennani def get_scripted_thread_plugin(self) -> str: 706cf66801SMed Ismail Bennani return f"{MultiplexedScriptedThread.__module__}.{MultiplexedScriptedThread.__name__}" 716cf66801SMed Ismail Bennani 72429e7483SMed Ismail Bennani 73*0e90ac9cSMed Ismail Bennaniclass MultiplexedScriptedThread(PassthroughScriptedThread): 746cf66801SMed Ismail Bennani def get_name(self) -> str: 756cf66801SMed Ismail Bennani parity = "Odd" if self.scripted_process.parity % 2 else "Even" 766cf66801SMed Ismail Bennani return f"{parity}{MultiplexedScriptedThread.__name__}.thread-{self.idx}" 776cf66801SMed Ismail Bennani 786cf66801SMed Ismail Bennani 79*0e90ac9cSMed Ismail Bennaniclass MultiplexerScriptedProcess(PassthroughScriptedProcess): 806cf66801SMed Ismail Bennani listener = None 816cf66801SMed Ismail Bennani multiplexed_processes = None 826cf66801SMed Ismail Bennani 836cf66801SMed Ismail Bennani def wait_for_driving_process_to_stop(self): 846cf66801SMed Ismail Bennani def handle_process_state_event(): 856cf66801SMed Ismail Bennani # Update multiplexer process 866cf66801SMed Ismail Bennani log("Updating interactive scripted process threads") 876cf66801SMed Ismail Bennani dbg = self.driving_target.GetDebugger() 88*0e90ac9cSMed Ismail Bennani new_driving_thread_ids = [] 896cf66801SMed Ismail Bennani for driving_thread in self.driving_process: 90*0e90ac9cSMed Ismail Bennani new_driving_thread_ids.append(driving_thread.id) 916cf66801SMed Ismail Bennani log(f"{len(self.threads)} New thread {hex(driving_thread.id)}") 926cf66801SMed Ismail Bennani structured_data = lldb.SBStructuredData() 936cf66801SMed Ismail Bennani structured_data.SetFromJSON( 946cf66801SMed Ismail Bennani json.dumps( 956cf66801SMed Ismail Bennani { 966cf66801SMed Ismail Bennani "driving_target_idx": dbg.GetIndexOfTarget( 976cf66801SMed Ismail Bennani self.driving_target 986cf66801SMed Ismail Bennani ), 996cf66801SMed Ismail Bennani "thread_idx": driving_thread.GetIndexID(), 1006cf66801SMed Ismail Bennani } 1016cf66801SMed Ismail Bennani ) 1026cf66801SMed Ismail Bennani ) 1036cf66801SMed Ismail Bennani 104*0e90ac9cSMed Ismail Bennani self.threads[driving_thread.id] = PassthroughScriptedThread( 1056cf66801SMed Ismail Bennani self, structured_data 1066cf66801SMed Ismail Bennani ) 1076cf66801SMed Ismail Bennani 108*0e90ac9cSMed Ismail Bennani for thread_id in self.threads: 109*0e90ac9cSMed Ismail Bennani if thread_id not in new_driving_thread_ids: 110*0e90ac9cSMed Ismail Bennani log(f"Removing old thread {hex(thread_id)}") 111*0e90ac9cSMed Ismail Bennani del self.threads[thread_id] 112*0e90ac9cSMed Ismail Bennani 113*0e90ac9cSMed Ismail Bennani print(f"New thread count: {len(self.threads)}") 114*0e90ac9cSMed Ismail Bennani 1156cf66801SMed Ismail Bennani mux_process = self.target.GetProcess() 1166cf66801SMed Ismail Bennani mux_process.ForceScriptedState(lldb.eStateRunning) 1176cf66801SMed Ismail Bennani mux_process.ForceScriptedState(lldb.eStateStopped) 1186cf66801SMed Ismail Bennani 1196cf66801SMed Ismail Bennani for child_process in self.multiplexed_processes.values(): 1206cf66801SMed Ismail Bennani child_process.ForceScriptedState(lldb.eStateRunning) 1216cf66801SMed Ismail Bennani child_process.ForceScriptedState(lldb.eStateStopped) 1226cf66801SMed Ismail Bennani 1236cf66801SMed Ismail Bennani event = lldb.SBEvent() 1246cf66801SMed Ismail Bennani while True: 125*0e90ac9cSMed Ismail Bennani if not self.driving_process: 126*0e90ac9cSMed Ismail Bennani continue 1276cf66801SMed Ismail Bennani if self.listener.WaitForEvent(1, event): 1286cf66801SMed Ismail Bennani event_mask = event.GetType() 1296cf66801SMed Ismail Bennani if event_mask & lldb.SBProcess.eBroadcastBitStateChanged: 1306cf66801SMed Ismail Bennani state = lldb.SBProcess.GetStateFromEvent(event) 1316cf66801SMed Ismail Bennani log(f"Received public process state event: {state}") 1326cf66801SMed Ismail Bennani if state == lldb.eStateStopped: 1336cf66801SMed Ismail Bennani # If it's a stop event, iterate over the driving process 1346cf66801SMed Ismail Bennani # thread, looking for a breakpoint stop reason, if internal 1356cf66801SMed Ismail Bennani # continue. 1366cf66801SMed Ismail Bennani handle_process_state_event() 1376cf66801SMed Ismail Bennani else: 1386cf66801SMed Ismail Bennani continue 1396cf66801SMed Ismail Bennani 1406cf66801SMed Ismail Bennani def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData): 1416cf66801SMed Ismail Bennani super().__init__(exe_ctx, args, launched_driving_process=False) 1426cf66801SMed Ismail Bennani if isinstance(self.driving_target, lldb.SBTarget) and self.driving_target: 1436cf66801SMed Ismail Bennani self.listener = lldb.SBListener( 1446cf66801SMed Ismail Bennani "lldb.listener.multiplexer-scripted-process" 1456cf66801SMed Ismail Bennani ) 1466cf66801SMed Ismail Bennani self.multiplexed_processes = {} 1476cf66801SMed Ismail Bennani 148e31d0c20SMed Ismail Bennani # Copy breakpoints from real target to passthrough 149e31d0c20SMed Ismail Bennani with tempfile.NamedTemporaryFile() as tf: 150e31d0c20SMed Ismail Bennani bkpt_file = lldb.SBFileSpec(tf.name) 151e31d0c20SMed Ismail Bennani error = self.driving_target.BreakpointsWriteToFile(bkpt_file) 152e31d0c20SMed Ismail Bennani if error.Fail(): 153e31d0c20SMed Ismail Bennani log( 154e31d0c20SMed Ismail Bennani "Failed to save breakpoints from driving target (%s)" 155e31d0c20SMed Ismail Bennani % error.GetCString() 156e31d0c20SMed Ismail Bennani ) 157e31d0c20SMed Ismail Bennani bkpts_list = lldb.SBBreakpointList(self.target) 158e31d0c20SMed Ismail Bennani error = self.target.BreakpointsCreateFromFile(bkpt_file, bkpts_list) 159e31d0c20SMed Ismail Bennani if error.Fail(): 160e31d0c20SMed Ismail Bennani log( 161e31d0c20SMed Ismail Bennani "Failed create breakpoints from driving target \ 162e31d0c20SMed Ismail Bennani (bkpt file: %s)" 163e31d0c20SMed Ismail Bennani % tf.name 164e31d0c20SMed Ismail Bennani ) 165e31d0c20SMed Ismail Bennani 166e31d0c20SMed Ismail Bennani # Copy breakpoint from passthrough to real target 167e31d0c20SMed Ismail Bennani if error.Success(): 168e31d0c20SMed Ismail Bennani self.driving_target.DeleteAllBreakpoints() 169e31d0c20SMed Ismail Bennani for bkpt in self.target.breakpoints: 170e31d0c20SMed Ismail Bennani if bkpt.IsValid(): 171e31d0c20SMed Ismail Bennani for bl in bkpt: 172e31d0c20SMed Ismail Bennani real_bpkt = self.driving_target.BreakpointCreateBySBAddress( 173e31d0c20SMed Ismail Bennani bl.GetAddress() 174e31d0c20SMed Ismail Bennani ) 175e31d0c20SMed Ismail Bennani if not real_bpkt.IsValid(): 176e31d0c20SMed Ismail Bennani log( 177e31d0c20SMed Ismail Bennani "Failed to set breakpoint at address %s in \ 178e31d0c20SMed Ismail Bennani driving target" 179e31d0c20SMed Ismail Bennani % hex(bl.GetLoadAddress()) 180e31d0c20SMed Ismail Bennani ) 181e31d0c20SMed Ismail Bennani 1826cf66801SMed Ismail Bennani self.listener_thread = Thread( 1836cf66801SMed Ismail Bennani target=self.wait_for_driving_process_to_stop, daemon=True 1846cf66801SMed Ismail Bennani ) 1856cf66801SMed Ismail Bennani self.listener_thread.start() 1866cf66801SMed Ismail Bennani 1876cf66801SMed Ismail Bennani def launch(self, should_stop: bool = True) -> lldb.SBError: 1886cf66801SMed Ismail Bennani if not self.driving_target: 1896cf66801SMed Ismail Bennani return lldb.SBError( 1906cf66801SMed Ismail Bennani f"{self.__class__.__name__}.resume: Invalid driving target." 1916cf66801SMed Ismail Bennani ) 1926cf66801SMed Ismail Bennani 1936cf66801SMed Ismail Bennani if self.driving_process: 1946cf66801SMed Ismail Bennani return lldb.SBError( 1956cf66801SMed Ismail Bennani f"{self.__class__.__name__}.resume: Invalid driving process." 1966cf66801SMed Ismail Bennani ) 1976cf66801SMed Ismail Bennani 1986cf66801SMed Ismail Bennani error = lldb.SBError() 1996cf66801SMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 2006cf66801SMed Ismail Bennani launch_info.SetListener(self.listener) 2016cf66801SMed Ismail Bennani driving_process = self.driving_target.Launch(launch_info, error) 2026cf66801SMed Ismail Bennani 2036cf66801SMed Ismail Bennani if not driving_process or error.Fail(): 2046cf66801SMed Ismail Bennani return error 2056cf66801SMed Ismail Bennani 2066cf66801SMed Ismail Bennani self.driving_process = driving_process 2076cf66801SMed Ismail Bennani 2086cf66801SMed Ismail Bennani for module in self.driving_target.modules: 2096cf66801SMed Ismail Bennani path = module.file.fullpath 2106cf66801SMed Ismail Bennani load_addr = module.GetObjectFileHeaderAddress().GetLoadAddress( 2116cf66801SMed Ismail Bennani self.driving_target 2126cf66801SMed Ismail Bennani ) 2136cf66801SMed Ismail Bennani self.loaded_images.append({"path": path, "load_addr": load_addr}) 2146cf66801SMed Ismail Bennani 2156cf66801SMed Ismail Bennani self.first_resume = True 2166cf66801SMed Ismail Bennani return error 2176cf66801SMed Ismail Bennani 2186cf66801SMed Ismail Bennani def resume(self, should_stop: bool = True) -> lldb.SBError: 2196cf66801SMed Ismail Bennani if self.first_resume: 2206cf66801SMed Ismail Bennani # When we resume the multiplexer process for the first time, 2216cf66801SMed Ismail Bennani # we shouldn't do anything because lldb's execution machinery 2226cf66801SMed Ismail Bennani # will resume the driving process by itself. 2236cf66801SMed Ismail Bennani 2246cf66801SMed Ismail Bennani # Also, no need to update the multiplexer scripted process state 2256cf66801SMed Ismail Bennani # here because since it's listening for the real process stop events. 2266cf66801SMed Ismail Bennani # Once it receives the stop event from the driving process, 2276cf66801SMed Ismail Bennani # `wait_for_driving_process_to_stop` will update the multiplexer 2286cf66801SMed Ismail Bennani # state for us. 2296cf66801SMed Ismail Bennani 2306cf66801SMed Ismail Bennani self.first_resume = False 2316cf66801SMed Ismail Bennani return lldb.SBError() 2326cf66801SMed Ismail Bennani 2336cf66801SMed Ismail Bennani if not self.driving_process: 2346cf66801SMed Ismail Bennani return lldb.SBError( 2356cf66801SMed Ismail Bennani f"{self.__class__.__name__}.resume: Invalid driving process." 2366cf66801SMed Ismail Bennani ) 2376cf66801SMed Ismail Bennani 2386cf66801SMed Ismail Bennani return self.driving_process.Continue() 2396cf66801SMed Ismail Bennani 2406cf66801SMed Ismail Bennani def get_threads_info(self, pid: int = None) -> Dict[int, Any]: 2416cf66801SMed Ismail Bennani if not pid: 2426cf66801SMed Ismail Bennani return super().get_threads_info() 2436cf66801SMed Ismail Bennani parity = pid % 2 2446cf66801SMed Ismail Bennani return dict(filter(lambda pair: pair[0] % 2 == parity, self.threads.items())) 2456cf66801SMed Ismail Bennani 246e31d0c20SMed Ismail Bennani def create_breakpoint(self, addr, error, pid=None): 247e31d0c20SMed Ismail Bennani if not self.driving_target: 248e31d0c20SMed Ismail Bennani error.SetErrorString("%s has no driving target." % self.__class__.__name__) 249e31d0c20SMed Ismail Bennani return False 250e31d0c20SMed Ismail Bennani 251e31d0c20SMed Ismail Bennani def create_breakpoint_with_name(target, load_addr, name, error): 252e31d0c20SMed Ismail Bennani addr = lldb.SBAddress(load_addr, target) 253e31d0c20SMed Ismail Bennani if not addr.IsValid(): 254e31d0c20SMed Ismail Bennani error.SetErrorString("Invalid breakpoint address %s" % hex(load_addr)) 255e31d0c20SMed Ismail Bennani return False 256e31d0c20SMed Ismail Bennani bkpt = target.BreakpointCreateBySBAddress(addr) 257e31d0c20SMed Ismail Bennani if not bkpt.IsValid(): 258e31d0c20SMed Ismail Bennani error.SetErrorString( 259e31d0c20SMed Ismail Bennani "Failed to create breakpoint at address %s" 260e31d0c20SMed Ismail Bennani % hex(addr.GetLoadAddress()) 261e31d0c20SMed Ismail Bennani ) 262e31d0c20SMed Ismail Bennani return False 263e31d0c20SMed Ismail Bennani error = bkpt.AddNameWithErrorHandling(name) 264e31d0c20SMed Ismail Bennani return error.Success() 265e31d0c20SMed Ismail Bennani 266e31d0c20SMed Ismail Bennani name = ( 267e31d0c20SMed Ismail Bennani "multiplexer_scripted_process" 268e31d0c20SMed Ismail Bennani if not pid 269e31d0c20SMed Ismail Bennani else f"multiplexed_scripted_process_{pid}" 270e31d0c20SMed Ismail Bennani ) 271e31d0c20SMed Ismail Bennani 272e31d0c20SMed Ismail Bennani if pid is not None: 273e31d0c20SMed Ismail Bennani # This means that this method has been called from one of the 274e31d0c20SMed Ismail Bennani # multiplexed scripted process. That also means that the multiplexer 275e31d0c20SMed Ismail Bennani # target doesn't have this breakpoint created. 276e31d0c20SMed Ismail Bennani mux_error = lldb.SBError() 277e31d0c20SMed Ismail Bennani bkpt = create_breakpoint_with_name(self.target, addr, name, mux_error) 278e31d0c20SMed Ismail Bennani if mux_error.Fail(): 279e31d0c20SMed Ismail Bennani error.SetError( 280e31d0c20SMed Ismail Bennani "Failed to create breakpoint in multiplexer \ 281e31d0c20SMed Ismail Bennani target: %s" 282e31d0c20SMed Ismail Bennani % mux_error.GetCString() 283e31d0c20SMed Ismail Bennani ) 284e31d0c20SMed Ismail Bennani return False 285e31d0c20SMed Ismail Bennani return create_breakpoint_with_name(self.driving_target, addr, name, error) 286e31d0c20SMed Ismail Bennani 2876cf66801SMed Ismail Bennani 2886cf66801SMed Ismail Bennanidef multiplex(mux_process, muxed_process): 2896cf66801SMed Ismail Bennani muxed_process.GetScriptedImplementation().multiplexer = ( 2906cf66801SMed Ismail Bennani mux_process.GetScriptedImplementation() 2916cf66801SMed Ismail Bennani ) 2926cf66801SMed Ismail Bennani mux_process.GetScriptedImplementation().multiplexed_processes[ 2936cf66801SMed Ismail Bennani muxed_process.GetProcessID() 2946cf66801SMed Ismail Bennani ] = muxed_process 2956cf66801SMed Ismail Bennani 2966cf66801SMed Ismail Bennani 2976cf66801SMed Ismail Bennanidef launch_scripted_process(target, class_name, dictionary): 2986cf66801SMed Ismail Bennani structured_data = lldb.SBStructuredData() 2996cf66801SMed Ismail Bennani structured_data.SetFromJSON(json.dumps(dictionary)) 3006cf66801SMed Ismail Bennani 3016cf66801SMed Ismail Bennani launch_info = lldb.SBLaunchInfo(None) 3026cf66801SMed Ismail Bennani launch_info.SetProcessPluginName("ScriptedProcess") 3036cf66801SMed Ismail Bennani launch_info.SetScriptedProcessClassName(class_name) 3046cf66801SMed Ismail Bennani launch_info.SetScriptedProcessDictionary(structured_data) 3056cf66801SMed Ismail Bennani 3066cf66801SMed Ismail Bennani error = lldb.SBError() 3076cf66801SMed Ismail Bennani return target.Launch(launch_info, error) 3086cf66801SMed Ismail Bennani 3096cf66801SMed Ismail Bennani 3106cf66801SMed Ismail Bennanidef duplicate_target(driving_target): 3116cf66801SMed Ismail Bennani error = lldb.SBError() 3126cf66801SMed Ismail Bennani exe = driving_target.executable.fullpath 3136cf66801SMed Ismail Bennani triple = driving_target.triple 3146cf66801SMed Ismail Bennani debugger = driving_target.GetDebugger() 3156cf66801SMed Ismail Bennani return debugger.CreateTargetWithFileAndTargetTriple(exe, triple) 3166cf66801SMed Ismail Bennani 317429e7483SMed Ismail Bennani 3186cf66801SMed Ismail Bennanidef create_mux_process(debugger, command, exe_ctx, result, dict): 3196cf66801SMed Ismail Bennani if not debugger.GetNumTargets() > 0: 3206cf66801SMed Ismail Bennani return result.SetError( 3216cf66801SMed Ismail Bennani "Interactive scripted processes requires one non scripted process." 3226cf66801SMed Ismail Bennani ) 3236cf66801SMed Ismail Bennani 3246cf66801SMed Ismail Bennani debugger.SetAsync(True) 3256cf66801SMed Ismail Bennani 3266cf66801SMed Ismail Bennani driving_target = debugger.GetSelectedTarget() 3276cf66801SMed Ismail Bennani if not driving_target: 3286cf66801SMed Ismail Bennani return result.SetError("Driving target is invalid") 3296cf66801SMed Ismail Bennani 3306cf66801SMed Ismail Bennani # Create a seconde target for the multiplexer scripted process 3316cf66801SMed Ismail Bennani mux_target = duplicate_target(driving_target) 3326cf66801SMed Ismail Bennani if not mux_target: 3336cf66801SMed Ismail Bennani return result.SetError( 3346cf66801SMed Ismail Bennani "Couldn't duplicate driving target to launch multiplexer scripted process" 3356cf66801SMed Ismail Bennani ) 3366cf66801SMed Ismail Bennani 3376cf66801SMed Ismail Bennani class_name = f"{__name__}.{MultiplexerScriptedProcess.__name__}" 3386cf66801SMed Ismail Bennani dictionary = {"driving_target_idx": debugger.GetIndexOfTarget(driving_target)} 3396cf66801SMed Ismail Bennani mux_process = launch_scripted_process(mux_target, class_name, dictionary) 3406cf66801SMed Ismail Bennani if not mux_process: 3416cf66801SMed Ismail Bennani return result.SetError("Couldn't launch multiplexer scripted process") 3426cf66801SMed Ismail Bennani 3436cf66801SMed Ismail Bennani 3446cf66801SMed Ismail Bennanidef create_child_processes(debugger, command, exe_ctx, result, dict): 3456cf66801SMed Ismail Bennani if not debugger.GetNumTargets() >= 2: 3466cf66801SMed Ismail Bennani return result.SetError("Scripted Multiplexer process not setup") 3476cf66801SMed Ismail Bennani 3486cf66801SMed Ismail Bennani debugger.SetAsync(True) 3496cf66801SMed Ismail Bennani 3506cf66801SMed Ismail Bennani # Create a seconde target for the multiplexer scripted process 3516cf66801SMed Ismail Bennani mux_target = debugger.GetSelectedTarget() 3526cf66801SMed Ismail Bennani if not mux_target: 3536cf66801SMed Ismail Bennani return result.SetError("Couldn't get multiplexer scripted process target") 3546cf66801SMed Ismail Bennani mux_process = mux_target.GetProcess() 3556cf66801SMed Ismail Bennani if not mux_process: 3566cf66801SMed Ismail Bennani return result.SetError("Couldn't get multiplexer scripted process") 3576cf66801SMed Ismail Bennani 3586cf66801SMed Ismail Bennani driving_target = mux_process.GetScriptedImplementation().driving_target 3596cf66801SMed Ismail Bennani if not driving_target: 3606cf66801SMed Ismail Bennani return result.SetError("Driving target is invalid") 3616cf66801SMed Ismail Bennani 3626cf66801SMed Ismail Bennani # Create a target for the multiplexed even scripted process 3636cf66801SMed Ismail Bennani even_target = duplicate_target(driving_target) 3646cf66801SMed Ismail Bennani if not even_target: 3656cf66801SMed Ismail Bennani return result.SetError( 3666cf66801SMed Ismail Bennani "Couldn't duplicate driving target to launch multiplexed even scripted process" 3676cf66801SMed Ismail Bennani ) 3686cf66801SMed Ismail Bennani 3696cf66801SMed Ismail Bennani class_name = f"{__name__}.{MultiplexedScriptedProcess.__name__}" 3706cf66801SMed Ismail Bennani dictionary = {"driving_target_idx": debugger.GetIndexOfTarget(mux_target)} 3716cf66801SMed Ismail Bennani dictionary["parity"] = 0 3726cf66801SMed Ismail Bennani even_process = launch_scripted_process(even_target, class_name, dictionary) 3736cf66801SMed Ismail Bennani if not even_process: 3746cf66801SMed Ismail Bennani return result.SetError("Couldn't launch multiplexed even scripted process") 3756cf66801SMed Ismail Bennani multiplex(mux_process, even_process) 3766cf66801SMed Ismail Bennani 3776cf66801SMed Ismail Bennani # Create a target for the multiplexed odd scripted process 3786cf66801SMed Ismail Bennani odd_target = duplicate_target(driving_target) 3796cf66801SMed Ismail Bennani if not odd_target: 3806cf66801SMed Ismail Bennani return result.SetError( 3816cf66801SMed Ismail Bennani "Couldn't duplicate driving target to launch multiplexed odd scripted process" 3826cf66801SMed Ismail Bennani ) 3836cf66801SMed Ismail Bennani 3846cf66801SMed Ismail Bennani dictionary["parity"] = 1 3856cf66801SMed Ismail Bennani odd_process = launch_scripted_process(odd_target, class_name, dictionary) 3866cf66801SMed Ismail Bennani if not odd_process: 3876cf66801SMed Ismail Bennani return result.SetError("Couldn't launch multiplexed odd scripted process") 3886cf66801SMed Ismail Bennani multiplex(mux_process, odd_process) 3896cf66801SMed Ismail Bennani 3906cf66801SMed Ismail Bennani 3916cf66801SMed Ismail Bennanidef log(message): 3926cf66801SMed Ismail Bennani # FIXME: For now, we discard the log message until we can pass it to an lldb 3936cf66801SMed Ismail Bennani # logging channel. 3946cf66801SMed Ismail Bennani should_log = False 3956cf66801SMed Ismail Bennani if should_log: 3966cf66801SMed Ismail Bennani print(message) 3976cf66801SMed Ismail Bennani 3986cf66801SMed Ismail Bennani 3996cf66801SMed Ismail Bennanidef __lldb_init_module(dbg, dict): 4006cf66801SMed Ismail Bennani dbg.HandleCommand( 4016cf66801SMed Ismail Bennani "command script add -o -f interactive_scripted_process.create_mux_process create_mux" 4026cf66801SMed Ismail Bennani ) 4036cf66801SMed Ismail Bennani dbg.HandleCommand( 4046cf66801SMed Ismail Bennani "command script add -o -f interactive_scripted_process.create_child_processes create_sub" 4056cf66801SMed Ismail Bennani ) 406