13a870bffSDavid Spickett"""
23a870bffSDavid SpickettTest the 'memory read' command.
33a870bffSDavid Spickett"""
43a870bffSDavid Spickett
53a870bffSDavid Spickettimport lldb
63a870bffSDavid Spickettimport lldbsuite.test.lldbutil as lldbutil
73a870bffSDavid Spickett
83a870bffSDavid Spickettfrom lldbsuite.test.decorators import *
93a870bffSDavid Spickettfrom lldbsuite.test.lldbtest import *
103a870bffSDavid Spickett
113a870bffSDavid Spickett
125ce0f876SPavel Labathclass MemoryReadTestCase(TestBase):
135ce0f876SPavel Labath    NO_DEBUG_INFO_TESTCASE = True
143a870bffSDavid Spickett
153a870bffSDavid Spickett    def build_run_stop(self):
163a870bffSDavid Spickett        self.build()
175ce0f876SPavel Labath        lldbutil.run_to_source_breakpoint(self, "// break here",
185ce0f876SPavel Labath                lldb.SBFileSpec("main.c"))
193a870bffSDavid Spickett
203a870bffSDavid Spickett    def test_memory_read_c_string(self):
213a870bffSDavid Spickett        """Test that reading memory as a c string respects the size limit given
223a870bffSDavid Spickett           and warns if the null terminator is missing."""
233a870bffSDavid Spickett        self.build_run_stop()
243a870bffSDavid Spickett
253a870bffSDavid Spickett        # The size here is the size in memory so it includes the null terminator.
265ce0f876SPavel Labath        cmd = "memory read --format \"c-string\" --size {} &my_string"
273a870bffSDavid Spickett
283a870bffSDavid Spickett        # Size matches the size of the array.
295ce0f876SPavel Labath        self.expect(cmd.format(8), substrs=['\"abcdefg\"'])
303a870bffSDavid Spickett
313a870bffSDavid Spickett        # If size would take us past the terminator we stop at the terminator.
325ce0f876SPavel Labath        self.expect(cmd.format(10), substrs=['\"abcdefg\"'])
333a870bffSDavid Spickett
343a870bffSDavid Spickett        # Size 3 means 2 chars and a terminator. So we print 2 chars but warn because
353a870bffSDavid Spickett        # the third isn't 0 as expected.
363a870bffSDavid Spickett        self.expect(cmd.format(3), substrs=['\"ab\"'])
373a870bffSDavid Spickett        self.assertRegex(self.res.GetError(),
38*0dfafa48SDavid Spickett            "unable to find a NULL terminated string at 0x[0-9A-Fa-f]+."
393a870bffSDavid Spickett            " Consider increasing the maximum read length.")
405ce0f876SPavel Labath
415ce0f876SPavel Labath    def test_memory_read(self):
425ce0f876SPavel Labath        """Test the 'memory read' command with plain and vector formats."""
435ce0f876SPavel Labath        self.build_run_stop()
445ce0f876SPavel Labath
455ce0f876SPavel Labath        # (lldb) memory read -f d -c 1 `&argc`
465ce0f876SPavel Labath        # 0x7fff5fbff9a0: 1
475ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 `&argc`")
485ce0f876SPavel Labath
495ce0f876SPavel Labath        # Find the starting address for variable 'argc' to verify later that the
505ce0f876SPavel Labath        # '--format uint32_t[] --size 4 --count 4' option increments the address
515ce0f876SPavel Labath        # correctly.
525ce0f876SPavel Labath        line = self.res.GetOutput().splitlines()[0]
535ce0f876SPavel Labath        items = line.split(':')
545ce0f876SPavel Labath        address = int(items[0], 0)
555ce0f876SPavel Labath        argc = int(items[1], 0)
565ce0f876SPavel Labath        self.assertGreater(address, 0)
575ce0f876SPavel Labath        self.assertEquals(argc, 1)
585ce0f876SPavel Labath
595ce0f876SPavel Labath        # (lldb) memory read --format uint32_t[] --size 4 --count 4 `&argc`
605ce0f876SPavel Labath        # 0x7fff5fbff9a0: {0x00000001}
615ce0f876SPavel Labath        # 0x7fff5fbff9a4: {0x00000000}
625ce0f876SPavel Labath        # 0x7fff5fbff9a8: {0x0ec0bf27}
635ce0f876SPavel Labath        # 0x7fff5fbff9ac: {0x215db505}
645ce0f876SPavel Labath        self.runCmd(
655ce0f876SPavel Labath            "memory read --format uint32_t[] --size 4 --count 4 `&argc`")
665ce0f876SPavel Labath        lines = self.res.GetOutput().splitlines()
675ce0f876SPavel Labath        for i in range(4):
685ce0f876SPavel Labath            if i == 0:
695ce0f876SPavel Labath                # Verify that the printout for argc is correct.
705ce0f876SPavel Labath                self.assertEqual(
715ce0f876SPavel Labath                    argc, int(lines[i].split(':')[1].strip(' {}'), 0))
725ce0f876SPavel Labath            addr = int(lines[i].split(':')[0], 0)
735ce0f876SPavel Labath            # Verify that the printout for addr is incremented correctly.
745ce0f876SPavel Labath            self.assertEqual(addr, (address + i * 4))
755ce0f876SPavel Labath
765ce0f876SPavel Labath        # (lldb) memory read --format char[] --size 7 --count 1 `&my_string`
775ce0f876SPavel Labath        # 0x7fff5fbff990: {abcdefg}
785ce0f876SPavel Labath        self.expect(
795ce0f876SPavel Labath            "memory read --format char[] --size 7 --count 1 `&my_string`",
805ce0f876SPavel Labath            substrs=['abcdefg'])
815ce0f876SPavel Labath
825ce0f876SPavel Labath        # (lldb) memory read --format 'hex float' --size 16 `&argc`
835ce0f876SPavel Labath        # 0x7fff5fbff5b0: error: unsupported byte size (16) for hex float
845ce0f876SPavel Labath        # format
855ce0f876SPavel Labath        self.expect(
865ce0f876SPavel Labath            "memory read --format 'hex float' --size 16 `&argc`",
875ce0f876SPavel Labath            substrs=['unsupported byte size (16) for hex float format'])
885ce0f876SPavel Labath
895ce0f876SPavel Labath        self.expect(
905ce0f876SPavel Labath            "memory read --format 'float' --count 1 --size 8 `&my_double`",
915ce0f876SPavel Labath            substrs=['1234.'])
925ce0f876SPavel Labath
935ce0f876SPavel Labath        # (lldb) memory read --format 'float' --count 1 --size 20 `&my_double`
945ce0f876SPavel Labath        # 0x7fff5fbff598: error: unsupported byte size (20) for float format
955ce0f876SPavel Labath        self.expect(
965ce0f876SPavel Labath            "memory read --format 'float' --count 1 --size 20 `&my_double`",
975ce0f876SPavel Labath            substrs=['unsupported byte size (20) for float format'])
985ce0f876SPavel Labath
995ce0f876SPavel Labath        self.expect('memory read --type int --count 5 `&my_ints[0]`',
1005ce0f876SPavel Labath                    substrs=['(int) 0x', '2', '4', '6', '8', '10'])
1015ce0f876SPavel Labath
1025ce0f876SPavel Labath        self.expect(
1035ce0f876SPavel Labath            'memory read --type int --count 5 --format hex `&my_ints[0]`',
1045ce0f876SPavel Labath            substrs=[
1055ce0f876SPavel Labath                '(int) 0x',
1065ce0f876SPavel Labath                '0x',
1075ce0f876SPavel Labath                '0a'])
1085ce0f876SPavel Labath
1095ce0f876SPavel Labath        self.expect(
1105ce0f876SPavel Labath            'memory read --type int --count 5 --offset 5 `&my_ints[0]`',
1115ce0f876SPavel Labath            substrs=[
1125ce0f876SPavel Labath                '(int) 0x',
1135ce0f876SPavel Labath                '12',
1145ce0f876SPavel Labath                '14',
1155ce0f876SPavel Labath                '16',
1165ce0f876SPavel Labath                '18',
1175ce0f876SPavel Labath                '20'])
1185ce0f876SPavel Labath
1195ce0f876SPavel Labath        # the gdb format specifier and the size in characters for
1205ce0f876SPavel Labath        # the returned values including the 0x prefix.
1215ce0f876SPavel Labath        variations = [['b', 4], ['h', 6], ['w', 10], ['g', 18]]
1225ce0f876SPavel Labath        for v in variations:
1235ce0f876SPavel Labath          formatter = v[0]
1245ce0f876SPavel Labath          expected_object_length = v[1]
1255ce0f876SPavel Labath          self.runCmd(
1265ce0f876SPavel Labath              "memory read --gdb-format 4%s &my_uint64s" % formatter)
1275ce0f876SPavel Labath          lines = self.res.GetOutput().splitlines()
1285ce0f876SPavel Labath          objects_read = []
1295ce0f876SPavel Labath          for l in lines:
1305ce0f876SPavel Labath              objects_read.extend(l.split(':')[1].split())
1315ce0f876SPavel Labath          # Check that we got back 4 0x0000 etc bytes
1325ce0f876SPavel Labath          for o in objects_read:
1335ce0f876SPavel Labath              self.assertEqual(len(o), expected_object_length)
1345ce0f876SPavel Labath          self.assertEquals(len(objects_read), 4)
1355ce0f876SPavel Labath
1365ce0f876SPavel Labath    def test_memory_read_file(self):
1375ce0f876SPavel Labath        self.build_run_stop()
1385ce0f876SPavel Labath        res = lldb.SBCommandReturnObject()
1395ce0f876SPavel Labath        self.ci.HandleCommand("memory read -f d -c 1 `&argc`", res)
1405ce0f876SPavel Labath        self.assertTrue(res.Succeeded(), "memory read failed:" + res.GetError())
1415ce0f876SPavel Labath
1425ce0f876SPavel Labath        # Record golden output.
1435ce0f876SPavel Labath        golden_output = res.GetOutput()
1445ce0f876SPavel Labath
1455ce0f876SPavel Labath        memory_read_file = self.getBuildArtifact("memory-read-output")
1465ce0f876SPavel Labath
1475ce0f876SPavel Labath        def check_file_content(expected):
1485ce0f876SPavel Labath            with open(memory_read_file) as f:
1495ce0f876SPavel Labath                lines = f.readlines()
1505ce0f876SPavel Labath                lines = [s.strip() for s in lines]
1515ce0f876SPavel Labath                expected = [s.strip() for s in expected]
1525ce0f876SPavel Labath                self.assertEqual(lines, expected)
1535ce0f876SPavel Labath
1545ce0f876SPavel Labath        # Sanity check.
1555ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))
1565ce0f876SPavel Labath        check_file_content([golden_output])
1575ce0f876SPavel Labath
1585ce0f876SPavel Labath        # Write some garbage to the file.
1595ce0f876SPavel Labath        with open(memory_read_file, 'w') as f:
1605ce0f876SPavel Labath            f.write("some garbage")
1615ce0f876SPavel Labath
1625ce0f876SPavel Labath        # Make sure the file is truncated when we run the command again.
1635ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))
1645ce0f876SPavel Labath        check_file_content([golden_output])
1655ce0f876SPavel Labath
1665ce0f876SPavel Labath        # Make sure the file is appended when we run the command with --append-outfile.
1675ce0f876SPavel Labath        self.runCmd(
1685ce0f876SPavel Labath            "memory read -f d -c 1 -o '{}' --append-outfile `&argc`".format(
1695ce0f876SPavel Labath                memory_read_file))
1705ce0f876SPavel Labath        check_file_content([golden_output, golden_output])
171