Skip tests that are incompatible with MTE. Depends on: - https://github.com/llvm/llvm-project/pull/185780
212 lines
8.1 KiB
Python
212 lines
8.1 KiB
Python
import gdbremote_testcase
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test.lldbdwarf import *
|
|
|
|
|
|
@skipIfMTE # MTE security transition shims restrict socket operations.
|
|
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)
|