1""" 2Test case for testing the gdbremote protocol. 3 4Tests run against debugserver and lldb-server (llgs). 5lldb-server tests run where the lldb-server exe is 6available. 7 8This class will be broken into smaller test case classes by 9gdb remote packet functional areas. For now it contains 10the initial set of tests implemented. 11""" 12 13import binascii 14import itertools 15import struct 16 17import gdbremote_testcase 18import lldbgdbserverutils 19from lldbsuite.support import seven 20from lldbsuite.test.decorators import * 21from lldbsuite.test.lldbtest import * 22from lldbsuite.test.lldbdwarf import * 23from lldbsuite.test import lldbutil, lldbplatformutil 24 25 26class LldbGdbServerTestCase( 27 gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcodeParser 28): 29 def test_thread_suffix_supported(self): 30 server = self.connect_to_debug_monitor() 31 self.assertIsNotNone(server) 32 33 self.do_handshake() 34 self.test_sequence.add_log_lines( 35 [ 36 "lldb-server < 26> read packet: $QThreadSuffixSupported#e4", 37 "lldb-server < 6> send packet: $OK#9a", 38 ], 39 True, 40 ) 41 42 self.expect_gdbremote_sequence() 43 44 def test_list_threads_in_stop_reply_supported(self): 45 server = self.connect_to_debug_monitor() 46 self.assertIsNotNone(server) 47 48 self.do_handshake() 49 self.test_sequence.add_log_lines( 50 [ 51 "lldb-server < 27> read packet: $QListThreadsInStopReply#21", 52 "lldb-server < 6> send packet: $OK#9a", 53 ], 54 True, 55 ) 56 self.expect_gdbremote_sequence() 57 58 def test_c_packet_works(self): 59 self.build() 60 procs = self.prep_debug_monitor_and_inferior() 61 self.test_sequence.add_log_lines( 62 ["read packet: $c#63", "send packet: $W00#00"], True 63 ) 64 65 self.expect_gdbremote_sequence() 66 67 @skipIfWindows # No pty support to test any inferior output 68 def test_inferior_print_exit(self): 69 self.build() 70 procs = self.prep_debug_monitor_and_inferior(inferior_args=["hello, world"]) 71 self.test_sequence.add_log_lines( 72 [ 73 "read packet: $vCont;c#a8", 74 { 75 "type": "output_match", 76 "regex": self.maybe_strict_output_regex(r"hello, world\r\n"), 77 }, 78 "send packet: $W00#00", 79 ], 80 True, 81 ) 82 83 context = self.expect_gdbremote_sequence() 84 self.assertIsNotNone(context) 85 86 def test_first_launch_stop_reply_thread_matches_first_qC(self): 87 self.build() 88 procs = self.prep_debug_monitor_and_inferior() 89 self.test_sequence.add_log_lines( 90 [ 91 "read packet: $qC#00", 92 { 93 "direction": "send", 94 "regex": r"^\$QC([0-9a-fA-F]+)#", 95 "capture": {1: "thread_id_QC"}, 96 }, 97 "read packet: $?#00", 98 { 99 "direction": "send", 100 "regex": r"^\$T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+)", 101 "capture": {1: "thread_id_?"}, 102 }, 103 ], 104 True, 105 ) 106 context = self.expect_gdbremote_sequence() 107 self.assertEqual(context.get("thread_id_QC"), context.get("thread_id_?")) 108 109 def test_attach_commandline_continue_app_exits(self): 110 self.build() 111 self.set_inferior_startup_attach() 112 procs = self.prep_debug_monitor_and_inferior() 113 self.test_sequence.add_log_lines( 114 ["read packet: $vCont;c#a8", "send packet: $W00#00"], True 115 ) 116 self.expect_gdbremote_sequence() 117 118 # Wait a moment for completed and now-detached inferior process to 119 # clear. 120 time.sleep(1) 121 122 if not lldb.remote_platform: 123 # Process should be dead now. Reap results. 124 poll_result = procs["inferior"].poll() 125 self.assertIsNotNone(poll_result) 126 127 # Where possible, verify at the system level that the process is not 128 # running. 129 self.assertFalse( 130 lldbgdbserverutils.process_is_running(procs["inferior"].pid, False) 131 ) 132 133 def test_qRegisterInfo_returns_one_valid_result(self): 134 self.build() 135 self.prep_debug_monitor_and_inferior() 136 self.test_sequence.add_log_lines( 137 [ 138 "read packet: $qRegisterInfo0#00", 139 { 140 "direction": "send", 141 "regex": r"^\$(.+);#[0-9A-Fa-f]{2}", 142 "capture": {1: "reginfo_0"}, 143 }, 144 ], 145 True, 146 ) 147 148 # Run the stream 149 context = self.expect_gdbremote_sequence() 150 self.assertIsNotNone(context) 151 152 reg_info_packet = context.get("reginfo_0") 153 self.assertIsNotNone(reg_info_packet) 154 self.assert_valid_reg_info( 155 lldbgdbserverutils.parse_reg_info_response(reg_info_packet) 156 ) 157 158 def test_qRegisterInfo_returns_all_valid_results(self): 159 self.build() 160 self.prep_debug_monitor_and_inferior() 161 self.add_register_info_collection_packets() 162 163 # Run the stream. 164 context = self.expect_gdbremote_sequence() 165 self.assertIsNotNone(context) 166 167 # Validate that each register info returned validates. 168 for reg_info in self.parse_register_info_packets(context): 169 self.assert_valid_reg_info(reg_info) 170 171 def test_qRegisterInfo_contains_required_generics_debugserver(self): 172 self.build() 173 self.prep_debug_monitor_and_inferior() 174 self.add_register_info_collection_packets() 175 176 # Run the packet stream. 177 context = self.expect_gdbremote_sequence() 178 self.assertIsNotNone(context) 179 180 # Gather register info entries. 181 reg_infos = self.parse_register_info_packets(context) 182 183 # Collect all generic registers found. 184 generic_regs = { 185 reg_info["generic"]: 1 for reg_info in reg_infos if "generic" in reg_info 186 } 187 188 # Ensure we have a program counter register. 189 self.assertIn("pc", generic_regs) 190 191 # Ensure we have a frame pointer register. PPC64le's FP is the same as SP 192 if self.getArchitecture() != "powerpc64le": 193 self.assertIn("fp", generic_regs) 194 195 # Ensure we have a stack pointer register. 196 self.assertIn("sp", generic_regs) 197 198 # Ensure we have a flags register. 199 self.assertIn("flags", generic_regs) 200 201 def test_qRegisterInfo_contains_at_least_one_register_set(self): 202 self.build() 203 self.prep_debug_monitor_and_inferior() 204 self.add_register_info_collection_packets() 205 206 # Run the packet stream. 207 context = self.expect_gdbremote_sequence() 208 self.assertIsNotNone(context) 209 210 # Gather register info entries. 211 reg_infos = self.parse_register_info_packets(context) 212 213 # Collect all register sets found. 214 register_sets = { 215 reg_info["set"]: 1 for reg_info in reg_infos if "set" in reg_info 216 } 217 self.assertGreaterEqual(len(register_sets), 1) 218 219 def targetHasAVX(self): 220 triple = self.dbg.GetSelectedPlatform().GetTriple() 221 222 # TODO other platforms, please implement this function 223 if not re.match(".*-.*-linux", triple): 224 return True 225 226 # Need to do something different for non-Linux/Android targets 227 if lldb.remote_platform: 228 self.runCmd('platform get-file "/proc/cpuinfo" "cpuinfo"') 229 cpuinfo_path = "cpuinfo" 230 self.addTearDownHook(lambda: os.unlink("cpuinfo")) 231 else: 232 cpuinfo_path = "/proc/cpuinfo" 233 234 f = open(cpuinfo_path, "r") 235 cpuinfo = f.read() 236 f.close() 237 return " avx " in cpuinfo 238 239 @expectedFailureAll(oslist=["windows"]) # no avx for now. 240 @skipIf(archs=no_match(["amd64", "i386", "x86_64"])) 241 @add_test_categories(["llgs"]) 242 def test_qRegisterInfo_contains_avx_registers(self): 243 self.build() 244 self.prep_debug_monitor_and_inferior() 245 self.add_register_info_collection_packets() 246 247 # Run the packet stream. 248 context = self.expect_gdbremote_sequence() 249 self.assertIsNotNone(context) 250 251 # Gather register info entries. 252 reg_infos = self.parse_register_info_packets(context) 253 254 # Collect all generics found. 255 register_sets = { 256 reg_info["set"]: 1 for reg_info in reg_infos if "set" in reg_info 257 } 258 self.assertEqual( 259 self.targetHasAVX(), "Advanced Vector Extensions" in register_sets 260 ) 261 262 def qThreadInfo_contains_thread(self): 263 procs = self.prep_debug_monitor_and_inferior() 264 self.add_threadinfo_collection_packets() 265 266 # Run the packet stream. 267 context = self.expect_gdbremote_sequence() 268 self.assertIsNotNone(context) 269 270 # Gather threadinfo entries. 271 threads = self.parse_threadinfo_packets(context) 272 self.assertIsNotNone(threads) 273 274 # We should have exactly one thread. 275 self.assertEqual(len(threads), 1) 276 277 def test_qThreadInfo_contains_thread_launch(self): 278 self.build() 279 self.set_inferior_startup_launch() 280 self.qThreadInfo_contains_thread() 281 282 @expectedFailureAll(oslist=["windows"]) # expect one more thread stopped 283 def test_qThreadInfo_contains_thread_attach(self): 284 self.build() 285 self.set_inferior_startup_attach() 286 self.qThreadInfo_contains_thread() 287 288 def qThreadInfo_matches_qC(self): 289 procs = self.prep_debug_monitor_and_inferior() 290 291 self.add_threadinfo_collection_packets() 292 self.test_sequence.add_log_lines( 293 [ 294 "read packet: $qC#00", 295 { 296 "direction": "send", 297 "regex": r"^\$QC([0-9a-fA-F]+)#", 298 "capture": {1: "thread_id"}, 299 }, 300 ], 301 True, 302 ) 303 304 # Run the packet stream. 305 context = self.expect_gdbremote_sequence() 306 self.assertIsNotNone(context) 307 308 # Gather threadinfo entries. 309 threads = self.parse_threadinfo_packets(context) 310 self.assertIsNotNone(threads) 311 312 # We should have exactly one thread from threadinfo. 313 self.assertEqual(len(threads), 1) 314 315 # We should have a valid thread_id from $QC. 316 QC_thread_id_hex = context.get("thread_id") 317 self.assertIsNotNone(QC_thread_id_hex) 318 QC_thread_id = int(QC_thread_id_hex, 16) 319 320 # Those two should be the same. 321 self.assertEqual(threads[0], QC_thread_id) 322 323 def test_qThreadInfo_matches_qC_launch(self): 324 self.build() 325 self.set_inferior_startup_launch() 326 self.qThreadInfo_matches_qC() 327 328 @expectedFailureAll(oslist=["windows"]) # expect one more thread stopped 329 def test_qThreadInfo_matches_qC_attach(self): 330 self.build() 331 self.set_inferior_startup_attach() 332 self.qThreadInfo_matches_qC() 333 334 def test_p_returns_correct_data_size_for_each_qRegisterInfo_launch(self): 335 self.build() 336 self.set_inferior_startup_launch() 337 procs = self.prep_debug_monitor_and_inferior() 338 self.add_register_info_collection_packets() 339 340 # Run the packet stream. 341 context = self.expect_gdbremote_sequence() 342 self.assertIsNotNone(context) 343 344 # Gather register info entries. 345 reg_infos = self.parse_register_info_packets(context) 346 self.assertIsNotNone(reg_infos) 347 self.assertGreater(len(reg_infos), 0) 348 349 byte_order = self.get_target_byte_order() 350 351 # Read value for each register. 352 reg_index = 0 353 for reg_info in reg_infos: 354 # Skip registers that don't have a register set. For x86, these are 355 # the DRx registers, which have no LLDB-kind register number and thus 356 # cannot be read via normal 357 # NativeRegisterContext::ReadRegister(reg_info,...) calls. 358 if not "set" in reg_info: 359 continue 360 361 # Clear existing packet expectations. 362 self.reset_test_sequence() 363 364 # Run the register query 365 self.test_sequence.add_log_lines( 366 [ 367 "read packet: $p{0:x}#00".format(reg_index), 368 { 369 "direction": "send", 370 "regex": r"^\$([0-9a-fA-F]+)#", 371 "capture": {1: "p_response"}, 372 }, 373 ], 374 True, 375 ) 376 context = self.expect_gdbremote_sequence() 377 self.assertIsNotNone(context) 378 379 # Verify the response length. 380 p_response = context.get("p_response") 381 self.assertIsNotNone(p_response) 382 383 # Skip erraneous (unsupported) registers. 384 # TODO: remove this once we make unsupported registers disappear. 385 if p_response.startswith("E") and len(p_response) == 3: 386 continue 387 388 if "dynamic_size_dwarf_expr_bytes" in reg_info: 389 self.updateRegInfoBitsize(reg_info, byte_order) 390 self.assertEqual( 391 len(p_response), 2 * int(reg_info["bitsize"]) / 8, reg_info 392 ) 393 394 # Increment loop 395 reg_index += 1 396 397 def Hg_switches_to_3_threads(self, pass_pid=False): 398 _, threads = self.launch_with_threads(3) 399 400 pid_str = "" 401 if pass_pid: 402 pid_str = "p{0:x}.".format(procs["inferior"].pid) 403 404 # verify we can $H to each thead, and $qC matches the thread we set. 405 for thread in threads: 406 # Change to each thread, verify current thread id. 407 self.reset_test_sequence() 408 self.test_sequence.add_log_lines( 409 [ 410 "read packet: $Hg{0}{1:x}#00".format( 411 pid_str, thread 412 ), # Set current thread. 413 "send packet: $OK#00", 414 "read packet: $qC#00", 415 { 416 "direction": "send", 417 "regex": r"^\$QC([0-9a-fA-F]+)#", 418 "capture": {1: "thread_id"}, 419 }, 420 ], 421 True, 422 ) 423 424 context = self.expect_gdbremote_sequence() 425 self.assertIsNotNone(context) 426 427 # Verify the thread id. 428 self.assertIsNotNone(context.get("thread_id")) 429 self.assertEqual(int(context.get("thread_id"), 16), thread) 430 431 @skipIf(compiler="clang", compiler_version=["<", "11.0"]) 432 def test_Hg_switches_to_3_threads_launch(self): 433 self.build() 434 self.set_inferior_startup_launch() 435 self.Hg_switches_to_3_threads() 436 437 def Hg_fails_on_pid(self, pass_pid): 438 _, threads = self.launch_with_threads(2) 439 440 if pass_pid == -1: 441 pid_str = "p-1." 442 else: 443 pid_str = "p{0:x}.".format(pass_pid) 444 thread = threads[1] 445 446 self.test_sequence.add_log_lines( 447 [ 448 "read packet: $Hg{0}{1:x}#00".format( 449 pid_str, thread 450 ), # Set current thread. 451 "send packet: $Eff#00", 452 ], 453 True, 454 ) 455 456 self.expect_gdbremote_sequence() 457 458 @add_test_categories(["llgs"]) 459 def test_Hg_fails_on_another_pid(self): 460 self.build() 461 self.set_inferior_startup_launch() 462 self.Hg_fails_on_pid(1) 463 464 @add_test_categories(["llgs"]) 465 def test_Hg_fails_on_zero_pid(self): 466 self.build() 467 self.set_inferior_startup_launch() 468 self.Hg_fails_on_pid(0) 469 470 @add_test_categories(["llgs"]) 471 @skipIfWindows # Sometimes returns '$E37'. 472 def test_Hg_fails_on_minus_one_pid(self): 473 self.build() 474 self.set_inferior_startup_launch() 475 self.Hg_fails_on_pid(-1) 476 477 def Hc_then_Csignal_signals_correct_thread(self, segfault_signo): 478 # NOTE only run this one in inferior-launched mode: we can't grab inferior stdout when running attached, 479 # and the test requires getting stdout from the exe. 480 481 NUM_THREADS = 3 482 483 # Startup the inferior with three threads (main + NUM_THREADS-1 worker threads). 484 # inferior_args=["thread:print-ids"] 485 inferior_args = ["thread:segfault"] 486 for i in range(NUM_THREADS - 1): 487 # if i > 0: 488 # Give time between thread creation/segfaulting for the handler to work. 489 # inferior_args.append("sleep:1") 490 inferior_args.append("thread:new") 491 inferior_args.append("sleep:10") 492 493 # Launch/attach. (In our case, this should only ever be launched since 494 # we need inferior stdout/stderr). 495 procs = self.prep_debug_monitor_and_inferior(inferior_args=inferior_args) 496 self.test_sequence.add_log_lines(["read packet: $c#63"], True) 497 context = self.expect_gdbremote_sequence() 498 499 signaled_tids = {} 500 print_thread_ids = {} 501 502 # Switch to each thread, deliver a signal, and verify signal delivery 503 for i in range(NUM_THREADS - 1): 504 # Run until SIGSEGV comes in. 505 self.reset_test_sequence() 506 self.test_sequence.add_log_lines( 507 [ 508 { 509 "direction": "send", 510 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 511 "capture": {1: "signo", 2: "thread_id"}, 512 } 513 ], 514 True, 515 ) 516 517 context = self.expect_gdbremote_sequence() 518 self.assertIsNotNone(context) 519 signo = context.get("signo") 520 self.assertEqual(int(signo, 16), segfault_signo) 521 522 # Ensure we haven't seen this tid yet. 523 thread_id = int(context.get("thread_id"), 16) 524 self.assertNotIn(thread_id, signaled_tids) 525 signaled_tids[thread_id] = 1 526 527 # Send SIGUSR1 to the thread that signaled the SIGSEGV. 528 self.reset_test_sequence() 529 self.test_sequence.add_log_lines( 530 [ 531 # Set the continue thread. 532 # Set current thread. 533 "read packet: $Hc{0:x}#00".format(thread_id), 534 "send packet: $OK#00", 535 # Continue sending the signal number to the continue thread. 536 # The commented out packet is a way to do this same operation without using 537 # a $Hc (but this test is testing $Hc, so we'll stick with the former). 538 "read packet: $C{0:x}#00".format( 539 lldbutil.get_signal_number("SIGUSR1") 540 ), 541 # "read packet: $vCont;C{0:x}:{1:x};c#00".format(lldbutil.get_signal_number('SIGUSR1'), thread_id), 542 # FIXME: Linux does not report the thread stop on the delivered signal (SIGUSR1 here). MacOSX debugserver does. 543 # But MacOSX debugserver isn't guaranteeing the thread the signal handler runs on, so currently its an XFAIL. 544 # Need to rectify behavior here. The linux behavior is more intuitive to me since we're essentially swapping out 545 # an about-to-be-delivered signal (for which we already sent a stop packet) to a different signal. 546 # {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} }, 547 # "read packet: $c#63", 548 { 549 "type": "output_match", 550 "regex": r"^received SIGUSR1 on thread id: ([0-9a-fA-F]+)\r\nthread ([0-9a-fA-F]+): past SIGSEGV\r\n", 551 "capture": {1: "print_thread_id", 2: "post_handle_thread_id"}, 552 }, 553 ], 554 True, 555 ) 556 557 # Run the sequence. 558 context = self.expect_gdbremote_sequence() 559 self.assertIsNotNone(context) 560 561 # Ensure the stop signal is the signal we delivered. 562 # stop_signo = context.get("stop_signo") 563 # self.assertIsNotNone(stop_signo) 564 # self.assertEqual(int(stop_signo,16), lldbutil.get_signal_number('SIGUSR1')) 565 566 # Ensure the stop thread is the thread to which we delivered the signal. 567 # stop_thread_id = context.get("stop_thread_id") 568 # self.assertIsNotNone(stop_thread_id) 569 # self.assertEqual(int(stop_thread_id,16), thread_id) 570 571 # Ensure we haven't seen this thread id yet. The inferior's 572 # self-obtained thread ids are not guaranteed to match the stub 573 # tids (at least on MacOSX). 574 print_thread_id = context.get("print_thread_id") 575 self.assertIsNotNone(print_thread_id) 576 print_thread_id = int(print_thread_id, 16) 577 self.assertNotIn(print_thread_id, print_thread_ids) 578 579 # Now remember this print (i.e. inferior-reflected) thread id and 580 # ensure we don't hit it again. 581 print_thread_ids[print_thread_id] = 1 582 583 # Ensure post signal-handle thread id matches the thread that 584 # initially raised the SIGSEGV. 585 post_handle_thread_id = context.get("post_handle_thread_id") 586 self.assertIsNotNone(post_handle_thread_id) 587 post_handle_thread_id = int(post_handle_thread_id, 16) 588 self.assertEqual(post_handle_thread_id, print_thread_id) 589 590 @expectedFailureDarwin 591 @skipIfWindows # no SIGSEGV support 592 @expectedFailureNetBSD 593 def test_Hc_then_Csignal_signals_correct_thread_launch(self): 594 self.build() 595 self.set_inferior_startup_launch() 596 597 if self.platformIsDarwin(): 598 # Darwin debugserver translates some signals like SIGSEGV into some gdb 599 # expectations about fixed signal numbers. 600 self.Hc_then_Csignal_signals_correct_thread(self.TARGET_EXC_BAD_ACCESS) 601 else: 602 self.Hc_then_Csignal_signals_correct_thread( 603 lldbutil.get_signal_number("SIGSEGV") 604 ) 605 606 @skipIfWindows # No pty support to test any inferior output 607 def test_m_packet_reads_memory(self): 608 self.build() 609 self.set_inferior_startup_launch() 610 # This is the memory we will write into the inferior and then ensure we 611 # can read back with $m. 612 MEMORY_CONTENTS = "Test contents 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz" 613 614 # Start up the inferior. 615 procs = self.prep_debug_monitor_and_inferior( 616 inferior_args=[ 617 "set-message:%s" % MEMORY_CONTENTS, 618 "get-data-address-hex:g_message", 619 "sleep:5", 620 ] 621 ) 622 623 # Run the process 624 self.test_sequence.add_log_lines( 625 [ 626 # Start running after initial stop. 627 "read packet: $c#63", 628 # Match output line that prints the memory address of the message buffer within the inferior. 629 # Note we require launch-only testing so we can get inferior otuput. 630 { 631 "type": "output_match", 632 "regex": self.maybe_strict_output_regex( 633 r"data address: 0x([0-9a-fA-F]+)\r\n" 634 ), 635 "capture": {1: "message_address"}, 636 }, 637 # Now stop the inferior. 638 "read packet: {}".format(chr(3)), 639 # And wait for the stop notification. 640 { 641 "direction": "send", 642 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 643 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 644 }, 645 ], 646 True, 647 ) 648 649 # Run the packet stream. 650 context = self.expect_gdbremote_sequence() 651 self.assertIsNotNone(context) 652 653 # Grab the message address. 654 self.assertIsNotNone(context.get("message_address")) 655 message_address = int(context.get("message_address"), 16) 656 657 # Grab contents from the inferior. 658 self.reset_test_sequence() 659 self.test_sequence.add_log_lines( 660 [ 661 "read packet: $m{0:x},{1:x}#00".format( 662 message_address, len(MEMORY_CONTENTS) 663 ), 664 { 665 "direction": "send", 666 "regex": r"^\$(.+)#[0-9a-fA-F]{2}$", 667 "capture": {1: "read_contents"}, 668 }, 669 ], 670 True, 671 ) 672 673 # Run the packet stream. 674 context = self.expect_gdbremote_sequence() 675 self.assertIsNotNone(context) 676 677 # Ensure what we read from inferior memory is what we wrote. 678 self.assertIsNotNone(context.get("read_contents")) 679 read_contents = seven.unhexlify(context.get("read_contents")) 680 self.assertEqual(read_contents, MEMORY_CONTENTS) 681 682 def test_qMemoryRegionInfo_is_supported(self): 683 self.build() 684 self.set_inferior_startup_launch() 685 # Start up the inferior. 686 procs = self.prep_debug_monitor_and_inferior() 687 688 # Ask if it supports $qMemoryRegionInfo. 689 self.test_sequence.add_log_lines( 690 ["read packet: $qMemoryRegionInfo#00", "send packet: $OK#00"], True 691 ) 692 self.expect_gdbremote_sequence() 693 694 @skipIfWindows # No pty support to test any inferior output 695 def test_qMemoryRegionInfo_reports_code_address_as_executable(self): 696 self.build() 697 self.set_inferior_startup_launch() 698 699 # Start up the inferior. 700 procs = self.prep_debug_monitor_and_inferior( 701 inferior_args=["get-code-address-hex:hello", "sleep:5"] 702 ) 703 704 # Run the process 705 self.test_sequence.add_log_lines( 706 [ 707 # Start running after initial stop. 708 "read packet: $c#63", 709 # Match output line that prints the memory address of the message buffer within the inferior. 710 # Note we require launch-only testing so we can get inferior otuput. 711 { 712 "type": "output_match", 713 "regex": self.maybe_strict_output_regex( 714 r"code address: 0x([0-9a-fA-F]+)\r\n" 715 ), 716 "capture": {1: "code_address"}, 717 }, 718 # Now stop the inferior. 719 "read packet: {}".format(chr(3)), 720 # And wait for the stop notification. 721 { 722 "direction": "send", 723 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 724 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 725 }, 726 ], 727 True, 728 ) 729 730 # Run the packet stream. 731 context = self.expect_gdbremote_sequence() 732 self.assertIsNotNone(context) 733 734 # Grab the code address. 735 self.assertIsNotNone(context.get("code_address")) 736 code_address = int(context.get("code_address"), 16) 737 738 # Grab memory region info from the inferior. 739 self.reset_test_sequence() 740 self.add_query_memory_region_packets(code_address) 741 742 # Run the packet stream. 743 context = self.expect_gdbremote_sequence() 744 self.assertIsNotNone(context) 745 mem_region_dict = self.parse_memory_region_packet(context) 746 747 # Ensure there are no errors reported. 748 self.assertNotIn("error", mem_region_dict) 749 750 # Ensure code address is readable and executable. 751 self.assertIn("permissions", mem_region_dict) 752 self.assertIn("r", mem_region_dict["permissions"]) 753 self.assertIn("x", mem_region_dict["permissions"]) 754 755 # Ensure the start address and size encompass the address we queried. 756 self.assert_address_within_memory_region(code_address, mem_region_dict) 757 758 @skipIfWindows # No pty support to test any inferior output 759 def test_qMemoryRegionInfo_reports_stack_address_as_rw(self): 760 self.build() 761 self.set_inferior_startup_launch() 762 763 # Start up the inferior. 764 procs = self.prep_debug_monitor_and_inferior( 765 inferior_args=["get-stack-address-hex:", "sleep:5"] 766 ) 767 768 # Run the process 769 self.test_sequence.add_log_lines( 770 [ 771 # Start running after initial stop. 772 "read packet: $c#63", 773 # Match output line that prints the memory address of the message buffer within the inferior. 774 # Note we require launch-only testing so we can get inferior otuput. 775 { 776 "type": "output_match", 777 "regex": self.maybe_strict_output_regex( 778 r"stack address: 0x([0-9a-fA-F]+)\r\n" 779 ), 780 "capture": {1: "stack_address"}, 781 }, 782 # Now stop the inferior. 783 "read packet: {}".format(chr(3)), 784 # And wait for the stop notification. 785 { 786 "direction": "send", 787 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 788 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 789 }, 790 ], 791 True, 792 ) 793 794 # Run the packet stream. 795 context = self.expect_gdbremote_sequence() 796 self.assertIsNotNone(context) 797 798 # Grab the address. 799 self.assertIsNotNone(context.get("stack_address")) 800 stack_address = int(context.get("stack_address"), 16) 801 802 # Grab memory region info from the inferior. 803 self.reset_test_sequence() 804 self.add_query_memory_region_packets(stack_address) 805 806 # Run the packet stream. 807 context = self.expect_gdbremote_sequence() 808 self.assertIsNotNone(context) 809 mem_region_dict = self.parse_memory_region_packet(context) 810 811 # Ensure there are no errors reported. 812 self.assertNotIn("error", mem_region_dict) 813 814 # Ensure address is readable and executable. 815 self.assertIn("permissions", mem_region_dict) 816 self.assertIn("r", mem_region_dict["permissions"]) 817 self.assertIn("w", mem_region_dict["permissions"]) 818 819 # Ensure the start address and size encompass the address we queried. 820 self.assert_address_within_memory_region(stack_address, mem_region_dict) 821 822 @skipIfWindows # No pty support to test any inferior output 823 def test_qMemoryRegionInfo_reports_heap_address_as_rw(self): 824 self.build() 825 self.set_inferior_startup_launch() 826 827 # Start up the inferior. 828 procs = self.prep_debug_monitor_and_inferior( 829 inferior_args=["get-heap-address-hex:", "sleep:5"] 830 ) 831 832 # Run the process 833 self.test_sequence.add_log_lines( 834 [ 835 # Start running after initial stop. 836 "read packet: $c#63", 837 # Match output line that prints the memory address of the message buffer within the inferior. 838 # Note we require launch-only testing so we can get inferior otuput. 839 { 840 "type": "output_match", 841 "regex": self.maybe_strict_output_regex( 842 r"heap address: 0x([0-9a-fA-F]+)\r\n" 843 ), 844 "capture": {1: "heap_address"}, 845 }, 846 # Now stop the inferior. 847 "read packet: {}".format(chr(3)), 848 # And wait for the stop notification. 849 { 850 "direction": "send", 851 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 852 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 853 }, 854 ], 855 True, 856 ) 857 858 # Run the packet stream. 859 context = self.expect_gdbremote_sequence() 860 self.assertIsNotNone(context) 861 862 # Grab the address. 863 self.assertIsNotNone(context.get("heap_address")) 864 heap_address = int(context.get("heap_address"), 16) 865 866 # Grab memory region info from the inferior. 867 self.reset_test_sequence() 868 self.add_query_memory_region_packets(heap_address) 869 870 # Run the packet stream. 871 context = self.expect_gdbremote_sequence() 872 self.assertIsNotNone(context) 873 mem_region_dict = self.parse_memory_region_packet(context) 874 875 # Ensure there are no errors reported. 876 self.assertNotIn("error", mem_region_dict) 877 878 # Ensure address is readable and executable. 879 self.assertIn("permissions", mem_region_dict) 880 self.assertIn("r", mem_region_dict["permissions"]) 881 self.assertIn("w", mem_region_dict["permissions"]) 882 883 # Ensure the start address and size encompass the address we queried. 884 self.assert_address_within_memory_region(heap_address, mem_region_dict) 885 886 def breakpoint_set_and_remove_work(self, want_hardware): 887 # Start up the inferior. 888 procs = self.prep_debug_monitor_and_inferior( 889 inferior_args=[ 890 "get-code-address-hex:hello", 891 "sleep:1", 892 "call-function:hello", 893 ] 894 ) 895 896 # Run the process 897 self.add_register_info_collection_packets() 898 self.add_process_info_collection_packets() 899 self.test_sequence.add_log_lines( 900 [ # Start running after initial stop. 901 "read packet: $c#63", 902 # Match output line that prints the memory address of the function call entry point. 903 # Note we require launch-only testing so we can get inferior otuput. 904 { 905 "type": "output_match", 906 "regex": self.maybe_strict_output_regex( 907 r"code address: 0x([0-9a-fA-F]+)\r\n" 908 ), 909 "capture": {1: "function_address"}, 910 }, 911 # Now stop the inferior. 912 "read packet: {}".format(chr(3)), 913 # And wait for the stop notification. 914 { 915 "direction": "send", 916 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 917 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 918 }, 919 ], 920 True, 921 ) 922 923 # Run the packet stream. 924 context = self.expect_gdbremote_sequence() 925 self.assertIsNotNone(context) 926 927 # Gather process info - we need endian of target to handle register 928 # value conversions. 929 process_info = self.parse_process_info_response(context) 930 endian = process_info.get("endian") 931 self.assertIsNotNone(endian) 932 933 # Gather register info entries. 934 reg_infos = self.parse_register_info_packets(context) 935 (pc_lldb_reg_index, pc_reg_info) = self.find_pc_reg_info(reg_infos) 936 self.assertIsNotNone(pc_lldb_reg_index) 937 self.assertIsNotNone(pc_reg_info) 938 939 # Grab the function address. 940 self.assertIsNotNone(context.get("function_address")) 941 function_address = int(context.get("function_address"), 16) 942 943 # Get current target architecture 944 target_arch = self.getArchitecture() 945 946 # Set the breakpoint. 947 if target_arch in ["arm", "arm64", "aarch64"]: 948 # TODO: Handle case when setting breakpoint in thumb code 949 BREAKPOINT_KIND = 4 950 else: 951 BREAKPOINT_KIND = 1 952 953 # Set default packet type to Z0 (software breakpoint) 954 z_packet_type = 0 955 956 # If hardware breakpoint is requested set packet type to Z1 957 if want_hardware: 958 z_packet_type = 1 959 960 self.reset_test_sequence() 961 self.add_set_breakpoint_packets( 962 function_address, 963 z_packet_type, 964 do_continue=True, 965 breakpoint_kind=BREAKPOINT_KIND, 966 ) 967 968 # Run the packet stream. 969 context = self.expect_gdbremote_sequence() 970 self.assertIsNotNone(context) 971 972 # Verify the stop signal reported was the breakpoint signal number. 973 stop_signo = context.get("stop_signo") 974 self.assertIsNotNone(stop_signo) 975 self.assertEqual(int(stop_signo, 16), lldbutil.get_signal_number("SIGTRAP")) 976 977 # Ensure we did not receive any output. If the breakpoint was not set, we would 978 # see output (from a launched process with captured stdio) printing a hello, world message. 979 # That would indicate the breakpoint didn't take. 980 self.assertEqual(len(context["O_content"]), 0) 981 982 # Verify that the PC for the main thread is where we expect it - right at the breakpoint address. 983 # This acts as a another validation on the register reading code. 984 self.reset_test_sequence() 985 self.test_sequence.add_log_lines( 986 [ 987 # Print the PC. This should match the breakpoint address. 988 "read packet: $p{0:x}#00".format(pc_lldb_reg_index), 989 # Capture $p results. 990 { 991 "direction": "send", 992 "regex": r"^\$([0-9a-fA-F]+)#", 993 "capture": {1: "p_response"}, 994 }, 995 ], 996 True, 997 ) 998 999 context = self.expect_gdbremote_sequence() 1000 self.assertIsNotNone(context) 1001 1002 # Verify the PC is where we expect. Note response is in endianness of 1003 # the inferior. 1004 p_response = context.get("p_response") 1005 self.assertIsNotNone(p_response) 1006 1007 # Convert from target endian to int. 1008 returned_pc = lldbgdbserverutils.unpack_register_hex_unsigned( 1009 endian, p_response 1010 ) 1011 self.assertEqual(returned_pc, function_address) 1012 1013 # Verify that a breakpoint remove and continue gets us the expected 1014 # output. 1015 self.reset_test_sequence() 1016 1017 # Add breakpoint remove packets 1018 self.add_remove_breakpoint_packets( 1019 function_address, z_packet_type, breakpoint_kind=BREAKPOINT_KIND 1020 ) 1021 1022 self.test_sequence.add_log_lines( 1023 [ 1024 # Continue running. 1025 "read packet: $c#63", 1026 # We should now receive the output from the call. 1027 {"type": "output_match", "regex": r"^hello, world\r\n$"}, 1028 # And wait for program completion. 1029 {"direction": "send", "regex": r"^\$W00(.*)#[0-9a-fA-F]{2}$"}, 1030 ], 1031 True, 1032 ) 1033 1034 context = self.expect_gdbremote_sequence() 1035 self.assertIsNotNone(context) 1036 1037 @skipIfWindows # No pty support to test any inferior output 1038 def test_software_breakpoint_set_and_remove_work(self): 1039 if self.getArchitecture() == "arm": 1040 # TODO: Handle case when setting breakpoint in thumb code 1041 self.build(dictionary={"CFLAGS_EXTRAS": "-marm"}) 1042 else: 1043 self.build() 1044 self.set_inferior_startup_launch() 1045 self.breakpoint_set_and_remove_work(want_hardware=False) 1046 1047 @skipUnlessPlatform(oslist=["linux"]) 1048 @skipIf(archs=no_match(["arm", "aarch64"])) 1049 def test_hardware_breakpoint_set_and_remove_work(self): 1050 if self.getArchitecture() == "arm": 1051 # TODO: Handle case when setting breakpoint in thumb code 1052 self.build(dictionary={"CFLAGS_EXTRAS": "-marm"}) 1053 else: 1054 self.build() 1055 self.set_inferior_startup_launch() 1056 self.breakpoint_set_and_remove_work(want_hardware=True) 1057 1058 def get_qSupported_dict(self, features=[]): 1059 self.build() 1060 self.set_inferior_startup_launch() 1061 1062 # Start up the stub and start/prep the inferior. 1063 procs = self.prep_debug_monitor_and_inferior() 1064 self.add_qSupported_packets(features) 1065 1066 # Run the packet stream. 1067 context = self.expect_gdbremote_sequence() 1068 self.assertIsNotNone(context) 1069 1070 # Retrieve the qSupported features. 1071 return self.parse_qSupported_response(context) 1072 1073 def test_qSupported_returns_known_stub_features(self): 1074 supported_dict = self.get_qSupported_dict() 1075 self.assertIsNotNone(supported_dict) 1076 self.assertGreater(len(supported_dict), 0) 1077 1078 def test_qSupported_auvx(self): 1079 expected = ( 1080 "+" 1081 if lldbplatformutil.getPlatform() in ["freebsd", "linux", "netbsd"] 1082 else "-" 1083 ) 1084 supported_dict = self.get_qSupported_dict() 1085 self.assertEqual(supported_dict.get("qXfer:auxv:read", "-"), expected) 1086 1087 def test_qSupported_libraries_svr4(self): 1088 expected = ( 1089 "+" 1090 if lldbplatformutil.getPlatform() in ["freebsd", "linux", "netbsd"] 1091 else "-" 1092 ) 1093 supported_dict = self.get_qSupported_dict() 1094 self.assertEqual(supported_dict.get("qXfer:libraries-svr4:read", "-"), expected) 1095 1096 def test_qSupported_siginfo_read(self): 1097 expected = ( 1098 "+" if lldbplatformutil.getPlatform() in ["freebsd", "linux"] else "-" 1099 ) 1100 supported_dict = self.get_qSupported_dict() 1101 self.assertEqual(supported_dict.get("qXfer:siginfo:read", "-"), expected) 1102 1103 def test_qSupported_QPassSignals(self): 1104 expected = ( 1105 "+" 1106 if lldbplatformutil.getPlatform() in ["freebsd", "linux", "netbsd"] 1107 else "-" 1108 ) 1109 supported_dict = self.get_qSupported_dict() 1110 self.assertEqual(supported_dict.get("QPassSignals", "-"), expected) 1111 1112 @add_test_categories(["fork"]) 1113 def test_qSupported_fork_events(self): 1114 supported_dict = self.get_qSupported_dict(["multiprocess+", "fork-events+"]) 1115 self.assertEqual(supported_dict.get("multiprocess", "-"), "+") 1116 self.assertEqual(supported_dict.get("fork-events", "-"), "+") 1117 self.assertEqual(supported_dict.get("vfork-events", "-"), "-") 1118 1119 @add_test_categories(["fork"]) 1120 def test_qSupported_fork_events_without_multiprocess(self): 1121 supported_dict = self.get_qSupported_dict(["fork-events+"]) 1122 self.assertEqual(supported_dict.get("multiprocess", "-"), "-") 1123 self.assertEqual(supported_dict.get("fork-events", "-"), "-") 1124 self.assertEqual(supported_dict.get("vfork-events", "-"), "-") 1125 1126 @add_test_categories(["fork"]) 1127 def test_qSupported_vfork_events(self): 1128 supported_dict = self.get_qSupported_dict(["multiprocess+", "vfork-events+"]) 1129 self.assertEqual(supported_dict.get("multiprocess", "-"), "+") 1130 self.assertEqual(supported_dict.get("fork-events", "-"), "-") 1131 self.assertEqual(supported_dict.get("vfork-events", "-"), "+") 1132 1133 @add_test_categories(["fork"]) 1134 def test_qSupported_vfork_events_without_multiprocess(self): 1135 supported_dict = self.get_qSupported_dict(["vfork-events+"]) 1136 self.assertEqual(supported_dict.get("multiprocess", "-"), "-") 1137 self.assertEqual(supported_dict.get("fork-events", "-"), "-") 1138 self.assertEqual(supported_dict.get("vfork-events", "-"), "-") 1139 1140 # We need to be able to self.runCmd to get cpuinfo, 1141 # which is not possible when using a remote platform. 1142 @skipIfRemote 1143 def test_qSupported_memory_tagging(self): 1144 supported_dict = self.get_qSupported_dict() 1145 self.assertEqual( 1146 supported_dict.get("memory-tagging", "-"), 1147 "+" if self.isAArch64MTE() else "-", 1148 ) 1149 1150 @skipIfWindows # No pty support to test any inferior output 1151 def test_written_M_content_reads_back_correctly(self): 1152 self.build() 1153 self.set_inferior_startup_launch() 1154 1155 TEST_MESSAGE = "Hello, memory" 1156 1157 # Start up the stub and start/prep the inferior. 1158 procs = self.prep_debug_monitor_and_inferior( 1159 inferior_args=[ 1160 "set-message:xxxxxxxxxxxxxX", 1161 "get-data-address-hex:g_message", 1162 "sleep:1", 1163 "print-message:", 1164 ] 1165 ) 1166 self.test_sequence.add_log_lines( 1167 [ 1168 # Start running after initial stop. 1169 "read packet: $c#63", 1170 # Match output line that prints the memory address of the message buffer within the inferior. 1171 # Note we require launch-only testing so we can get inferior otuput. 1172 { 1173 "type": "output_match", 1174 "regex": self.maybe_strict_output_regex( 1175 r"data address: 0x([0-9a-fA-F]+)\r\n" 1176 ), 1177 "capture": {1: "message_address"}, 1178 }, 1179 # Now stop the inferior. 1180 "read packet: {}".format(chr(3)), 1181 # And wait for the stop notification. 1182 { 1183 "direction": "send", 1184 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 1185 "capture": {1: "stop_signo", 2: "stop_thread_id"}, 1186 }, 1187 ], 1188 True, 1189 ) 1190 context = self.expect_gdbremote_sequence() 1191 self.assertIsNotNone(context) 1192 1193 # Grab the message address. 1194 self.assertIsNotNone(context.get("message_address")) 1195 message_address = int(context.get("message_address"), 16) 1196 1197 # Hex-encode the test message, adding null termination. 1198 hex_encoded_message = seven.hexlify(TEST_MESSAGE) 1199 1200 # Write the message to the inferior. Verify that we can read it with the hex-encoded (m) 1201 # and binary (x) memory read packets. 1202 self.reset_test_sequence() 1203 self.test_sequence.add_log_lines( 1204 [ 1205 "read packet: $M{0:x},{1:x}:{2}#00".format( 1206 message_address, len(TEST_MESSAGE), hex_encoded_message 1207 ), 1208 "send packet: $OK#00", 1209 "read packet: $m{0:x},{1:x}#00".format( 1210 message_address, len(TEST_MESSAGE) 1211 ), 1212 "send packet: ${0}#00".format(hex_encoded_message), 1213 "read packet: $x{0:x},{1:x}#00".format( 1214 message_address, len(TEST_MESSAGE) 1215 ), 1216 "send packet: ${0}#00".format(TEST_MESSAGE), 1217 "read packet: $m{0:x},4#00".format(message_address), 1218 "send packet: ${0}#00".format(hex_encoded_message[0:8]), 1219 "read packet: $x{0:x},4#00".format(message_address), 1220 "send packet: ${0}#00".format(TEST_MESSAGE[0:4]), 1221 "read packet: $c#63", 1222 { 1223 "type": "output_match", 1224 "regex": r"^message: (.+)\r\n$", 1225 "capture": {1: "printed_message"}, 1226 }, 1227 "send packet: $W00#00", 1228 ], 1229 True, 1230 ) 1231 context = self.expect_gdbremote_sequence() 1232 self.assertIsNotNone(context) 1233 1234 # Ensure what we read from inferior memory is what we wrote. 1235 printed_message = context.get("printed_message") 1236 self.assertIsNotNone(printed_message) 1237 self.assertEqual(printed_message, TEST_MESSAGE + "X") 1238 1239 # Note: as of this moment, a hefty number of the GPR writes are failing with E32 (everything except rax-rdx, rdi, rsi, rbp). 1240 # Come back to this. I have the test rigged to verify that at least some 1241 # of the bit-flip writes work. 1242 def test_P_writes_all_gpr_registers(self): 1243 self.build() 1244 self.set_inferior_startup_launch() 1245 1246 # Start inferior debug session, grab all register info. 1247 procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:2"]) 1248 self.add_register_info_collection_packets() 1249 self.add_process_info_collection_packets() 1250 1251 context = self.expect_gdbremote_sequence() 1252 self.assertIsNotNone(context) 1253 1254 # Process register infos. 1255 reg_infos = self.parse_register_info_packets(context) 1256 self.assertIsNotNone(reg_infos) 1257 self.add_lldb_register_index(reg_infos) 1258 1259 # Process endian. 1260 process_info = self.parse_process_info_response(context) 1261 endian = process_info.get("endian") 1262 self.assertIsNotNone(endian) 1263 1264 # Pull out the register infos that we think we can bit flip 1265 # successfully,. 1266 gpr_reg_infos = [ 1267 reg_info 1268 for reg_info in reg_infos 1269 if self.is_bit_flippable_register(reg_info) 1270 ] 1271 self.assertGreater(len(gpr_reg_infos), 0) 1272 1273 # Write flipped bit pattern of existing value to each register. 1274 (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value( 1275 gpr_reg_infos, endian 1276 ) 1277 self.trace( 1278 "successful writes: {}, failed writes: {}".format( 1279 successful_writes, failed_writes 1280 ) 1281 ) 1282 self.assertGreater(successful_writes, 0) 1283 1284 # Note: as of this moment, a hefty number of the GPR writes are failing 1285 # with E32 (everything except rax-rdx, rdi, rsi, rbp). 1286 @skipIfWindows 1287 def test_P_and_p_thread_suffix_work(self): 1288 self.build() 1289 self.set_inferior_startup_launch() 1290 1291 # Startup the inferior with three threads. 1292 _, threads = self.launch_with_threads(3) 1293 1294 self.reset_test_sequence() 1295 self.add_thread_suffix_request_packets() 1296 self.add_register_info_collection_packets() 1297 self.add_process_info_collection_packets() 1298 1299 context = self.expect_gdbremote_sequence() 1300 self.assertIsNotNone(context) 1301 1302 process_info = self.parse_process_info_response(context) 1303 self.assertIsNotNone(process_info) 1304 endian = process_info.get("endian") 1305 self.assertIsNotNone(endian) 1306 1307 reg_infos = self.parse_register_info_packets(context) 1308 self.assertIsNotNone(reg_infos) 1309 self.add_lldb_register_index(reg_infos) 1310 1311 reg_index = self.select_modifiable_register(reg_infos) 1312 self.assertIsNotNone(reg_index) 1313 reg_byte_size = int(reg_infos[reg_index]["bitsize"]) // 8 1314 self.assertGreater(reg_byte_size, 0) 1315 1316 expected_reg_values = [] 1317 register_increment = 1 1318 next_value = None 1319 1320 # Set the same register in each of 3 threads to a different value. 1321 # Verify each one has the unique value. 1322 for thread in threads: 1323 # If we don't have a next value yet, start it with the initial read 1324 # value + 1 1325 if not next_value: 1326 # Read pre-existing register value. 1327 self.reset_test_sequence() 1328 self.test_sequence.add_log_lines( 1329 [ 1330 "read packet: $p{0:x};thread:{1:x}#00".format( 1331 reg_index, thread 1332 ), 1333 { 1334 "direction": "send", 1335 "regex": r"^\$([0-9a-fA-F]+)#", 1336 "capture": {1: "p_response"}, 1337 }, 1338 ], 1339 True, 1340 ) 1341 context = self.expect_gdbremote_sequence() 1342 self.assertIsNotNone(context) 1343 1344 # Set the next value to use for writing as the increment plus 1345 # current value. 1346 p_response = context.get("p_response") 1347 self.assertIsNotNone(p_response) 1348 next_value = lldbgdbserverutils.unpack_register_hex_unsigned( 1349 endian, p_response 1350 ) 1351 1352 # Set new value using P and thread suffix. 1353 self.reset_test_sequence() 1354 self.test_sequence.add_log_lines( 1355 [ 1356 "read packet: $P{0:x}={1};thread:{2:x}#00".format( 1357 reg_index, 1358 lldbgdbserverutils.pack_register_hex( 1359 endian, next_value, byte_size=reg_byte_size 1360 ), 1361 thread, 1362 ), 1363 "send packet: $OK#00", 1364 ], 1365 True, 1366 ) 1367 context = self.expect_gdbremote_sequence() 1368 self.assertIsNotNone(context) 1369 1370 # Save the value we set. 1371 expected_reg_values.append(next_value) 1372 1373 # Increment value for next thread to use (we want them all 1374 # different so we can verify they wrote to each thread correctly 1375 # next.) 1376 next_value += register_increment 1377 1378 # Revisit each thread and verify they have the expected value set for 1379 # the register we wrote. 1380 thread_index = 0 1381 for thread in threads: 1382 # Read pre-existing register value. 1383 self.reset_test_sequence() 1384 self.test_sequence.add_log_lines( 1385 [ 1386 "read packet: $p{0:x};thread:{1:x}#00".format(reg_index, thread), 1387 { 1388 "direction": "send", 1389 "regex": r"^\$([0-9a-fA-F]+)#", 1390 "capture": {1: "p_response"}, 1391 }, 1392 ], 1393 True, 1394 ) 1395 context = self.expect_gdbremote_sequence() 1396 self.assertIsNotNone(context) 1397 1398 # Get the register value. 1399 p_response = context.get("p_response") 1400 self.assertIsNotNone(p_response) 1401 read_value = lldbgdbserverutils.unpack_register_hex_unsigned( 1402 endian, p_response 1403 ) 1404 1405 # Make sure we read back what we wrote. 1406 self.assertEqual(read_value, expected_reg_values[thread_index]) 1407 thread_index += 1 1408 1409 @skipUnlessPlatform(oslist=["freebsd", "linux"]) 1410 @add_test_categories(["llgs"]) 1411 def test_qXfer_siginfo_read(self): 1412 self.build() 1413 self.set_inferior_startup_launch() 1414 procs = self.prep_debug_monitor_and_inferior( 1415 inferior_args=["thread:segfault", "thread:new", "sleep:10"] 1416 ) 1417 self.test_sequence.add_log_lines(["read packet: $c#63"], True) 1418 self.expect_gdbremote_sequence() 1419 1420 # Run until SIGSEGV comes in. 1421 self.reset_test_sequence() 1422 self.test_sequence.add_log_lines( 1423 [ 1424 { 1425 "direction": "send", 1426 "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", 1427 "capture": {1: "signo", 2: "thread_id"}, 1428 } 1429 ], 1430 True, 1431 ) 1432 1433 # Figure out which thread crashed. 1434 context = self.expect_gdbremote_sequence() 1435 self.assertIsNotNone(context) 1436 self.assertEqual( 1437 int(context["signo"], 16), lldbutil.get_signal_number("SIGSEGV") 1438 ) 1439 crashing_thread = int(context["thread_id"], 16) 1440 1441 # Grab siginfo for the crashing thread. 1442 self.reset_test_sequence() 1443 self.add_process_info_collection_packets() 1444 self.test_sequence.add_log_lines( 1445 [ 1446 "read packet: $Hg{:x}#00".format(crashing_thread), 1447 "send packet: $OK#00", 1448 "read packet: $qXfer:siginfo:read::0,80:#00", 1449 { 1450 "direction": "send", 1451 "regex": re.compile( 1452 r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL 1453 ), 1454 "capture": {1: "response_type", 2: "content_raw"}, 1455 }, 1456 ], 1457 True, 1458 ) 1459 context = self.expect_gdbremote_sequence() 1460 self.assertIsNotNone(context) 1461 1462 # Ensure we end up with all data in one packet. 1463 self.assertEqual(context.get("response_type"), "l") 1464 1465 # Decode binary data. 1466 content_raw = context.get("content_raw") 1467 self.assertIsNotNone(content_raw) 1468 content = self.decode_gdbremote_binary(content_raw).encode("latin1") 1469 1470 # Decode siginfo_t. 1471 process_info = self.parse_process_info_response(context) 1472 pad = "" 1473 if process_info["ptrsize"] == "8": 1474 pad = "i" 1475 signo_idx = 0 1476 errno_idx = 1 1477 code_idx = 2 1478 addr_idx = -1 1479 SEGV_MAPERR = 1 1480 if process_info["ostype"] == "linux": 1481 # si_signo, si_errno, si_code, [pad], _sifields._sigfault.si_addr 1482 format_str = "iii{}P".format(pad) 1483 elif process_info["ostype"].startswith("freebsd"): 1484 # si_signo, si_errno, si_code, si_pid, si_uid, si_status, si_addr 1485 format_str = "iiiiiiP" 1486 elif process_info["ostype"].startswith("netbsd"): 1487 # _signo, _code, _errno, [pad], _reason._fault._addr 1488 format_str = "iii{}P".format(pad) 1489 errno_idx = 2 1490 code_idx = 1 1491 else: 1492 assert False, "unknown ostype" 1493 1494 decoder = struct.Struct(format_str) 1495 decoded = decoder.unpack(content[: decoder.size]) 1496 self.assertEqual(decoded[signo_idx], lldbutil.get_signal_number("SIGSEGV")) 1497 self.assertEqual(decoded[errno_idx], 0) # si_errno 1498 self.assertEqual(decoded[code_idx], SEGV_MAPERR) # si_code 1499 self.assertEqual(decoded[addr_idx], 0) # si_addr 1500