199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest the AddressSanitizer runtime support for report breakpoint and data extraction.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprecht
799451b44SJordan Rupprechtimport json
899451b44SJordan Rupprechtimport lldb
999451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
1099451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1199451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1299451b44SJordan Rupprecht
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprechtclass AsanTestReportDataCase(TestBase):
1599451b44SJordan Rupprecht
1699451b44SJordan Rupprecht    @skipIfFreeBSD  # llvm.org/pr21136 runtimes not yet available by default
1799451b44SJordan Rupprecht    @expectedFailureNetBSD
1899451b44SJordan Rupprecht    @skipUnlessAddressSanitizer
1999451b44SJordan Rupprecht    @skipIf(archs=['i386'], bugnumber="llvm.org/PR36710")
2099451b44SJordan Rupprecht    def test(self):
2199451b44SJordan Rupprecht        self.build()
2299451b44SJordan Rupprecht        self.asan_tests()
2399451b44SJordan Rupprecht
2499451b44SJordan Rupprecht    def setUp(self):
2599451b44SJordan Rupprecht        # Call super's setUp().
2699451b44SJordan Rupprecht        TestBase.setUp(self)
2799451b44SJordan Rupprecht        self.line_malloc = line_number('main.c', '// malloc line')
2899451b44SJordan Rupprecht        self.line_malloc2 = line_number('main.c', '// malloc2 line')
2999451b44SJordan Rupprecht        self.line_free = line_number('main.c', '// free line')
3099451b44SJordan Rupprecht        self.line_breakpoint = line_number('main.c', '// break line')
3199451b44SJordan Rupprecht        self.line_crash = line_number('main.c', '// BOOM line')
3299451b44SJordan Rupprecht        self.col_crash = 16
3399451b44SJordan Rupprecht
3499451b44SJordan Rupprecht    def asan_tests(self):
35*54c26872SRaphael Isemann        target = self.createTestTarget()
3699451b44SJordan Rupprecht
3799451b44SJordan Rupprecht        self.registerSanitizerLibrariesWithTarget(target)
3899451b44SJordan Rupprecht
3999451b44SJordan Rupprecht        self.runCmd("run")
4099451b44SJordan Rupprecht
4199451b44SJordan Rupprecht        stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
4299451b44SJordan Rupprecht        if stop_reason == lldb.eStopReasonExec:
4399451b44SJordan Rupprecht            # On OS X 10.10 and older, we need to re-exec to enable
4499451b44SJordan Rupprecht            # interceptors.
4599451b44SJordan Rupprecht            self.runCmd("continue")
4699451b44SJordan Rupprecht
4799451b44SJordan Rupprecht        self.expect(
4899451b44SJordan Rupprecht            "thread list",
4999451b44SJordan Rupprecht            "Process should be stopped due to ASan report",
5099451b44SJordan Rupprecht            substrs=[
5199451b44SJordan Rupprecht                'stopped',
5299451b44SJordan Rupprecht                'stop reason = Use of deallocated memory'])
5399451b44SJordan Rupprecht
5499451b44SJordan Rupprecht        self.assertEqual(
5599451b44SJordan Rupprecht            self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(),
5699451b44SJordan Rupprecht            lldb.eStopReasonInstrumentation)
5799451b44SJordan Rupprecht
5899451b44SJordan Rupprecht        self.expect("bt", "The backtrace should show the crashing line",
5999451b44SJordan Rupprecht                    substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)])
6099451b44SJordan Rupprecht
6199451b44SJordan Rupprecht        self.expect(
6299451b44SJordan Rupprecht            "thread info -s",
6399451b44SJordan Rupprecht            "The extended stop info should contain the ASan provided fields",
6499451b44SJordan Rupprecht            substrs=[
6599451b44SJordan Rupprecht                "access_size",
6699451b44SJordan Rupprecht                "access_type",
6799451b44SJordan Rupprecht                "address",
6899451b44SJordan Rupprecht                "description",
6999451b44SJordan Rupprecht                "heap-use-after-free",
7099451b44SJordan Rupprecht                "pc",
7199451b44SJordan Rupprecht            ])
7299451b44SJordan Rupprecht
7399451b44SJordan Rupprecht        output_lines = self.res.GetOutput().split('\n')
7499451b44SJordan Rupprecht        json_line = '\n'.join(output_lines[2:])
7599451b44SJordan Rupprecht        data = json.loads(json_line)
7699451b44SJordan Rupprecht        self.assertEqual(data["description"], "heap-use-after-free")
7799451b44SJordan Rupprecht        self.assertEqual(data["instrumentation_class"], "AddressSanitizer")
7899451b44SJordan Rupprecht        self.assertEqual(data["stop_type"], "fatal_error")
7999451b44SJordan Rupprecht
8099451b44SJordan Rupprecht        # now let's try the SB API
8199451b44SJordan Rupprecht        process = self.dbg.GetSelectedTarget().process
8299451b44SJordan Rupprecht        thread = process.GetSelectedThread()
8399451b44SJordan Rupprecht
8499451b44SJordan Rupprecht        s = lldb.SBStream()
8599451b44SJordan Rupprecht        self.assertTrue(thread.GetStopReasonExtendedInfoAsJSON(s))
8699451b44SJordan Rupprecht        s = s.GetData()
8799451b44SJordan Rupprecht        data2 = json.loads(s)
8899451b44SJordan Rupprecht        self.assertEqual(data, data2)
89