2 Test case for testing the gdbremote protocol.
4 Tests run against debugserver and lldb-server (llgs).
5 lldb-server tests run where the lldb-server exe is
8 This class will be broken into smaller test case classes by
9 gdb remote packet functional areas. For now it contains
10 the initial set of tests implemented.
17 import gdbremote_testcase
18 import lldbgdbserverutils
19 from lldbsuite
.support
import seven
20 from lldbsuite
.test
.decorators
import *
21 from lldbsuite
.test
.lldbtest
import *
22 from lldbsuite
.test
.lldbdwarf
import *
23 from lldbsuite
.test
import lldbutil
, lldbplatformutil
26 class LldbGdbServerTestCase(
27 gdbremote_testcase
.GdbRemoteTestCaseBase
, DwarfOpcodeParser
29 def test_thread_suffix_supported(self
):
30 server
= self
.connect_to_debug_monitor()
31 self
.assertIsNotNone(server
)
34 self
.test_sequence
.add_log_lines(
36 "lldb-server < 26> read packet: $QThreadSuffixSupported#e4",
37 "lldb-server < 6> send packet: $OK#9a",
42 self
.expect_gdbremote_sequence()
44 def test_list_threads_in_stop_reply_supported(self
):
45 server
= self
.connect_to_debug_monitor()
46 self
.assertIsNotNone(server
)
49 self
.test_sequence
.add_log_lines(
51 "lldb-server < 27> read packet: $QListThreadsInStopReply#21",
52 "lldb-server < 6> send packet: $OK#9a",
56 self
.expect_gdbremote_sequence()
58 def test_c_packet_works(self
):
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
65 self
.expect_gdbremote_sequence()
67 @skipIfWindows # No pty support to test any inferior output
68 def test_inferior_print_exit(self
):
70 procs
= self
.prep_debug_monitor_and_inferior(inferior_args
=["hello, world"])
71 self
.test_sequence
.add_log_lines(
73 "read packet: $vCont;c#a8",
75 "type": "output_match",
76 "regex": self
.maybe_strict_output_regex(r
"hello, world\r\n"),
78 "send packet: $W00#00",
83 context
= self
.expect_gdbremote_sequence()
84 self
.assertIsNotNone(context
)
86 def test_first_launch_stop_reply_thread_matches_first_qC(self
):
88 procs
= self
.prep_debug_monitor_and_inferior()
89 self
.test_sequence
.add_log_lines(
91 "read packet: $qC#00",
94 "regex": r
"^\$QC([0-9a-fA-F]+)#",
95 "capture": {1: "thread_id_QC"},
100 "regex": r
"^\$T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+)",
101 "capture": {1: "thread_id_?"},
106 context
= self
.expect_gdbremote_sequence()
107 self
.assertEqual(context
.get("thread_id_QC"), context
.get("thread_id_?"))
109 def test_attach_commandline_continue_app_exits(self
):
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
116 self
.expect_gdbremote_sequence()
118 # Wait a moment for completed and now-detached inferior process to
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
)
127 # Where possible, verify at the system level that the process is not
130 lldbgdbserverutils
.process_is_running(procs
["inferior"].pid
, False)
133 def test_qRegisterInfo_returns_one_valid_result(self
):
135 self
.prep_debug_monitor_and_inferior()
136 self
.test_sequence
.add_log_lines(
138 "read packet: $qRegisterInfo0#00",
141 "regex": r
"^\$(.+);#[0-9A-Fa-f]{2}",
142 "capture": {1: "reginfo_0"},
149 context
= self
.expect_gdbremote_sequence()
150 self
.assertIsNotNone(context
)
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
)
158 def test_qRegisterInfo_returns_all_valid_results(self
):
160 self
.prep_debug_monitor_and_inferior()
161 self
.add_register_info_collection_packets()
164 context
= self
.expect_gdbremote_sequence()
165 self
.assertIsNotNone(context
)
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
)
171 def test_qRegisterInfo_contains_required_generics_debugserver(self
):
173 self
.prep_debug_monitor_and_inferior()
174 self
.add_register_info_collection_packets()
176 # Run the packet stream.
177 context
= self
.expect_gdbremote_sequence()
178 self
.assertIsNotNone(context
)
180 # Gather register info entries.
181 reg_infos
= self
.parse_register_info_packets(context
)
183 # Collect all generic registers found.
185 reg_info
["generic"]: 1 for reg_info
in reg_infos
if "generic" in reg_info
188 # Ensure we have a program counter register.
189 self
.assertIn("pc", generic_regs
)
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
)
195 # Ensure we have a stack pointer register.
196 self
.assertIn("sp", generic_regs
)
198 # Ensure we have a flags register.
199 self
.assertIn("flags", generic_regs
)
201 def test_qRegisterInfo_contains_at_least_one_register_set(self
):
203 self
.prep_debug_monitor_and_inferior()
204 self
.add_register_info_collection_packets()
206 # Run the packet stream.
207 context
= self
.expect_gdbremote_sequence()
208 self
.assertIsNotNone(context
)
210 # Gather register info entries.
211 reg_infos
= self
.parse_register_info_packets(context
)
213 # Collect all register sets found.
215 reg_info
["set"]: 1 for reg_info
in reg_infos
if "set" in reg_info
217 self
.assertGreaterEqual(len(register_sets
), 1)
219 def targetHasAVX(self
):
220 triple
= self
.dbg
.GetSelectedPlatform().GetTriple()
222 # TODO other platforms, please implement this function
223 if not re
.match(".*-.*-linux", triple
):
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"))
232 cpuinfo_path
= "/proc/cpuinfo"
234 f
= open(cpuinfo_path
, "r")
237 return " avx " in cpuinfo
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
):
244 self
.prep_debug_monitor_and_inferior()
245 self
.add_register_info_collection_packets()
247 # Run the packet stream.
248 context
= self
.expect_gdbremote_sequence()
249 self
.assertIsNotNone(context
)
251 # Gather register info entries.
252 reg_infos
= self
.parse_register_info_packets(context
)
254 # Collect all generics found.
256 reg_info
["set"]: 1 for reg_info
in reg_infos
if "set" in reg_info
259 self
.targetHasAVX(), "Advanced Vector Extensions" in register_sets
262 def qThreadInfo_contains_thread(self
):
263 procs
= self
.prep_debug_monitor_and_inferior()
264 self
.add_threadinfo_collection_packets()
266 # Run the packet stream.
267 context
= self
.expect_gdbremote_sequence()
268 self
.assertIsNotNone(context
)
270 # Gather threadinfo entries.
271 threads
= self
.parse_threadinfo_packets(context
)
272 self
.assertIsNotNone(threads
)
274 # We should have exactly one thread.
275 self
.assertEqual(len(threads
), 1)
277 def test_qThreadInfo_contains_thread_launch(self
):
279 self
.set_inferior_startup_launch()
280 self
.qThreadInfo_contains_thread()
282 @expectedFailureAll(oslist
=["windows"]) # expect one more thread stopped
283 def test_qThreadInfo_contains_thread_attach(self
):
285 self
.set_inferior_startup_attach()
286 self
.qThreadInfo_contains_thread()
288 def qThreadInfo_matches_qC(self
):
289 procs
= self
.prep_debug_monitor_and_inferior()
291 self
.add_threadinfo_collection_packets()
292 self
.test_sequence
.add_log_lines(
294 "read packet: $qC#00",
297 "regex": r
"^\$QC([0-9a-fA-F]+)#",
298 "capture": {1: "thread_id"},
304 # Run the packet stream.
305 context
= self
.expect_gdbremote_sequence()
306 self
.assertIsNotNone(context
)
308 # Gather threadinfo entries.
309 threads
= self
.parse_threadinfo_packets(context
)
310 self
.assertIsNotNone(threads
)
312 # We should have exactly one thread from threadinfo.
313 self
.assertEqual(len(threads
), 1)
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)
320 # Those two should be the same.
321 self
.assertEqual(threads
[0], QC_thread_id
)
323 def test_qThreadInfo_matches_qC_launch(self
):
325 self
.set_inferior_startup_launch()
326 self
.qThreadInfo_matches_qC()
328 @expectedFailureAll(oslist
=["windows"]) # expect one more thread stopped
329 def test_qThreadInfo_matches_qC_attach(self
):
331 self
.set_inferior_startup_attach()
332 self
.qThreadInfo_matches_qC()
334 def test_p_returns_correct_data_size_for_each_qRegisterInfo_launch(self
):
336 self
.set_inferior_startup_launch()
337 procs
= self
.prep_debug_monitor_and_inferior()
338 self
.add_register_info_collection_packets()
340 # Run the packet stream.
341 context
= self
.expect_gdbremote_sequence()
342 self
.assertIsNotNone(context
)
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)
349 byte_order
= self
.get_target_byte_order()
351 # Read value for each register.
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
:
361 # Clear existing packet expectations.
362 self
.reset_test_sequence()
364 # Run the register query
365 self
.test_sequence
.add_log_lines(
367 "read packet: $p{0:x}#00".format(reg_index
),
370 "regex": r
"^\$([0-9a-fA-F]+)#",
371 "capture": {1: "p_response"},
376 context
= self
.expect_gdbremote_sequence()
377 self
.assertIsNotNone(context
)
379 # Verify the response length.
380 p_response
= context
.get("p_response")
381 self
.assertIsNotNone(p_response
)
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:
388 if "dynamic_size_dwarf_expr_bytes" in reg_info
:
389 self
.updateRegInfoBitsize(reg_info
, byte_order
)
391 len(p_response
), 2 * int(reg_info
["bitsize"]) / 8, reg_info
397 def Hg_switches_to_3_threads(self
, pass_pid
=False):
398 _
, threads
= self
.launch_with_threads(3)
402 pid_str
= "p{0:x}.".format(procs
["inferior"].pid
)
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(
410 "read packet: $Hg{0}{1:x}#00".format(
412 ), # Set current thread.
413 "send packet: $OK#00",
414 "read packet: $qC#00",
417 "regex": r
"^\$QC([0-9a-fA-F]+)#",
418 "capture": {1: "thread_id"},
424 context
= self
.expect_gdbremote_sequence()
425 self
.assertIsNotNone(context
)
427 # Verify the thread id.
428 self
.assertIsNotNone(context
.get("thread_id"))
429 self
.assertEqual(int(context
.get("thread_id"), 16), thread
)
431 @skipIf(compiler
="clang", compiler_version
=["<", "11.0"])
432 def test_Hg_switches_to_3_threads_launch(self
):
434 self
.set_inferior_startup_launch()
435 self
.Hg_switches_to_3_threads()
437 def Hg_fails_on_pid(self
, pass_pid
):
438 _
, threads
= self
.launch_with_threads(2)
443 pid_str
= "p{0:x}.".format(pass_pid
)
446 self
.test_sequence
.add_log_lines(
448 "read packet: $Hg{0}{1:x}#00".format(
450 ), # Set current thread.
451 "send packet: $Eff#00",
456 self
.expect_gdbremote_sequence()
458 @add_test_categories(["llgs"])
459 def test_Hg_fails_on_another_pid(self
):
461 self
.set_inferior_startup_launch()
462 self
.Hg_fails_on_pid(1)
464 @add_test_categories(["llgs"])
465 def test_Hg_fails_on_zero_pid(self
):
467 self
.set_inferior_startup_launch()
468 self
.Hg_fails_on_pid(0)
470 @add_test_categories(["llgs"])
471 @skipIfWindows # Sometimes returns '$E37'.
472 def test_Hg_fails_on_minus_one_pid(self
):
474 self
.set_inferior_startup_launch()
475 self
.Hg_fails_on_pid(-1)
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.
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):
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")
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()
500 print_thread_ids
= {}
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(
510 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
511 "capture": {1: "signo", 2: "thread_id"},
517 context
= self
.expect_gdbremote_sequence()
518 self
.assertIsNotNone(context
)
519 signo
= context
.get("signo")
520 self
.assertEqual(int(signo
, 16), segfault_signo
)
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
527 # Send SIGUSR1 to the thread that signaled the SIGSEGV.
528 self
.reset_test_sequence()
529 self
.test_sequence
.add_log_lines(
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")
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",
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"},
558 context
= self
.expect_gdbremote_sequence()
559 self
.assertIsNotNone(context
)
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'))
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)
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
)
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
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
)
590 @expectedFailureDarwin
591 @skipIfWindows # no SIGSEGV support
592 @expectedFailureNetBSD
593 def test_Hc_then_Csignal_signals_correct_thread_launch(self
):
595 self
.set_inferior_startup_launch()
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
)
602 self
.Hc_then_Csignal_signals_correct_thread(
603 lldbutil
.get_signal_number("SIGSEGV")
606 @skipIfWindows # No pty support to test any inferior output
607 def test_m_packet_reads_memory(self
):
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"
614 # Start up the inferior.
615 procs
= self
.prep_debug_monitor_and_inferior(
617 "set-message:%s" % MEMORY_CONTENTS
,
618 "get-data-address-hex:g_message",
624 self
.test_sequence
.add_log_lines(
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.
631 "type": "output_match",
632 "regex": self
.maybe_strict_output_regex(
633 r
"data address: 0x([0-9a-fA-F]+)\r\n"
635 "capture": {1: "message_address"},
637 # Now stop the inferior.
638 "read packet: {}".format(chr(3)),
639 # And wait for the stop notification.
642 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
643 "capture": {1: "stop_signo", 2: "stop_thread_id"},
649 # Run the packet stream.
650 context
= self
.expect_gdbremote_sequence()
651 self
.assertIsNotNone(context
)
653 # Grab the message address.
654 self
.assertIsNotNone(context
.get("message_address"))
655 message_address
= int(context
.get("message_address"), 16)
657 # Grab contents from the inferior.
658 self
.reset_test_sequence()
659 self
.test_sequence
.add_log_lines(
661 "read packet: $m{0:x},{1:x}#00".format(
662 message_address
, len(MEMORY_CONTENTS
)
666 "regex": r
"^\$(.+)#[0-9a-fA-F]{2}$",
667 "capture": {1: "read_contents"},
673 # Run the packet stream.
674 context
= self
.expect_gdbremote_sequence()
675 self
.assertIsNotNone(context
)
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
)
682 def test_qMemoryRegionInfo_is_supported(self
):
684 self
.set_inferior_startup_launch()
685 # Start up the inferior.
686 procs
= self
.prep_debug_monitor_and_inferior()
688 # Ask if it supports $qMemoryRegionInfo.
689 self
.test_sequence
.add_log_lines(
690 ["read packet: $qMemoryRegionInfo#00", "send packet: $OK#00"], True
692 self
.expect_gdbremote_sequence()
694 @skipIfWindows # No pty support to test any inferior output
695 def test_qMemoryRegionInfo_reports_code_address_as_executable(self
):
697 self
.set_inferior_startup_launch()
699 # Start up the inferior.
700 procs
= self
.prep_debug_monitor_and_inferior(
701 inferior_args
=["get-code-address-hex:hello", "sleep:5"]
705 self
.test_sequence
.add_log_lines(
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.
712 "type": "output_match",
713 "regex": self
.maybe_strict_output_regex(
714 r
"code address: 0x([0-9a-fA-F]+)\r\n"
716 "capture": {1: "code_address"},
718 # Now stop the inferior.
719 "read packet: {}".format(chr(3)),
720 # And wait for the stop notification.
723 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
724 "capture": {1: "stop_signo", 2: "stop_thread_id"},
730 # Run the packet stream.
731 context
= self
.expect_gdbremote_sequence()
732 self
.assertIsNotNone(context
)
734 # Grab the code address.
735 self
.assertIsNotNone(context
.get("code_address"))
736 code_address
= int(context
.get("code_address"), 16)
738 # Grab memory region info from the inferior.
739 self
.reset_test_sequence()
740 self
.add_query_memory_region_packets(code_address
)
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
)
747 # Ensure there are no errors reported.
748 self
.assertNotIn("error", mem_region_dict
)
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"])
755 # Ensure the start address and size encompass the address we queried.
756 self
.assert_address_within_memory_region(code_address
, mem_region_dict
)
758 @skipIfWindows # No pty support to test any inferior output
759 def test_qMemoryRegionInfo_reports_stack_address_as_rw(self
):
761 self
.set_inferior_startup_launch()
763 # Start up the inferior.
764 procs
= self
.prep_debug_monitor_and_inferior(
765 inferior_args
=["get-stack-address-hex:", "sleep:5"]
769 self
.test_sequence
.add_log_lines(
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.
776 "type": "output_match",
777 "regex": self
.maybe_strict_output_regex(
778 r
"stack address: 0x([0-9a-fA-F]+)\r\n"
780 "capture": {1: "stack_address"},
782 # Now stop the inferior.
783 "read packet: {}".format(chr(3)),
784 # And wait for the stop notification.
787 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
788 "capture": {1: "stop_signo", 2: "stop_thread_id"},
794 # Run the packet stream.
795 context
= self
.expect_gdbremote_sequence()
796 self
.assertIsNotNone(context
)
799 self
.assertIsNotNone(context
.get("stack_address"))
800 stack_address
= int(context
.get("stack_address"), 16)
802 # Grab memory region info from the inferior.
803 self
.reset_test_sequence()
804 self
.add_query_memory_region_packets(stack_address
)
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
)
811 # Ensure there are no errors reported.
812 self
.assertNotIn("error", mem_region_dict
)
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"])
819 # Ensure the start address and size encompass the address we queried.
820 self
.assert_address_within_memory_region(stack_address
, mem_region_dict
)
822 @skipIfWindows # No pty support to test any inferior output
823 def test_qMemoryRegionInfo_reports_heap_address_as_rw(self
):
825 self
.set_inferior_startup_launch()
827 # Start up the inferior.
828 procs
= self
.prep_debug_monitor_and_inferior(
829 inferior_args
=["get-heap-address-hex:", "sleep:5"]
833 self
.test_sequence
.add_log_lines(
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.
840 "type": "output_match",
841 "regex": self
.maybe_strict_output_regex(
842 r
"heap address: 0x([0-9a-fA-F]+)\r\n"
844 "capture": {1: "heap_address"},
846 # Now stop the inferior.
847 "read packet: {}".format(chr(3)),
848 # And wait for the stop notification.
851 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
852 "capture": {1: "stop_signo", 2: "stop_thread_id"},
858 # Run the packet stream.
859 context
= self
.expect_gdbremote_sequence()
860 self
.assertIsNotNone(context
)
863 self
.assertIsNotNone(context
.get("heap_address"))
864 heap_address
= int(context
.get("heap_address"), 16)
866 # Grab memory region info from the inferior.
867 self
.reset_test_sequence()
868 self
.add_query_memory_region_packets(heap_address
)
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
)
875 # Ensure there are no errors reported.
876 self
.assertNotIn("error", mem_region_dict
)
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"])
883 # Ensure the start address and size encompass the address we queried.
884 self
.assert_address_within_memory_region(heap_address
, mem_region_dict
)
886 def breakpoint_set_and_remove_work(self
, want_hardware
):
887 # Start up the inferior.
888 procs
= self
.prep_debug_monitor_and_inferior(
890 "get-code-address-hex:hello",
892 "call-function:hello",
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.
905 "type": "output_match",
906 "regex": self
.maybe_strict_output_regex(
907 r
"code address: 0x([0-9a-fA-F]+)\r\n"
909 "capture": {1: "function_address"},
911 # Now stop the inferior.
912 "read packet: {}".format(chr(3)),
913 # And wait for the stop notification.
916 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
917 "capture": {1: "stop_signo", 2: "stop_thread_id"},
923 # Run the packet stream.
924 context
= self
.expect_gdbremote_sequence()
925 self
.assertIsNotNone(context
)
927 # Gather process info - we need endian of target to handle register
929 process_info
= self
.parse_process_info_response(context
)
930 endian
= process_info
.get("endian")
931 self
.assertIsNotNone(endian
)
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
)
939 # Grab the function address.
940 self
.assertIsNotNone(context
.get("function_address"))
941 function_address
= int(context
.get("function_address"), 16)
943 # Get current target architecture
944 target_arch
= self
.getArchitecture()
946 # Set the breakpoint.
947 if target_arch
in ["arm", "arm64", "aarch64"]:
948 # TODO: Handle case when setting breakpoint in thumb code
953 # Set default packet type to Z0 (software breakpoint)
956 # If hardware breakpoint is requested set packet type to Z1
960 self
.reset_test_sequence()
961 self
.add_set_breakpoint_packets(
965 breakpoint_kind
=BREAKPOINT_KIND
,
968 # Run the packet stream.
969 context
= self
.expect_gdbremote_sequence()
970 self
.assertIsNotNone(context
)
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"))
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)
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(
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.
992 "regex": r
"^\$([0-9a-fA-F]+)#",
993 "capture": {1: "p_response"},
999 context
= self
.expect_gdbremote_sequence()
1000 self
.assertIsNotNone(context
)
1002 # Verify the PC is where we expect. Note response is in endianness of
1004 p_response
= context
.get("p_response")
1005 self
.assertIsNotNone(p_response
)
1007 # Convert from target endian to int.
1008 returned_pc
= lldbgdbserverutils
.unpack_register_hex_unsigned(
1011 self
.assertEqual(returned_pc
, function_address
)
1013 # Verify that a breakpoint remove and continue gets us the expected
1015 self
.reset_test_sequence()
1017 # Add breakpoint remove packets
1018 self
.add_remove_breakpoint_packets(
1019 function_address
, z_packet_type
, breakpoint_kind
=BREAKPOINT_KIND
1022 self
.test_sequence
.add_log_lines(
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}$"},
1034 context
= self
.expect_gdbremote_sequence()
1035 self
.assertIsNotNone(context
)
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"})
1044 self
.set_inferior_startup_launch()
1045 self
.breakpoint_set_and_remove_work(want_hardware
=False)
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"})
1055 self
.set_inferior_startup_launch()
1056 self
.breakpoint_set_and_remove_work(want_hardware
=True)
1058 def get_qSupported_dict(self
, features
=[]):
1060 self
.set_inferior_startup_launch()
1062 # Start up the stub and start/prep the inferior.
1063 procs
= self
.prep_debug_monitor_and_inferior()
1064 self
.add_qSupported_packets(features
)
1066 # Run the packet stream.
1067 context
= self
.expect_gdbremote_sequence()
1068 self
.assertIsNotNone(context
)
1070 # Retrieve the qSupported features.
1071 return self
.parse_qSupported_response(context
)
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)
1078 def test_qSupported_auvx(self
):
1081 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1084 supported_dict
= self
.get_qSupported_dict()
1085 self
.assertEqual(supported_dict
.get("qXfer:auxv:read", "-"), expected
)
1087 def test_qSupported_libraries_svr4(self
):
1090 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1093 supported_dict
= self
.get_qSupported_dict()
1094 self
.assertEqual(supported_dict
.get("qXfer:libraries-svr4:read", "-"), expected
)
1096 def test_qSupported_siginfo_read(self
):
1098 "+" if lldbplatformutil
.getPlatform() in ["freebsd", "linux"] else "-"
1100 supported_dict
= self
.get_qSupported_dict()
1101 self
.assertEqual(supported_dict
.get("qXfer:siginfo:read", "-"), expected
)
1103 def test_qSupported_QPassSignals(self
):
1106 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1109 supported_dict
= self
.get_qSupported_dict()
1110 self
.assertEqual(supported_dict
.get("QPassSignals", "-"), expected
)
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", "-"), "-")
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", "-"), "-")
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", "-"), "+")
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", "-"), "-")
1140 # We need to be able to self.runCmd to get cpuinfo,
1141 # which is not possible when using a remote platform.
1143 def test_qSupported_memory_tagging(self
):
1144 supported_dict
= self
.get_qSupported_dict()
1146 supported_dict
.get("memory-tagging", "-"),
1147 "+" if self
.isAArch64MTE() else "-",
1150 @skipIfWindows # No pty support to test any inferior output
1151 def test_written_M_content_reads_back_correctly(self
):
1153 self
.set_inferior_startup_launch()
1155 TEST_MESSAGE
= "Hello, memory"
1157 # Start up the stub and start/prep the inferior.
1158 procs
= self
.prep_debug_monitor_and_inferior(
1160 "set-message:xxxxxxxxxxxxxX",
1161 "get-data-address-hex:g_message",
1166 self
.test_sequence
.add_log_lines(
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.
1173 "type": "output_match",
1174 "regex": self
.maybe_strict_output_regex(
1175 r
"data address: 0x([0-9a-fA-F]+)\r\n"
1177 "capture": {1: "message_address"},
1179 # Now stop the inferior.
1180 "read packet: {}".format(chr(3)),
1181 # And wait for the stop notification.
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"},
1190 context
= self
.expect_gdbremote_sequence()
1191 self
.assertIsNotNone(context
)
1193 # Grab the message address.
1194 self
.assertIsNotNone(context
.get("message_address"))
1195 message_address
= int(context
.get("message_address"), 16)
1197 # Hex-encode the test message, adding null termination.
1198 hex_encoded_message
= seven
.hexlify(TEST_MESSAGE
)
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(
1205 "read packet: $M{0:x},{1:x}:{2}#00".format(
1206 message_address
, len(TEST_MESSAGE
), hex_encoded_message
1208 "send packet: $OK#00",
1209 "read packet: $m{0:x},{1:x}#00".format(
1210 message_address
, len(TEST_MESSAGE
)
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
)
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",
1223 "type": "output_match",
1224 "regex": r
"^message: (.+)\r\n$",
1225 "capture": {1: "printed_message"},
1227 "send packet: $W00#00",
1231 context
= self
.expect_gdbremote_sequence()
1232 self
.assertIsNotNone(context
)
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")
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
):
1244 self
.set_inferior_startup_launch()
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()
1251 context
= self
.expect_gdbremote_sequence()
1252 self
.assertIsNotNone(context
)
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
)
1260 process_info
= self
.parse_process_info_response(context
)
1261 endian
= process_info
.get("endian")
1262 self
.assertIsNotNone(endian
)
1264 # Pull out the register infos that we think we can bit flip
1268 for reg_info
in reg_infos
1269 if self
.is_bit_flippable_register(reg_info
)
1271 self
.assertGreater(len(gpr_reg_infos
), 0)
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
1278 "successful writes: {}, failed writes: {}".format(
1279 successful_writes
, failed_writes
1282 self
.assertGreater(successful_writes
, 0)
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).
1287 def test_P_and_p_thread_suffix_work(self
):
1289 self
.set_inferior_startup_launch()
1291 # Startup the inferior with three threads.
1292 _
, threads
= self
.launch_with_threads(3)
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()
1299 context
= self
.expect_gdbremote_sequence()
1300 self
.assertIsNotNone(context
)
1302 process_info
= self
.parse_process_info_response(context
)
1303 self
.assertIsNotNone(process_info
)
1304 endian
= process_info
.get("endian")
1305 self
.assertIsNotNone(endian
)
1307 reg_infos
= self
.parse_register_info_packets(context
)
1308 self
.assertIsNotNone(reg_infos
)
1309 self
.add_lldb_register_index(reg_infos
)
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)
1316 expected_reg_values
= []
1317 register_increment
= 1
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
1326 # Read pre-existing register value.
1327 self
.reset_test_sequence()
1328 self
.test_sequence
.add_log_lines(
1330 "read packet: $p{0:x};thread:{1:x}#00".format(
1334 "direction": "send",
1335 "regex": r
"^\$([0-9a-fA-F]+)#",
1336 "capture": {1: "p_response"},
1341 context
= self
.expect_gdbremote_sequence()
1342 self
.assertIsNotNone(context
)
1344 # Set the next value to use for writing as the increment plus
1346 p_response
= context
.get("p_response")
1347 self
.assertIsNotNone(p_response
)
1348 next_value
= lldbgdbserverutils
.unpack_register_hex_unsigned(
1352 # Set new value using P and thread suffix.
1353 self
.reset_test_sequence()
1354 self
.test_sequence
.add_log_lines(
1356 "read packet: $P{0:x}={1};thread:{2:x}#00".format(
1358 lldbgdbserverutils
.pack_register_hex(
1359 endian
, next_value
, byte_size
=reg_byte_size
1363 "send packet: $OK#00",
1367 context
= self
.expect_gdbremote_sequence()
1368 self
.assertIsNotNone(context
)
1370 # Save the value we set.
1371 expected_reg_values
.append(next_value
)
1373 # Increment value for next thread to use (we want them all
1374 # different so we can verify they wrote to each thread correctly
1376 next_value
+= register_increment
1378 # Revisit each thread and verify they have the expected value set for
1379 # the register we wrote.
1381 for thread
in threads
:
1382 # Read pre-existing register value.
1383 self
.reset_test_sequence()
1384 self
.test_sequence
.add_log_lines(
1386 "read packet: $p{0:x};thread:{1:x}#00".format(reg_index
, thread
),
1388 "direction": "send",
1389 "regex": r
"^\$([0-9a-fA-F]+)#",
1390 "capture": {1: "p_response"},
1395 context
= self
.expect_gdbremote_sequence()
1396 self
.assertIsNotNone(context
)
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(
1405 # Make sure we read back what we wrote.
1406 self
.assertEqual(read_value
, expected_reg_values
[thread_index
])
1409 @skipUnlessPlatform(oslist
=["freebsd", "linux"])
1410 @add_test_categories(["llgs"])
1411 def test_qXfer_siginfo_read(self
):
1413 self
.set_inferior_startup_launch()
1414 procs
= self
.prep_debug_monitor_and_inferior(
1415 inferior_args
=["thread:segfault", "thread:new", "sleep:10"]
1417 self
.test_sequence
.add_log_lines(["read packet: $c#63"], True)
1418 self
.expect_gdbremote_sequence()
1420 # Run until SIGSEGV comes in.
1421 self
.reset_test_sequence()
1422 self
.test_sequence
.add_log_lines(
1425 "direction": "send",
1426 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
1427 "capture": {1: "signo", 2: "thread_id"},
1433 # Figure out which thread crashed.
1434 context
= self
.expect_gdbremote_sequence()
1435 self
.assertIsNotNone(context
)
1437 int(context
["signo"], 16), lldbutil
.get_signal_number("SIGSEGV")
1439 crashing_thread
= int(context
["thread_id"], 16)
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(
1446 "read packet: $Hg{:x}#00".format(crashing_thread
),
1447 "send packet: $OK#00",
1448 "read packet: $qXfer:siginfo:read::0,80:#00",
1450 "direction": "send",
1451 "regex": re
.compile(
1452 r
"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re
.MULTILINE | re
.DOTALL
1454 "capture": {1: "response_type", 2: "content_raw"},
1459 context
= self
.expect_gdbremote_sequence()
1460 self
.assertIsNotNone(context
)
1462 # Ensure we end up with all data in one packet.
1463 self
.assertEqual(context
.get("response_type"), "l")
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")
1471 process_info
= self
.parse_process_info_response(context
)
1473 if process_info
["ptrsize"] == "8":
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
)
1492 assert False, "unknown ostype"
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