1"""Test stepping and setting breakpoints in indirect and re-exported symbols.""" 2 3 4 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 10 11class TestIndirectFunctions(TestBase): 12 13 mydir = TestBase.compute_mydir(__file__) 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line numbers that we will step to in main: 19 self.main_source = "main.c" 20 21 @skipUnlessDarwin 22 @add_test_categories(['pyapi']) 23 def test_with_python_api(self): 24 """Test stepping and setting breakpoints in indirect and re-exported symbols.""" 25 self.build() 26 exe = self.getBuildArtifact("a.out") 27 28 target = self.dbg.CreateTarget(exe) 29 self.assertTrue(target, VALID_TARGET) 30 31 lib1 = self.getBuildArtifact('libindirect.dylib') 32 lib2 = self.getBuildArtifact('libreexport.dylib') 33 self.registerSharedLibrariesWithTarget(target, [lib1, lib2]) 34 35 self.main_source_spec = lldb.SBFileSpec(self.main_source) 36 37 break1 = target.BreakpointCreateBySourceRegex( 38 "Set breakpoint here to step in indirect.", self.main_source_spec) 39 self.assertTrue(break1, VALID_BREAKPOINT) 40 41 break2 = target.BreakpointCreateBySourceRegex( 42 "Set breakpoint here to step in reexported.", self.main_source_spec) 43 self.assertTrue(break2, VALID_BREAKPOINT) 44 45 # Now launch the process, and do not stop at entry point. 46 process = target.LaunchSimple( 47 None, None, self.get_process_working_directory()) 48 49 self.assertTrue(process, PROCESS_IS_VALID) 50 51 # The stop reason of the thread should be breakpoint. 52 threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1) 53 if len(threads) != 1: 54 self.fail("Failed to stop at breakpoint 1.") 55 56 thread = threads[0] 57 58 # Now do a step-into, and we should end up in the hidden target of this 59 # indirect function. 60 thread.StepInto() 61 curr_function = thread.GetFrameAtIndex(0).GetFunctionName() 62 self.assertEqual(curr_function, "call_through_indirect_hidden", 63 "Stepped into indirect symbols.") 64 65 # Now set a breakpoint using the indirect symbol name, and make sure we 66 # get to that: 67 break_indirect = target.BreakpointCreateByName("call_through_indirect") 68 self.assertTrue(break_indirect, VALID_BREAKPOINT) 69 70 # Now continue should take us to the second call through the indirect 71 # symbol: 72 73 threads = lldbutil.continue_to_breakpoint(process, break_indirect) 74 self.assertTrue( 75 len(threads) == 1, 76 "Stopped at breakpoint in indirect function.") 77 curr_function = thread.GetFrameAtIndex(0).GetFunctionName() 78 self.assertTrue( 79 curr_function == "call_through_indirect_hidden", 80 "Stepped into indirect symbols.") 81 82 # Delete this breakpoint so it won't get in the way: 83 target.BreakpointDelete(break_indirect.GetID()) 84 85 # Now continue to the site of the first re-exported function call in 86 # main: 87 threads = lldbutil.continue_to_breakpoint(process, break2) 88 89 # This is stepping Into through a re-exported symbol to an indirect 90 # symbol: 91 thread.StepInto() 92 curr_function = thread.GetFrameAtIndex(0).GetFunctionName() 93 self.assertTrue( 94 curr_function == "call_through_indirect_hidden", 95 "Stepped into indirect symbols.") 96 97 # And the last bit is to set a breakpoint on the re-exported symbol and 98 # make sure we are again in out target function. 99 break_reexported = target.BreakpointCreateByName( 100 "reexport_to_indirect") 101 self.assertTrue(break_reexported, VALID_BREAKPOINT) 102 103 # Now continue should take us to the second call through the indirect 104 # symbol: 105 106 threads = lldbutil.continue_to_breakpoint(process, break_reexported) 107 self.assertTrue( 108 len(threads) == 1, 109 "Stopped at breakpoint in reexported function target.") 110 curr_function = thread.GetFrameAtIndex(0).GetFunctionName() 111 self.assertTrue( 112 curr_function == "call_through_indirect_hidden", 113 "Stepped into indirect symbols.") 114