1import gdbremote_testcase 2from lldbsuite.test.decorators import * 3from lldbsuite.test.lldbtest import * 4from lldbsuite.test import lldbutil 5 6class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase): 7 mydir = TestBase.compute_mydir(__file__) 8 9 def fork_and_detach_test(self, variant): 10 self.build() 11 self.prep_debug_monitor_and_inferior(inferior_args=[variant]) 12 self.add_qSupported_packets(["multiprocess+", 13 "{}-events+".format(variant)]) 14 ret = self.expect_gdbremote_sequence() 15 self.assertIn("{}-events+".format(variant), ret["qSupported_response"]) 16 self.reset_test_sequence() 17 18 # continue and expect fork 19 fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant) 20 self.test_sequence.add_log_lines([ 21 "read packet: $c#00", 22 {"direction": "send", "regex": fork_regex, 23 "capture": {1: "pid", 2: "tid"}}, 24 ], True) 25 ret = self.expect_gdbremote_sequence() 26 pid = int(ret["pid"], 16) 27 self.reset_test_sequence() 28 29 # detach the forked child 30 self.test_sequence.add_log_lines([ 31 "read packet: $D;{:x}#00".format(pid), 32 {"direction": "send", "regex": r"[$]OK#.*"}, 33 ], True) 34 ret = self.expect_gdbremote_sequence() 35 self.reset_test_sequence() 36 37 @add_test_categories(["fork"]) 38 def test_fork(self): 39 self.fork_and_detach_test("fork") 40 41 # resume the parent 42 self.test_sequence.add_log_lines([ 43 "read packet: $c#00", 44 {"direction": "send", "regex": r"[$]W00#.*"}, 45 ], True) 46 self.expect_gdbremote_sequence() 47 48 @add_test_categories(["fork"]) 49 def test_vfork(self): 50 self.fork_and_detach_test("vfork") 51 52 # resume the parent 53 self.test_sequence.add_log_lines([ 54 "read packet: $c#00", 55 {"direction": "send", "regex": r"[$]T.*vforkdone.*"}, 56 "read packet: $c#00", 57 {"direction": "send", "regex": r"[$]W00#.*"}, 58 ], True) 59 self.expect_gdbremote_sequence() 60 61 def fork_and_follow_test(self, variant): 62 self.build() 63 self.prep_debug_monitor_and_inferior(inferior_args=[variant]) 64 self.add_qSupported_packets(["multiprocess+", 65 "{}-events+".format(variant)]) 66 ret = self.expect_gdbremote_sequence() 67 self.assertIn("{}-events+".format(variant), ret["qSupported_response"]) 68 self.reset_test_sequence() 69 70 # continue and expect fork 71 procinfo_regex = "[$]pid:([0-9a-f]+);.*" 72 fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant) 73 self.test_sequence.add_log_lines([ 74 "read packet: $qProcessInfo#00", 75 {"direction": "send", "regex": procinfo_regex, 76 "capture": {1: "parent_pid"}}, 77 "read packet: $c#00", 78 {"direction": "send", "regex": fork_regex, 79 "capture": {1: "pid", 2: "tid"}}, 80 ], True) 81 ret = self.expect_gdbremote_sequence() 82 parent_pid, pid, tid = (int(ret[x], 16) for x 83 in ("parent_pid", "pid", "tid")) 84 self.reset_test_sequence() 85 86 # switch to the forked child 87 self.test_sequence.add_log_lines([ 88 "read packet: $Hgp{:x}.{:x}#00".format(pid, tid), 89 {"direction": "send", "regex": r"[$]OK#.*"}, 90 "read packet: $Hcp{:x}.{:x}#00".format(pid, tid), 91 {"direction": "send", "regex": r"[$]OK#.*"}, 92 ], True) 93 94 # detach the parent 95 self.test_sequence.add_log_lines([ 96 "read packet: $D;{:x}#00".format(parent_pid), 97 {"direction": "send", "regex": r"[$]OK#.*"}, 98 ], True) 99 ret = self.expect_gdbremote_sequence() 100 self.reset_test_sequence() 101 102 # resume the child 103 self.test_sequence.add_log_lines([ 104 "read packet: $c#00", 105 {"direction": "send", "regex": r"[$]W00#.*"}, 106 ], True) 107 self.expect_gdbremote_sequence() 108 109 @add_test_categories(["fork"]) 110 def test_fork_follow(self): 111 self.fork_and_follow_test("fork") 112 113 @add_test_categories(["fork"]) 114 def test_vfork_follow(self): 115 self.fork_and_follow_test("vfork") 116 117 @add_test_categories(["fork"]) 118 def test_select_wrong_pid(self): 119 self.build() 120 self.prep_debug_monitor_and_inferior() 121 self.add_qSupported_packets(["multiprocess+"]) 122 ret = self.expect_gdbremote_sequence() 123 self.assertIn("multiprocess+", ret["qSupported_response"]) 124 self.reset_test_sequence() 125 126 # get process pid 127 procinfo_regex = "[$]pid:([0-9a-f]+);.*" 128 self.test_sequence.add_log_lines([ 129 "read packet: $qProcessInfo#00", 130 {"direction": "send", "regex": procinfo_regex, 131 "capture": {1: "pid"}}, 132 "read packet: $qC#00", 133 {"direction": "send", "regex": "[$]QC([0-9a-f]+)#.*", 134 "capture": {1: "tid"}}, 135 ], True) 136 ret = self.expect_gdbremote_sequence() 137 pid, tid = (int(ret[x], 16) for x in ("pid", "tid")) 138 self.reset_test_sequence() 139 140 # try switching to correct pid 141 self.test_sequence.add_log_lines([ 142 "read packet: $Hgp{:x}.{:x}#00".format(pid, tid), 143 {"direction": "send", "regex": r"[$]OK#.*"}, 144 "read packet: $Hcp{:x}.{:x}#00".format(pid, tid), 145 {"direction": "send", "regex": r"[$]OK#.*"}, 146 ], True) 147 ret = self.expect_gdbremote_sequence() 148 149 # try switching to invalid tid 150 self.test_sequence.add_log_lines([ 151 "read packet: $Hgp{:x}.{:x}#00".format(pid, tid+1), 152 {"direction": "send", "regex": r"[$]E15#.*"}, 153 "read packet: $Hcp{:x}.{:x}#00".format(pid, tid+1), 154 {"direction": "send", "regex": r"[$]E15#.*"}, 155 ], True) 156 ret = self.expect_gdbremote_sequence() 157 158 # try switching to invalid pid 159 self.test_sequence.add_log_lines([ 160 "read packet: $Hgp{:x}.{:x}#00".format(pid+1, tid), 161 {"direction": "send", "regex": r"[$]Eff#.*"}, 162 "read packet: $Hcp{:x}.{:x}#00".format(pid+1, tid), 163 {"direction": "send", "regex": r"[$]Eff#.*"}, 164 ], True) 165 ret = self.expect_gdbremote_sequence() 166 167 @add_test_categories(["fork"]) 168 def test_detach_current(self): 169 self.build() 170 self.prep_debug_monitor_and_inferior() 171 self.add_qSupported_packets(["multiprocess+"]) 172 ret = self.expect_gdbremote_sequence() 173 self.assertIn("multiprocess+", ret["qSupported_response"]) 174 self.reset_test_sequence() 175 176 # get process pid 177 procinfo_regex = "[$]pid:([0-9a-f]+);.*" 178 self.test_sequence.add_log_lines([ 179 "read packet: $qProcessInfo#00", 180 {"direction": "send", "regex": procinfo_regex, 181 "capture": {1: "pid"}}, 182 ], True) 183 ret = self.expect_gdbremote_sequence() 184 pid = int(ret["pid"], 16) 185 self.reset_test_sequence() 186 187 # detach the process 188 self.test_sequence.add_log_lines([ 189 "read packet: $D;{:x}#00".format(pid), 190 {"direction": "send", "regex": r"[$]OK#.*"}, 191 "read packet: $qC#00", 192 {"direction": "send", "regex": r"[$]E44#.*"}, 193 ], True) 194 ret = self.expect_gdbremote_sequence() 195