brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 51a28c5 Raw
149 lines · python
1"""2Tests basic ThreadSanitizer support (detecting a data race).3"""4 5import lldb6from lldbsuite.test.lldbtest import *7from lldbsuite.test.decorators import *8import lldbsuite.test.lldbutil as lldbutil9import json10 11 12class TsanBasicTestCase(TestBase):13    @expectedFailureAll(14        oslist=["linux"],15        bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)",16    )17    @expectedFailureNetBSD18    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default19    @skipIfRemote20    @skipUnlessThreadSanitizer21    @no_debug_info_test22    def test(self):23        self.build()24        self.tsan_tests()25 26    def setUp(self):27        # Call super's setUp().28        TestBase.setUp(self)29        self.line_malloc = line_number("main.c", "// malloc line")30        self.line_thread1 = line_number("main.c", "// thread1 line")31        self.line_thread2 = line_number("main.c", "// thread2 line")32 33    def tsan_tests(self):34        exe = self.getBuildArtifact("a.out")35        self.expect("file " + exe, patterns=["Current executable set to .*a.out"])36 37        self.runCmd("run")38 39        stop_reason = (40            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()41        )42        if stop_reason == lldb.eStopReasonExec:43            # On OS X 10.10 and older, we need to re-exec to enable44            # interceptors.45            self.runCmd("continue")46 47        # the stop reason of the thread should be breakpoint.48        self.expect(49            "thread list",50            "A data race should be detected",51            substrs=["stopped", "stop reason = Data race detected"],52        )53 54        self.assertEqual(55            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(),56            lldb.eStopReasonInstrumentation,57        )58 59        # test that the TSan dylib is present60        self.expect(61            "image lookup -n __tsan_get_current_report",62            "__tsan_get_current_report should be present",63            substrs=["1 match found"],64        )65 66        process = self.dbg.GetSelectedTarget().process67        thread = process.GetSelectedThread()68        frame = thread.GetSelectedFrame()69        if self.platformIsDarwin():70            # We should not be stopped in the sanitizer library.71            self.assertIn("f2", frame.GetFunctionName())72        else:73            self.assertIn("__tsan_on_report", frame.GetFunctionName())74 75        # The stopped thread backtrace should contain either line1 or line276        # from main.c.77        found = False78        for i in range(0, thread.GetNumFrames()):79            frame = thread.GetFrameAtIndex(i)80            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":81                if frame.GetLineEntry().GetLine() == self.line_thread1:82                    found = True83                if frame.GetLineEntry().GetLine() == self.line_thread2:84                    found = True85        self.assertTrue(found)86 87        self.expect(88            "thread info -s",89            "The extended stop info should contain the TSan provided fields",90            substrs=["instrumentation_class", "description", "mops"],91        )92 93        output_lines = self.res.GetOutput().split("\n")94        json_line = "\n".join(output_lines[2:])95        data = json.loads(json_line)96        self.assertEqual(data["instrumentation_class"], "ThreadSanitizer")97        self.assertEqual(data["issue_type"], "data-race")98        self.assertEqual(len(data["mops"]), 2)99 100        backtraces = thread.GetStopReasonExtendedBacktraces(101            lldb.eInstrumentationRuntimeTypeAddressSanitizer102        )103        self.assertEqual(backtraces.GetSize(), 0)104 105        backtraces = thread.GetStopReasonExtendedBacktraces(106            lldb.eInstrumentationRuntimeTypeThreadSanitizer107        )108        self.assertGreaterEqual(backtraces.GetSize(), 2)109 110        # First backtrace is a memory operation111        thread = backtraces.GetThreadAtIndex(0)112        found = False113        for i in range(0, thread.GetNumFrames()):114            frame = thread.GetFrameAtIndex(i)115            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":116                if frame.GetLineEntry().GetLine() == self.line_thread1:117                    found = True118                if frame.GetLineEntry().GetLine() == self.line_thread2:119                    found = True120        self.assertTrue(found)121 122        # Second backtrace is a memory operation123        thread = backtraces.GetThreadAtIndex(1)124        found = False125        for i in range(0, thread.GetNumFrames()):126            frame = thread.GetFrameAtIndex(i)127            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":128                if frame.GetLineEntry().GetLine() == self.line_thread1:129                    found = True130                if frame.GetLineEntry().GetLine() == self.line_thread2:131                    found = True132        self.assertTrue(found)133 134        self.runCmd("continue")135 136        # the stop reason of the thread should be a SIGABRT.137        self.expect(138            "thread list",139            "We should be stopped due a SIGABRT",140            substrs=["stopped", "stop reason = signal SIGABRT"],141        )142 143        # test that we're in pthread_kill now (TSan abort the process)144        self.expect(145            "thread list",146            "We should be stopped in pthread_kill",147            substrs=["pthread_kill"],148        )149