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