1import gdbremote_testcase 2 3 4class GdbRemoteForkTestBase(gdbremote_testcase.GdbRemoteTestCaseBase): 5 fork_regex = ("[$]T[0-9a-fA-F]{{2}}thread:p([0-9a-f]+)[.]([0-9a-f]+);.*" 6 "{}:p([0-9a-f]+)[.]([0-9a-f]+).*") 7 fork_regex_nonstop = ("%Stop:T[0-9a-fA-F]{{2}}" 8 "thread:p([0-9a-f]+)[.]([0-9a-f]+);.*" 9 "{}:p([0-9a-f]+)[.]([0-9a-f]+).*") 10 fork_capture = {1: "parent_pid", 2: "parent_tid", 11 3: "child_pid", 4: "child_tid"} 12 stop_regex_base = "T[0-9a-fA-F]{{2}}thread:p{}.{};.*reason:signal.*" 13 stop_regex = "^[$]" + stop_regex_base 14 15 def start_fork_test(self, args, variant="fork", nonstop=False): 16 self.build() 17 self.prep_debug_monitor_and_inferior(inferior_args=args) 18 self.add_qSupported_packets(["multiprocess+", 19 "{}-events+".format(variant)]) 20 ret = self.expect_gdbremote_sequence() 21 self.assertIn("{}-events+".format(variant), ret["qSupported_response"]) 22 self.reset_test_sequence() 23 24 # continue and expect fork 25 if nonstop: 26 self.test_sequence.add_log_lines([ 27 "read packet: $QNonStop:1#00", 28 "send packet: $OK#00", 29 "read packet: $c#00", 30 "send packet: $OK#00", 31 {"direction": "send", 32 "regex": self.fork_regex_nonstop.format(variant), 33 "capture": self.fork_capture}, 34 "read packet: $vStopped#00", 35 "send packet: $OK#00", 36 ], True) 37 else: 38 self.test_sequence.add_log_lines([ 39 "read packet: $c#00", 40 {"direction": "send", "regex": self.fork_regex.format(variant), 41 "capture": self.fork_capture}, 42 ], True) 43 ret = self.expect_gdbremote_sequence() 44 self.reset_test_sequence() 45 46 return tuple(ret[x] for x in ("parent_pid", "parent_tid", 47 "child_pid", "child_tid")) 48 49 def fork_and_detach_test(self, variant, nonstop=False): 50 parent_pid, parent_tid, child_pid, child_tid = ( 51 self.start_fork_test([variant], variant, nonstop=nonstop)) 52 53 # detach the forked child 54 self.test_sequence.add_log_lines([ 55 "read packet: $D;{}#00".format(child_pid), 56 "send packet: $OK#00", 57 # verify that the current process is correct 58 "read packet: $qC#00", 59 "send packet: $QCp{}.{}#00".format(parent_pid, parent_tid), 60 # verify that the correct processes are detached/available 61 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 62 "send packet: $Eff#00", 63 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 64 "send packet: $OK#00", 65 ], True) 66 self.expect_gdbremote_sequence() 67 self.reset_test_sequence() 68 return parent_pid, parent_tid 69 70 def fork_and_follow_test(self, variant, nonstop=False): 71 parent_pid, parent_tid, child_pid, child_tid = ( 72 self.start_fork_test([variant], variant, nonstop=nonstop)) 73 74 # switch to the forked child 75 self.test_sequence.add_log_lines([ 76 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 77 "send packet: $OK#00", 78 "read packet: $Hcp{}.{}#00".format(child_pid, child_tid), 79 "send packet: $OK#00", 80 # detach the parent 81 "read packet: $D;{}#00".format(parent_pid), 82 "send packet: $OK#00", 83 # verify that the correct processes are detached/available 84 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 85 "send packet: $Eff#00", 86 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 87 "send packet: $OK#00", 88 # then resume the child 89 "read packet: $c#00", 90 ], True) 91 92 if nonstop: 93 self.test_sequence.add_log_lines([ 94 "send packet: $OK#00", 95 "send packet: %Stop:W00;process:{}#00".format(child_pid), 96 "read packet: $vStopped#00", 97 "send packet: $OK#00", 98 ], True) 99 else: 100 self.test_sequence.add_log_lines([ 101 "send packet: $W00;process:{}#00".format(child_pid), 102 ], True) 103 self.expect_gdbremote_sequence() 104 105 def detach_all_test(self, nonstop=False): 106 parent_pid, parent_tid, child_pid, child_tid = ( 107 self.start_fork_test(["fork"], nonstop=nonstop)) 108 109 self.test_sequence.add_log_lines([ 110 # double-check our PIDs 111 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 112 "send packet: $OK#00", 113 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 114 "send packet: $OK#00", 115 # detach all processes 116 "read packet: $D#00", 117 "send packet: $OK#00", 118 # verify that both PIDs are invalid now 119 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 120 "send packet: $Eff#00", 121 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 122 "send packet: $Eff#00", 123 ], True) 124 self.expect_gdbremote_sequence() 125 126 def vkill_test(self, kill_parent=False, kill_child=False, nonstop=False): 127 assert kill_parent or kill_child 128 parent_pid, parent_tid, child_pid, child_tid = ( 129 self.start_fork_test(["fork"], nonstop=nonstop)) 130 131 if kill_parent: 132 self.test_sequence.add_log_lines([ 133 # kill the process 134 "read packet: $vKill;{}#00".format(parent_pid), 135 "send packet: $OK#00", 136 ], True) 137 if kill_child: 138 self.test_sequence.add_log_lines([ 139 # kill the process 140 "read packet: $vKill;{}#00".format(child_pid), 141 "send packet: $OK#00", 142 ], True) 143 self.test_sequence.add_log_lines([ 144 # check child PID/TID 145 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 146 "send packet: ${}#00".format("Eff" if kill_child else "OK"), 147 # check parent PID/TID 148 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 149 "send packet: ${}#00".format("Eff" if kill_parent else "OK"), 150 ], True) 151 self.expect_gdbremote_sequence() 152 153 def resume_one_test(self, run_order, use_vCont=False, nonstop=False): 154 parent_pid, parent_tid, child_pid, child_tid = ( 155 self.start_fork_test(["fork", "stop"], nonstop=nonstop)) 156 157 parent_expect = [ 158 self.stop_regex_base.format(parent_pid, parent_tid), 159 "W00;process:{}#.*".format(parent_pid), 160 ] 161 child_expect = [ 162 self.stop_regex_base.format(child_pid, child_tid), 163 "W00;process:{}#.*".format(child_pid), 164 ] 165 166 for x in run_order: 167 if x == "parent": 168 pidtid = (parent_pid, parent_tid) 169 expect = parent_expect.pop(0) 170 elif x == "child": 171 pidtid = (child_pid, child_tid) 172 expect = child_expect.pop(0) 173 else: 174 assert False, "unexpected x={}".format(x) 175 176 if use_vCont: 177 self.test_sequence.add_log_lines([ 178 # continue the selected process 179 "read packet: $vCont;c:p{}.{}#00".format(*pidtid), 180 ], True) 181 else: 182 self.test_sequence.add_log_lines([ 183 # continue the selected process 184 "read packet: $Hcp{}.{}#00".format(*pidtid), 185 "send packet: $OK#00", 186 "read packet: $c#00", 187 ], True) 188 if nonstop: 189 self.test_sequence.add_log_lines([ 190 "send packet: $OK#00", 191 {"direction": "send", "regex": "%Stop:" + expect}, 192 "read packet: $vStopped#00", 193 "send packet: $OK#00", 194 ], True) 195 else: 196 self.test_sequence.add_log_lines([ 197 {"direction": "send", "regex": "[$]" + expect}, 198 ], True) 199 # if at least one process remained, check both PIDs 200 if parent_expect or child_expect: 201 self.test_sequence.add_log_lines([ 202 "read packet: $Hgp{}.{}#00".format(parent_pid, parent_tid), 203 "send packet: ${}#00".format("OK" if parent_expect else "Eff"), 204 "read packet: $Hgp{}.{}#00".format(child_pid, child_tid), 205 "send packet: ${}#00".format("OK" if child_expect else "Eff"), 206 ], True) 207 self.expect_gdbremote_sequence() 208