472 lines · python
1from lldbsuite.test.decorators import *2from lldbsuite.test.lldbtest import *3 4import gdbremote_testcase5 6 7class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):8 @skipIfWindows # no SIGSEGV support9 @add_test_categories(["llgs"])10 def test_run(self):11 self.build()12 self.set_inferior_startup_launch()13 thread_num = 314 procs = self.prep_debug_monitor_and_inferior(15 inferior_args=["thread:segfault"] + thread_num * ["thread:new"]16 )17 self.test_sequence.add_log_lines(18 [19 "read packet: $QNonStop:1#00",20 "send packet: $OK#00",21 "read packet: $c#63",22 "send packet: $OK#00",23 ],24 True,25 )26 self.expect_gdbremote_sequence()27 28 segv_signo = lldbutil.get_signal_number("SIGSEGV")29 all_threads = set()30 all_segv_threads = []31 32 # we should get segfaults from all the threads33 for segv_no in range(thread_num):34 # first wait for the notification event35 self.reset_test_sequence()36 self.test_sequence.add_log_lines(37 [38 {39 "direction": "send",40 "regex": r"^%Stop:(T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",41 "capture": {1: "packet", 2: "signo", 3: "thread_id"},42 },43 ],44 True,45 )46 m = self.expect_gdbremote_sequence()47 del m["O_content"]48 threads = [m]49 50 # then we may get events for the remaining threads51 # (but note that not all threads may have been started yet)52 while True:53 self.reset_test_sequence()54 self.test_sequence.add_log_lines(55 [56 "read packet: $vStopped#00",57 {58 "direction": "send",59 "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",60 "capture": {1: "packet", 2: "signo", 3: "thread_id"},61 },62 ],63 True,64 )65 m = self.expect_gdbremote_sequence()66 if m["packet"] == "OK":67 break68 del m["O_content"]69 threads.append(m)70 71 segv_threads = []72 other_threads = []73 for t in threads:74 signo = int(t["signo"], 16)75 if signo == segv_signo:76 segv_threads.append(t["thread_id"])77 else:78 self.assertEqual(signo, 0)79 other_threads.append(t["thread_id"])80 81 # verify that exactly one thread segfaulted82 self.assertEqual(len(segv_threads), 1)83 # we should get only one segv from every thread84 self.assertNotIn(segv_threads[0], all_segv_threads)85 all_segv_threads.extend(segv_threads)86 # segv_threads + other_threads should always be a superset87 # of all_threads, i.e. we should get states for all threads88 # already started89 self.assertFalse(all_threads.difference(other_threads + segv_threads))90 all_threads.update(other_threads + segv_threads)91 92 # verify that `?` returns the same result93 self.reset_test_sequence()94 self.test_sequence.add_log_lines(95 [96 "read packet: $?#00",97 ],98 True,99 )100 threads_verify = []101 while True:102 self.test_sequence.add_log_lines(103 [104 {105 "direction": "send",106 "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",107 "capture": {1: "packet", 2: "signo", 3: "thread_id"},108 },109 ],110 True,111 )112 m = self.expect_gdbremote_sequence()113 if m["packet"] == "OK":114 break115 del m["O_content"]116 threads_verify.append(m)117 self.reset_test_sequence()118 self.test_sequence.add_log_lines(119 [120 "read packet: $vStopped#00",121 ],122 True,123 )124 125 self.assertEqual(threads, threads_verify)126 127 self.reset_test_sequence()128 self.test_sequence.add_log_lines(129 [130 "read packet: $vCont;C{:02x}:{};c#00".format(131 segv_signo, segv_threads[0]132 ),133 "send packet: $OK#00",134 ],135 True,136 )137 self.expect_gdbremote_sequence()138 139 # finally, verify that all threads have started140 self.assertEqual(len(all_threads), thread_num + 1)141 142 @add_test_categories(["llgs"])143 def test_vCtrlC(self):144 self.build()145 self.set_inferior_startup_launch()146 procs = self.prep_debug_monitor_and_inferior(inferior_args=["thread:new"])147 self.test_sequence.add_log_lines(148 [149 "read packet: $QNonStop:1#00",150 "send packet: $OK#00",151 "read packet: $c#63",152 "send packet: $OK#00",153 "read packet: $vCtrlC#00",154 "send packet: $OK#00",155 {156 "direction": "send",157 "regex": r"^%Stop:T",158 },159 ],160 True,161 )162 self.expect_gdbremote_sequence()163 164 @add_test_categories(["llgs"])165 def test_exit(self):166 self.build()167 self.set_inferior_startup_launch()168 procs = self.prep_debug_monitor_and_inferior()169 self.test_sequence.add_log_lines(170 [171 "read packet: $QNonStop:1#00",172 "send packet: $OK#00",173 "read packet: $c#63",174 "send packet: $OK#00",175 "send packet: %Stop:W00#00",176 "read packet: $vStopped#00",177 "send packet: $OK#00",178 ],179 True,180 )181 self.expect_gdbremote_sequence()182 183 @skipIfWindows # no clue, the result makes zero sense184 @add_test_categories(["llgs"])185 def test_exit_query(self):186 self.build()187 self.set_inferior_startup_launch()188 procs = self.prep_debug_monitor_and_inferior()189 self.test_sequence.add_log_lines(190 [191 "read packet: $QNonStop:1#00",192 "send packet: $OK#00",193 "read packet: $c#63",194 "send packet: $OK#00",195 "send packet: %Stop:W00#00",196 "read packet: $?#00",197 "send packet: $W00#00",198 "read packet: $vStopped#00",199 "send packet: $OK#00",200 ],201 True,202 )203 self.expect_gdbremote_sequence()204 205 def multiple_resume_test(self, second_command):206 self.build()207 self.set_inferior_startup_launch()208 procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:15"])209 self.test_sequence.add_log_lines(210 [211 "read packet: $QNonStop:1#00",212 "send packet: $OK#00",213 "read packet: $c#63",214 "send packet: $OK#00",215 "read packet: ${}#00".format(second_command),216 "send packet: $E37#00",217 ],218 True,219 )220 self.expect_gdbremote_sequence()221 222 @add_test_categories(["llgs"])223 def test_multiple_C_continue_with_signal(self):224 self.multiple_resume_test("C05")225 226 @add_test_categories(["llgs"])227 def test_multiple_c_continue_with_addr(self):228 self.multiple_resume_test("c")229 230 @add_test_categories(["llgs"])231 def test_multiple_s_single_step_with_addr(self):232 self.multiple_resume_test("s")233 234 @skipIfWindows235 @add_test_categories(["llgs"])236 def test_multiple_vCont(self):237 self.build()238 self.set_inferior_startup_launch()239 procs = self.prep_debug_monitor_and_inferior(240 inferior_args=["thread:new", "stop", "sleep:15"]241 )242 self.test_sequence.add_log_lines(243 [244 "read packet: $QNonStop:1#00",245 "send packet: $OK#00",246 "read packet: $c#63",247 "send packet: $OK#00",248 {249 "direction": "send",250 "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",251 "capture": {1: "tid1"},252 },253 "read packet: $vStopped#63",254 {255 "direction": "send",256 "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",257 "capture": {1: "tid2"},258 },259 "read packet: $vStopped#63",260 "send packet: $OK#00",261 ],262 True,263 )264 ret = self.expect_gdbremote_sequence()265 266 self.reset_test_sequence()267 self.test_sequence.add_log_lines(268 [269 "read packet: $vCont;c:{}#00".format(ret["tid1"]),270 "send packet: $OK#00",271 "read packet: $vCont;c:{}#00".format(ret["tid2"]),272 "send packet: $E37#00",273 ],274 True,275 )276 self.expect_gdbremote_sequence()277 278 @add_test_categories(["llgs"])279 @skipIfWindows # Sometimes results in '$E37' instead of expected '$OK'280 def test_vCont_then_stop(self):281 self.build()282 self.set_inferior_startup_launch()283 procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:15"])284 self.test_sequence.add_log_lines(285 [286 "read packet: $QNonStop:1#00",287 "send packet: $OK#00",288 "read packet: $c#63",289 "send packet: $OK#00",290 "read packet: $vCont;t#00",291 "send packet: $OK#00",292 ],293 True,294 )295 self.expect_gdbremote_sequence()296 297 def vCont_then_partial_stop_test(self, run_both):298 self.build()299 self.set_inferior_startup_launch()300 procs = self.prep_debug_monitor_and_inferior(301 inferior_args=["thread:new", "stop", "sleep:15"]302 )303 self.test_sequence.add_log_lines(304 [305 "read packet: $QNonStop:1#00",306 "send packet: $OK#00",307 "read packet: $c#63",308 "send packet: $OK#00",309 {310 "direction": "send",311 "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",312 "capture": {1: "tid1"},313 },314 "read packet: $vStopped#63",315 {316 "direction": "send",317 "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",318 "capture": {1: "tid2"},319 },320 "read packet: $vStopped#63",321 "send packet: $OK#00",322 ],323 True,324 )325 ret = self.expect_gdbremote_sequence()326 327 self.reset_test_sequence()328 if run_both:329 self.test_sequence.add_log_lines(330 [331 "read packet: $vCont;c#00",332 ],333 True,334 )335 else:336 self.test_sequence.add_log_lines(337 [338 "read packet: $vCont;c:{}#00".format(ret["tid1"]),339 ],340 True,341 )342 self.test_sequence.add_log_lines(343 [344 "send packet: $OK#00",345 "read packet: $vCont;t:{}#00".format(ret["tid2"]),346 "send packet: $E03#00",347 ],348 True,349 )350 self.expect_gdbremote_sequence()351 352 @skipIfWindows353 @add_test_categories(["llgs"])354 def test_vCont_then_partial_stop(self):355 self.vCont_then_partial_stop_test(False)356 357 @skipIfWindows358 @add_test_categories(["llgs"])359 def test_vCont_then_partial_stop_run_both(self):360 self.vCont_then_partial_stop_test(True)361 362 @skipIfWindows363 @add_test_categories(["llgs"])364 def test_stdio(self):365 self.build()366 self.set_inferior_startup_launch()367 # Since we can't easily ensure that lldb will send output in two parts,368 # just put a stop in the middle. Since we don't clear vStdio,369 # the second message won't be delivered immediately.370 self.prep_debug_monitor_and_inferior(371 inferior_args=["message 1", "stop", "message 2"]372 )373 self.test_sequence.add_log_lines(374 [375 "read packet: $QNonStop:1#00",376 "send packet: $OK#00",377 "read packet: $c#63",378 "send packet: $OK#00",379 {"direction": "send", "regex": r"^%Stop:T.*"},380 "read packet: $vStopped#00",381 "send packet: $OK#00",382 "read packet: $c#63",383 "send packet: $OK#00",384 "send packet: %Stop:W00#00",385 ],386 True,387 )388 ret = self.expect_gdbremote_sequence()389 390 # We know there will be at least two messages, but there may be more.391 # Loop until we have everything. The first message waiting for us in the392 # packet queue.393 count = 1394 output = self._server.get_raw_output_packet()395 while not (b"message 2\r\n" in output):396 self._server.send_packet(b"vStdio")397 output += self._server.get_raw_output_packet()398 count += 1399 self.assertGreaterEqual(count, 2)400 401 self.reset_test_sequence()402 self.test_sequence.add_log_lines(403 [404 "read packet: $vStdio#00",405 "send packet: $OK#00",406 "read packet: $vStopped#00",407 "send packet: $OK#00",408 ],409 True,410 )411 self.expect_gdbremote_sequence()412 413 @skipIfWindows414 @add_test_categories(["llgs"])415 def test_stop_reason_while_running(self):416 self.build()417 self.set_inferior_startup_launch()418 procs = self.prep_debug_monitor_and_inferior(419 inferior_args=["thread:new", "thread:new", "stop", "sleep:15"]420 )421 self.test_sequence.add_log_lines(422 [423 "read packet: $QNonStop:1#00",424 "send packet: $OK#00",425 # stop is used to synchronize starting threads426 "read packet: $c#63",427 "send packet: $OK#00",428 {"direction": "send", "regex": "%Stop:T.*"},429 "read packet: $c#63",430 "send packet: $OK#00",431 "read packet: $?#00",432 "send packet: $OK#00",433 ],434 True,435 )436 self.expect_gdbremote_sequence()437 438 @skipIfWindows439 @add_test_categories(["llgs"])440 def test_leave_nonstop(self):441 self.build()442 self.set_inferior_startup_launch()443 procs = self.prep_debug_monitor_and_inferior(444 inferior_args=["thread:new", "thread:new", "stop", "sleep:15"]445 )446 self.test_sequence.add_log_lines(447 [448 "read packet: $QNonStop:1#00",449 "send packet: $OK#00",450 # stop is used to synchronize starting threads451 "read packet: $c#63",452 "send packet: $OK#00",453 {"direction": "send", "regex": "%Stop:T.*"},454 "read packet: $c#63",455 "send packet: $OK#00",456 # verify that the threads are running now457 "read packet: $?#00",458 "send packet: $OK#00",459 "read packet: $QNonStop:0#00",460 "send packet: $OK#00",461 # we should issue some random request now to verify that the stub462 # did not send stop reasons -- we may verify whether notification463 # queue was cleared while at it464 "read packet: $vStopped#00",465 "send packet: $Eff#00",466 "read packet: $?#00",467 {"direction": "send", "regex": "[$]T.*"},468 ],469 True,470 )471 self.expect_gdbremote_sequence()472