199451b44SJordan Rupprecht""" 299451b44SJordan RupprechtTest the 'memory region' command. 399451b44SJordan Rupprecht""" 499451b44SJordan Rupprecht 599451b44SJordan Rupprechtimport lldb 699451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 799451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 899451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 9ee582001SDavid Spickettfrom lldbsuite.test.gdbclientutils import MockGDBServerResponder 10ee582001SDavid Spickettfrom lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 1199451b44SJordan Rupprecht 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprechtclass MemoryCommandRegion(TestBase): 1499451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1599451b44SJordan Rupprecht 1699451b44SJordan Rupprecht def setUp(self): 1799451b44SJordan Rupprecht TestBase.setUp(self) 1899451b44SJordan Rupprecht # Find the line number to break for main.c. 1999451b44SJordan Rupprecht self.line = line_number( 202238dcc3SJonas Devlieghere "main.cpp", "// Run here before printing memory regions" 212238dcc3SJonas Devlieghere ) 2299451b44SJordan Rupprecht 2313e1cf80SDavid Spickett def test_help(self): 2413e1cf80SDavid Spickett """Test that help shows you must have one of address or --all, not both.""" 252238dcc3SJonas Devlieghere self.expect( 262238dcc3SJonas Devlieghere "help memory region", 272238dcc3SJonas Devlieghere substrs=["memory region <address-expression>", "memory region -a"], 282238dcc3SJonas Devlieghere ) 2913e1cf80SDavid Spickett 301ca8a978SDavid Spickett def setup_program(self): 3199451b44SJordan Rupprecht self.build() 3299451b44SJordan Rupprecht 3399451b44SJordan Rupprecht # Set breakpoint in main and run 3499451b44SJordan Rupprecht self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) 3599451b44SJordan Rupprecht lldbutil.run_break_set_by_file_and_line( 362238dcc3SJonas Devlieghere self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True 372238dcc3SJonas Devlieghere ) 3899451b44SJordan Rupprecht 3999451b44SJordan Rupprecht self.runCmd("run", RUN_SUCCEEDED) 4099451b44SJordan Rupprecht 4136a461b8SJim Ingham # This test and the next build a large result string in such a way that 4236a461b8SJim Ingham # when run under ASAN the test always times out. Most of the time is in the asan 430c86fbb5SJim Ingham # checker under PyUnicode_Append. 440c86fbb5SJim Ingham # This seems to be a worst-case scenario for ASAN performance. 450c86fbb5SJim Ingham @skipIfAsan 461ca8a978SDavid Spickett def test_command(self): 471ca8a978SDavid Spickett self.setup_program() 481ca8a978SDavid Spickett 4999451b44SJordan Rupprecht interp = self.dbg.GetCommandInterpreter() 5099451b44SJordan Rupprecht result = lldb.SBCommandReturnObject() 5199451b44SJordan Rupprecht 5299451b44SJordan Rupprecht # Test that the first 'memory region' command prints the usage. 5399451b44SJordan Rupprecht interp.HandleCommand("memory region", result) 5499451b44SJordan Rupprecht self.assertFalse(result.Succeeded()) 552238dcc3SJonas Devlieghere self.assertEqual( 562238dcc3SJonas Devlieghere result.GetError(), 5713e1cf80SDavid Spickett "error: 'memory region' takes one argument or \"--all\" option:\n" 582238dcc3SJonas Devlieghere "Usage: memory region <address-expression> (or --all)\n", 592238dcc3SJonas Devlieghere ) 6013e1cf80SDavid Spickett 6113e1cf80SDavid Spickett # We allow --all or an address argument, not both 6213e1cf80SDavid Spickett interp.HandleCommand("memory region --all 0", result) 6313e1cf80SDavid Spickett self.assertFalse(result.Succeeded()) 64*737bc9f7SJonas Devlieghere self.assertRegex( 652238dcc3SJonas Devlieghere result.GetError(), 662238dcc3SJonas Devlieghere 'The "--all" option cannot be used when an address argument is given', 672238dcc3SJonas Devlieghere ) 6899451b44SJordan Rupprecht 6971cf97e9SDavid Spickett # Test that when the address fails to parse, we show an error and do not continue 7071cf97e9SDavid Spickett interp.HandleCommand("memory region not_an_address", result) 7171cf97e9SDavid Spickett self.assertFalse(result.Succeeded()) 722238dcc3SJonas Devlieghere self.assertEqual( 732238dcc3SJonas Devlieghere result.GetError(), 742238dcc3SJonas Devlieghere 'error: invalid address argument "not_an_address": address expression "not_an_address" evaluation failed\n', 752238dcc3SJonas Devlieghere ) 7671cf97e9SDavid Spickett 7713e1cf80SDavid Spickett # Accumulate the results to compare with the --all output 7813e1cf80SDavid Spickett all_regions = "" 7913e1cf80SDavid Spickett 8099451b44SJordan Rupprecht # Now let's print the memory region starting at 0 which should always work. 8199451b44SJordan Rupprecht interp.HandleCommand("memory region 0x0", result) 8299451b44SJordan Rupprecht self.assertTrue(result.Succeeded()) 83*737bc9f7SJonas Devlieghere self.assertRegex(result.GetOutput(), "\\[0x0+-") 8413e1cf80SDavid Spickett all_regions += result.GetOutput() 8599451b44SJordan Rupprecht 8699451b44SJordan Rupprecht # Keep printing memory regions until we printed all of them. 8799451b44SJordan Rupprecht while True: 8899451b44SJordan Rupprecht interp.HandleCommand("memory region", result) 8999451b44SJordan Rupprecht if not result.Succeeded(): 9099451b44SJordan Rupprecht break 9113e1cf80SDavid Spickett all_regions += result.GetOutput() 9299451b44SJordan Rupprecht 9399451b44SJordan Rupprecht # Now that we reached the end, 'memory region' should again print the usage. 9499451b44SJordan Rupprecht interp.HandleCommand("memory region", result) 9599451b44SJordan Rupprecht self.assertFalse(result.Succeeded()) 96*737bc9f7SJonas Devlieghere self.assertRegex( 972238dcc3SJonas Devlieghere result.GetError(), 982238dcc3SJonas Devlieghere "Usage: memory region <address\-expression> \(or \-\-all\)", 992238dcc3SJonas Devlieghere ) 10013e1cf80SDavid Spickett 10113e1cf80SDavid Spickett # --all should match what repeating the command gives you 10213e1cf80SDavid Spickett interp.HandleCommand("memory region --all", result) 10313e1cf80SDavid Spickett self.assertTrue(result.Succeeded()) 10413e1cf80SDavid Spickett self.assertEqual(result.GetOutput(), all_regions) 1051ca8a978SDavid Spickett 10636a461b8SJim Ingham @skipIfAsan 107f3d43ecaSDavid Spickett def test_no_overlapping_regions(self): 1081ca8a978SDavid Spickett # In the past on Windows we were recording AllocationBase as the base address 1091ca8a978SDavid Spickett # of the current region, not BaseAddress. So if a range of pages was split 1101ca8a978SDavid Spickett # into regions you would see several regions with the same base address. 1111ca8a978SDavid Spickett # This checks that this no longer happens (and it shouldn't happen on any 1121ca8a978SDavid Spickett # other OS either). 1131ca8a978SDavid Spickett self.setup_program() 1141ca8a978SDavid Spickett 1151ca8a978SDavid Spickett regions = self.process().GetMemoryRegions() 1161ca8a978SDavid Spickett num_regions = regions.GetSize() 1171ca8a978SDavid Spickett 1181ca8a978SDavid Spickett if num_regions: 1191ca8a978SDavid Spickett region = lldb.SBMemoryRegionInfo() 1201ca8a978SDavid Spickett regions.GetMemoryRegionAtIndex(0, region) 1211ca8a978SDavid Spickett previous_base = region.GetRegionBase() 1221ca8a978SDavid Spickett previous_end = region.GetRegionEnd() 1231ca8a978SDavid Spickett 1241ca8a978SDavid Spickett for idx in range(1, regions.GetSize()): 1251ca8a978SDavid Spickett regions.GetMemoryRegionAtIndex(idx, region) 1261ca8a978SDavid Spickett 1271ca8a978SDavid Spickett # Check that it does not overlap the previous region. 1281ca8a978SDavid Spickett # This could happen if we got the base addresses or size wrong. 1291ca8a978SDavid Spickett # Also catches the base addresses being the same. 1301ca8a978SDavid Spickett region_base = region.GetRegionBase() 1311ca8a978SDavid Spickett region_end = region.GetRegionEnd() 1321ca8a978SDavid Spickett 133f3d43ecaSDavid Spickett self.assertFalse( 134f3d43ecaSDavid Spickett (region_base < previous_end) and (previous_base < region_end), 1352238dcc3SJonas Devlieghere "Unexpected overlapping memory region found.", 1362238dcc3SJonas Devlieghere ) 1371ca8a978SDavid Spickett 1381ca8a978SDavid Spickett previous_base = region_base 1391ca8a978SDavid Spickett previous_end = region_end 140ee582001SDavid Spickett 1412238dcc3SJonas Devlieghere 142ee582001SDavid Spickettclass MemoryCommandRegionAll(GDBRemoteTestBase): 143ee582001SDavid Spickett NO_DEBUG_INFO_TESTCASE = True 144ee582001SDavid Spickett 145ee582001SDavid Spickett def test_all_error(self): 146ee582001SDavid Spickett # The --all option should keep looping until the end of the memory range. 147ee582001SDavid Spickett # If there is an error it should be reported as if you were just asking 148ee582001SDavid Spickett # for one region. In this case the error is the remote not supporting 149ee582001SDavid Spickett # qMemoryRegionInfo. 150ee582001SDavid Spickett # (a region being unmapped is not an error, we just get a result 151ee582001SDavid Spickett # describing an unmapped range) 152ee582001SDavid Spickett class MyResponder(MockGDBServerResponder): 153ee582001SDavid Spickett def qMemoryRegionInfo(self, addr): 154ee582001SDavid Spickett # Empty string means unsupported. 155ee582001SDavid Spickett return "" 156ee582001SDavid Spickett 157ee582001SDavid Spickett self.server.responder = MyResponder() 1582238dcc3SJonas Devlieghere target = self.dbg.CreateTarget("") 159ee582001SDavid Spickett if self.TraceOn(): 160ee582001SDavid Spickett self.runCmd("log enable gdb-remote packets") 1612238dcc3SJonas Devlieghere self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets")) 162ee582001SDavid Spickett 163ee582001SDavid Spickett process = self.connect(target) 1642238dcc3SJonas Devlieghere lldbutil.expect_state_changes( 1652238dcc3SJonas Devlieghere self, self.dbg.GetListener(), process, [lldb.eStateStopped] 1662238dcc3SJonas Devlieghere ) 167ee582001SDavid Spickett 168ee582001SDavid Spickett interp = self.dbg.GetCommandInterpreter() 169ee582001SDavid Spickett result = lldb.SBCommandReturnObject() 170ee582001SDavid Spickett interp.HandleCommand("memory region --all ", result) 171ee582001SDavid Spickett self.assertFalse(result.Succeeded()) 1722238dcc3SJonas Devlieghere self.assertEqual( 1732238dcc3SJonas Devlieghere result.GetError(), "error: qMemoryRegionInfo is not supported\n" 1742238dcc3SJonas Devlieghere ) 175c831cea5SDavid Spickett 176c831cea5SDavid Spickett @skipIfAsan 177c831cea5SDavid Spickett def test_all_no_abi_plugin(self): 178c831cea5SDavid Spickett # There are two conditions for breaking the all loop. Either we get to 179c831cea5SDavid Spickett # LLDB_INVALID_ADDRESS, or the ABI plugin tells us we have got beyond 180c831cea5SDavid Spickett # the mappable range. If we don't have an ABI plugin, the option should still 181c831cea5SDavid Spickett # work and only check the first condition. 182c831cea5SDavid Spickett 183c831cea5SDavid Spickett class MyResponder(MockGDBServerResponder): 184c831cea5SDavid Spickett def qMemoryRegionInfo(self, addr): 185c831cea5SDavid Spickett if addr == 0: 186c831cea5SDavid Spickett return "start:0;size:100000000;" 187c831cea5SDavid Spickett # Goes until the end of memory. 188c831cea5SDavid Spickett if addr == 0x100000000: 189c831cea5SDavid Spickett return "start:100000000;size:fffffffeffffffff;" 190c831cea5SDavid Spickett 191c831cea5SDavid Spickett self.server.responder = MyResponder() 1922238dcc3SJonas Devlieghere target = self.dbg.CreateTarget("") 193c831cea5SDavid Spickett if self.TraceOn(): 194c831cea5SDavid Spickett self.runCmd("log enable gdb-remote packets") 1952238dcc3SJonas Devlieghere self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets")) 196c831cea5SDavid Spickett 197c831cea5SDavid Spickett process = self.connect(target) 1982238dcc3SJonas Devlieghere lldbutil.expect_state_changes( 1992238dcc3SJonas Devlieghere self, self.dbg.GetListener(), process, [lldb.eStateStopped] 2002238dcc3SJonas Devlieghere ) 201c831cea5SDavid Spickett 202c831cea5SDavid Spickett interp = self.dbg.GetCommandInterpreter() 203c831cea5SDavid Spickett result = lldb.SBCommandReturnObject() 204c831cea5SDavid Spickett interp.HandleCommand("memory region --all ", result) 205c831cea5SDavid Spickett self.assertTrue(result.Succeeded()) 2062238dcc3SJonas Devlieghere self.assertEqual( 2072238dcc3SJonas Devlieghere result.GetOutput(), 208c831cea5SDavid Spickett "[0x0000000000000000-0x0000000100000000) ---\n" 2092238dcc3SJonas Devlieghere "[0x0000000100000000-0xffffffffffffffff) ---\n", 2102238dcc3SJonas Devlieghere ) 211