2 Test the 'memory region' command.
6 from lldbsuite
.test
.decorators
import *
7 from lldbsuite
.test
.lldbtest
import *
8 from lldbsuite
.test
import lldbutil
9 from lldbsuite
.test
.gdbclientutils
import MockGDBServerResponder
10 from lldbsuite
.test
.lldbgdbclient
import GDBRemoteTestBase
13 class MemoryCommandRegion(TestBase
):
14 NO_DEBUG_INFO_TESTCASE
= True
18 # Find the line number to break for main.c.
19 self
.line
= line_number(
20 "main.cpp", "// Run here before printing memory regions"
24 """Test that help shows you must have one of address or --all, not both."""
27 substrs
=["memory region <address-expression>", "memory region -a"],
30 def setup_program(self
):
33 # Set breakpoint in main and run
34 self
.runCmd("file " + self
.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET
)
35 lldbutil
.run_break_set_by_file_and_line(
36 self
, "main.cpp", self
.line
, num_expected_locations
=-1, loc_exact
=True
39 self
.runCmd("run", RUN_SUCCEEDED
)
41 # This test and the next build a large result string in such a way that
42 # when run under ASAN the test always times out. Most of the time is in the asan
43 # checker under PyUnicode_Append.
44 # This seems to be a worst-case scenario for ASAN performance.
46 def test_command(self
):
49 interp
= self
.dbg
.GetCommandInterpreter()
50 result
= lldb
.SBCommandReturnObject()
52 # Test that the first 'memory region' command prints the usage.
53 interp
.HandleCommand("memory region", result
)
54 self
.assertFalse(result
.Succeeded())
57 "error: 'memory region' takes one argument or \"--all\" option:\n"
58 "Usage: memory region <address-expression> (or --all)\n",
61 # We allow --all or an address argument, not both
62 interp
.HandleCommand("memory region --all 0", result
)
63 self
.assertFalse(result
.Succeeded())
66 'The "--all" option cannot be used when an address argument is given',
69 # Test that when the address fails to parse, we show an error and do not continue
70 interp
.HandleCommand("memory region not_an_address", result
)
71 self
.assertFalse(result
.Succeeded())
74 'error: invalid address argument "not_an_address": address expression "not_an_address" evaluation failed\n',
77 # Accumulate the results to compare with the --all output
80 # Now let's print the memory region starting at 0 which should always work.
81 interp
.HandleCommand("memory region 0x0", result
)
82 self
.assertTrue(result
.Succeeded())
83 self
.assertRegex(result
.GetOutput(), "\\[0x0+-")
84 all_regions
+= result
.GetOutput()
86 # Keep printing memory regions until we printed all of them.
88 interp
.HandleCommand("memory region", result
)
89 if not result
.Succeeded():
91 all_regions
+= result
.GetOutput()
93 # Now that we reached the end, 'memory region' should again print the usage.
94 interp
.HandleCommand("memory region", result
)
95 self
.assertFalse(result
.Succeeded())
98 "Usage: memory region <address\-expression> \(or \-\-all\)",
101 # --all should match what repeating the command gives you
102 interp
.HandleCommand("memory region --all", result
)
103 self
.assertTrue(result
.Succeeded())
104 self
.assertEqual(result
.GetOutput(), all_regions
)
107 def test_no_overlapping_regions(self
):
108 # In the past on Windows we were recording AllocationBase as the base address
109 # of the current region, not BaseAddress. So if a range of pages was split
110 # into regions you would see several regions with the same base address.
111 # This checks that this no longer happens (and it shouldn't happen on any
115 regions
= self
.process().GetMemoryRegions()
116 num_regions
= regions
.GetSize()
119 region
= lldb
.SBMemoryRegionInfo()
120 regions
.GetMemoryRegionAtIndex(0, region
)
121 previous_base
= region
.GetRegionBase()
122 previous_end
= region
.GetRegionEnd()
124 for idx
in range(1, regions
.GetSize()):
125 regions
.GetMemoryRegionAtIndex(idx
, region
)
127 # Check that it does not overlap the previous region.
128 # This could happen if we got the base addresses or size wrong.
129 # Also catches the base addresses being the same.
130 region_base
= region
.GetRegionBase()
131 region_end
= region
.GetRegionEnd()
134 (region_base
< previous_end
) and (previous_base
< region_end
),
135 "Unexpected overlapping memory region found.",
138 previous_base
= region_base
139 previous_end
= region_end
142 class MemoryCommandRegionAll(GDBRemoteTestBase
):
143 NO_DEBUG_INFO_TESTCASE
= True
145 def test_all_error(self
):
146 # The --all option should keep looping until the end of the memory range.
147 # If there is an error it should be reported as if you were just asking
148 # for one region. In this case the error is the remote not supporting
150 # (a region being unmapped is not an error, we just get a result
151 # describing an unmapped range)
152 class MyResponder(MockGDBServerResponder
):
153 def qMemoryRegionInfo(self
, addr
):
154 # Empty string means unsupported.
157 self
.server
.responder
= MyResponder()
158 target
= self
.dbg
.CreateTarget("")
160 self
.runCmd("log enable gdb-remote packets")
161 self
.addTearDownHook(lambda: self
.runCmd("log disable gdb-remote packets"))
163 process
= self
.connect(target
)
164 lldbutil
.expect_state_changes(
165 self
, self
.dbg
.GetListener(), process
, [lldb
.eStateStopped
]
168 interp
= self
.dbg
.GetCommandInterpreter()
169 result
= lldb
.SBCommandReturnObject()
170 interp
.HandleCommand("memory region --all ", result
)
171 self
.assertFalse(result
.Succeeded())
173 result
.GetError(), "error: qMemoryRegionInfo is not supported\n"
177 def test_all_no_abi_plugin(self
):
178 # There are two conditions for breaking the all loop. Either we get to
179 # LLDB_INVALID_ADDRESS, or the ABI plugin tells us we have got beyond
180 # the mappable range. If we don't have an ABI plugin, the option should still
181 # work and only check the first condition.
183 class MyResponder(MockGDBServerResponder
):
184 def qMemoryRegionInfo(self
, addr
):
186 return "start:0;size:100000000;"
187 # Goes until the end of memory.
188 if addr
== 0x100000000:
189 return "start:100000000;size:fffffffeffffffff;"
191 self
.server
.responder
= MyResponder()
192 target
= self
.dbg
.CreateTarget("")
194 self
.runCmd("log enable gdb-remote packets")
195 self
.addTearDownHook(lambda: self
.runCmd("log disable gdb-remote packets"))
197 process
= self
.connect(target
)
198 lldbutil
.expect_state_changes(
199 self
, self
.dbg
.GetListener(), process
, [lldb
.eStateStopped
]
202 interp
= self
.dbg
.GetCommandInterpreter()
203 result
= lldb
.SBCommandReturnObject()
204 interp
.HandleCommand("memory region --all ", result
)
205 self
.assertTrue(result
.Succeeded())
208 "[0x0000000000000000-0x0000000100000000) ---\n"
209 "[0x0000000100000000-0xffffffffffffffff) ---\n",