diff --git a/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py b/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py index 727f328ee3b4..d51bf3a66016 100644 --- a/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py +++ b/lldb/test/tools/lldb-gdbserver/TestLldbGdbServer.py @@ -5,6 +5,7 @@ Test lldb-gdbserver operation import unittest2 import pexpect import socket +import subprocess import sys from lldbtest import * from lldbgdbserverutils import * @@ -64,9 +65,14 @@ class LldbGdbServerTestCase(TestBase): sock.connect(('localhost', self.port)) return sock - def start_server(self): + def start_server(self, attach_pid=None): + # Create the command line + commandline = "{} localhost:{}".format(self.debug_monitor_exe, self.port) + if attach_pid: + commandline += " --attach=%d" % attach_pid + # start the server - server = pexpect.spawn("{} localhost:{}".format(self.debug_monitor_exe, self.port)) + server = pexpect.spawn(commandline) # Turn on logging for what the child sends back. if self.TraceOn(): @@ -90,6 +96,17 @@ class LldbGdbServerTestCase(TestBase): return server + def launch_process_for_attach(self): + # We're going to start a child process that the debug monitor stub can later attach to. + # This process needs to be started so that it just hangs around for a while. We'll + # have it sleep. + exe_path = os.path.abspath("a.out") + print("using exe for attach: %s" % exe_path) + print("exists? {}".format(os.path.exists(exe_path))) + + args = [exe_path, "sleep:5"] + return subprocess.Popen(args) + def add_no_ack_remote_stream(self): self.test_sequence.add_log_lines( ["read packet: +", @@ -380,5 +397,44 @@ class LldbGdbServerTestCase(TestBase): self.buildDwarf() self.qProcessInfo_returns_running_process() + def attach_commandline_qProcessInfo_reports_pid(self): + # Launch the process that we'll use as the inferior. + inferior = self.launch_process_for_attach() + self.assertIsNotNone(inferior) + self.assertTrue(inferior.pid > 0) + + # Launch the debug monitor stub, attaching to the inferior. + server = self.start_server(attach_pid=inferior.pid) + self.assertIsNotNone(server) + + # Check that the stub reports attachment to the inferior. + self.add_no_ack_remote_stream() + self.test_sequence.add_log_lines( + ["read packet: $qProcessInfo#00", + { "direction":"send", "regex":r"^\$pid:([0-9a-fA-F]+);", "capture":{1:"pid"} }], + True) + context = self.expect_gdbremote_sequence() + + # Ensure the process id matches what we expected. + pid_text = context.get('pid', None) + self.assertIsNotNone(pid_text) + reported_pid = int(pid_text, base=16) + self.assertEqual(reported_pid, inferior.pid) + + @debugserver_test + @dsym_test + def test_attach_commandline_qProcessInfo_reports_pid_debugserver_dsym(self): + self.init_debugserver_test() + self.buildDsym() + self.attach_commandline_qProcessInfo_reports_pid() + + @llgs_test + @dwarf_test + @unittest2.expectedFailure() + def test_attach_commandline_qProcessInfo_reports_pid_llgs_dwarf(self): + self.init_llgs_test() + self.buildDwarf() + self.attach_commandline_qProcessInfo_reports_pid() + if __name__ == '__main__': unittest2.main() diff --git a/lldb/test/tools/lldb-gdbserver/main.cpp b/lldb/test/tools/lldb-gdbserver/main.cpp index 88c397cadb99..91f81d669c37 100644 --- a/lldb/test/tools/lldb-gdbserver/main.cpp +++ b/lldb/test/tools/lldb-gdbserver/main.cpp @@ -1,9 +1,11 @@ #include #include #include +#include -static const char *const STDERR_PREFIX = "stderr:"; static const char *const RETVAL_PREFIX = "retval:"; +static const char *const SLEEP_PREFIX = "sleep:"; +static const char *const STDERR_PREFIX = "stderr:"; int main (int argc, char **argv) { @@ -21,6 +23,13 @@ int main (int argc, char **argv) // Treat as the return value for the program. return_value = std::atoi (argv[i] + strlen (RETVAL_PREFIX)); } + else if (std::strstr (argv[i], SLEEP_PREFIX)) + { + // Treat as the amount of time to have this process sleep (in seconds). + const int sleep_seconds = std::atoi (argv[i] + strlen (SLEEP_PREFIX)); + const int sleep_result = sleep(sleep_seconds); + printf("sleep result: %d\n", sleep_result); + } else { // Treat the argument as text for stdout.