xref: /llvm-project/lldb/test/API/functionalities/asan/TestMemoryHistory.py (revision 988ffd06722e7e056b239efe497345ac97be33db)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest that ASan memory history provider returns correct stack traces
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprechtimport lldb
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
999451b44SJordan Rupprechtfrom lldbsuite.test import lldbplatform
1099451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
11*988ffd06SUsama Hameedfrom lldbsuite.test_event.build_exception import BuildError
1299451b44SJordan Rupprecht
1399451b44SJordan Rupprechtclass AsanTestCase(TestBase):
1499451b44SJordan Rupprecht    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
1599451b44SJordan Rupprecht    @expectedFailureNetBSD
1699451b44SJordan Rupprecht    @skipUnlessAddressSanitizer
1799451b44SJordan Rupprecht    def test(self):
18*988ffd06SUsama Hameed        self.build(make_targets=["asan"])
1999451b44SJordan Rupprecht        self.asan_tests()
2099451b44SJordan Rupprecht
21*988ffd06SUsama Hameed    @skipIf(oslist=no_match(["macosx"]))
22*988ffd06SUsama Hameed    def test_libsanitizers_asan(self):
23*988ffd06SUsama Hameed        try:
24*988ffd06SUsama Hameed            self.build(make_targets=["libsanitizers"])
25*988ffd06SUsama Hameed        except BuildError as e:
26*988ffd06SUsama Hameed            self.skipTest("failed to build with libsanitizers")
27*988ffd06SUsama Hameed        self.libsanitizer_tests()
28*988ffd06SUsama Hameed
2999451b44SJordan Rupprecht    def setUp(self):
3099451b44SJordan Rupprecht        # Call super's setUp().
3199451b44SJordan Rupprecht        TestBase.setUp(self)
322238dcc3SJonas Devlieghere        self.line_malloc = line_number("main.c", "// malloc line")
332238dcc3SJonas Devlieghere        self.line_malloc2 = line_number("main.c", "// malloc2 line")
342238dcc3SJonas Devlieghere        self.line_free = line_number("main.c", "// free line")
352238dcc3SJonas Devlieghere        self.line_breakpoint = line_number("main.c", "// break line")
3699451b44SJordan Rupprecht
37*988ffd06SUsama Hameed    # Test line numbers: rdar://126237493
38*988ffd06SUsama Hameed    def libsanitizer_tests(self):
39*988ffd06SUsama Hameed        target = self.createTestTarget()
40*988ffd06SUsama Hameed
41*988ffd06SUsama Hameed        self.runCmd(
42*988ffd06SUsama Hameed            "env SanitizersAddress=1 MallocSanitizerZone=1 MallocSecureAllocator=0"
43*988ffd06SUsama Hameed        )
44*988ffd06SUsama Hameed
45*988ffd06SUsama Hameed        self.runCmd("run")
46*988ffd06SUsama Hameed
47*988ffd06SUsama Hameed        # In libsanitizers, memory history is not supported until a report has been generated
48*988ffd06SUsama Hameed        self.expect(
49*988ffd06SUsama Hameed            "thread list",
50*988ffd06SUsama Hameed            "Process should be stopped due to ASan report",
51*988ffd06SUsama Hameed            substrs=["stopped", "stop reason = Use of deallocated memory"],
52*988ffd06SUsama Hameed        )
53*988ffd06SUsama Hameed
54*988ffd06SUsama Hameed        # test the 'memory history' command
55*988ffd06SUsama Hameed        self.expect(
56*988ffd06SUsama Hameed            "memory history 'pointer'",
57*988ffd06SUsama Hameed            substrs=[
58*988ffd06SUsama Hameed                "Memory deallocated by Thread",
59*988ffd06SUsama Hameed                "a.out`f2",
60*988ffd06SUsama Hameed                "main.c",
61*988ffd06SUsama Hameed                "Memory allocated by Thread",
62*988ffd06SUsama Hameed                "a.out`f1",
63*988ffd06SUsama Hameed                "main.c",
64*988ffd06SUsama Hameed            ],
65*988ffd06SUsama Hameed        )
66*988ffd06SUsama Hameed
67*988ffd06SUsama Hameed        # do the same using SB API
68*988ffd06SUsama Hameed        process = self.dbg.GetSelectedTarget().process
69*988ffd06SUsama Hameed        val = (
70*988ffd06SUsama Hameed            process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")
71*988ffd06SUsama Hameed        )
72*988ffd06SUsama Hameed        addr = val.GetValueAsUnsigned()
73*988ffd06SUsama Hameed        threads = process.GetHistoryThreads(addr)
74*988ffd06SUsama Hameed        self.assertEqual(threads.GetSize(), 2)
75*988ffd06SUsama Hameed
76*988ffd06SUsama Hameed        history_thread = threads.GetThreadAtIndex(0)
77*988ffd06SUsama Hameed        self.assertTrue(history_thread.num_frames >= 2)
78*988ffd06SUsama Hameed        self.assertEqual(
79*988ffd06SUsama Hameed            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
80*988ffd06SUsama Hameed            "main.c",
81*988ffd06SUsama Hameed        )
82*988ffd06SUsama Hameed
83*988ffd06SUsama Hameed        history_thread = threads.GetThreadAtIndex(1)
84*988ffd06SUsama Hameed        self.assertTrue(history_thread.num_frames >= 2)
85*988ffd06SUsama Hameed        self.assertEqual(
86*988ffd06SUsama Hameed            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
87*988ffd06SUsama Hameed            "main.c",
88*988ffd06SUsama Hameed        )
89*988ffd06SUsama Hameed
90*988ffd06SUsama Hameed        # let's free the container (SBThreadCollection) and see if the
91*988ffd06SUsama Hameed        # SBThreads still live
92*988ffd06SUsama Hameed        threads = None
93*988ffd06SUsama Hameed        self.assertTrue(history_thread.num_frames >= 2)
94*988ffd06SUsama Hameed        self.assertEqual(
95*988ffd06SUsama Hameed            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
96*988ffd06SUsama Hameed            "main.c",
97*988ffd06SUsama Hameed        )
98*988ffd06SUsama Hameed
9999451b44SJordan Rupprecht    def asan_tests(self):
10054c26872SRaphael Isemann        target = self.createTestTarget()
10199451b44SJordan Rupprecht
10299451b44SJordan Rupprecht        self.registerSanitizerLibrariesWithTarget(target)
10399451b44SJordan Rupprecht
10499451b44SJordan Rupprecht        self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)
10599451b44SJordan Rupprecht
10699451b44SJordan Rupprecht        # "memory history" command should not work without a process
1072238dcc3SJonas Devlieghere        self.expect(
1082238dcc3SJonas Devlieghere            "memory history 0",
10999451b44SJordan Rupprecht            error=True,
1102238dcc3SJonas Devlieghere            substrs=["Command requires a current process"],
1112238dcc3SJonas Devlieghere        )
11299451b44SJordan Rupprecht
11399451b44SJordan Rupprecht        self.runCmd("run")
11499451b44SJordan Rupprecht
1152238dcc3SJonas Devlieghere        stop_reason = (
1162238dcc3SJonas Devlieghere            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
1172238dcc3SJonas Devlieghere        )
11899451b44SJordan Rupprecht        if stop_reason == lldb.eStopReasonExec:
11999451b44SJordan Rupprecht            # On OS X 10.10 and older, we need to re-exec to enable
12099451b44SJordan Rupprecht            # interceptors.
12199451b44SJordan Rupprecht            self.runCmd("continue")
12299451b44SJordan Rupprecht
12399451b44SJordan Rupprecht        # the stop reason of the thread should be breakpoint.
1242238dcc3SJonas Devlieghere        self.expect(
1252238dcc3SJonas Devlieghere            "thread list",
1262238dcc3SJonas Devlieghere            STOPPED_DUE_TO_BREAKPOINT,
1272238dcc3SJonas Devlieghere            substrs=["stopped", "stop reason = breakpoint"],
1282238dcc3SJonas Devlieghere        )
12999451b44SJordan Rupprecht
13099451b44SJordan Rupprecht        # test that the ASan dylib is present
13199451b44SJordan Rupprecht        self.expect(
13299451b44SJordan Rupprecht            "image lookup -n __asan_describe_address",
13399451b44SJordan Rupprecht            "__asan_describe_address should be present",
1342238dcc3SJonas Devlieghere            substrs=["1 match found"],
1352238dcc3SJonas Devlieghere        )
13699451b44SJordan Rupprecht
13799451b44SJordan Rupprecht        # test the 'memory history' command
13899451b44SJordan Rupprecht        self.expect(
13999451b44SJordan Rupprecht            "memory history 'pointer'",
14099451b44SJordan Rupprecht            substrs=[
1412238dcc3SJonas Devlieghere                "Memory deallocated by Thread",
1422238dcc3SJonas Devlieghere                "a.out`f2",
1432238dcc3SJonas Devlieghere                "main.c:%d" % self.line_free,
1442238dcc3SJonas Devlieghere                "Memory allocated by Thread",
1452238dcc3SJonas Devlieghere                "a.out`f1",
1462238dcc3SJonas Devlieghere                "main.c:%d" % self.line_malloc,
1472238dcc3SJonas Devlieghere            ],
1482238dcc3SJonas Devlieghere        )
14999451b44SJordan Rupprecht
15099451b44SJordan Rupprecht        # do the same using SB API
15199451b44SJordan Rupprecht        process = self.dbg.GetSelectedTarget().process
1522238dcc3SJonas Devlieghere        val = (
1532238dcc3SJonas Devlieghere            process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")
1542238dcc3SJonas Devlieghere        )
15599451b44SJordan Rupprecht        addr = val.GetValueAsUnsigned()
15699451b44SJordan Rupprecht        threads = process.GetHistoryThreads(addr)
15799451b44SJordan Rupprecht        self.assertEqual(threads.GetSize(), 2)
15899451b44SJordan Rupprecht
15999451b44SJordan Rupprecht        history_thread = threads.GetThreadAtIndex(0)
1609c246882SJordan Rupprecht        self.assertGreaterEqual(history_thread.num_frames, 2)
16199451b44SJordan Rupprecht        self.assertEqual(
1622238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
1632238dcc3SJonas Devlieghere            "main.c",
1642238dcc3SJonas Devlieghere        )
1652238dcc3SJonas Devlieghere        self.assertEqual(
1662238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetLine(), self.line_free
1672238dcc3SJonas Devlieghere        )
16899451b44SJordan Rupprecht
16999451b44SJordan Rupprecht        history_thread = threads.GetThreadAtIndex(1)
1709c246882SJordan Rupprecht        self.assertGreaterEqual(history_thread.num_frames, 2)
17199451b44SJordan Rupprecht        self.assertEqual(
1722238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
1732238dcc3SJonas Devlieghere            "main.c",
1742238dcc3SJonas Devlieghere        )
1752238dcc3SJonas Devlieghere        self.assertEqual(
1762238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc
1772238dcc3SJonas Devlieghere        )
17899451b44SJordan Rupprecht
17999451b44SJordan Rupprecht        # let's free the container (SBThreadCollection) and see if the
18099451b44SJordan Rupprecht        # SBThreads still live
18199451b44SJordan Rupprecht        threads = None
1829c246882SJordan Rupprecht        self.assertGreaterEqual(history_thread.num_frames, 2)
18399451b44SJordan Rupprecht        self.assertEqual(
1842238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),
1852238dcc3SJonas Devlieghere            "main.c",
1862238dcc3SJonas Devlieghere        )
1872238dcc3SJonas Devlieghere        self.assertEqual(
1882238dcc3SJonas Devlieghere            history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc
1892238dcc3SJonas Devlieghere        )
19099451b44SJordan Rupprecht
19199451b44SJordan Rupprecht        # ASan will break when a report occurs and we'll try the API then
19299451b44SJordan Rupprecht        self.runCmd("continue")
19399451b44SJordan Rupprecht
19499451b44SJordan Rupprecht        self.expect(
19599451b44SJordan Rupprecht            "thread list",
19699451b44SJordan Rupprecht            "Process should be stopped due to ASan report",
1972238dcc3SJonas Devlieghere            substrs=["stopped", "stop reason = Use of deallocated memory"],
1982238dcc3SJonas Devlieghere        )
19999451b44SJordan Rupprecht
20099451b44SJordan Rupprecht        # make sure the 'memory history' command still works even when we're
20199451b44SJordan Rupprecht        # generating a report now
20299451b44SJordan Rupprecht        self.expect(
20399451b44SJordan Rupprecht            "memory history 'another_pointer'",
20499451b44SJordan Rupprecht            substrs=[
2052238dcc3SJonas Devlieghere                "Memory allocated by Thread",
2062238dcc3SJonas Devlieghere                "a.out`f1",
2072238dcc3SJonas Devlieghere                "main.c:%d" % self.line_malloc2,
2082238dcc3SJonas Devlieghere            ],
2092238dcc3SJonas Devlieghere        )
210