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
.assertTrue(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
.assertTrue(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 def test_Hg_fails_on_minus_one_pid(self
):
473 self
.set_inferior_startup_launch()
474 self
.Hg_fails_on_pid(-1)
476 def Hc_then_Csignal_signals_correct_thread(self
, segfault_signo
):
477 # NOTE only run this one in inferior-launched mode: we can't grab inferior stdout when running attached,
478 # and the test requires getting stdout from the exe.
482 # Startup the inferior with three threads (main + NUM_THREADS-1 worker threads).
483 # inferior_args=["thread:print-ids"]
484 inferior_args
= ["thread:segfault"]
485 for i
in range(NUM_THREADS
- 1):
487 # Give time between thread creation/segfaulting for the handler to work.
488 # inferior_args.append("sleep:1")
489 inferior_args
.append("thread:new")
490 inferior_args
.append("sleep:10")
492 # Launch/attach. (In our case, this should only ever be launched since
493 # we need inferior stdout/stderr).
494 procs
= self
.prep_debug_monitor_and_inferior(inferior_args
=inferior_args
)
495 self
.test_sequence
.add_log_lines(["read packet: $c#63"], True)
496 context
= self
.expect_gdbremote_sequence()
499 print_thread_ids
= {}
501 # Switch to each thread, deliver a signal, and verify signal delivery
502 for i
in range(NUM_THREADS
- 1):
503 # Run until SIGSEGV comes in.
504 self
.reset_test_sequence()
505 self
.test_sequence
.add_log_lines(
509 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
510 "capture": {1: "signo", 2: "thread_id"},
516 context
= self
.expect_gdbremote_sequence()
517 self
.assertIsNotNone(context
)
518 signo
= context
.get("signo")
519 self
.assertEqual(int(signo
, 16), segfault_signo
)
521 # Ensure we haven't seen this tid yet.
522 thread_id
= int(context
.get("thread_id"), 16)
523 self
.assertNotIn(thread_id
, signaled_tids
)
524 signaled_tids
[thread_id
] = 1
526 # Send SIGUSR1 to the thread that signaled the SIGSEGV.
527 self
.reset_test_sequence()
528 self
.test_sequence
.add_log_lines(
530 # Set the continue thread.
531 # Set current thread.
532 "read packet: $Hc{0:x}#00".format(thread_id
),
533 "send packet: $OK#00",
534 # Continue sending the signal number to the continue thread.
535 # The commented out packet is a way to do this same operation without using
536 # a $Hc (but this test is testing $Hc, so we'll stick with the former).
537 "read packet: $C{0:x}#00".format(
538 lldbutil
.get_signal_number("SIGUSR1")
540 # "read packet: $vCont;C{0:x}:{1:x};c#00".format(lldbutil.get_signal_number('SIGUSR1'), thread_id),
541 # FIXME: Linux does not report the thread stop on the delivered signal (SIGUSR1 here). MacOSX debugserver does.
542 # But MacOSX debugserver isn't guaranteeing the thread the signal handler runs on, so currently its an XFAIL.
543 # Need to rectify behavior here. The linux behavior is more intuitive to me since we're essentially swapping out
544 # an about-to-be-delivered signal (for which we already sent a stop packet) to a different signal.
545 # {"direction":"send", "regex":r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);", "capture":{1:"stop_signo", 2:"stop_thread_id"} },
546 # "read packet: $c#63",
548 "type": "output_match",
549 "regex": r
"^received SIGUSR1 on thread id: ([0-9a-fA-F]+)\r\nthread ([0-9a-fA-F]+): past SIGSEGV\r\n",
550 "capture": {1: "print_thread_id", 2: "post_handle_thread_id"},
557 context
= self
.expect_gdbremote_sequence()
558 self
.assertIsNotNone(context
)
560 # Ensure the stop signal is the signal we delivered.
561 # stop_signo = context.get("stop_signo")
562 # self.assertIsNotNone(stop_signo)
563 # self.assertEquals(int(stop_signo,16), lldbutil.get_signal_number('SIGUSR1'))
565 # Ensure the stop thread is the thread to which we delivered the signal.
566 # stop_thread_id = context.get("stop_thread_id")
567 # self.assertIsNotNone(stop_thread_id)
568 # self.assertEquals(int(stop_thread_id,16), thread_id)
570 # Ensure we haven't seen this thread id yet. The inferior's
571 # self-obtained thread ids are not guaranteed to match the stub
572 # tids (at least on MacOSX).
573 print_thread_id
= context
.get("print_thread_id")
574 self
.assertIsNotNone(print_thread_id
)
575 print_thread_id
= int(print_thread_id
, 16)
576 self
.assertNotIn(print_thread_id
, print_thread_ids
)
578 # Now remember this print (i.e. inferior-reflected) thread id and
579 # ensure we don't hit it again.
580 print_thread_ids
[print_thread_id
] = 1
582 # Ensure post signal-handle thread id matches the thread that
583 # initially raised the SIGSEGV.
584 post_handle_thread_id
= context
.get("post_handle_thread_id")
585 self
.assertIsNotNone(post_handle_thread_id
)
586 post_handle_thread_id
= int(post_handle_thread_id
, 16)
587 self
.assertEqual(post_handle_thread_id
, print_thread_id
)
589 @expectedFailureDarwin
590 @skipIfWindows # no SIGSEGV support
591 @expectedFailureNetBSD
592 def test_Hc_then_Csignal_signals_correct_thread_launch(self
):
594 self
.set_inferior_startup_launch()
596 if self
.platformIsDarwin():
597 # Darwin debugserver translates some signals like SIGSEGV into some gdb
598 # expectations about fixed signal numbers.
599 self
.Hc_then_Csignal_signals_correct_thread(self
.TARGET_EXC_BAD_ACCESS
)
601 self
.Hc_then_Csignal_signals_correct_thread(
602 lldbutil
.get_signal_number("SIGSEGV")
605 @skipIfWindows # No pty support to test any inferior output
606 def test_m_packet_reads_memory(self
):
608 self
.set_inferior_startup_launch()
609 # This is the memory we will write into the inferior and then ensure we
610 # can read back with $m.
611 MEMORY_CONTENTS
= "Test contents 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
613 # Start up the inferior.
614 procs
= self
.prep_debug_monitor_and_inferior(
616 "set-message:%s" % MEMORY_CONTENTS
,
617 "get-data-address-hex:g_message",
623 self
.test_sequence
.add_log_lines(
625 # Start running after initial stop.
626 "read packet: $c#63",
627 # Match output line that prints the memory address of the message buffer within the inferior.
628 # Note we require launch-only testing so we can get inferior otuput.
630 "type": "output_match",
631 "regex": self
.maybe_strict_output_regex(
632 r
"data address: 0x([0-9a-fA-F]+)\r\n"
634 "capture": {1: "message_address"},
636 # Now stop the inferior.
637 "read packet: {}".format(chr(3)),
638 # And wait for the stop notification.
641 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
642 "capture": {1: "stop_signo", 2: "stop_thread_id"},
648 # Run the packet stream.
649 context
= self
.expect_gdbremote_sequence()
650 self
.assertIsNotNone(context
)
652 # Grab the message address.
653 self
.assertIsNotNone(context
.get("message_address"))
654 message_address
= int(context
.get("message_address"), 16)
656 # Grab contents from the inferior.
657 self
.reset_test_sequence()
658 self
.test_sequence
.add_log_lines(
660 "read packet: $m{0:x},{1:x}#00".format(
661 message_address
, len(MEMORY_CONTENTS
)
665 "regex": r
"^\$(.+)#[0-9a-fA-F]{2}$",
666 "capture": {1: "read_contents"},
672 # Run the packet stream.
673 context
= self
.expect_gdbremote_sequence()
674 self
.assertIsNotNone(context
)
676 # Ensure what we read from inferior memory is what we wrote.
677 self
.assertIsNotNone(context
.get("read_contents"))
678 read_contents
= seven
.unhexlify(context
.get("read_contents"))
679 self
.assertEqual(read_contents
, MEMORY_CONTENTS
)
681 def test_qMemoryRegionInfo_is_supported(self
):
683 self
.set_inferior_startup_launch()
684 # Start up the inferior.
685 procs
= self
.prep_debug_monitor_and_inferior()
687 # Ask if it supports $qMemoryRegionInfo.
688 self
.test_sequence
.add_log_lines(
689 ["read packet: $qMemoryRegionInfo#00", "send packet: $OK#00"], True
691 self
.expect_gdbremote_sequence()
693 @skipIfWindows # No pty support to test any inferior output
694 def test_qMemoryRegionInfo_reports_code_address_as_executable(self
):
696 self
.set_inferior_startup_launch()
698 # Start up the inferior.
699 procs
= self
.prep_debug_monitor_and_inferior(
700 inferior_args
=["get-code-address-hex:hello", "sleep:5"]
704 self
.test_sequence
.add_log_lines(
706 # Start running after initial stop.
707 "read packet: $c#63",
708 # Match output line that prints the memory address of the message buffer within the inferior.
709 # Note we require launch-only testing so we can get inferior otuput.
711 "type": "output_match",
712 "regex": self
.maybe_strict_output_regex(
713 r
"code address: 0x([0-9a-fA-F]+)\r\n"
715 "capture": {1: "code_address"},
717 # Now stop the inferior.
718 "read packet: {}".format(chr(3)),
719 # And wait for the stop notification.
722 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
723 "capture": {1: "stop_signo", 2: "stop_thread_id"},
729 # Run the packet stream.
730 context
= self
.expect_gdbremote_sequence()
731 self
.assertIsNotNone(context
)
733 # Grab the code address.
734 self
.assertIsNotNone(context
.get("code_address"))
735 code_address
= int(context
.get("code_address"), 16)
737 # Grab memory region info from the inferior.
738 self
.reset_test_sequence()
739 self
.add_query_memory_region_packets(code_address
)
741 # Run the packet stream.
742 context
= self
.expect_gdbremote_sequence()
743 self
.assertIsNotNone(context
)
744 mem_region_dict
= self
.parse_memory_region_packet(context
)
746 # Ensure there are no errors reported.
747 self
.assertNotIn("error", mem_region_dict
)
749 # Ensure code address is readable and executable.
750 self
.assertIn("permissions", mem_region_dict
)
751 self
.assertIn("r", mem_region_dict
["permissions"])
752 self
.assertIn("x", mem_region_dict
["permissions"])
754 # Ensure the start address and size encompass the address we queried.
755 self
.assert_address_within_memory_region(code_address
, mem_region_dict
)
757 @skipIfWindows # No pty support to test any inferior output
758 def test_qMemoryRegionInfo_reports_stack_address_as_rw(self
):
760 self
.set_inferior_startup_launch()
762 # Start up the inferior.
763 procs
= self
.prep_debug_monitor_and_inferior(
764 inferior_args
=["get-stack-address-hex:", "sleep:5"]
768 self
.test_sequence
.add_log_lines(
770 # Start running after initial stop.
771 "read packet: $c#63",
772 # Match output line that prints the memory address of the message buffer within the inferior.
773 # Note we require launch-only testing so we can get inferior otuput.
775 "type": "output_match",
776 "regex": self
.maybe_strict_output_regex(
777 r
"stack address: 0x([0-9a-fA-F]+)\r\n"
779 "capture": {1: "stack_address"},
781 # Now stop the inferior.
782 "read packet: {}".format(chr(3)),
783 # And wait for the stop notification.
786 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
787 "capture": {1: "stop_signo", 2: "stop_thread_id"},
793 # Run the packet stream.
794 context
= self
.expect_gdbremote_sequence()
795 self
.assertIsNotNone(context
)
798 self
.assertIsNotNone(context
.get("stack_address"))
799 stack_address
= int(context
.get("stack_address"), 16)
801 # Grab memory region info from the inferior.
802 self
.reset_test_sequence()
803 self
.add_query_memory_region_packets(stack_address
)
805 # Run the packet stream.
806 context
= self
.expect_gdbremote_sequence()
807 self
.assertIsNotNone(context
)
808 mem_region_dict
= self
.parse_memory_region_packet(context
)
810 # Ensure there are no errors reported.
811 self
.assertNotIn("error", mem_region_dict
)
813 # Ensure address is readable and executable.
814 self
.assertIn("permissions", mem_region_dict
)
815 self
.assertIn("r", mem_region_dict
["permissions"])
816 self
.assertIn("w", mem_region_dict
["permissions"])
818 # Ensure the start address and size encompass the address we queried.
819 self
.assert_address_within_memory_region(stack_address
, mem_region_dict
)
821 @skipIfWindows # No pty support to test any inferior output
822 def test_qMemoryRegionInfo_reports_heap_address_as_rw(self
):
824 self
.set_inferior_startup_launch()
826 # Start up the inferior.
827 procs
= self
.prep_debug_monitor_and_inferior(
828 inferior_args
=["get-heap-address-hex:", "sleep:5"]
832 self
.test_sequence
.add_log_lines(
834 # Start running after initial stop.
835 "read packet: $c#63",
836 # Match output line that prints the memory address of the message buffer within the inferior.
837 # Note we require launch-only testing so we can get inferior otuput.
839 "type": "output_match",
840 "regex": self
.maybe_strict_output_regex(
841 r
"heap address: 0x([0-9a-fA-F]+)\r\n"
843 "capture": {1: "heap_address"},
845 # Now stop the inferior.
846 "read packet: {}".format(chr(3)),
847 # And wait for the stop notification.
850 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
851 "capture": {1: "stop_signo", 2: "stop_thread_id"},
857 # Run the packet stream.
858 context
= self
.expect_gdbremote_sequence()
859 self
.assertIsNotNone(context
)
862 self
.assertIsNotNone(context
.get("heap_address"))
863 heap_address
= int(context
.get("heap_address"), 16)
865 # Grab memory region info from the inferior.
866 self
.reset_test_sequence()
867 self
.add_query_memory_region_packets(heap_address
)
869 # Run the packet stream.
870 context
= self
.expect_gdbremote_sequence()
871 self
.assertIsNotNone(context
)
872 mem_region_dict
= self
.parse_memory_region_packet(context
)
874 # Ensure there are no errors reported.
875 self
.assertNotIn("error", mem_region_dict
)
877 # Ensure address is readable and executable.
878 self
.assertIn("permissions", mem_region_dict
)
879 self
.assertIn("r", mem_region_dict
["permissions"])
880 self
.assertIn("w", mem_region_dict
["permissions"])
882 # Ensure the start address and size encompass the address we queried.
883 self
.assert_address_within_memory_region(heap_address
, mem_region_dict
)
885 def breakpoint_set_and_remove_work(self
, want_hardware
):
886 # Start up the inferior.
887 procs
= self
.prep_debug_monitor_and_inferior(
889 "get-code-address-hex:hello",
891 "call-function:hello",
896 self
.add_register_info_collection_packets()
897 self
.add_process_info_collection_packets()
898 self
.test_sequence
.add_log_lines(
899 [ # Start running after initial stop.
900 "read packet: $c#63",
901 # Match output line that prints the memory address of the function call entry point.
902 # Note we require launch-only testing so we can get inferior otuput.
904 "type": "output_match",
905 "regex": self
.maybe_strict_output_regex(
906 r
"code address: 0x([0-9a-fA-F]+)\r\n"
908 "capture": {1: "function_address"},
910 # Now stop the inferior.
911 "read packet: {}".format(chr(3)),
912 # And wait for the stop notification.
915 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
916 "capture": {1: "stop_signo", 2: "stop_thread_id"},
922 # Run the packet stream.
923 context
= self
.expect_gdbremote_sequence()
924 self
.assertIsNotNone(context
)
926 # Gather process info - we need endian of target to handle register
928 process_info
= self
.parse_process_info_response(context
)
929 endian
= process_info
.get("endian")
930 self
.assertIsNotNone(endian
)
932 # Gather register info entries.
933 reg_infos
= self
.parse_register_info_packets(context
)
934 (pc_lldb_reg_index
, pc_reg_info
) = self
.find_pc_reg_info(reg_infos
)
935 self
.assertIsNotNone(pc_lldb_reg_index
)
936 self
.assertIsNotNone(pc_reg_info
)
938 # Grab the function address.
939 self
.assertIsNotNone(context
.get("function_address"))
940 function_address
= int(context
.get("function_address"), 16)
942 # Get current target architecture
943 target_arch
= self
.getArchitecture()
945 # Set the breakpoint.
946 if target_arch
in ["arm", "arm64", "aarch64"]:
947 # TODO: Handle case when setting breakpoint in thumb code
952 # Set default packet type to Z0 (software breakpoint)
955 # If hardware breakpoint is requested set packet type to Z1
956 if want_hardware
== True:
959 self
.reset_test_sequence()
960 self
.add_set_breakpoint_packets(
964 breakpoint_kind
=BREAKPOINT_KIND
,
967 # Run the packet stream.
968 context
= self
.expect_gdbremote_sequence()
969 self
.assertIsNotNone(context
)
971 # Verify the stop signal reported was the breakpoint signal number.
972 stop_signo
= context
.get("stop_signo")
973 self
.assertIsNotNone(stop_signo
)
974 self
.assertEqual(int(stop_signo
, 16), lldbutil
.get_signal_number("SIGTRAP"))
976 # Ensure we did not receive any output. If the breakpoint was not set, we would
977 # see output (from a launched process with captured stdio) printing a hello, world message.
978 # That would indicate the breakpoint didn't take.
979 self
.assertEqual(len(context
["O_content"]), 0)
981 # Verify that the PC for the main thread is where we expect it - right at the breakpoint address.
982 # This acts as a another validation on the register reading code.
983 self
.reset_test_sequence()
984 self
.test_sequence
.add_log_lines(
986 # Print the PC. This should match the breakpoint address.
987 "read packet: $p{0:x}#00".format(pc_lldb_reg_index
),
988 # Capture $p results.
991 "regex": r
"^\$([0-9a-fA-F]+)#",
992 "capture": {1: "p_response"},
998 context
= self
.expect_gdbremote_sequence()
999 self
.assertIsNotNone(context
)
1001 # Verify the PC is where we expect. Note response is in endianness of
1003 p_response
= context
.get("p_response")
1004 self
.assertIsNotNone(p_response
)
1006 # Convert from target endian to int.
1007 returned_pc
= lldbgdbserverutils
.unpack_register_hex_unsigned(
1010 self
.assertEqual(returned_pc
, function_address
)
1012 # Verify that a breakpoint remove and continue gets us the expected
1014 self
.reset_test_sequence()
1016 # Add breakpoint remove packets
1017 self
.add_remove_breakpoint_packets(
1018 function_address
, z_packet_type
, breakpoint_kind
=BREAKPOINT_KIND
1021 self
.test_sequence
.add_log_lines(
1024 "read packet: $c#63",
1025 # We should now receive the output from the call.
1026 {"type": "output_match", "regex": r
"^hello, world\r\n$"},
1027 # And wait for program completion.
1028 {"direction": "send", "regex": r
"^\$W00(.*)#[0-9a-fA-F]{2}$"},
1033 context
= self
.expect_gdbremote_sequence()
1034 self
.assertIsNotNone(context
)
1036 @skipIfWindows # No pty support to test any inferior output
1037 def test_software_breakpoint_set_and_remove_work(self
):
1038 if self
.getArchitecture() == "arm":
1039 # TODO: Handle case when setting breakpoint in thumb code
1040 self
.build(dictionary
={"CFLAGS_EXTRAS": "-marm"})
1043 self
.set_inferior_startup_launch()
1044 self
.breakpoint_set_and_remove_work(want_hardware
=False)
1046 @skipUnlessPlatform(oslist
=["linux"])
1047 @skipIf(archs
=no_match(["arm", "aarch64"]))
1048 def test_hardware_breakpoint_set_and_remove_work(self
):
1049 if self
.getArchitecture() == "arm":
1050 # TODO: Handle case when setting breakpoint in thumb code
1051 self
.build(dictionary
={"CFLAGS_EXTRAS": "-marm"})
1054 self
.set_inferior_startup_launch()
1055 self
.breakpoint_set_and_remove_work(want_hardware
=True)
1057 def get_qSupported_dict(self
, features
=[]):
1059 self
.set_inferior_startup_launch()
1061 # Start up the stub and start/prep the inferior.
1062 procs
= self
.prep_debug_monitor_and_inferior()
1063 self
.add_qSupported_packets(features
)
1065 # Run the packet stream.
1066 context
= self
.expect_gdbremote_sequence()
1067 self
.assertIsNotNone(context
)
1069 # Retrieve the qSupported features.
1070 return self
.parse_qSupported_response(context
)
1072 def test_qSupported_returns_known_stub_features(self
):
1073 supported_dict
= self
.get_qSupported_dict()
1074 self
.assertIsNotNone(supported_dict
)
1075 self
.assertTrue(len(supported_dict
) > 0)
1077 def test_qSupported_auvx(self
):
1080 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1083 supported_dict
= self
.get_qSupported_dict()
1084 self
.assertEqual(supported_dict
.get("qXfer:auxv:read", "-"), expected
)
1086 def test_qSupported_libraries_svr4(self
):
1089 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1092 supported_dict
= self
.get_qSupported_dict()
1093 self
.assertEqual(supported_dict
.get("qXfer:libraries-svr4:read", "-"), expected
)
1095 def test_qSupported_siginfo_read(self
):
1097 "+" if lldbplatformutil
.getPlatform() in ["freebsd", "linux"] else "-"
1099 supported_dict
= self
.get_qSupported_dict()
1100 self
.assertEqual(supported_dict
.get("qXfer:siginfo:read", "-"), expected
)
1102 def test_qSupported_QPassSignals(self
):
1105 if lldbplatformutil
.getPlatform() in ["freebsd", "linux", "netbsd"]
1108 supported_dict
= self
.get_qSupported_dict()
1109 self
.assertEqual(supported_dict
.get("QPassSignals", "-"), expected
)
1111 @add_test_categories(["fork"])
1112 def test_qSupported_fork_events(self
):
1113 supported_dict
= self
.get_qSupported_dict(["multiprocess+", "fork-events+"])
1114 self
.assertEqual(supported_dict
.get("multiprocess", "-"), "+")
1115 self
.assertEqual(supported_dict
.get("fork-events", "-"), "+")
1116 self
.assertEqual(supported_dict
.get("vfork-events", "-"), "-")
1118 @add_test_categories(["fork"])
1119 def test_qSupported_fork_events_without_multiprocess(self
):
1120 supported_dict
= self
.get_qSupported_dict(["fork-events+"])
1121 self
.assertEqual(supported_dict
.get("multiprocess", "-"), "-")
1122 self
.assertEqual(supported_dict
.get("fork-events", "-"), "-")
1123 self
.assertEqual(supported_dict
.get("vfork-events", "-"), "-")
1125 @add_test_categories(["fork"])
1126 def test_qSupported_vfork_events(self
):
1127 supported_dict
= self
.get_qSupported_dict(["multiprocess+", "vfork-events+"])
1128 self
.assertEqual(supported_dict
.get("multiprocess", "-"), "+")
1129 self
.assertEqual(supported_dict
.get("fork-events", "-"), "-")
1130 self
.assertEqual(supported_dict
.get("vfork-events", "-"), "+")
1132 @add_test_categories(["fork"])
1133 def test_qSupported_vfork_events_without_multiprocess(self
):
1134 supported_dict
= self
.get_qSupported_dict(["vfork-events+"])
1135 self
.assertEqual(supported_dict
.get("multiprocess", "-"), "-")
1136 self
.assertEqual(supported_dict
.get("fork-events", "-"), "-")
1137 self
.assertEqual(supported_dict
.get("vfork-events", "-"), "-")
1139 # We need to be able to self.runCmd to get cpuinfo,
1140 # which is not possible when using a remote platform.
1142 def test_qSupported_memory_tagging(self
):
1143 supported_dict
= self
.get_qSupported_dict()
1145 supported_dict
.get("memory-tagging", "-"),
1146 "+" if self
.isAArch64MTE() else "-",
1149 @skipIfWindows # No pty support to test any inferior output
1150 def test_written_M_content_reads_back_correctly(self
):
1152 self
.set_inferior_startup_launch()
1154 TEST_MESSAGE
= "Hello, memory"
1156 # Start up the stub and start/prep the inferior.
1157 procs
= self
.prep_debug_monitor_and_inferior(
1159 "set-message:xxxxxxxxxxxxxX",
1160 "get-data-address-hex:g_message",
1165 self
.test_sequence
.add_log_lines(
1167 # Start running after initial stop.
1168 "read packet: $c#63",
1169 # Match output line that prints the memory address of the message buffer within the inferior.
1170 # Note we require launch-only testing so we can get inferior otuput.
1172 "type": "output_match",
1173 "regex": self
.maybe_strict_output_regex(
1174 r
"data address: 0x([0-9a-fA-F]+)\r\n"
1176 "capture": {1: "message_address"},
1178 # Now stop the inferior.
1179 "read packet: {}".format(chr(3)),
1180 # And wait for the stop notification.
1182 "direction": "send",
1183 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
1184 "capture": {1: "stop_signo", 2: "stop_thread_id"},
1189 context
= self
.expect_gdbremote_sequence()
1190 self
.assertIsNotNone(context
)
1192 # Grab the message address.
1193 self
.assertIsNotNone(context
.get("message_address"))
1194 message_address
= int(context
.get("message_address"), 16)
1196 # Hex-encode the test message, adding null termination.
1197 hex_encoded_message
= seven
.hexlify(TEST_MESSAGE
)
1199 # Write the message to the inferior. Verify that we can read it with the hex-encoded (m)
1200 # and binary (x) memory read packets.
1201 self
.reset_test_sequence()
1202 self
.test_sequence
.add_log_lines(
1204 "read packet: $M{0:x},{1:x}:{2}#00".format(
1205 message_address
, len(TEST_MESSAGE
), hex_encoded_message
1207 "send packet: $OK#00",
1208 "read packet: $m{0:x},{1:x}#00".format(
1209 message_address
, len(TEST_MESSAGE
)
1211 "send packet: ${0}#00".format(hex_encoded_message
),
1212 "read packet: $x{0:x},{1:x}#00".format(
1213 message_address
, len(TEST_MESSAGE
)
1215 "send packet: ${0}#00".format(TEST_MESSAGE
),
1216 "read packet: $m{0:x},4#00".format(message_address
),
1217 "send packet: ${0}#00".format(hex_encoded_message
[0:8]),
1218 "read packet: $x{0:x},4#00".format(message_address
),
1219 "send packet: ${0}#00".format(TEST_MESSAGE
[0:4]),
1220 "read packet: $c#63",
1222 "type": "output_match",
1223 "regex": r
"^message: (.+)\r\n$",
1224 "capture": {1: "printed_message"},
1226 "send packet: $W00#00",
1230 context
= self
.expect_gdbremote_sequence()
1231 self
.assertIsNotNone(context
)
1233 # Ensure what we read from inferior memory is what we wrote.
1234 printed_message
= context
.get("printed_message")
1235 self
.assertIsNotNone(printed_message
)
1236 self
.assertEqual(printed_message
, TEST_MESSAGE
+ "X")
1238 # Note: as of this moment, a hefty number of the GPR writes are failing with E32 (everything except rax-rdx, rdi, rsi, rbp).
1239 # Come back to this. I have the test rigged to verify that at least some
1240 # of the bit-flip writes work.
1241 def test_P_writes_all_gpr_registers(self
):
1243 self
.set_inferior_startup_launch()
1245 # Start inferior debug session, grab all register info.
1246 procs
= self
.prep_debug_monitor_and_inferior(inferior_args
=["sleep:2"])
1247 self
.add_register_info_collection_packets()
1248 self
.add_process_info_collection_packets()
1250 context
= self
.expect_gdbremote_sequence()
1251 self
.assertIsNotNone(context
)
1253 # Process register infos.
1254 reg_infos
= self
.parse_register_info_packets(context
)
1255 self
.assertIsNotNone(reg_infos
)
1256 self
.add_lldb_register_index(reg_infos
)
1259 process_info
= self
.parse_process_info_response(context
)
1260 endian
= process_info
.get("endian")
1261 self
.assertIsNotNone(endian
)
1263 # Pull out the register infos that we think we can bit flip
1267 for reg_info
in reg_infos
1268 if self
.is_bit_flippable_register(reg_info
)
1270 self
.assertTrue(len(gpr_reg_infos
) > 0)
1272 # Write flipped bit pattern of existing value to each register.
1273 (successful_writes
, failed_writes
) = self
.flip_all_bits_in_each_register_value(
1274 gpr_reg_infos
, endian
1277 "successful writes: {}, failed writes: {}".format(
1278 successful_writes
, failed_writes
1281 self
.assertTrue(successful_writes
> 0)
1283 # Note: as of this moment, a hefty number of the GPR writes are failing
1284 # with E32 (everything except rax-rdx, rdi, rsi, rbp).
1286 def test_P_and_p_thread_suffix_work(self
):
1288 self
.set_inferior_startup_launch()
1290 # Startup the inferior with three threads.
1291 _
, threads
= self
.launch_with_threads(3)
1293 self
.reset_test_sequence()
1294 self
.add_thread_suffix_request_packets()
1295 self
.add_register_info_collection_packets()
1296 self
.add_process_info_collection_packets()
1298 context
= self
.expect_gdbremote_sequence()
1299 self
.assertIsNotNone(context
)
1301 process_info
= self
.parse_process_info_response(context
)
1302 self
.assertIsNotNone(process_info
)
1303 endian
= process_info
.get("endian")
1304 self
.assertIsNotNone(endian
)
1306 reg_infos
= self
.parse_register_info_packets(context
)
1307 self
.assertIsNotNone(reg_infos
)
1308 self
.add_lldb_register_index(reg_infos
)
1310 reg_index
= self
.select_modifiable_register(reg_infos
)
1311 self
.assertIsNotNone(reg_index
)
1312 reg_byte_size
= int(reg_infos
[reg_index
]["bitsize"]) // 8
1313 self
.assertTrue(reg_byte_size
> 0)
1315 expected_reg_values
= []
1316 register_increment
= 1
1319 # Set the same register in each of 3 threads to a different value.
1320 # Verify each one has the unique value.
1321 for thread
in threads
:
1322 # If we don't have a next value yet, start it with the initial read
1325 # Read pre-existing register value.
1326 self
.reset_test_sequence()
1327 self
.test_sequence
.add_log_lines(
1329 "read packet: $p{0:x};thread:{1:x}#00".format(
1333 "direction": "send",
1334 "regex": r
"^\$([0-9a-fA-F]+)#",
1335 "capture": {1: "p_response"},
1340 context
= self
.expect_gdbremote_sequence()
1341 self
.assertIsNotNone(context
)
1343 # Set the next value to use for writing as the increment plus
1345 p_response
= context
.get("p_response")
1346 self
.assertIsNotNone(p_response
)
1347 next_value
= lldbgdbserverutils
.unpack_register_hex_unsigned(
1351 # Set new value using P and thread suffix.
1352 self
.reset_test_sequence()
1353 self
.test_sequence
.add_log_lines(
1355 "read packet: $P{0:x}={1};thread:{2:x}#00".format(
1357 lldbgdbserverutils
.pack_register_hex(
1358 endian
, next_value
, byte_size
=reg_byte_size
1362 "send packet: $OK#00",
1366 context
= self
.expect_gdbremote_sequence()
1367 self
.assertIsNotNone(context
)
1369 # Save the value we set.
1370 expected_reg_values
.append(next_value
)
1372 # Increment value for next thread to use (we want them all
1373 # different so we can verify they wrote to each thread correctly
1375 next_value
+= register_increment
1377 # Revisit each thread and verify they have the expected value set for
1378 # the register we wrote.
1380 for thread
in threads
:
1381 # Read pre-existing register value.
1382 self
.reset_test_sequence()
1383 self
.test_sequence
.add_log_lines(
1385 "read packet: $p{0:x};thread:{1:x}#00".format(reg_index
, thread
),
1387 "direction": "send",
1388 "regex": r
"^\$([0-9a-fA-F]+)#",
1389 "capture": {1: "p_response"},
1394 context
= self
.expect_gdbremote_sequence()
1395 self
.assertIsNotNone(context
)
1397 # Get the register value.
1398 p_response
= context
.get("p_response")
1399 self
.assertIsNotNone(p_response
)
1400 read_value
= lldbgdbserverutils
.unpack_register_hex_unsigned(
1404 # Make sure we read back what we wrote.
1405 self
.assertEqual(read_value
, expected_reg_values
[thread_index
])
1408 @skipUnlessPlatform(oslist
=["freebsd", "linux"])
1409 @add_test_categories(["llgs"])
1410 def test_qXfer_siginfo_read(self
):
1412 self
.set_inferior_startup_launch()
1413 procs
= self
.prep_debug_monitor_and_inferior(
1414 inferior_args
=["thread:segfault", "thread:new", "sleep:10"]
1416 self
.test_sequence
.add_log_lines(["read packet: $c#63"], True)
1417 self
.expect_gdbremote_sequence()
1419 # Run until SIGSEGV comes in.
1420 self
.reset_test_sequence()
1421 self
.test_sequence
.add_log_lines(
1424 "direction": "send",
1425 "regex": r
"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
1426 "capture": {1: "signo", 2: "thread_id"},
1432 # Figure out which thread crashed.
1433 context
= self
.expect_gdbremote_sequence()
1434 self
.assertIsNotNone(context
)
1436 int(context
["signo"], 16), lldbutil
.get_signal_number("SIGSEGV")
1438 crashing_thread
= int(context
["thread_id"], 16)
1440 # Grab siginfo for the crashing thread.
1441 self
.reset_test_sequence()
1442 self
.add_process_info_collection_packets()
1443 self
.test_sequence
.add_log_lines(
1445 "read packet: $Hg{:x}#00".format(crashing_thread
),
1446 "send packet: $OK#00",
1447 "read packet: $qXfer:siginfo:read::0,80:#00",
1449 "direction": "send",
1450 "regex": re
.compile(
1451 r
"^\$([^E])(.*)#[0-9a-fA-F]{2}$", re
.MULTILINE | re
.DOTALL
1453 "capture": {1: "response_type", 2: "content_raw"},
1458 context
= self
.expect_gdbremote_sequence()
1459 self
.assertIsNotNone(context
)
1461 # Ensure we end up with all data in one packet.
1462 self
.assertEqual(context
.get("response_type"), "l")
1464 # Decode binary data.
1465 content_raw
= context
.get("content_raw")
1466 self
.assertIsNotNone(content_raw
)
1467 content
= self
.decode_gdbremote_binary(content_raw
).encode("latin1")
1470 process_info
= self
.parse_process_info_response(context
)
1472 if process_info
["ptrsize"] == "8":
1479 if process_info
["ostype"] == "linux":
1480 # si_signo, si_errno, si_code, [pad], _sifields._sigfault.si_addr
1481 format_str
= "iii{}P".format(pad
)
1482 elif process_info
["ostype"].startswith("freebsd"):
1483 # si_signo, si_errno, si_code, si_pid, si_uid, si_status, si_addr
1484 format_str
= "iiiiiiP"
1485 elif process_info
["ostype"].startswith("netbsd"):
1486 # _signo, _code, _errno, [pad], _reason._fault._addr
1487 format_str
= "iii{}P".format(pad
)
1491 assert False, "unknown ostype"
1493 decoder
= struct
.Struct(format_str
)
1494 decoded
= decoder
.unpack(content
[: decoder
.size
])
1495 self
.assertEqual(decoded
[signo_idx
], lldbutil
.get_signal_number("SIGSEGV"))
1496 self
.assertEqual(decoded
[errno_idx
], 0) # si_errno
1497 self
.assertEqual(decoded
[code_idx
], SEGV_MAPERR
) # si_code
1498 self
.assertEqual(decoded
[addr_idx
], 0) # si_addr