xref: /llvm-project/lldb/test/API/commands/memory/read/TestMemoryRead.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
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()
172238dcc3SJonas Devlieghere        lldbutil.run_to_source_breakpoint(
182238dcc3SJonas Devlieghere            self, "// break here", lldb.SBFileSpec("main.c")
192238dcc3SJonas Devlieghere        )
203a870bffSDavid Spickett
213a870bffSDavid Spickett    def test_memory_read_c_string(self):
223a870bffSDavid Spickett        """Test that reading memory as a c string respects the size limit given
233a870bffSDavid Spickett        and warns if the null terminator is missing."""
243a870bffSDavid Spickett        self.build_run_stop()
253a870bffSDavid Spickett
263a870bffSDavid Spickett        # The size here is the size in memory so it includes the null terminator.
272238dcc3SJonas Devlieghere        cmd = 'memory read --format "c-string" --size {} &my_string'
283a870bffSDavid Spickett
293a870bffSDavid Spickett        # Size matches the size of the array.
302238dcc3SJonas Devlieghere        self.expect(cmd.format(8), substrs=['"abcdefg"'])
313a870bffSDavid Spickett
323a870bffSDavid Spickett        # If size would take us past the terminator we stop at the terminator.
332238dcc3SJonas Devlieghere        self.expect(cmd.format(10), substrs=['"abcdefg"'])
343a870bffSDavid Spickett
353a870bffSDavid Spickett        # Size 3 means 2 chars and a terminator. So we print 2 chars but warn because
363a870bffSDavid Spickett        # the third isn't 0 as expected.
372238dcc3SJonas Devlieghere        self.expect(cmd.format(3), substrs=['"ab"'])
382238dcc3SJonas Devlieghere        self.assertRegex(
392238dcc3SJonas Devlieghere            self.res.GetError(),
400dfafa48SDavid Spickett            "unable to find a NULL terminated string at 0x[0-9A-Fa-f]+."
412238dcc3SJonas Devlieghere            " Consider increasing the maximum read length.",
422238dcc3SJonas Devlieghere        )
435ce0f876SPavel Labath
445ce0f876SPavel Labath    def test_memory_read(self):
455ce0f876SPavel Labath        """Test the 'memory read' command with plain and vector formats."""
465ce0f876SPavel Labath        self.build_run_stop()
475ce0f876SPavel Labath
485ce0f876SPavel Labath        # (lldb) memory read -f d -c 1 `&argc`
495ce0f876SPavel Labath        # 0x7fff5fbff9a0: 1
505ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 `&argc`")
515ce0f876SPavel Labath
525ce0f876SPavel Labath        # Find the starting address for variable 'argc' to verify later that the
535ce0f876SPavel Labath        # '--format uint32_t[] --size 4 --count 4' option increments the address
545ce0f876SPavel Labath        # correctly.
555ce0f876SPavel Labath        line = self.res.GetOutput().splitlines()[0]
562238dcc3SJonas Devlieghere        items = line.split(":")
575ce0f876SPavel Labath        address = int(items[0], 0)
585ce0f876SPavel Labath        argc = int(items[1], 0)
595ce0f876SPavel Labath        self.assertGreater(address, 0)
60*80fcecb1SJonas Devlieghere        self.assertEqual(argc, 1)
615ce0f876SPavel Labath
625ce0f876SPavel Labath        # (lldb) memory read --format uint32_t[] --size 4 --count 4 `&argc`
635ce0f876SPavel Labath        # 0x7fff5fbff9a0: {0x00000001}
645ce0f876SPavel Labath        # 0x7fff5fbff9a4: {0x00000000}
655ce0f876SPavel Labath        # 0x7fff5fbff9a8: {0x0ec0bf27}
665ce0f876SPavel Labath        # 0x7fff5fbff9ac: {0x215db505}
672238dcc3SJonas Devlieghere        self.runCmd("memory read --format uint32_t[] --size 4 --count 4 `&argc`")
685ce0f876SPavel Labath        lines = self.res.GetOutput().splitlines()
695ce0f876SPavel Labath        for i in range(4):
705ce0f876SPavel Labath            if i == 0:
715ce0f876SPavel Labath                # Verify that the printout for argc is correct.
722238dcc3SJonas Devlieghere                self.assertEqual(argc, int(lines[i].split(":")[1].strip(" {}"), 0))
732238dcc3SJonas Devlieghere            addr = int(lines[i].split(":")[0], 0)
745ce0f876SPavel Labath            # Verify that the printout for addr is incremented correctly.
755ce0f876SPavel Labath            self.assertEqual(addr, (address + i * 4))
765ce0f876SPavel Labath
775ce0f876SPavel Labath        # (lldb) memory read --format char[] --size 7 --count 1 `&my_string`
785ce0f876SPavel Labath        # 0x7fff5fbff990: {abcdefg}
795ce0f876SPavel Labath        self.expect(
805ce0f876SPavel Labath            "memory read --format char[] --size 7 --count 1 `&my_string`",
812238dcc3SJonas Devlieghere            substrs=["abcdefg"],
822238dcc3SJonas Devlieghere        )
835ce0f876SPavel Labath
845ce0f876SPavel Labath        # (lldb) memory read --format 'hex float' --size 16 `&argc`
855ce0f876SPavel Labath        # 0x7fff5fbff5b0: error: unsupported byte size (16) for hex float
865ce0f876SPavel Labath        # format
875ce0f876SPavel Labath        self.expect(
885ce0f876SPavel Labath            "memory read --format 'hex float' --size 16 `&argc`",
892238dcc3SJonas Devlieghere            substrs=["unsupported byte size (16) for hex float format"],
902238dcc3SJonas Devlieghere        )
915ce0f876SPavel Labath
925ce0f876SPavel Labath        self.expect(
935ce0f876SPavel Labath            "memory read --format 'float' --count 1 --size 8 `&my_double`",
942238dcc3SJonas Devlieghere            substrs=["1234."],
952238dcc3SJonas Devlieghere        )
965ce0f876SPavel Labath
975ce0f876SPavel Labath        # (lldb) memory read --format 'float' --count 1 --size 20 `&my_double`
985ce0f876SPavel Labath        # 0x7fff5fbff598: error: unsupported byte size (20) for float format
995ce0f876SPavel Labath        self.expect(
1005ce0f876SPavel Labath            "memory read --format 'float' --count 1 --size 20 `&my_double`",
1012238dcc3SJonas Devlieghere            substrs=["unsupported byte size (20) for float format"],
1022238dcc3SJonas Devlieghere        )
1035ce0f876SPavel Labath
1045ce0f876SPavel Labath        self.expect(
1052238dcc3SJonas Devlieghere            "memory read --type int --count 5 `&my_ints[0]`",
1062238dcc3SJonas Devlieghere            substrs=["(int) 0x", "2", "4", "6", "8", "10"],
1072238dcc3SJonas Devlieghere        )
1085ce0f876SPavel Labath
1095ce0f876SPavel Labath        self.expect(
1102238dcc3SJonas Devlieghere            "memory read --type int --count 5 --format hex `&my_ints[0]`",
1112238dcc3SJonas Devlieghere            substrs=["(int) 0x", "0x", "0a"],
1122238dcc3SJonas Devlieghere        )
1132238dcc3SJonas Devlieghere
1142238dcc3SJonas Devlieghere        self.expect(
1152238dcc3SJonas Devlieghere            "memory read --type int --count 5 --offset 5 `&my_ints[0]`",
1162238dcc3SJonas Devlieghere            substrs=["(int) 0x", "12", "14", "16", "18", "20"],
1172238dcc3SJonas Devlieghere        )
1185ce0f876SPavel Labath
1195ce0f876SPavel Labath        # the gdb format specifier and the size in characters for
1205ce0f876SPavel Labath        # the returned values including the 0x prefix.
1212238dcc3SJonas Devlieghere        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]
1252238dcc3SJonas Devlieghere            self.runCmd("memory read --gdb-format 4%s &my_uint64s" % formatter)
1265ce0f876SPavel Labath            lines = self.res.GetOutput().splitlines()
1275ce0f876SPavel Labath            objects_read = []
1285ce0f876SPavel Labath            for l in lines:
1292238dcc3SJonas Devlieghere                objects_read.extend(l.split(":")[1].split())
1305ce0f876SPavel Labath            # Check that we got back 4 0x0000 etc bytes
1315ce0f876SPavel Labath            for o in objects_read:
1325ce0f876SPavel Labath                self.assertEqual(len(o), expected_object_length)
133*80fcecb1SJonas Devlieghere            self.assertEqual(len(objects_read), 4)
1345ce0f876SPavel Labath
1355ce0f876SPavel Labath    def test_memory_read_file(self):
1365ce0f876SPavel Labath        self.build_run_stop()
1375ce0f876SPavel Labath        res = lldb.SBCommandReturnObject()
1385ce0f876SPavel Labath        self.ci.HandleCommand("memory read -f d -c 1 `&argc`", res)
1395ce0f876SPavel Labath        self.assertTrue(res.Succeeded(), "memory read failed:" + res.GetError())
1405ce0f876SPavel Labath
1415ce0f876SPavel Labath        # Record golden output.
1425ce0f876SPavel Labath        golden_output = res.GetOutput()
1435ce0f876SPavel Labath
1445ce0f876SPavel Labath        memory_read_file = self.getBuildArtifact("memory-read-output")
1455ce0f876SPavel Labath
1465ce0f876SPavel Labath        def check_file_content(expected):
1475ce0f876SPavel Labath            with open(memory_read_file) as f:
1485ce0f876SPavel Labath                lines = f.readlines()
1495ce0f876SPavel Labath                lines = [s.strip() for s in lines]
1505ce0f876SPavel Labath                expected = [s.strip() for s in expected]
1515ce0f876SPavel Labath                self.assertEqual(lines, expected)
1525ce0f876SPavel Labath
1535ce0f876SPavel Labath        # Sanity check.
1545ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))
1555ce0f876SPavel Labath        check_file_content([golden_output])
1565ce0f876SPavel Labath
1575ce0f876SPavel Labath        # Write some garbage to the file.
1582238dcc3SJonas Devlieghere        with open(memory_read_file, "w") as f:
1595ce0f876SPavel Labath            f.write("some garbage")
1605ce0f876SPavel Labath
1615ce0f876SPavel Labath        # Make sure the file is truncated when we run the command again.
1625ce0f876SPavel Labath        self.runCmd("memory read -f d -c 1 -o '{}' `&argc`".format(memory_read_file))
1635ce0f876SPavel Labath        check_file_content([golden_output])
1645ce0f876SPavel Labath
1655ce0f876SPavel Labath        # Make sure the file is appended when we run the command with --append-outfile.
1665ce0f876SPavel Labath        self.runCmd(
1675ce0f876SPavel Labath            "memory read -f d -c 1 -o '{}' --append-outfile `&argc`".format(
1682238dcc3SJonas Devlieghere                memory_read_file
1692238dcc3SJonas Devlieghere            )
1702238dcc3SJonas Devlieghere        )
1715ce0f876SPavel Labath        check_file_content([golden_output, golden_output])
172