brintos

brintos / llvm-project-archived public Read only

0
0
Text · 41.1 KiB · f1c0519 Raw
1092 lines · python
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 is6available.7 8This class will be broken into smaller test case classes by9gdb remote packet functional areas.  For now it contains10the initial set of tests implemented.11"""12 13import binascii14import itertools15import struct16 17import gdbremote_testcase18import lldbgdbserverutils19from lldbsuite.support import seven20from lldbsuite.test.decorators import *21from lldbsuite.test.lldbtest import *22from lldbsuite.test.lldbdwarf import *23from lldbsuite.test import lldbutil, lldbplatformutil24 25# On Linux systems with Yama ptrace_scope = 1 there is a race condition when the26# debugee enables tracing. See https://github.com/llvm/llvm-project/issues/161510.27@skipIfLinux28class LldbGdbServerTestCase(29    gdbremote_testcase.GdbRemoteTestCaseBase, DwarfOpcodeParser30):31    def test_thread_suffix_supported(self):32        server = self.connect_to_debug_monitor()33        self.assertIsNotNone(server)34 35        self.do_handshake()36        self.test_sequence.add_log_lines(37            [38                "lldb-server <  26> read packet: $QThreadSuffixSupported#e4",39                "lldb-server <   6> send packet: $OK#9a",40            ],41            True,42        )43 44        self.expect_gdbremote_sequence()45 46    def test_list_threads_in_stop_reply_supported(self):47        server = self.connect_to_debug_monitor()48        self.assertIsNotNone(server)49 50        self.do_handshake()51        self.test_sequence.add_log_lines(52            [53                "lldb-server <  27> read packet: $QListThreadsInStopReply#21",54                "lldb-server <   6> send packet: $OK#9a",55            ],56            True,57        )58        self.expect_gdbremote_sequence()59 60    def test_c_packet_works(self):61        self.build()62        procs = self.prep_debug_monitor_and_inferior()63        self.test_sequence.add_log_lines(64            ["read packet: $c#63", "send packet: $W00#00"], True65        )66 67        self.expect_gdbremote_sequence()68 69    @skipIfWindows  # No pty support to test any inferior output70    def test_inferior_print_exit(self):71        self.build()72        procs = self.prep_debug_monitor_and_inferior(inferior_args=["hello, world"])73        self.test_sequence.add_log_lines(74            [75                "read packet: $vCont;c#a8",76                {77                    "type": "output_match",78                    "regex": self.maybe_strict_output_regex(r"hello, world\r\n"),79                },80                "send packet: $W00#00",81            ],82            True,83        )84 85        context = self.expect_gdbremote_sequence()86        self.assertIsNotNone(context)87 88    # Sometimes fails:89    # regex '^\$QC([0-9a-fA-F]+)#' failed to match against content '$E45#ae'90    # See https://github.com/llvm/llvm-project/issues/138085.91    @skipIfWindows92    def test_first_launch_stop_reply_thread_matches_first_qC(self):93        self.build()94        procs = self.prep_debug_monitor_and_inferior()95        self.test_sequence.add_log_lines(96            [97                "read packet: $qC#00",98                {99                    "direction": "send",100                    "regex": r"^\$QC([0-9a-fA-F]+)#",101                    "capture": {1: "thread_id_QC"},102                },103                "read packet: $?#00",104                {105                    "direction": "send",106                    "regex": r"^\$T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+)",107                    "capture": {1: "thread_id_?"},108                },109            ],110            True,111        )112        context = self.expect_gdbremote_sequence()113        self.assertEqual(context.get("thread_id_QC"), context.get("thread_id_?"))114 115    # This test is flaky on Windows. Sometimes returns 'Exception 0x80000003'.116    @skipIf(oslist=["windows"], bugnumber="github.com/llvm/llvm-project/issues/138085")117    def test_attach_commandline_continue_app_exits(self):118        self.build()119        self.set_inferior_startup_attach()120        procs = self.prep_debug_monitor_and_inferior()121        self.test_sequence.add_log_lines(122            ["read packet: $vCont;c#a8", "send packet: $W00#00"], True123        )124        self.expect_gdbremote_sequence()125 126        # Wait a moment for completed and now-detached inferior process to127        # clear.128        time.sleep(1)129 130        if not lldb.remote_platform:131            # Process should be dead now. Reap results.132            poll_result = procs["inferior"].poll()133            self.assertIsNotNone(poll_result)134 135        # Where possible, verify at the system level that the process is not136        # running.137        self.assertFalse(138            lldbgdbserverutils.process_is_running(procs["inferior"].pid, False)139        )140 141    def qThreadInfo_contains_thread(self):142        procs = self.prep_debug_monitor_and_inferior()143        self.add_threadinfo_collection_packets()144 145        # Run the packet stream.146        context = self.expect_gdbremote_sequence()147        self.assertIsNotNone(context)148 149        # Gather threadinfo entries.150        threads = self.parse_threadinfo_packets(context)151        self.assertIsNotNone(threads)152 153        # We should have exactly one thread.154        self.assertEqual(len(threads), 1)155 156    def test_qThreadInfo_contains_thread_launch(self):157        self.build()158        self.set_inferior_startup_launch()159        self.qThreadInfo_contains_thread()160 161    @expectedFailureAll(oslist=["windows"])  # expect one more thread stopped162    def test_qThreadInfo_contains_thread_attach(self):163        self.build()164        self.set_inferior_startup_attach()165        self.qThreadInfo_contains_thread()166 167    def qThreadInfo_matches_qC(self):168        procs = self.prep_debug_monitor_and_inferior()169 170        self.add_threadinfo_collection_packets()171        self.test_sequence.add_log_lines(172            [173                "read packet: $qC#00",174                {175                    "direction": "send",176                    "regex": r"^\$QC([0-9a-fA-F]+)#",177                    "capture": {1: "thread_id"},178                },179            ],180            True,181        )182 183        # Run the packet stream.184        context = self.expect_gdbremote_sequence()185        self.assertIsNotNone(context)186 187        # Gather threadinfo entries.188        threads = self.parse_threadinfo_packets(context)189        self.assertIsNotNone(threads)190 191        # We should have exactly one thread from threadinfo.192        self.assertEqual(len(threads), 1)193 194        # We should have a valid thread_id from $QC.195        QC_thread_id_hex = context.get("thread_id")196        self.assertIsNotNone(QC_thread_id_hex)197        QC_thread_id = int(QC_thread_id_hex, 16)198 199        # Those two should be the same.200        self.assertEqual(threads[0], QC_thread_id)201 202    def test_qThreadInfo_matches_qC_launch(self):203        self.build()204        self.set_inferior_startup_launch()205        self.qThreadInfo_matches_qC()206 207    # This test is flaky on AArch64 Linux. Sometimes it causes an unhandled Error:208    # Operation not permitted in lldb_private::process_linux::NativeProcessLinux::Attach(int).209    @skipIf(210        oslist=["linux"],211        archs=["aarch64"],212        bugnumber="github.com/llvm/llvm-project/issues/138085",213    )214    @expectedFailureAll(oslist=["windows"])  # expect one more thread stopped215    def test_qThreadInfo_matches_qC_attach(self):216        self.build()217        self.set_inferior_startup_attach()218        self.qThreadInfo_matches_qC()219 220    def test_p_returns_correct_data_size_for_each_qRegisterInfo_launch(self):221        self.build()222        self.set_inferior_startup_launch()223        procs = self.prep_debug_monitor_and_inferior()224        self.add_register_info_collection_packets()225 226        # Run the packet stream.227        context = self.expect_gdbremote_sequence()228        self.assertIsNotNone(context)229 230        # Gather register info entries.231        reg_infos = self.parse_register_info_packets(context)232        self.assertIsNotNone(reg_infos)233        self.assertGreater(len(reg_infos), 0)234 235        byte_order = self.get_target_byte_order()236 237        # Read value for each register.238        reg_index = 0239        for reg_info in reg_infos:240            # Skip registers that don't have a register set.  For x86, these are241            # the DRx registers, which have no LLDB-kind register number and thus242            # cannot be read via normal243            # NativeRegisterContext::ReadRegister(reg_info,...) calls.244            if not "set" in reg_info:245                continue246 247            # Clear existing packet expectations.248            self.reset_test_sequence()249 250            # Run the register query251            self.test_sequence.add_log_lines(252                [253                    "read packet: $p{0:x}#00".format(reg_index),254                    {255                        "direction": "send",256                        "regex": r"^\$([0-9a-fA-F]+)#",257                        "capture": {1: "p_response"},258                    },259                ],260                True,261            )262            context = self.expect_gdbremote_sequence()263            self.assertIsNotNone(context)264 265            # Verify the response length.266            p_response = context.get("p_response")267            self.assertIsNotNone(p_response)268 269            # Skip erraneous (unsupported) registers.270            # TODO: remove this once we make unsupported registers disappear.271            if p_response.startswith("E") and len(p_response) == 3:272                continue273 274            if "dynamic_size_dwarf_expr_bytes" in reg_info:275                self.updateRegInfoBitsize(reg_info, byte_order)276            self.assertEqual(277                len(p_response), 2 * int(reg_info["bitsize"]) / 8, reg_info278            )279 280            # Increment loop281            reg_index += 1282 283    def Hg_switches_to_3_threads(self, pass_pid=False):284        _, threads = self.launch_with_threads(3)285 286        pid_str = ""287        if pass_pid:288            pid_str = "p{0:x}.".format(procs["inferior"].pid)289 290        # verify we can $H to each thead, and $qC matches the thread we set.291        for thread in threads:292            # Change to each thread, verify current thread id.293            self.reset_test_sequence()294            self.test_sequence.add_log_lines(295                [296                    "read packet: $Hg{0}{1:x}#00".format(297                        pid_str, thread298                    ),  # Set current thread.299                    "send packet: $OK#00",300                    "read packet: $qC#00",301                    {302                        "direction": "send",303                        "regex": r"^\$QC([0-9a-fA-F]+)#",304                        "capture": {1: "thread_id"},305                    },306                ],307                True,308            )309 310            context = self.expect_gdbremote_sequence()311            self.assertIsNotNone(context)312 313            # Verify the thread id.314            self.assertIsNotNone(context.get("thread_id"))315            self.assertEqual(int(context.get("thread_id"), 16), thread)316 317    # This test is flaky on Windows. Sometimes returns '$E37#af'.318    @skipIf(oslist=["windows"], bugnumber="github.com/llvm/llvm-project/issues/138085")319    @skipIf(compiler="clang", compiler_version=["<", "11.0"])320    def test_Hg_switches_to_3_threads_launch(self):321        self.build()322        self.set_inferior_startup_launch()323        self.Hg_switches_to_3_threads()324 325    def Hg_fails_on_pid(self, pass_pid):326        _, threads = self.launch_with_threads(2)327 328        if pass_pid == -1:329            pid_str = "p-1."330        else:331            pid_str = "p{0:x}.".format(pass_pid)332        thread = threads[1]333 334        self.test_sequence.add_log_lines(335            [336                "read packet: $Hg{0}{1:x}#00".format(337                    pid_str, thread338                ),  # Set current thread.339                "send packet: $Eff#00",340            ],341            True,342        )343 344        self.expect_gdbremote_sequence()345 346    @add_test_categories(["llgs"])347    def test_Hg_fails_on_another_pid(self):348        self.build()349        self.set_inferior_startup_launch()350        self.Hg_fails_on_pid(1)351 352    @add_test_categories(["llgs"])353    def test_Hg_fails_on_zero_pid(self):354        self.build()355        self.set_inferior_startup_launch()356        self.Hg_fails_on_pid(0)357 358    @add_test_categories(["llgs"])359    @skipIfWindows  # Sometimes returns '$E37'.360    def test_Hg_fails_on_minus_one_pid(self):361        self.build()362        self.set_inferior_startup_launch()363        self.Hg_fails_on_pid(-1)364 365    def Hc_then_Csignal_signals_correct_thread(self, segfault_signo):366        # NOTE only run this one in inferior-launched mode: we can't grab inferior stdout when running attached,367        # and the test requires getting stdout from the exe.368 369        NUM_THREADS = 3370 371        # Startup the inferior with three threads (main + NUM_THREADS-1 worker threads).372        # inferior_args=["thread:print-ids"]373        inferior_args = ["thread:segfault"]374        for i in range(NUM_THREADS - 1):375            # if i > 0:376            # Give time between thread creation/segfaulting for the handler to work.377            # inferior_args.append("sleep:1")378            inferior_args.append("thread:new")379        inferior_args.append("sleep:10")380 381        # Launch/attach.  (In our case, this should only ever be launched since382        # we need inferior stdout/stderr).383        procs = self.prep_debug_monitor_and_inferior(inferior_args=inferior_args)384        self.test_sequence.add_log_lines(["read packet: $c#63"], True)385        context = self.expect_gdbremote_sequence()386 387        signaled_tids = {}388        print_thread_ids = {}389 390        # Switch to each thread, deliver a signal, and verify signal delivery391        for i in range(NUM_THREADS - 1):392            # Run until SIGSEGV comes in.393            self.reset_test_sequence()394            self.test_sequence.add_log_lines(395                [396                    {397                        "direction": "send",398                        "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",399                        "capture": {1: "signo", 2: "thread_id"},400                    }401                ],402                True,403            )404 405            context = self.expect_gdbremote_sequence()406            self.assertIsNotNone(context)407            signo = context.get("signo")408            self.assertEqual(int(signo, 16), segfault_signo)409 410            # Ensure we haven't seen this tid yet.411            thread_id = int(context.get("thread_id"), 16)412            self.assertNotIn(thread_id, signaled_tids)413            signaled_tids[thread_id] = 1414 415            # Send SIGUSR1 to the thread that signaled the SIGSEGV.416            self.reset_test_sequence()417            self.test_sequence.add_log_lines(418                [419                    # Set the continue thread.420                    # Set current thread.421                    "read packet: $Hc{0:x}#00".format(thread_id),422                    "send packet: $OK#00",423                    # Continue sending the signal number to the continue thread.424                    # The commented out packet is a way to do this same operation without using425                    # a $Hc (but this test is testing $Hc, so we'll stick with the former).426                    "read packet: $C{0:x}#00".format(427                        lldbutil.get_signal_number("SIGUSR1")428                    ),429                    # "read packet: $vCont;C{0:x}:{1:x};c#00".format(lldbutil.get_signal_number('SIGUSR1'), thread_id),430                    # FIXME: Linux does not report the thread stop on the delivered signal (SIGUSR1 here).  MacOSX debugserver does.431                    # But MacOSX debugserver isn't guaranteeing the thread the signal handler runs on, so currently its an XFAIL.432                    # Need to rectify behavior here.  The linux behavior is more intuitive to me since we're essentially swapping out433                    # an about-to-be-delivered signal (for which we already sent a stop packet) to a different signal.434                    # {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },435                    #  "read packet: $c#63",436                    {437                        "type": "output_match",438                        "regex": r"^received SIGUSR1 on thread id: ([0-9a-fA-F]+)\r\nthread ([0-9a-fA-F]+): past SIGSEGV\r\n",439                        "capture": {1: "print_thread_id", 2: "post_handle_thread_id"},440                    },441                ],442                True,443            )444 445            # Run the sequence.446            context = self.expect_gdbremote_sequence()447            self.assertIsNotNone(context)448 449            # Ensure the stop signal is the signal we delivered.450            # stop_signo = context.get("stop_signo")451            # self.assertIsNotNone(stop_signo)452            # self.assertEqual(int(stop_signo,16), lldbutil.get_signal_number('SIGUSR1'))453 454            # Ensure the stop thread is the thread to which we delivered the signal.455            # stop_thread_id = context.get("stop_thread_id")456            # self.assertIsNotNone(stop_thread_id)457            # self.assertEqual(int(stop_thread_id,16), thread_id)458 459            # Ensure we haven't seen this thread id yet.  The inferior's460            # self-obtained thread ids are not guaranteed to match the stub461            # tids (at least on MacOSX).462            print_thread_id = context.get("print_thread_id")463            self.assertIsNotNone(print_thread_id)464            print_thread_id = int(print_thread_id, 16)465            self.assertNotIn(print_thread_id, print_thread_ids)466 467            # Now remember this print (i.e. inferior-reflected) thread id and468            # ensure we don't hit it again.469            print_thread_ids[print_thread_id] = 1470 471            # Ensure post signal-handle thread id matches the thread that472            # initially raised the SIGSEGV.473            post_handle_thread_id = context.get("post_handle_thread_id")474            self.assertIsNotNone(post_handle_thread_id)475            post_handle_thread_id = int(post_handle_thread_id, 16)476            self.assertEqual(post_handle_thread_id, print_thread_id)477 478    @expectedFailureDarwin479    @skipIfWindows  # no SIGSEGV support480    @expectedFailureNetBSD481    def test_Hc_then_Csignal_signals_correct_thread_launch(self):482        self.build()483        self.set_inferior_startup_launch()484 485        if self.platformIsDarwin():486            # Darwin debugserver translates some signals like SIGSEGV into some gdb487            # expectations about fixed signal numbers.488            self.Hc_then_Csignal_signals_correct_thread(self.TARGET_EXC_BAD_ACCESS)489        else:490            self.Hc_then_Csignal_signals_correct_thread(491                lldbutil.get_signal_number("SIGSEGV")492            )493 494    @skipIfWindows  # No pty support to test any inferior output495    def test_m_packet_reads_memory(self):496        self.build()497        self.set_inferior_startup_launch()498        # This is the memory we will write into the inferior and then ensure we499        # can read back with $m.500        MEMORY_CONTENTS = "Test contents 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"501 502        # Start up the inferior.503        procs = self.prep_debug_monitor_and_inferior(504            inferior_args=[505                "set-message:%s" % MEMORY_CONTENTS,506                "get-data-address-hex:g_message",507                "sleep:5",508            ]509        )510 511        # Run the process512        self.test_sequence.add_log_lines(513            [514                # Start running after initial stop.515                "read packet: $c#63",516                # Match output line that prints the memory address of the message buffer within the inferior.517                # Note we require launch-only testing so we can get inferior otuput.518                {519                    "type": "output_match",520                    "regex": self.maybe_strict_output_regex(521                        r"data address: 0x([0-9a-fA-F]+)\r\n"522                    ),523                    "capture": {1: "message_address"},524                },525                # Now stop the inferior.526                "read packet: {}".format(chr(3)),527                # And wait for the stop notification.528                {529                    "direction": "send",530                    "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",531                    "capture": {1: "stop_signo", 2: "stop_thread_id"},532                },533            ],534            True,535        )536 537        # Run the packet stream.538        context = self.expect_gdbremote_sequence()539        self.assertIsNotNone(context)540 541        # Grab the message address.542        self.assertIsNotNone(context.get("message_address"))543        message_address = int(context.get("message_address"), 16)544 545        # Grab contents from the inferior.546        self.reset_test_sequence()547        self.test_sequence.add_log_lines(548            [549                "read packet: $m{0:x},{1:x}#00".format(550                    message_address, len(MEMORY_CONTENTS)551                ),552                {553                    "direction": "send",554                    "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",555                    "capture": {1: "read_contents"},556                },557            ],558            True,559        )560 561        # Run the packet stream.562        context = self.expect_gdbremote_sequence()563        self.assertIsNotNone(context)564 565        # Ensure what we read from inferior memory is what we wrote.566        self.assertIsNotNone(context.get("read_contents"))567        read_contents = seven.unhexlify(context.get("read_contents"))568        self.assertEqual(read_contents, MEMORY_CONTENTS)569 570    def breakpoint_set_and_remove_work(self, want_hardware):571        # Start up the inferior.572        procs = self.prep_debug_monitor_and_inferior(573            inferior_args=[574                "get-code-address-hex:hello",575                "sleep:1",576                "call-function:hello",577            ]578        )579 580        # Run the process581        self.add_register_info_collection_packets()582        self.add_process_info_collection_packets()583        self.test_sequence.add_log_lines(584            [  # Start running after initial stop.585                "read packet: $c#63",586                # Match output line that prints the memory address of the function call entry point.587                # Note we require launch-only testing so we can get inferior otuput.588                {589                    "type": "output_match",590                    "regex": self.maybe_strict_output_regex(591                        r"code address: 0x([0-9a-fA-F]+)\r\n"592                    ),593                    "capture": {1: "function_address"},594                },595                # Now stop the inferior.596                "read packet: {}".format(chr(3)),597                # And wait for the stop notification.598                {599                    "direction": "send",600                    "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",601                    "capture": {1: "stop_signo", 2: "stop_thread_id"},602                },603            ],604            True,605        )606 607        # Run the packet stream.608        context = self.expect_gdbremote_sequence()609        self.assertIsNotNone(context)610 611        # Gather process info - we need endian of target to handle register612        # value conversions.613        process_info = self.parse_process_info_response(context)614        endian = process_info.get("endian")615        self.assertIsNotNone(endian)616 617        # Gather register info entries.618        reg_infos = self.parse_register_info_packets(context)619        (pc_lldb_reg_index, pc_reg_info) = self.find_pc_reg_info(reg_infos)620        self.assertIsNotNone(pc_lldb_reg_index)621        self.assertIsNotNone(pc_reg_info)622 623        # Grab the function address.624        self.assertIsNotNone(context.get("function_address"))625        function_address = int(context.get("function_address"), 16)626 627        # Get current target architecture628        target_arch = self.getArchitecture()629 630        # Set the breakpoint.631        if target_arch in ["arm", "arm64", "aarch64"]:632            # TODO: Handle case when setting breakpoint in thumb code633            BREAKPOINT_KIND = 4634        else:635            BREAKPOINT_KIND = 1636 637        # Set default packet type to Z0 (software breakpoint)638        z_packet_type = 0639 640        # If hardware breakpoint is requested set packet type to Z1641        if want_hardware:642            z_packet_type = 1643 644        self.reset_test_sequence()645        self.add_set_breakpoint_packets(646            function_address,647            z_packet_type,648            do_continue=True,649            breakpoint_kind=BREAKPOINT_KIND,650        )651 652        # Run the packet stream.653        context = self.expect_gdbremote_sequence()654        self.assertIsNotNone(context)655 656        # Verify the stop signal reported was the breakpoint signal number.657        stop_signo = context.get("stop_signo")658        self.assertIsNotNone(stop_signo)659        self.assertEqual(int(stop_signo, 16), lldbutil.get_signal_number("SIGTRAP"))660 661        # Ensure we did not receive any output.  If the breakpoint was not set, we would662        # see output (from a launched process with captured stdio) printing a hello, world message.663        # That would indicate the breakpoint didn't take.664        self.assertEqual(len(context["O_content"]), 0)665 666        # Verify that the PC for the main thread is where we expect it - right at the breakpoint address.667        # This acts as a another validation on the register reading code.668        self.reset_test_sequence()669        self.test_sequence.add_log_lines(670            [671                # Print the PC.  This should match the breakpoint address.672                "read packet: $p{0:x}#00".format(pc_lldb_reg_index),673                # Capture $p results.674                {675                    "direction": "send",676                    "regex": r"^\$([0-9a-fA-F]+)#",677                    "capture": {1: "p_response"},678                },679            ],680            True,681        )682 683        context = self.expect_gdbremote_sequence()684        self.assertIsNotNone(context)685 686        # Verify the PC is where we expect.  Note response is in endianness of687        # the inferior.688        p_response = context.get("p_response")689        self.assertIsNotNone(p_response)690 691        # Convert from target endian to int.692        returned_pc = lldbgdbserverutils.unpack_register_hex_unsigned(693            endian, p_response694        )695        self.assertEqual(returned_pc, function_address)696 697        # Verify that a breakpoint remove and continue gets us the expected698        # output.699        self.reset_test_sequence()700 701        # Add breakpoint remove packets702        self.add_remove_breakpoint_packets(703            function_address, z_packet_type, breakpoint_kind=BREAKPOINT_KIND704        )705 706        self.test_sequence.add_log_lines(707            [708                # Continue running.709                "read packet: $c#63",710                # We should now receive the output from the call.711                {"type": "output_match", "regex": r"^hello, world\r\n$"},712                # And wait for program completion.713                {"direction": "send", "regex": r"^\$W00(.*)#[0-9a-fA-F]{2}$"},714            ],715            True,716        )717 718        context = self.expect_gdbremote_sequence()719        self.assertIsNotNone(context)720 721    @skipIfWindows  # No pty support to test any inferior output722    def test_software_breakpoint_set_and_remove_work(self):723        if self.getArchitecture() == "arm":724            # TODO: Handle case when setting breakpoint in thumb code725            self.build(dictionary={"CFLAGS_EXTRAS": "-marm"})726        else:727            self.build()728        self.set_inferior_startup_launch()729        self.breakpoint_set_and_remove_work(want_hardware=False)730 731    @skipUnlessPlatform(oslist=["linux"])732    @skipIf(archs=no_match(["arm$", "aarch64"]))733    def test_hardware_breakpoint_set_and_remove_work(self):734        if self.getArchitecture() == "arm":735            # TODO: Handle case when setting breakpoint in thumb code736            self.build(dictionary={"CFLAGS_EXTRAS": "-marm"})737        else:738            self.build()739        self.set_inferior_startup_launch()740        self.breakpoint_set_and_remove_work(want_hardware=True)741 742    @skipIfWindows  # No pty support to test any inferior output743    def test_written_M_content_reads_back_correctly(self):744        self.build()745        self.set_inferior_startup_launch()746 747        TEST_MESSAGE = "Hello, memory"748 749        # Start up the stub and start/prep the inferior.750        procs = self.prep_debug_monitor_and_inferior(751            inferior_args=[752                "set-message:xxxxxxxxxxxxxX",753                "get-data-address-hex:g_message",754                "sleep:1",755                "print-message:",756            ]757        )758        self.test_sequence.add_log_lines(759            [760                # Start running after initial stop.761                "read packet: $c#63",762                # Match output line that prints the memory address of the message buffer within the inferior.763                # Note we require launch-only testing so we can get inferior otuput.764                {765                    "type": "output_match",766                    "regex": self.maybe_strict_output_regex(767                        r"data address: 0x([0-9a-fA-F]+)\r\n"768                    ),769                    "capture": {1: "message_address"},770                },771                # Now stop the inferior.772                "read packet: {}".format(chr(3)),773                # And wait for the stop notification.774                {775                    "direction": "send",776                    "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",777                    "capture": {1: "stop_signo", 2: "stop_thread_id"},778                },779            ],780            True,781        )782        context = self.expect_gdbremote_sequence()783        self.assertIsNotNone(context)784 785        # Grab the message address.786        self.assertIsNotNone(context.get("message_address"))787        message_address = int(context.get("message_address"), 16)788 789        # Hex-encode the test message, adding null termination.790        hex_encoded_message = seven.hexlify(TEST_MESSAGE)791 792        # Write the message to the inferior. Verify that we can read it with the hex-encoded (m)793        # and binary (x) memory read packets.794        self.reset_test_sequence()795        self.test_sequence.add_log_lines(796            [797                "read packet: $M{0:x},{1:x}:{2}#00".format(798                    message_address, len(TEST_MESSAGE), hex_encoded_message799                ),800                "send packet: $OK#00",801                "read packet: $m{0:x},{1:x}#00".format(802                    message_address, len(TEST_MESSAGE)803                ),804                "send packet: ${0}#00".format(hex_encoded_message),805                "read packet: $x{0:x},{1:x}#00".format(806                    message_address, len(TEST_MESSAGE)807                ),808                "send packet: ${0}#00".format(TEST_MESSAGE),809                "read packet: $m{0:x},4#00".format(message_address),810                "send packet: ${0}#00".format(hex_encoded_message[0:8]),811                "read packet: $x{0:x},4#00".format(message_address),812                "send packet: ${0}#00".format(TEST_MESSAGE[0:4]),813                "read packet: $c#63",814                {815                    "type": "output_match",816                    "regex": r"^message: (.+)\r\n$",817                    "capture": {1: "printed_message"},818                },819                "send packet: $W00#00",820            ],821            True,822        )823        context = self.expect_gdbremote_sequence()824        self.assertIsNotNone(context)825 826        # Ensure what we read from inferior memory is what we wrote.827        printed_message = context.get("printed_message")828        self.assertIsNotNone(printed_message)829        self.assertEqual(printed_message, TEST_MESSAGE + "X")830 831    # Note: as of this moment, a hefty number of the GPR writes are failing with E32 (everything except rax-rdx, rdi, rsi, rbp).832    # Come back to this.  I have the test rigged to verify that at least some833    # of the bit-flip writes work.834    def test_P_writes_all_gpr_registers(self):835        self.build()836        self.set_inferior_startup_launch()837 838        # Start inferior debug session, grab all register info.839        procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:2"])840        self.add_register_info_collection_packets()841        self.add_process_info_collection_packets()842 843        context = self.expect_gdbremote_sequence()844        self.assertIsNotNone(context)845 846        # Process register infos.847        reg_infos = self.parse_register_info_packets(context)848        self.assertIsNotNone(reg_infos)849        self.add_lldb_register_index(reg_infos)850 851        # Process endian.852        process_info = self.parse_process_info_response(context)853        endian = process_info.get("endian")854        self.assertIsNotNone(endian)855 856        # Pull out the register infos that we think we can bit flip857        # successfully,.858        gpr_reg_infos = [859            reg_info860            for reg_info in reg_infos861            if self.is_bit_flippable_register(reg_info)862        ]863        self.assertGreater(len(gpr_reg_infos), 0)864 865        # Write flipped bit pattern of existing value to each register.866        (successful_writes, failed_writes) = self.flip_all_bits_in_each_register_value(867            gpr_reg_infos, endian868        )869        self.trace(870            "successful writes: {}, failed writes: {}".format(871                successful_writes, failed_writes872            )873        )874        self.assertGreater(successful_writes, 0)875 876    # Note: as of this moment, a hefty number of the GPR writes are failing877    # with E32 (everything except rax-rdx, rdi, rsi, rbp).878    @skipIfWindows879    def test_P_and_p_thread_suffix_work(self):880        self.build()881        self.set_inferior_startup_launch()882 883        # Startup the inferior with three threads.884        _, threads = self.launch_with_threads(3)885 886        self.reset_test_sequence()887        self.add_thread_suffix_request_packets()888        self.add_register_info_collection_packets()889        self.add_process_info_collection_packets()890 891        context = self.expect_gdbremote_sequence()892        self.assertIsNotNone(context)893 894        process_info = self.parse_process_info_response(context)895        self.assertIsNotNone(process_info)896        endian = process_info.get("endian")897        self.assertIsNotNone(endian)898 899        reg_infos = self.parse_register_info_packets(context)900        self.assertIsNotNone(reg_infos)901        self.add_lldb_register_index(reg_infos)902 903        reg_index = self.select_modifiable_register(reg_infos)904        self.assertIsNotNone(reg_index)905        reg_byte_size = int(reg_infos[reg_index]["bitsize"]) // 8906        self.assertGreater(reg_byte_size, 0)907 908        expected_reg_values = []909        register_increment = 1910        next_value = None911 912        # Set the same register in each of 3 threads to a different value.913        # Verify each one has the unique value.914        for thread in threads:915            # If we don't have a next value yet, start it with the initial read916            # value + 1917            if not next_value:918                # Read pre-existing register value.919                self.reset_test_sequence()920                self.test_sequence.add_log_lines(921                    [922                        "read packet: $p{0:x};thread:{1:x}#00".format(923                            reg_index, thread924                        ),925                        {926                            "direction": "send",927                            "regex": r"^\$([0-9a-fA-F]+)#",928                            "capture": {1: "p_response"},929                        },930                    ],931                    True,932                )933                context = self.expect_gdbremote_sequence()934                self.assertIsNotNone(context)935 936                # Set the next value to use for writing as the increment plus937                # current value.938                p_response = context.get("p_response")939                self.assertIsNotNone(p_response)940                next_value = lldbgdbserverutils.unpack_register_hex_unsigned(941                    endian, p_response942                )943 944            # Set new value using P and thread suffix.945            self.reset_test_sequence()946            self.test_sequence.add_log_lines(947                [948                    "read packet: $P{0:x}={1};thread:{2:x}#00".format(949                        reg_index,950                        lldbgdbserverutils.pack_register_hex(951                            endian, next_value, byte_size=reg_byte_size952                        ),953                        thread,954                    ),955                    "send packet: $OK#00",956                ],957                True,958            )959            context = self.expect_gdbremote_sequence()960            self.assertIsNotNone(context)961 962            # Save the value we set.963            expected_reg_values.append(next_value)964 965            # Increment value for next thread to use (we want them all966            # different so we can verify they wrote to each thread correctly967            # next.)968            next_value += register_increment969 970        # Revisit each thread and verify they have the expected value set for971        # the register we wrote.972        thread_index = 0973        for thread in threads:974            # Read pre-existing register value.975            self.reset_test_sequence()976            self.test_sequence.add_log_lines(977                [978                    "read packet: $p{0:x};thread:{1:x}#00".format(reg_index, thread),979                    {980                        "direction": "send",981                        "regex": r"^\$([0-9a-fA-F]+)#",982                        "capture": {1: "p_response"},983                    },984                ],985                True,986            )987            context = self.expect_gdbremote_sequence()988            self.assertIsNotNone(context)989 990            # Get the register value.991            p_response = context.get("p_response")992            self.assertIsNotNone(p_response)993            read_value = lldbgdbserverutils.unpack_register_hex_unsigned(994                endian, p_response995            )996 997            # Make sure we read back what we wrote.998            self.assertEqual(read_value, expected_reg_values[thread_index])999            thread_index += 11000 1001    @skipUnlessPlatform(oslist=["freebsd", "linux"])1002    @add_test_categories(["llgs"])1003    def test_qXfer_siginfo_read(self):1004        self.build()1005        self.set_inferior_startup_launch()1006        procs = self.prep_debug_monitor_and_inferior(1007            inferior_args=["thread:segfault", "thread:new", "sleep:10"]1008        )1009        self.test_sequence.add_log_lines(["read packet: $c#63"], True)1010        self.expect_gdbremote_sequence()1011 1012        # Run until SIGSEGV comes in.1013        self.reset_test_sequence()1014        self.test_sequence.add_log_lines(1015            [1016                {1017                    "direction": "send",1018                    "regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",1019                    "capture": {1: "signo", 2: "thread_id"},1020                }1021            ],1022            True,1023        )1024 1025        # Figure out which thread crashed.1026        context = self.expect_gdbremote_sequence()1027        self.assertIsNotNone(context)1028        self.assertEqual(1029            int(context["signo"], 16), lldbutil.get_signal_number("SIGSEGV")1030        )1031        crashing_thread = int(context["thread_id"], 16)1032 1033        # Grab siginfo for the crashing thread.1034        self.reset_test_sequence()1035        self.add_process_info_collection_packets()1036        self.test_sequence.add_log_lines(1037            [1038                "read packet: $Hg{:x}#00".format(crashing_thread),1039                "send packet: $OK#00",1040                "read packet: $qXfer:siginfo:read::0,80:#00",1041                {1042                    "direction": "send",1043                    "regex": re.compile(1044                        r"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re.MULTILINE | re.DOTALL1045                    ),1046                    "capture": {1: "response_type", 2: "content_raw"},1047                },1048            ],1049            True,1050        )1051        context = self.expect_gdbremote_sequence()1052        self.assertIsNotNone(context)1053 1054        # Ensure we end up with all data in one packet.1055        self.assertEqual(context.get("response_type"), "l")1056 1057        # Decode binary data.1058        content_raw = context.get("content_raw")1059        self.assertIsNotNone(content_raw)1060        content = self.decode_gdbremote_binary(content_raw).encode("latin1")1061 1062        # Decode siginfo_t.1063        process_info = self.parse_process_info_response(context)1064        pad = ""1065        if process_info["ptrsize"] == "8":1066            pad = "i"1067        signo_idx = 01068        errno_idx = 11069        code_idx = 21070        addr_idx = -11071        SEGV_MAPERR = 11072        if process_info["ostype"] == "linux":1073            # si_signo, si_errno, si_code, [pad], _sifields._sigfault.si_addr1074            format_str = "iii{}P".format(pad)1075        elif process_info["ostype"].startswith("freebsd"):1076            # si_signo, si_errno, si_code, si_pid, si_uid, si_status, si_addr1077            format_str = "iiiiiiP"1078        elif process_info["ostype"].startswith("netbsd"):1079            # _signo, _code, _errno, [pad], _reason._fault._addr1080            format_str = "iii{}P".format(pad)1081            errno_idx = 21082            code_idx = 11083        else:1084            assert False, "unknown ostype"1085 1086        decoder = struct.Struct(format_str)1087        decoded = decoder.unpack(content[: decoder.size])1088        self.assertEqual(decoded[signo_idx], lldbutil.get_signal_number("SIGSEGV"))1089        self.assertEqual(decoded[errno_idx], 0)  # si_errno1090        self.assertEqual(decoded[code_idx], SEGV_MAPERR)  # si_code1091        self.assertEqual(decoded[addr_idx], 0)  # si_addr1092