summaryrefslogtreecommitdiffstats
path: root/lldb/test/functionalities/asan/TestMemoryHistory.py
blob: f8a3131d2352315da5413969dac80dfe5ff91281 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
Test that ASan memory history provider returns correct stack traces
"""

import os, time
import unittest2
import lldb
from lldbtest import *
import lldbutil

class AsanTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    # The default compiler ("clang") may not support Address Sanitizer or it
    # may not have the debugging API which was recently added, so we're calling
    # self.useBuiltClang() to use clang from the llvm-build directory instead

    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
    @skipIfRemote
    @dsym_test
    def test_with_dsym (self):
        compiler = self.findBuiltClang ()
        self.buildDsym (None, compiler)
        self.asan_tests ()

    @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default
    @skipIfRemote
    @dwarf_test
    def test_with_dwarf (self):
        compiler = self.findBuiltClang ()
        self.buildDwarf (None, compiler)
        self.asan_tests ()

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        self.line_malloc = line_number('main.c', '// malloc line')
        self.line_malloc2 = line_number('main.c', '// malloc2 line')
        self.line_free = line_number('main.c', '// free line')
        self.line_breakpoint = line_number('main.c', '// break line')

    def asan_tests (self):
        exe = os.path.join (os.getcwd(), "a.out")
        self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ])

        self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)

        # "memory history" command should not work without a process
        self.expect("memory history 0",
            error = True,
            substrs = ["invalid process"])

        self.runCmd("run")

        # ASan will relaunch the process to insert its library.
        self.expect("thread list", "Process should be stopped due to exec.",
            substrs = ['stopped', 'stop reason = exec'])

        self.runCmd("continue")

        # the stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
            substrs = ['stopped', 'stop reason = breakpoint'])

        # test that the ASan dylib is present
        self.expect("image lookup -n __asan_describe_address", "__asan_describe_address should be present",
            substrs = ['1 match found'])

        # test the 'memory history' command
        self.expect("memory history 'pointer'",
            substrs = [
                'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc,
                'Memory deallocated at', 'a.out`f2', 'main.c:%d' % self.line_free])

        # do the same using SB API
        process = self.dbg.GetSelectedTarget().process
        val = process.GetSelectedThread().GetSelectedFrame().EvaluateExpression("pointer")
        addr = val.GetValueAsUnsigned()
        threads = process.GetHistoryThreads(addr);
        self.assertEqual(threads.GetSize(), 2)
        
        history_thread = threads.GetThreadAtIndex(0)
        self.assertTrue(history_thread.num_frames >= 2)
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c")
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc)
        
        history_thread = threads.GetThreadAtIndex(1)
        self.assertTrue(history_thread.num_frames >= 2)
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c")
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_free)

        # let's free the container (SBThreadCollection) and see if the SBThreads still live
        threads = None
        self.assertTrue(history_thread.num_frames >= 2)
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c")
        self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_free)

        # now let's break when an ASan report occurs and try the API then
        self.runCmd("breakpoint set -n __asan_report_error")

        self.runCmd("continue")

        # the stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
            substrs = ['stopped', 'stop reason = breakpoint'])

        # make sure the 'memory history' command still works even when we're generating a report now
        self.expect("memory history 'another_pointer'",
            substrs = [
                'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc2])

if __name__ == '__main__':
    import atexit
    lldb.SBDebugger.Initialize()
    atexit.register(lambda: lldb.SBDebugger.Terminate())
    unittest2.main()
OpenPOWER on IntegriCloud