TestClassTypesDisassembly.py revision 6bc4dcdfbcdfa455299d2123011b82a77351ee72
1"""
2Test the lldb disassemble command on each call frame when stopped on C's ctor.
3"""
4
5import os, time
6import unittest2
7import lldb
8from lldbtest import *
9import lldbutil
10
11class IterateFrameAndDisassembleTestCase(TestBase):
12
13    mydir = os.path.join("lang", "cpp", "class_types")
14
15    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
16    @dsym_test
17    def test_with_dsym_and_run_command(self):
18        """Disassemble each call frame when stopped on C's constructor."""
19        self.buildDsym()
20        self.disassemble_call_stack()
21
22    @dwarf_test
23    @expectedFailureLinux # due to llvm.org/pr14540
24    def test_with_dwarf_and_run_command(self):
25        """Disassemble each call frame when stopped on C's constructor."""
26        self.buildDwarf()
27        self.disassemble_call_stack()
28
29    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
30    @python_api_test
31    @dsym_test
32    def test_with_dsym_and_python_api(self):
33        """Disassemble each call frame when stopped on C's constructor."""
34        self.buildDsym()
35        self.disassemble_call_stack_python()
36
37    @python_api_test
38    @dwarf_test
39    @expectedFailureLinux # due to llvm.org/pr14540
40    def test_with_dwarf_and_python_api(self):
41        """Disassemble each call frame when stopped on C's constructor."""
42        self.buildDwarf()
43        self.disassemble_call_stack_python()
44
45    def setUp(self):
46        # Call super's setUp().
47        TestBase.setUp(self)
48        # Find the line number to break for main.cpp.
49        self.line = line_number('main.cpp', '// Set break point at this line.')
50
51    def breakOnCtor(self):
52        """Setup/run the program so it stops on C's constructor."""
53        exe = os.path.join(os.getcwd(), "a.out")
54        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
55
56        # Break on the ctor function of class C.
57        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
58
59        self.runCmd("run", RUN_SUCCEEDED)
60
61        # The stop reason of the thread should be breakpoint.
62        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
63            substrs = ['stopped',
64                       'stop reason = breakpoint'])
65
66        # We should be stopped on the ctor function of class C.
67        self.expect("thread backtrace", BACKTRACE_DISPLAYED_CORRECTLY,
68            substrs = ['C::C'])
69
70    def disassemble_call_stack(self):
71        """Disassemble each call frame when stopped on C's constructor."""
72        self.breakOnCtor()
73
74        raw_output = self.res.GetOutput()
75        frameRE = re.compile(r"""
76                              ^\s\sframe        # heading for the frame info,
77                              .*                # wildcard, and
78                              0x[0-9a-f]{16}    # the frame pc, and
79                              \sa.out`(.+)      # module`function, and
80                              \s\+\s            # the rest ' + ....'
81                              """, re.VERBOSE)
82        for line in raw_output.split(os.linesep):
83            match = frameRE.search(line)
84            if match:
85                function = match.group(1)
86                #print "line:", line
87                #print "function:", function
88                self.runCmd("disassemble -n '%s'" % function)
89
90    def disassemble_call_stack_python(self):
91        """Disassemble each call frame when stopped on C's constructor."""
92        self.breakOnCtor()
93
94        # Now use the Python API to get at each function on the call stack and
95        # disassemble it.
96        target = self.dbg.GetSelectedTarget()
97        process = target.GetProcess()
98        thread = process.GetThreadAtIndex(0)
99        depth = thread.GetNumFrames()
100        for i in range(depth - 1):
101            frame = thread.GetFrameAtIndex(i)
102            function = frame.GetFunction()
103            # Print the function header.
104            if self.TraceOn():
105                print
106                print function
107            if function:
108                # Get all instructions for this function and print them out.
109                insts = function.GetInstructions(target)
110                for inst in insts:
111                    # We could simply do 'print inst' to print out the disassembly.
112                    # But we want to print to stdout only if self.TraceOn() is True.
113                    disasm = str(inst)
114                    if self.TraceOn():
115                        print disasm
116
117
118if __name__ == '__main__':
119    import atexit
120    lldb.SBDebugger.Initialize()
121    atexit.register(lambda: lldb.SBDebugger.Terminate())
122    unittest2.main()
123