1""" 2Test thread step-in, step-over and step-out work with the "Avoid no debug" option. 3""" 4 5 6 7 8import lldb 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12 13 14class StepAvoidsNoDebugTestCase(TestBase): 15 16 @add_test_categories(['pyapi']) 17 def test_step_out_with_python(self): 18 """Test stepping out using avoid-no-debug with dsyms.""" 19 self.build() 20 self.get_to_starting_point() 21 self.do_step_out_past_nodebug() 22 23 @add_test_categories(['pyapi']) 24 @decorators.expectedFailureAll( 25 compiler="gcc", bugnumber="llvm.org/pr28549") 26 @decorators.expectedFailureAll( 27 compiler="clang", 28 compiler_version=[ 29 ">=", 30 "3.9"], 31 archs=["i386"], 32 oslist=no_match(["freebsd"]), 33 bugnumber="llvm.org/pr28549") 34 def test_step_over_with_python(self): 35 """Test stepping over using avoid-no-debug with dwarf.""" 36 self.build() 37 self.get_to_starting_point() 38 self.do_step_over_past_nodebug() 39 40 @add_test_categories(['pyapi']) 41 @decorators.expectedFailureAll( 42 compiler="gcc", bugnumber="llvm.org/pr28549") 43 @decorators.expectedFailureAll( 44 compiler="clang", 45 compiler_version=[ 46 ">=", 47 "3.9"], 48 archs=["i386"], 49 oslist=no_match(["freebsd"]), 50 bugnumber="llvm.org/pr28549") 51 def test_step_in_with_python(self): 52 """Test stepping in using avoid-no-debug with dwarf.""" 53 self.build() 54 self.get_to_starting_point() 55 self.do_step_in_past_nodebug() 56 57 def setUp(self): 58 TestBase.setUp(self) 59 self.main_source = "with-debug.c" 60 self.main_source_spec = lldb.SBFileSpec("with-debug.c") 61 self.dbg.HandleCommand( 62 "settings set target.process.thread.step-out-avoid-nodebug true") 63 64 def tearDown(self): 65 self.dbg.HandleCommand( 66 "settings set target.process.thread.step-out-avoid-nodebug false") 67 TestBase.tearDown(self) 68 69 def hit_correct_line(self, pattern): 70 target_line = line_number(self.main_source, pattern) 71 self.assertTrue( 72 target_line != 0, 73 "Could not find source pattern " + 74 pattern) 75 cur_line = self.thread.frames[0].GetLineEntry().GetLine() 76 self.assertEqual( 77 cur_line, target_line, 78 "Stepped to line %d instead of expected %d with pattern '%s'." % 79 (cur_line, 80 target_line, 81 pattern)) 82 83 def hit_correct_function(self, pattern): 84 name = self.thread.frames[0].GetFunctionName() 85 self.assertTrue( 86 pattern in name, "Got to '%s' not the expected function '%s'." % 87 (name, pattern)) 88 89 def get_to_starting_point(self): 90 exe = self.getBuildArtifact("a.out") 91 error = lldb.SBError() 92 93 self.target = self.dbg.CreateTarget(exe) 94 self.assertTrue(self.target, VALID_TARGET) 95 96 inner_bkpt = self.target.BreakpointCreateBySourceRegex( 97 "Stop here and step out of me", self.main_source_spec) 98 self.assertTrue(inner_bkpt, VALID_BREAKPOINT) 99 100 # Now launch the process, and do not stop at entry point. 101 self.process = self.target.LaunchSimple( 102 None, None, self.get_process_working_directory()) 103 104 self.assertTrue(self.process, PROCESS_IS_VALID) 105 106 # Now finish, and make sure the return value is correct. 107 threads = lldbutil.get_threads_stopped_at_breakpoint( 108 self.process, inner_bkpt) 109 self.assertEquals(len(threads), 1, "Stopped at inner breakpoint.") 110 self.thread = threads[0] 111 112 def do_step_out_past_nodebug(self): 113 # The first step out takes us to the called_from_nodebug frame, just to make sure setting 114 # step-out-avoid-nodebug doesn't change the behavior in frames with 115 # debug info. 116 self.thread.StepOut() 117 self.hit_correct_line( 118 "intermediate_return_value = called_from_nodebug_actual(some_value)") 119 self.thread.StepOut() 120 self.hit_correct_line( 121 "int return_value = no_debug_caller(5, called_from_nodebug)") 122 123 def do_step_over_past_nodebug(self): 124 self.thread.StepOver() 125 self.hit_correct_line( 126 "intermediate_return_value = called_from_nodebug_actual(some_value)") 127 self.thread.StepOver() 128 self.hit_correct_line("return intermediate_return_value") 129 self.thread.StepOver() 130 # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" 131 # when exiting a frame. In all cases we leave the pc at the point where we exited the 132 # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. 133 # If we ever change this we will need to fix this test. 134 self.hit_correct_line( 135 "int return_value = no_debug_caller(5, called_from_nodebug)") 136 137 def do_step_in_past_nodebug(self): 138 self.thread.StepInto() 139 self.hit_correct_line( 140 "intermediate_return_value = called_from_nodebug_actual(some_value)") 141 self.thread.StepInto() 142 self.hit_correct_line("return intermediate_return_value") 143 self.thread.StepInto() 144 # Note, lldb doesn't follow gdb's distinction between "step-out" and "step-over/step-in" 145 # when exiting a frame. In all cases we leave the pc at the point where we exited the 146 # frame. In gdb, step-over/step-in move to the end of the line they stepped out to. 147 # If we ever change this we will need to fix this test. 148 self.hit_correct_line( 149 "int return_value = no_debug_caller(5, called_from_nodebug)") 150