Split test cases out of TestLldbGdbServer.py and TestGdbRemoteFork.py into separate files to avoid hitting the 600s timeout limit. The inferior used by these tests (main.cpp) takes approximately 20s to compile with a Debug build of clang, causing timeouts when a single test file contains many tests. By grouping similar tests into separate files, we can prevent timeouts and improve overall test efficiency.
211 lines
8.0 KiB
Python
211 lines
8.0 KiB
Python
import gdbremote_testcase
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test.lldbdwarf import *
|
|
|
|
|
|
class TestGdbRemote_qMemoryRegion(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|
def test_qMemoryRegionInfo_is_supported(self):
|
|
self.build()
|
|
self.set_inferior_startup_launch()
|
|
# Start up the inferior.
|
|
procs = self.prep_debug_monitor_and_inferior()
|
|
|
|
# Ask if it supports $qMemoryRegionInfo.
|
|
self.test_sequence.add_log_lines(
|
|
["read packet: $qMemoryRegionInfo#00", "send packet: $OK#00"], True
|
|
)
|
|
self.expect_gdbremote_sequence()
|
|
|
|
@skipIfWindows # No pty support to test any inferior output
|
|
def test_qMemoryRegionInfo_reports_code_address_as_executable(self):
|
|
self.build()
|
|
self.set_inferior_startup_launch()
|
|
|
|
# Start up the inferior.
|
|
procs = self.prep_debug_monitor_and_inferior(
|
|
inferior_args=["get-code-address-hex:hello", "sleep:5"]
|
|
)
|
|
|
|
# Run the process
|
|
self.test_sequence.add_log_lines(
|
|
[
|
|
# Start running after initial stop.
|
|
"read packet: $c#63",
|
|
# Match output line that prints the memory address of the message buffer within the inferior.
|
|
# Note we require launch-only testing so we can get inferior otuput.
|
|
{
|
|
"type": "output_match",
|
|
"regex": self.maybe_strict_output_regex(
|
|
r"code address: 0x([0-9a-fA-F]+)\r\n"
|
|
),
|
|
"capture": {1: "code_address"},
|
|
},
|
|
# Now stop the inferior.
|
|
"read packet: {}".format(chr(3)),
|
|
# And wait for the stop notification.
|
|
{
|
|
"direction": "send",
|
|
"regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
|
|
"capture": {1: "stop_signo", 2: "stop_thread_id"},
|
|
},
|
|
],
|
|
True,
|
|
)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
|
|
# Grab the code address.
|
|
self.assertIsNotNone(context.get("code_address"))
|
|
code_address = int(context.get("code_address"), 16)
|
|
|
|
# Grab memory region info from the inferior.
|
|
self.reset_test_sequence()
|
|
self.add_query_memory_region_packets(code_address)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
mem_region_dict = self.parse_memory_region_packet(context)
|
|
|
|
# Ensure there are no errors reported.
|
|
self.assertNotIn("error", mem_region_dict)
|
|
|
|
# Ensure code address is readable and executable.
|
|
self.assertIn("permissions", mem_region_dict)
|
|
self.assertIn("r", mem_region_dict["permissions"])
|
|
self.assertIn("x", mem_region_dict["permissions"])
|
|
|
|
# Ensure the start address and size encompass the address we queried.
|
|
self.assert_address_within_memory_region(code_address, mem_region_dict)
|
|
|
|
@skipIfWindows # No pty support to test any inferior output
|
|
def test_qMemoryRegionInfo_reports_stack_address_as_rw(self):
|
|
self.build()
|
|
self.set_inferior_startup_launch()
|
|
|
|
# Start up the inferior.
|
|
procs = self.prep_debug_monitor_and_inferior(
|
|
inferior_args=["get-stack-address-hex:", "sleep:5"]
|
|
)
|
|
|
|
# Run the process
|
|
self.test_sequence.add_log_lines(
|
|
[
|
|
# Start running after initial stop.
|
|
"read packet: $c#63",
|
|
# Match output line that prints the memory address of the message buffer within the inferior.
|
|
# Note we require launch-only testing so we can get inferior otuput.
|
|
{
|
|
"type": "output_match",
|
|
"regex": self.maybe_strict_output_regex(
|
|
r"stack address: 0x([0-9a-fA-F]+)\r\n"
|
|
),
|
|
"capture": {1: "stack_address"},
|
|
},
|
|
# Now stop the inferior.
|
|
"read packet: {}".format(chr(3)),
|
|
# And wait for the stop notification.
|
|
{
|
|
"direction": "send",
|
|
"regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
|
|
"capture": {1: "stop_signo", 2: "stop_thread_id"},
|
|
},
|
|
],
|
|
True,
|
|
)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
|
|
# Grab the address.
|
|
self.assertIsNotNone(context.get("stack_address"))
|
|
stack_address = int(context.get("stack_address"), 16)
|
|
|
|
# Grab memory region info from the inferior.
|
|
self.reset_test_sequence()
|
|
self.add_query_memory_region_packets(stack_address)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
mem_region_dict = self.parse_memory_region_packet(context)
|
|
|
|
# Ensure there are no errors reported.
|
|
self.assertNotIn("error", mem_region_dict)
|
|
|
|
# Ensure address is readable and executable.
|
|
self.assertIn("permissions", mem_region_dict)
|
|
self.assertIn("r", mem_region_dict["permissions"])
|
|
self.assertIn("w", mem_region_dict["permissions"])
|
|
|
|
# Ensure the start address and size encompass the address we queried.
|
|
self.assert_address_within_memory_region(stack_address, mem_region_dict)
|
|
|
|
@skipIfWindows # No pty support to test any inferior output
|
|
def test_qMemoryRegionInfo_reports_heap_address_as_rw(self):
|
|
self.build()
|
|
self.set_inferior_startup_launch()
|
|
|
|
# Start up the inferior.
|
|
procs = self.prep_debug_monitor_and_inferior(
|
|
inferior_args=["get-heap-address-hex:", "sleep:5"]
|
|
)
|
|
|
|
# Run the process
|
|
self.test_sequence.add_log_lines(
|
|
[
|
|
# Start running after initial stop.
|
|
"read packet: $c#63",
|
|
# Match output line that prints the memory address of the message buffer within the inferior.
|
|
# Note we require launch-only testing so we can get inferior otuput.
|
|
{
|
|
"type": "output_match",
|
|
"regex": self.maybe_strict_output_regex(
|
|
r"heap address: 0x([0-9a-fA-F]+)\r\n"
|
|
),
|
|
"capture": {1: "heap_address"},
|
|
},
|
|
# Now stop the inferior.
|
|
"read packet: {}".format(chr(3)),
|
|
# And wait for the stop notification.
|
|
{
|
|
"direction": "send",
|
|
"regex": r"^\$T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);",
|
|
"capture": {1: "stop_signo", 2: "stop_thread_id"},
|
|
},
|
|
],
|
|
True,
|
|
)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
|
|
# Grab the address.
|
|
self.assertIsNotNone(context.get("heap_address"))
|
|
heap_address = int(context.get("heap_address"), 16)
|
|
|
|
# Grab memory region info from the inferior.
|
|
self.reset_test_sequence()
|
|
self.add_query_memory_region_packets(heap_address)
|
|
|
|
# Run the packet stream.
|
|
context = self.expect_gdbremote_sequence()
|
|
self.assertIsNotNone(context)
|
|
mem_region_dict = self.parse_memory_region_packet(context)
|
|
|
|
# Ensure there are no errors reported.
|
|
self.assertNotIn("error", mem_region_dict)
|
|
|
|
# Ensure address is readable and executable.
|
|
self.assertIn("permissions", mem_region_dict)
|
|
self.assertIn("r", mem_region_dict["permissions"])
|
|
self.assertIn("w", mem_region_dict["permissions"])
|
|
|
|
# Ensure the start address and size encompass the address we queried.
|
|
self.assert_address_within_memory_region(heap_address, mem_region_dict)
|