184 lines · python
1"""2Test the 'memory read' command.3"""4 5import lldb6import lldbsuite.test.lldbutil as lldbutil7 8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10 11 12class MemoryReadTestCase(TestBase):13 NO_DEBUG_INFO_TESTCASE = True14 15 def build_run_stop(self):16 self.build()17 lldbutil.run_to_source_breakpoint(18 self, "// break here", lldb.SBFileSpec("main.c")19 )20 21 def test_memory_read_c_string(self):22 """Test that reading memory as a c string respects the size limit given23 and warns if the null terminator is missing."""24 self.build_run_stop()25 26 # The size here is the size in memory so it includes the null terminator.27 cmd = 'memory read --format "c-string" --size {} &my_string'28 29 # Size matches the size of the array.30 self.expect(cmd.format(8), substrs=['"abcdefg"'])31 32 # If size would take us past the terminator we stop at the terminator.33 self.expect(cmd.format(10), substrs=['"abcdefg"'])34 35 # Size 3 means 2 chars and a terminator. So we print 2 chars but warn because36 # the third isn't 0 as expected.37 self.expect(cmd.format(3), substrs=['"ab"'])38 self.assertRegex(39 self.res.GetError(),40 "unable to find a NULL terminated string at 0x[0-9A-Fa-f]+."41 " Consider increasing the maximum read length.",42 )43 44 @skipIf(archs=no_match("^(riscv|aarch64).*"))45 def test_memory_read_instruction_decode_failure(self):46 """Test the 'memory read' command with instruction format."""47 self.build_run_stop()48 49 # assume that 0xffffff is invalid instruction in RISC-V and AArch64,50 # so decoding it will fail51 self.expect(52 "memory read --format instruction `&my_insns[0]` `&my_insns[3]`",53 substrs=["failed to decode instructions at"],54 )55 56 def test_memory_read(self):57 """Test the 'memory read' command with plain and vector formats."""58 self.build_run_stop()59 60 # (lldb) memory read -f d -c 1 `&argc`61 # 0x7fff5fbff9a0: 162 self.runCmd("memory read -f d -c 1 `&argc`")63 64 # Find the starting address for variable 'argc' to verify later that the65 # '--format uint32_t[] --size 4 --count 4' option increments the address66 # correctly.67 line = self.res.GetOutput().splitlines()[0]68 items = line.split(":")69 address = int(items[0], 0)70 argc = int(items[1], 0)71 self.assertGreater(address, 0)72 self.assertEqual(argc, 1)73 74 # (lldb) memory read --format uint32_t[] --size 4 --count 4 `&argc`75 # 0x7fff5fbff9a0: {0x00000001}76 # 0x7fff5fbff9a4: {0x00000000}77 # 0x7fff5fbff9a8: {0x0ec0bf27}78 # 0x7fff5fbff9ac: {0x215db505}79 self.runCmd("memory read --format uint32_t[] --size 4 --count 4 `&argc`")80 lines = self.res.GetOutput().splitlines()81 for i in range(4):82 if i == 0:83 # Verify that the printout for argc is correct.84 self.assertEqual(argc, int(lines[i].split(":")[1].strip(" {}"), 0))85 addr = int(lines[i].split(":")[0], 0)86 # Verify that the printout for addr is incremented correctly.87 self.assertEqual(addr, (address + i * 4))88 89 # (lldb) memory read --format char[] --size 7 --count 1 `&my_string`90 # 0x7fff5fbff990: {abcdefg}91 self.expect(92 "memory read --format char[] --size 7 --count 1 `&my_string`",93 substrs=["abcdefg"],94 )95 96 # (lldb) memory read --format 'hex float' --size 16 `&argc`97 # 0x7fff5fbff5b0: error: unsupported byte size (16) for hex float98 # format99 self.expect(100 "memory read --format 'hex float' --size 16 `&argc`",101 substrs=["unsupported byte size (16) for hex float format"],102 )103 104 self.expect(105 "memory read --format 'float' --count 1 --size 8 `&my_double`",106 substrs=["1234."],107 )108 109 # (lldb) memory read --format 'float' --count 1 --size 20 `&my_double`110 # 0x7fff5fbff598: error: unsupported byte size (20) for float format111 self.expect(112 "memory read --format 'float' --count 1 --size 20 `&my_double`",113 substrs=["unsupported byte size (20) for float format"],114 )115 116 self.expect(117 "memory read --type int --count 5 `&my_ints[0]`",118 substrs=["(int) 0x", "2", "4", "6", "8", "10"],119 )120 121 self.expect(122 "memory read --type int --count 5 --format hex `&my_ints[0]`",123 substrs=["(int) 0x", "0x", "0a"],124 )125 126 self.expect(127 "memory read --type int --count 5 --offset 5 `&my_ints[0]`",128 substrs=["(int) 0x", "12", "14", "16", "18", "20"],129 )130 131 # the gdb format specifier and the size in characters for132 # the returned values including the 0x prefix.133 variations = [["b", 4], ["h", 6], ["w", 10], ["g", 18]]134 for v in variations:135 formatter = v[0]136 expected_object_length = v[1]137 self.runCmd("memory read --gdb-format 4%s &my_uint64s" % formatter)138 lines = self.res.GetOutput().splitlines()139 objects_read = []140 for l in lines:141 objects_read.extend(l.split(":")[1].split())142 # Check that we got back 4 0x0000 etc bytes143 for o in objects_read:144 self.assertEqual(len(o), expected_object_length)145 self.assertEqual(len(objects_read), 4)146 147 def test_memory_read_file(self):148 self.build_run_stop()149 res = lldb.SBCommandReturnObject()150 self.ci.HandleCommand("memory read -f d -c 1 `&argc`", res)151 self.assertTrue(res.Succeeded(), "memory read failed:" + res.GetError())152 153 # Record golden output.154 golden_output = res.GetOutput()155 156 memory_read_file = self.getBuildArtifact("memory-read-output")157 158 def check_file_content(expected):159 with open(memory_read_file) as f:160 lines = f.readlines()161 lines = [s.strip() for s in lines]162 expected = [s.strip() for s in expected]163 self.assertEqual(lines, expected)164 165 # Sanity check.166 self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))167 check_file_content([golden_output])168 169 # Write some garbage to the file.170 with open(memory_read_file, "w") as f:171 f.write("some garbage")172 173 # Make sure the file is truncated when we run the command again.174 self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))175 check_file_content([golden_output])176 177 # Make sure the file is appended when we run the command with --append-outfile.178 self.runCmd(179 "memory read -f d -c 1 -o '{}' --append-outfile `&argc`".format(180 memory_read_file181 )182 )183 check_file_content([golden_output, golden_output])184