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