brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · 8ae2d4a Raw
241 lines · python
1"""2Test that ASan memory history provider returns correct stack traces3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbplatform9from lldbsuite.test import lldbutil10from lldbsuite.test_event.build_exception import BuildError11 12 13class MemoryHistoryTestCase(TestBase):14    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default15    @expectedFailureNetBSD16    @skipUnlessAddressSanitizer17    def test_compiler_rt_asan(self):18        self.build(make_targets=["compiler_rt-asan"])19        self.compiler_rt_asan_tests()20 21    @skipUnlessDarwin22    @skipIf(bugnumber="rdar://109913184&143590169")23    def test_libsanitizers_asan(self):24        try:25            self.build(make_targets=["libsanitizers-asan"])26        except BuildError as e:27            self.skipTest("failed to build with libsanitizers")28        self.libsanitizers_asan_tests()29 30    @skipUnlessDarwin31    @skipIf(macos_version=["<", "15.5"])32    def test_libsanitizers_traces(self):33        self.build(make_targets=["libsanitizers-traces"])34        self.libsanitizers_traces_tests()35 36    def setUp(self):37        # Call super's setUp().38        TestBase.setUp(self)39        self.line_malloc = line_number("main.c", "// malloc line")40        self.line_malloc2 = line_number("main.c", "// malloc2 line")41        self.line_free = line_number("main.c", "// free line")42        self.line_breakpoint = line_number("main.c", "// break line")43 44    def check_traces(self):45        self.expect(46            "memory history 'pointer'",47            substrs=[48                "Memory deallocated by Thread",49                "a.out`f2",50                f"main.c:{self.line_free}",51                "Memory allocated by Thread",52                "a.out`f1",53                f"main.c:{self.line_malloc}",54            ],55        )56 57    # Set breakpoint: after free, but before bug58    def set_breakpoint(self, target):59        bkpt = target.BreakpointCreateByLocation("main.c", self.line_breakpoint)60        self.assertGreater(bkpt.GetNumLocations(), 0, "Set the breakpoint successfully")61 62    def run_to_breakpoint(self, target):63        self.set_breakpoint(target)64        self.runCmd("run")65        self.expect(66            "thread list",67            STOPPED_DUE_TO_BREAKPOINT,68            substrs=["stopped", "stop reason = breakpoint"],69        )70 71    def libsanitizers_traces_tests(self):72        target = self.createTestTarget()73 74        self.runCmd("env SanitizersAllocationTraces=all")75 76        self.run_to_breakpoint(target)77        self.check_traces()78 79    def libsanitizers_asan_tests(self):80        target = self.createTestTarget()81 82        self.runCmd("env SanitizersAddress=1 MallocSanitizerZone=1")83 84        self.run_to_breakpoint(target)85        self.check_traces()86 87        self.runCmd("continue")88 89        # Stop on report90        self.expect(91            "thread list",92            "Process should be stopped due to ASan report",93            substrs=["stopped", "stop reason = Use of deallocated memory"],94        )95        self.check_traces()96 97        if self.platformIsDarwin():98            # Make sure we're not stopped in the sanitizer library but instead at the99            # point of failure in the user-code.100            self.assertEqual(self.frame().GetFunctionName(), "main")101 102        # do the same using SB API103        process = self.dbg.GetSelectedTarget().process104        val = (105            process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")106        )107        addr = val.GetValueAsUnsigned()108        threads = process.GetHistoryThreads(addr)109        self.assertEqual(threads.GetSize(), 2)110 111        history_thread = threads.GetThreadAtIndex(0)112        self.assertTrue(history_thread.num_frames >= 2)113        self.assertEqual(114            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),115            "main.c",116        )117 118        history_thread = threads.GetThreadAtIndex(1)119        self.assertTrue(history_thread.num_frames >= 2)120        self.assertEqual(121            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),122            "main.c",123        )124 125        # let's free the container (SBThreadCollection) and see if the126        # SBThreads still live127        threads = None128        self.assertTrue(history_thread.num_frames >= 2)129        self.assertEqual(130            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),131            "main.c",132        )133 134    def compiler_rt_asan_tests(self):135        target = self.createTestTarget()136 137        self.registerSanitizerLibrariesWithTarget(target)138 139        self.set_breakpoint(target)140 141        # "memory history" command should not work without a process142        self.expect(143            "memory history 0",144            error=True,145            substrs=["Command requires a current process"],146        )147 148        self.runCmd("run")149 150        stop_reason = (151            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()152        )153        if stop_reason == lldb.eStopReasonExec:154            # On OS X 10.10 and older, we need to re-exec to enable155            # interceptors.156            self.runCmd("continue")157 158        # the stop reason of the thread should be breakpoint.159        self.expect(160            "thread list",161            STOPPED_DUE_TO_BREAKPOINT,162            substrs=["stopped", "stop reason = breakpoint"],163        )164 165        # test that the ASan dylib is present166        self.expect(167            "image lookup -n __asan_describe_address",168            "__asan_describe_address should be present",169            substrs=["1 match found"],170        )171 172        self.check_traces()173 174        # do the same using SB API175        process = self.dbg.GetSelectedTarget().process176        val = (177            process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")178        )179        addr = val.GetValueAsUnsigned()180        threads = process.GetHistoryThreads(addr)181        self.assertEqual(threads.GetSize(), 2)182 183        history_thread = threads.GetThreadAtIndex(0)184        self.assertGreaterEqual(history_thread.num_frames, 2)185        self.assertEqual(186            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),187            "main.c",188        )189        self.assertEqual(190            history_thread.frames[1].GetLineEntry().GetLine(), self.line_free191        )192 193        history_thread = threads.GetThreadAtIndex(1)194        self.assertGreaterEqual(history_thread.num_frames, 2)195        self.assertEqual(196            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),197            "main.c",198        )199        self.assertEqual(200            history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc201        )202 203        # let's free the container (SBThreadCollection) and see if the204        # SBThreads still live205        threads = None206        self.assertGreaterEqual(history_thread.num_frames, 2)207        self.assertEqual(208            history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(),209            "main.c",210        )211        self.assertEqual(212            history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc213        )214 215        # ASan will break when a report occurs and we'll try the API then216        self.runCmd("continue")217 218        self.expect(219            "thread list",220            "Process should be stopped due to ASan report",221            substrs=["stopped", "stop reason = Use of deallocated memory"],222        )223 224        self.check_traces()225 226        if self.platformIsDarwin():227            # Make sure we're not stopped in the sanitizer library but instead at the228            # point of failure in the user-code.229            self.assertEqual(self.frame().GetFunctionName(), "main")230 231        # make sure the 'memory history' command still works even when we're232        # generating a report now233        self.expect(234            "memory history 'another_pointer'",235            substrs=[236                "Memory allocated by Thread",237                "a.out`f1",238                "main.c:%d" % self.line_malloc2,239            ],240        )241