def test_io(self): """Test that process launch I/O redirection flags work properly.""" self.build() exe = self.getBuildArtifact("a.out") self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) in_file = os.path.join(self.getSourceDir(), "input-file.txt") out_file = lldbutil.append_to_process_working_directory(self, "output-test.out") err_file = lldbutil.append_to_process_working_directory(self, "output-test.err") # Make sure the output files do not exist before launching the process try: os.remove(out_file) except OSError: pass try: os.remove(err_file) except OSError: pass launch_command = "process launch -i '{0}' -o '{1}' -e '{2}' -w '{3}'".format( in_file, out_file, err_file, self.get_process_working_directory()) if lldb.remote_platform: self.runCmd('platform put-file "{local}" "{remote}"'.format( local=in_file, remote=in_file)) self.expect(launch_command, patterns=["Process .* launched: .*a.out"]) success = True err_msg = "" out = lldbutil.read_file_on_target(self, out_file) if out != "This should go to stdout.\n": success = False err_msg = err_msg + " ERROR: stdout file does not contain correct output.\n" err = lldbutil.read_file_on_target(self, err_file) if err != "This should go to stderr.\n": success = False err_msg = err_msg + " ERROR: stderr file does not contain correct output.\n" if not success: self.fail(err_msg)
def test_io(self): """Test that process launch I/O redirection flags work properly.""" self.build() exe = self.getBuildArtifact("a.out") self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) in_file = os.path.join(self.getSourceDir(), "input-file.txt") out_file = lldbutil.append_to_process_working_directory( self, "output-test.out") err_file = lldbutil.append_to_process_working_directory( self, "output-test.err") # Make sure the output files do not exist before launching the process try: os.remove(out_file) except OSError: pass try: os.remove(err_file) except OSError: pass launch_command = "process launch -i '{0}' -o '{1}' -e '{2}' -w '{3}'".format( in_file, out_file, err_file, self.get_process_working_directory()) if lldb.remote_platform: self.runCmd('platform put-file "{local}" "{remote}"'.format( local=in_file, remote=in_file)) self.expect(launch_command, patterns=["Process .* launched: .*a.out"]) success = True err_msg = "" out = lldbutil.read_file_on_target(self, out_file) if out != "This should go to stdout.\n": success = False err_msg = err_msg + " ERROR: stdout file does not contain correct output.\n" err = lldbutil.read_file_on_target(self, err_file) if err != "This should go to stderr.\n": success = False err_msg = err_msg + " ERROR: stderr file does not contain correct output.\n" if not success: self.fail(err_msg)
def test_attach_to_process_by_id_denied(self): """Test attach by process id denied""" self.build() exe = os.path.join(os.getcwd(), exe_name) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_%d" % (int(time.time()))) self.addTearDownHook(lambda: self.run_platform_command("rm %s" % (pid_file_path))) # Spawn a new process popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) max_attempts = 5 for i in range(max_attempts): err, retcode, msg = self.run_platform_command("ls %s" % pid_file_path) if err.Success() and retcode == 0: break else: print(msg) if i < max_attempts: # Exponential backoff! time.sleep(pow(2, i) * 0.25) else: self.fail("Child PID file %s not found even after %d attempts." % (pid_file_path, max_attempts)) err, retcode, pid = self.run_platform_command("cat %s" % (pid_file_path)) self.assertTrue(err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" % (pid_file_path, err.GetCString(), retcode)) self.expect('process attach -p ' + pid, startstr = 'error: attach failed:', error = True)
def test_setpgid(self): self.build() exe = os.path.join(os.getcwd(), 'a.out') # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_%d" % (int(time.time()))) self.addTearDownHook(lambda: self.run_platform_command("rm %s" % (pid_file_path))) popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) pid = lldbutil.wait_for_file_on_target(self, pid_file_path) # make sure we cleanup the forked child also def cleanupChild(): if lldb.remote_platform: lldb.remote_platform.Kill(int(pid)) else: if os.path.exists("/proc/" + pid): os.kill(int(pid), signal.SIGKILL) self.addTearDownHook(cleanupChild) # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() process = target.AttachToProcessWithID(listener, int(pid), error) self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # set a breakpoint just before the setpgid() call lldbutil.run_break_set_by_file_and_line(self, 'main.c', self.line, num_expected_locations=-1) thread = process.GetSelectedThread() # release the child from its loop value = thread.GetSelectedFrame().EvaluateExpression("release_child_flag = 1") self.assertTrue(value.IsValid() and value.GetValueAsUnsigned(0) == 1); process.Continue() # make sure the child's process group id is different from its pid value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid)); # step over the setpgid() call thread.StepOver() self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) # verify that the process group has been set correctly # this also checks that we are still in full control of the child value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertEqual(value.GetValueAsUnsigned(0), int(pid)); # run to completion process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited)
def test_attach(self): """ This test attaches to a process that creates a file. We attach and disconnect before the file is created, and as the process is not terminated upon disconnection, the file is created anyway. """ self.build_and_create_debug_adaptor() program = self.getBuildArtifact("a.out") # Use a file as a synchronization point between test and inferior. sync_file_path = lldbutil.append_to_process_working_directory( self, "sync_file_%d" % (int(time.time()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (sync_file_path))) self.process = subprocess.Popen([program, sync_file_path]) lldbutil.wait_for_file_on_target(self, sync_file_path) self.attach(pid=self.process.pid, disconnectAutomatically=False) response = self.vscode.request_evaluate("wait_for_attach = false;") self.assertTrue(response['success']) # verify we haven't produced the side effect file yet self.assertFalse(os.path.exists(program + ".side_effect")) self.vscode.request_disconnect() time.sleep(2) # verify we produced the side effect file, as the program continued after disconnecting self.assertTrue(os.path.exists(program + ".side_effect"))
def module_info(self): procs = self.prep_debug_monitor_and_inferior() self.add_process_info_collection_packets() context = self.expect_gdbremote_sequence() info = self.parse_process_info_response(context) self.test_sequence.add_log_lines([ 'read packet: $jModulesInfo:%s]#00' % json.dumps([{ "file": lldbutil.append_to_process_working_directory(self, "a.out"), "triple": seven.unhexlify(info["triple"]) }]), { "direction": "send", "regex": r'^\$\[{(.*)}\]\]#[0-9A-Fa-f]{2}', "capture": { 1: "spec" } }, ], True) context = self.expect_gdbremote_sequence() spec = context.get("spec") self.assertRegexpMatches(spec, '"file_path":".*"') self.assertRegexpMatches(spec, '"file_offset":\d+') self.assertRegexpMatches(spec, '"file_size":\d+') self.assertRegexpMatches(spec, '"triple":"\w*-\w*-.*"') self.assertRegexpMatches(spec, '"uuid":"[A-Fa-f0-9]+"')
def test_by_name(self): ''' Tests attaching to a process by process name. ''' self.build_and_create_debug_adaptor() orig_program = self.getBuildArtifact("a.out") # Since we are going to attach by process name, we need a unique # process name that has minimal chance to match a process that is # already running. To do this we use tempfile.mktemp() to give us a # full path to a location where we can copy our executable. We then # run this copy to ensure we don't get the error "more that one # process matches 'a.out'". program = tempfile.mktemp() shutil.copyfile(orig_program, program) shutil.copymode(orig_program, program) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( self, "pid_file_%d" % (int(time.time()))) def cleanup(): if os.path.exists(program): os.unlink(program) self.run_platform_command("rm %s" % (pid_file_path)) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) popen = self.spawnSubprocess(program, [pid_file_path]) pid = lldbutil.wait_for_file_on_target(self, pid_file_path) self.attach(program=program) self.set_and_hit_breakpoint(continueToExit=True)
def test_launch_new_process_and_redirect_stdout(self): """Exercise SBTaget.Launch() API with redirected stdout.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done. # We should still see the entire stdout redirected once the process is # finished. line = line_number('main.c', '// a(3) -> c(3)') breakpoint = target.BreakpointCreateByLocation('main.c', line) # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file. # The inferior should run to completion after "process.Continue()" # call. local_path = self.getBuildArtifact("stdout.txt") if os.path.exists(local_path): os.remove(local_path) if lldb.remote_platform: stdout_path = lldbutil.append_to_process_working_directory(self, "lldb-stdout-redirect.txt") else: stdout_path = local_path error = lldb.SBError() process = target.Launch( self.dbg.GetListener(), None, None, None, stdout_path, None, None, 0, False, error) process.Continue() #self.runCmd("process status") if lldb.remote_platform: # copy output file to host lldb.remote_platform.Get( lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path)) # The 'stdout.txt' file should now exist. self.assertTrue( os.path.isfile(local_path), "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.") # Read the output file produced by running the program. with open(local_path, 'r') as f: output = f.read() self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"])
def test_launch_new_process_and_redirect_stdout(self): """Exercise SBTaget.Launch() API with redirected stdout.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done. # We should still see the entire stdout redirected once the process is # finished. line = line_number('main.c', '// a(3) -> c(3)') breakpoint = target.BreakpointCreateByLocation('main.c', line) # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file. # The inferior should run to completion after "process.Continue()" # call. local_path = self.getBuildArtifact("stdout.txt") if os.path.exists(local_path): os.remove(local_path) if lldb.remote_platform: stdout_path = lldbutil.append_to_process_working_directory(self, "lldb-stdout-redirect.txt") else: stdout_path = local_path error = lldb.SBError() process = target.Launch( self.dbg.GetListener(), None, None, None, stdout_path, None, None, 0, False, error) process.Continue() #self.runCmd("process status") if lldb.remote_platform: # copy output file to host lldb.remote_platform.Get( lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path)) # The 'stdout.txt' file should now exist. self.assertTrue( os.path.isfile(local_path), "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.") # Read the output file produced by running the program. with open(local_path, 'r') as f: output = f.read() self.expect(output, exe=False, substrs=["a(1)", "b(2)", "a(3)"])
def test_set_error_output_path(self): """Test that setting target.error/output-path for the launched process works.""" self.build() exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # Set the error-path and output-path and verify both are set. self.runCmd("settings set target.error-path '{0}'".format( lldbutil.append_to_process_working_directory(self, "stderr.txt"))) self.runCmd("settings set target.output-path '{0}".format( lldbutil.append_to_process_working_directory(self, "stdout.txt"))) # And add hooks to restore the original settings during tearDown(). self.addTearDownHook( lambda: self.runCmd("settings clear target.output-path")) self.addTearDownHook( lambda: self.runCmd("settings clear target.error-path")) self.expect("settings show target.error-path", SETTING_MSG("target.error-path"), substrs=['target.error-path (file)', 'stderr.txt"']) self.expect("settings show target.output-path", SETTING_MSG("target.output-path"), substrs=['target.output-path (file)', 'stdout.txt"']) self.runCmd( "process launch --working-dir '{0}'".format( self.get_process_working_directory()), RUN_SUCCEEDED) output = lldbutil.read_file_from_process_wd(self, "stderr.txt") message = "This message should go to standard error." if lldbplatformutil.hasChattyStderr(self): self.expect(output, exe=False, substrs=[message]) else: self.expect(output, exe=False, startstr=message) output = lldbutil.read_file_from_process_wd(self, "stdout.txt") self.expect(output, exe=False, startstr="This message should go to standard out.")
def process_launch_o(self, localPath): # process launch command output redirect always goes to host the process is running on if lldb.remote_platform: # process launch -o requires a path that is valid on the target self.assertIsNotNone(lldb.remote_platform.GetWorkingDirectory()) remote_path = lldbutil.append_to_process_working_directory("lldb-stdout-redirect.txt") self.runCmd('process launch -o {remote}'.format(remote=remote_path)) # copy remote_path to local host self.runCmd('platform get-file {remote} "{local}"'.format( remote=remote_path, local=self.golden_filename)) else: self.runCmd('process launch -o "{local}"'.format(local=self.golden_filename))
def test_load_after_attach(self): self.build() sync_file_path = lldbutil.append_to_process_working_directory( self, "process_ready") ctx = self.platformContext lib_name = ctx.shlib_prefix + 'lib_b.' + ctx.shlib_extension exe = self.getBuildArtifact("a.out") lib = self.getBuildArtifact(lib_name) target = self.dbg.CreateTarget(exe) environment = self.registerSharedLibrariesWithTarget(target, ["lib_b"]) # Spawn a new process. # use realpath to workaround llvm.org/pr48376 # Pass path to solib for dlopen to properly locate the library. popen = self.spawnSubprocess(os.path.realpath(exe), [sync_file_path], extra_env=environment) lldbutil.wait_for_file_on_target(self, sync_file_path) # Attach to the spawned process. error = lldb.SBError() process = target.AttachToProcessWithID(self.dbg.GetListener(), popen.pid, error) self.assertSuccess(error) # Continue until first breakpoint. breakpoint1 = self.target().BreakpointCreateBySourceRegex( "// break here", lldb.SBFileSpec("main.cpp")) self.assertEqual(breakpoint1.GetNumResolvedLocations(), 1) stopped_threads = lldbutil.continue_to_breakpoint( self.process(), breakpoint1) self.assertEqual(len(stopped_threads), 1) # Change a variable to escape the loop self.runCmd("expression main_thread_continue = 1") # Continue so that dlopen is called. breakpoint2 = self.target().BreakpointCreateBySourceRegex( "// break after dlopen", lldb.SBFileSpec("main.cpp")) self.assertEqual(breakpoint2.GetNumResolvedLocations(), 1) stopped_threads = lldbutil.continue_to_breakpoint( self.process(), breakpoint2) self.assertEqual(len(stopped_threads), 1) # Check that image list contains liblib_b after dlopen. self.match("image list", patterns=[lib_name], matching=True, msg=lib_name + " missing in image list")
def test_set_error_output_path(self): """Test that setting target.error/output-path for the launched process works.""" self.build() exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # Set the error-path and output-path and verify both are set. self.runCmd("settings set target.error-path '{0}'".format( lldbutil.append_to_process_working_directory(self, "stderr.txt"))) self.runCmd("settings set target.output-path '{0}".format( lldbutil.append_to_process_working_directory(self, "stdout.txt"))) # And add hooks to restore the original settings during tearDown(). self.addTearDownHook( lambda: self.runCmd("settings clear target.output-path")) self.addTearDownHook( lambda: self.runCmd("settings clear target.error-path")) self.expect("settings show target.error-path", SETTING_MSG("target.error-path"), substrs=['target.error-path (file)', 'stderr.txt"']) self.expect("settings show target.output-path", SETTING_MSG("target.output-path"), substrs=['target.output-path (file)', 'stdout.txt"']) self.runCmd("process launch --working-dir '{0}'".format(self.get_process_working_directory()), RUN_SUCCEEDED) output = lldbutil.read_file_from_process_wd(self, "stderr.txt") message = "This message should go to standard error." if lldbplatformutil.hasChattyStderr(self): self.expect(output, exe=False, substrs=[message]) else: self.expect(output, exe=False, startstr=message) output = lldbutil.read_file_from_process_wd(self, "stdout.txt") self.expect(output, exe=False, startstr="This message should go to standard out.")
def test_process_list_with_args(self): """Test process list show process args""" self.build() exe = self.getBuildArtifact("TestProcess") # Spawn a new process sync_file = lldbutil.append_to_process_working_directory(self, "ready.txt") popen = self.spawnSubprocess(exe, args=[sync_file, "arg1", "--arg2", "arg3"]) lldbutil.wait_for_file_on_target(self, sync_file) substrs = [str(popen.pid), "TestProcess", "arg1 --arg2 arg3"] self.expect("platform process list -v", substrs=substrs)
def do_function_starts(self, in_memory): """Run the binary, stop at our unstripped function, make sure the caller has synthetic symbols""" exe = self.getBuildArtifact(exe_name) # Now strip the binary, but leave externals so we can break on dont_strip_me. try: fail_str = system([["strip", "-u", "-x", "-S", exe]]) except CalledProcessError as cmd_error: self.fail("Strip failed: %d" % (cmd_error.returncode)) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( self, "token_pid_%d" % (int(os.getpid()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) # Wait until process has fully started up. pid = lldbutil.wait_for_file_on_target(self, pid_file_path) if in_memory: remove_file(exe) target = self.dbg.CreateTarget(None) self.assertTrue(target.IsValid(), "Got a vaid empty target.") error = lldb.SBError() attach_info = lldb.SBAttachInfo() attach_info.SetProcessID(popen.pid) attach_info.SetIgnoreExisting(False) process = target.Attach(attach_info, error) self.assertTrue( error.Success(), "Didn't attach successfully to %d: %s" % (popen.pid, error.GetCString())) bkpt = target.BreakpointCreateByName("dont_strip_me", exe) self.assertTrue(bkpt.GetNumLocations() > 0, "Didn't set the dont_strip_me bkpt.") threads = lldbutil.continue_to_breakpoint(process, bkpt) self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.") # Our caller frame should have been stripped. Make sure we made a synthetic symbol # for it: thread = threads[0] self.assertTrue(thread.num_frames > 1, "Couldn't backtrace.") name = thread.frame[1].GetFunctionName() self.assertTrue(name.startswith("___lldb_unnamed_symbol")) self.assertTrue(name.endswith("$$StripMe"))
def test_attach_and_check_dsyms(self): """Test attach to binary, see if the framework dSYM is found""" exe = self.getBuildArtifact(exe_name) self.build() # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( self, "token_pid_%d" % (int(os.getpid()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) popen = self.spawnSubprocess(exe, [self.getBuildDir(), pid_file_path]) # Wait for the inferior to start up, dlopen a bundle, remove the bundle it linked in pid = lldbutil.wait_for_file_on_target(self, pid_file_path) # Since the library that was dlopen()'ed is now removed, lldb will need to find the # binary & dSYM via target.exec-search-paths settings_str = "settings set target.exec-search-paths " + self.get_process_working_directory( ) + "/hide.app" self.runCmd(settings_str) self.runCmd("process attach -p " + str(popen.pid)) target = self.dbg.GetSelectedTarget() self.assertTrue( target.IsValid(), 'Should have a valid Target after attaching to process') setup_complete = target.FindFirstGlobalVariable("setup_is_complete") self.assertEquals(setup_complete.GetValueAsUnsigned(), 1, 'Check that inferior process has completed setup') # Find the bundle module, see if we found the dSYM too (they're both in "hide.app") i = 0 found_module = False while i < target.GetNumModules(): mod = target.GetModuleAtIndex(i) if mod.GetFileSpec().GetFilename() == 'MyFramework': found_module = True dsym_name = mod.GetSymbolFileSpec().GetFilename() self.assertTrue( dsym_name == 'MyFramework', "Check that we found the dSYM for the bundle that was loaded" ) i = i + 1 self.assertTrue( found_module, "Check that we found the framework loaded in lldb's image list")
def process_launch_o(self, localPath): # process launch command output redirect always goes to host the process is running on if lldb.remote_platform: # process launch -o requires a path that is valid on the target self.assertIsNotNone(lldb.remote_platform.GetWorkingDirectory()) remote_path = lldbutil.append_to_process_working_directory( "lldb-stdout-redirect.txt") self.runCmd( 'process launch -o {remote}'.format(remote=remote_path)) # copy remote_path to local host self.runCmd('platform get-file {remote} "{local}"'.format( remote=remote_path, local=self.golden_filename)) else: self.runCmd('process launch -o "{local}"'.format( local=self.golden_filename))
def test_attach_to_process_by_id_denied(self): """Test attach by process id denied""" self.build() exe = os.path.join(os.getcwd(), exe_name) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_%d" % (int(time.time()))) self.addTearDownHook(lambda: self.run_platform_command("rm %s" % (pid_file_path))) # Spawn a new process popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) pid = lldbutil.wait_for_file_on_target(self, pid_file_path) self.expect('process attach -p ' + pid, startstr = 'error: attach failed:', error = True)
def test_attach_to_process_by_id_denied(self): """Test attach by process id denied""" self.build() exe = self.getBuildArtifact(exe_name) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( self, "pid_file_%d" % (int(time.time()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) # Spawn a new process popen = self.spawnSubprocess(exe, [pid_file_path]) pid = lldbutil.wait_for_file_on_target(self, pid_file_path) self.expect('process attach -p ' + pid, startstr='error: attach failed:', error=True)
def process_launch_o(self): # process launch command output redirect always goes to host the # process is running on if lldb.remote_platform: # process launch -o requires a path that is valid on the target self.assertIsNotNone(lldb.remote_platform.GetWorkingDirectory()) remote_path = lldbutil.append_to_process_working_directory( self, "lldb-stdout-redirect.txt") self.runCmd( 'process launch -- {remote}'.format(remote=remote_path)) # copy remote_path to local host self.runCmd('platform get-file {remote} "{local}"'.format( remote=remote_path, local=self.golden_filename)) elif configuration.is_reproducer_replay(): # Don't overwrite the golden file generated at capture time. self.runCmd('process launch') else: self.runCmd('process launch -o "{local}"'.format( local=self.golden_filename))
def test(self): self.build() exe = self.getBuildArtifact("a.out") # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( self, "token_pid_%d" % (int(os.getpid()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) # Spawn a new process popen = self.spawnSubprocess(exe, [pid_file_path]) # Wait until process has fully started up. pid = lldbutil.wait_for_file_on_target(self, pid_file_path) # Now we can safely remove the executable and test if we can attach. os.remove(exe) self.runCmd("process attach -p " + str(popen.pid)) self.runCmd("kill")
def module_info(self): procs = self.prep_debug_monitor_and_inferior() self.add_process_info_collection_packets() context = self.expect_gdbremote_sequence() info = self.parse_process_info_response(context) self.test_sequence.add_log_lines([ 'read packet: $jModulesInfo:[{"file":"%s","triple":"%s"}]]#00' % ( lldbutil.append_to_process_working_directory("a.out"), info["triple"].decode('hex')), {"direction": "send", "regex": r'^\$\[{(.*)}\]\]#[0-9A-Fa-f]{2}', "capture": {1: "spec"}}, ], True) context = self.expect_gdbremote_sequence() spec = context.get("spec") self.assertRegexpMatches(spec, '"file_path":".*"') self.assertRegexpMatches(spec, '"file_offset":\d+') self.assertRegexpMatches(spec, '"file_size":\d+') self.assertRegexpMatches(spec, '"triple":"\w*-\w*-.*"') self.assertRegexpMatches(spec, '"uuid":"[A-Fa-f0-9]+"')
def test_attach_to_process_by_id_denied(self): """Test attach by process id denied""" self.build() exe = os.path.join(os.getcwd(), exe_name) # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_%d" % (int(time.time()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) # Spawn a new process popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) max_attempts = 5 for i in range(max_attempts): err, retcode, msg = self.run_platform_command("ls %s" % pid_file_path) if err.Success() and retcode == 0: break else: print(msg) if i < max_attempts: # Exponential backoff! time.sleep(pow(2, i) * 0.25) else: self.fail("Child PID file %s not found even after %d attempts." % (pid_file_path, max_attempts)) err, retcode, pid = self.run_platform_command("cat %s" % (pid_file_path)) self.assertTrue( err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" % (pid_file_path, err.GetCString(), retcode)) self.expect('process attach -p ' + pid, startstr='error: attach failed:', error=True)
def test_setpgid(self): self.build() exe = os.path.join(os.getcwd(), 'a.out') # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_{0:d}".format((int(time.time())))) self.addTearDownHook(lambda: self.run_platform_command( "rm {0!s}".format((pid_file_path)))) popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) max_attempts = 5 for i in range(max_attempts): err, retcode, msg = self.run_platform_command( "ls {0!s}".format(pid_file_path)) if err.Success() and retcode == 0: break else: print(msg) if i < max_attempts: # Exponential backoff! time.sleep(pow(2, i) * 0.25) else: self.fail( "Child PID file {0!s} not found even after {1:d} attempts.". format(pid_file_path, max_attempts)) err, retcode, pid = self.run_platform_command("cat {0!s}".format( (pid_file_path))) self.assertTrue( err.Success() and retcode == 0, "Failed to read file {0!s}: {1!s}, retcode: {2:d}".format( pid_file_path, err.GetCString(), retcode)) # make sure we cleanup the forked child also def cleanupChild(): if lldb.remote_platform: lldb.remote_platform.Kill(int(pid)) else: if os.path.exists("/proc/" + pid): os.kill(int(pid), signal.SIGKILL) self.addTearDownHook(cleanupChild) # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() process = target.AttachToProcessWithID(listener, int(pid), error) self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # set a breakpoint just before the setpgid() call lldbutil.run_break_set_by_file_and_line(self, 'main.c', self.line, num_expected_locations=-1) thread = process.GetSelectedThread() # release the child from its loop value = thread.GetSelectedFrame().EvaluateExpression( "release_child_flag = 1") self.assertTrue(value.IsValid() and value.GetValueAsUnsigned(0) == 1) process.Continue() # make sure the child's process group id is different from its pid value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid)) # step over the setpgid() call thread.StepOver() self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) # verify that the process group has been set correctly # this also checks that we are still in full control of the child value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertEqual(value.GetValueAsUnsigned(0), int(pid)) # run to completion process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited)
def test_setpgid(self): self.build() exe = os.path.join(os.getcwd(), 'a.out') # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_{0:d}".format((int(time.time())))) self.addTearDownHook(lambda: self.run_platform_command("rm {0!s}".format((pid_file_path)))) popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) max_attempts = 5 for i in range(max_attempts): err, retcode, msg = self.run_platform_command("ls {0!s}".format(pid_file_path)) if err.Success() and retcode == 0: break else: print(msg) if i < max_attempts: # Exponential backoff! time.sleep(pow(2, i) * 0.25) else: self.fail("Child PID file {0!s} not found even after {1:d} attempts.".format(pid_file_path, max_attempts)) err, retcode, pid = self.run_platform_command("cat {0!s}".format((pid_file_path))) self.assertTrue(err.Success() and retcode == 0, "Failed to read file {0!s}: {1!s}, retcode: {2:d}".format(pid_file_path, err.GetCString(), retcode)) # make sure we cleanup the forked child also def cleanupChild(): if lldb.remote_platform: lldb.remote_platform.Kill(int(pid)) else: if os.path.exists("/proc/" + pid): os.kill(int(pid), signal.SIGKILL) self.addTearDownHook(cleanupChild) # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() process = target.AttachToProcessWithID(listener, int(pid), error) self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # set a breakpoint just before the setpgid() call lldbutil.run_break_set_by_file_and_line(self, 'main.c', self.line, num_expected_locations=-1) thread = process.GetSelectedThread() # release the child from its loop value = thread.GetSelectedFrame().EvaluateExpression("release_child_flag = 1") self.assertTrue(value.IsValid() and value.GetValueAsUnsigned(0) == 1); process.Continue() # make sure the child's process group id is different from its pid value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid)); # step over the setpgid() call thread.StepOver() self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) # verify that the process group has been set correctly # this also checks that we are still in full control of the child value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertEqual(value.GetValueAsUnsigned(0), int(pid)); # run to completion process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited)
def test_netbsd_path(self): core = lldbutil.append_to_process_working_directory(self, "core") self.coredump_test(core, core)
def _launch_and_wait_for_init(self): sync_file_path = lldbutil.append_to_process_working_directory( self, "process_ready") inferior = self._launch_inferior(self._run_args + [sync_file_path]) lldbutil.wait_for_file_on_target(self, sync_file_path) return inferior