| import gdbremote_testcase |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase): |
| mydir = TestBase.compute_mydir(__file__) |
| |
| def fork_and_detach_test(self, variant): |
| self.build() |
| self.prep_debug_monitor_and_inferior(inferior_args=[variant]) |
| self.add_qSupported_packets(["multiprocess+", |
| "{}-events+".format(variant)]) |
| ret = self.expect_gdbremote_sequence() |
| self.assertIn("{}-events+".format(variant), ret["qSupported_response"]) |
| self.reset_test_sequence() |
| |
| # continue and expect fork |
| fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant) |
| self.test_sequence.add_log_lines([ |
| "read packet: $c#00", |
| {"direction": "send", "regex": fork_regex, |
| "capture": {1: "pid", 2: "tid"}}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| pid = int(ret["pid"], 16) |
| self.reset_test_sequence() |
| |
| # detach the forked child |
| self.test_sequence.add_log_lines([ |
| "read packet: $D;{:x}#00".format(pid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| self.reset_test_sequence() |
| |
| @add_test_categories(["fork"]) |
| def test_fork(self): |
| self.fork_and_detach_test("fork") |
| |
| # resume the parent |
| self.test_sequence.add_log_lines([ |
| "read packet: $c#00", |
| {"direction": "send", "regex": r"[$]W00#.*"}, |
| ], True) |
| self.expect_gdbremote_sequence() |
| |
| @add_test_categories(["fork"]) |
| def test_vfork(self): |
| self.fork_and_detach_test("vfork") |
| |
| # resume the parent |
| self.test_sequence.add_log_lines([ |
| "read packet: $c#00", |
| {"direction": "send", "regex": r"[$]T.*vforkdone.*"}, |
| "read packet: $c#00", |
| {"direction": "send", "regex": r"[$]W00#.*"}, |
| ], True) |
| self.expect_gdbremote_sequence() |
| |
| def fork_and_follow_test(self, variant): |
| self.build() |
| self.prep_debug_monitor_and_inferior(inferior_args=[variant]) |
| self.add_qSupported_packets(["multiprocess+", |
| "{}-events+".format(variant)]) |
| ret = self.expect_gdbremote_sequence() |
| self.assertIn("{}-events+".format(variant), ret["qSupported_response"]) |
| self.reset_test_sequence() |
| |
| # continue and expect fork |
| procinfo_regex = "[$]pid:([0-9a-f]+);.*" |
| fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant) |
| self.test_sequence.add_log_lines([ |
| "read packet: $qProcessInfo#00", |
| {"direction": "send", "regex": procinfo_regex, |
| "capture": {1: "parent_pid"}}, |
| "read packet: $c#00", |
| {"direction": "send", "regex": fork_regex, |
| "capture": {1: "pid", 2: "tid"}}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| parent_pid, pid, tid = (int(ret[x], 16) for x |
| in ("parent_pid", "pid", "tid")) |
| self.reset_test_sequence() |
| |
| # switch to the forked child |
| self.test_sequence.add_log_lines([ |
| "read packet: $Hgp{:x}.{:x}#00".format(pid, tid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| "read packet: $Hcp{:x}.{:x}#00".format(pid, tid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| ], True) |
| |
| # detach the parent |
| self.test_sequence.add_log_lines([ |
| "read packet: $D;{:x}#00".format(parent_pid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| self.reset_test_sequence() |
| |
| # resume the child |
| self.test_sequence.add_log_lines([ |
| "read packet: $c#00", |
| {"direction": "send", "regex": r"[$]W00#.*"}, |
| ], True) |
| self.expect_gdbremote_sequence() |
| |
| @add_test_categories(["fork"]) |
| def test_fork_follow(self): |
| self.fork_and_follow_test("fork") |
| |
| @add_test_categories(["fork"]) |
| def test_vfork_follow(self): |
| self.fork_and_follow_test("vfork") |
| |
| @add_test_categories(["fork"]) |
| def test_select_wrong_pid(self): |
| self.build() |
| self.prep_debug_monitor_and_inferior() |
| self.add_qSupported_packets(["multiprocess+"]) |
| ret = self.expect_gdbremote_sequence() |
| self.assertIn("multiprocess+", ret["qSupported_response"]) |
| self.reset_test_sequence() |
| |
| # get process pid |
| procinfo_regex = "[$]pid:([0-9a-f]+);.*" |
| self.test_sequence.add_log_lines([ |
| "read packet: $qProcessInfo#00", |
| {"direction": "send", "regex": procinfo_regex, |
| "capture": {1: "pid"}}, |
| "read packet: $qC#00", |
| {"direction": "send", "regex": "[$]QC([0-9a-f]+)#.*", |
| "capture": {1: "tid"}}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| pid, tid = (int(ret[x], 16) for x in ("pid", "tid")) |
| self.reset_test_sequence() |
| |
| # try switching to correct pid |
| self.test_sequence.add_log_lines([ |
| "read packet: $Hgp{:x}.{:x}#00".format(pid, tid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| "read packet: $Hcp{:x}.{:x}#00".format(pid, tid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| |
| # try switching to invalid tid |
| self.test_sequence.add_log_lines([ |
| "read packet: $Hgp{:x}.{:x}#00".format(pid, tid+1), |
| {"direction": "send", "regex": r"[$]E15#.*"}, |
| "read packet: $Hcp{:x}.{:x}#00".format(pid, tid+1), |
| {"direction": "send", "regex": r"[$]E15#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| |
| # try switching to invalid pid |
| self.test_sequence.add_log_lines([ |
| "read packet: $Hgp{:x}.{:x}#00".format(pid+1, tid), |
| {"direction": "send", "regex": r"[$]Eff#.*"}, |
| "read packet: $Hcp{:x}.{:x}#00".format(pid+1, tid), |
| {"direction": "send", "regex": r"[$]Eff#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| |
| @add_test_categories(["fork"]) |
| def test_detach_current(self): |
| self.build() |
| self.prep_debug_monitor_and_inferior() |
| self.add_qSupported_packets(["multiprocess+"]) |
| ret = self.expect_gdbremote_sequence() |
| self.assertIn("multiprocess+", ret["qSupported_response"]) |
| self.reset_test_sequence() |
| |
| # get process pid |
| procinfo_regex = "[$]pid:([0-9a-f]+);.*" |
| self.test_sequence.add_log_lines([ |
| "read packet: $qProcessInfo#00", |
| {"direction": "send", "regex": procinfo_regex, |
| "capture": {1: "pid"}}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |
| pid = int(ret["pid"], 16) |
| self.reset_test_sequence() |
| |
| # detach the process |
| self.test_sequence.add_log_lines([ |
| "read packet: $D;{:x}#00".format(pid), |
| {"direction": "send", "regex": r"[$]OK#.*"}, |
| "read packet: $qC#00", |
| {"direction": "send", "regex": r"[$]E44#.*"}, |
| ], True) |
| ret = self.expect_gdbremote_sequence() |