xref: /llvm-project/lldb/test/API/tools/lldb-server/TestLldbGdbServer.py (revision 5a658ee933065d0e4ef1a65d9a6ddfba2874ee98)
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