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