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