1""" 2Test Debugger APIs. 3""" 4 5import lldb 6 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class DebuggerAPITestCase(TestBase): 13 NO_DEBUG_INFO_TESTCASE = True 14 15 def test_debugger_api_boundary_condition(self): 16 """Exercise SBDebugger APIs with boundary conditions.""" 17 self.dbg.HandleCommand(None) 18 self.dbg.SetDefaultArchitecture(None) 19 self.dbg.GetScriptingLanguage(None) 20 self.dbg.CreateTarget(None) 21 self.dbg.CreateTarget(None, None, None, True, lldb.SBError()) 22 self.dbg.CreateTargetWithFileAndTargetTriple(None, None) 23 self.dbg.CreateTargetWithFileAndArch(None, None) 24 self.dbg.FindTargetWithFileAndArch(None, None) 25 self.dbg.SetInternalVariable(None, None, None) 26 self.dbg.GetInternalVariableValue(None, None) 27 # FIXME (filcab): We must first allow for the swig bindings to know if 28 # a Python callback is set. (Check python-typemaps.swig) 29 # self.dbg.SetLoggingCallback(None) 30 self.dbg.SetPrompt(None) 31 self.dbg.SetCurrentPlatform(None) 32 self.dbg.SetCurrentPlatformSDKRoot(None) 33 34 fresh_dbg = lldb.SBDebugger() 35 self.assertEquals(len(fresh_dbg), 0) 36 37 def test_debugger_delete_invalid_target(self): 38 """SBDebugger.DeleteTarget() should not crash LLDB given and invalid target.""" 39 target = lldb.SBTarget() 40 self.assertFalse(target.IsValid()) 41 self.dbg.DeleteTarget(target) 42 43 def test_debugger_internal_variables(self): 44 """Ensure that SBDebugger reachs the same instance of properties 45 regardless CommandInterpreter's context initialization""" 46 self.build() 47 exe = self.getBuildArtifact("a.out") 48 49 # Create a target by the debugger. 50 target = self.dbg.CreateTarget(exe) 51 self.assertTrue(target, VALID_TARGET) 52 53 property_name = "target.process.memory-cache-line-size" 54 55 def get_cache_line_size(): 56 value_list = lldb.SBStringList() 57 value_list = self.dbg.GetInternalVariableValue( 58 property_name, self.dbg.GetInstanceName() 59 ) 60 61 self.assertEqual(value_list.GetSize(), 1) 62 try: 63 return int(value_list.GetStringAtIndex(0)) 64 except ValueError as error: 65 self.fail("Value is not a number: " + error) 66 67 # Get global property value while there are no processes. 68 global_cache_line_size = get_cache_line_size() 69 70 # Run a process via SB interface. CommandInterpreter's execution context 71 # remains empty. 72 error = lldb.SBError() 73 launch_info = lldb.SBLaunchInfo(None) 74 launch_info.SetLaunchFlags(lldb.eLaunchFlagStopAtEntry) 75 process = target.Launch(launch_info, error) 76 self.assertTrue(process, PROCESS_IS_VALID) 77 78 # This should change the value of a process's local property. 79 new_cache_line_size = global_cache_line_size + 512 80 error = self.dbg.SetInternalVariable( 81 property_name, str(new_cache_line_size), self.dbg.GetInstanceName() 82 ) 83 self.assertSuccess(error, property_name + " value was changed successfully") 84 85 # Check that it was set actually. 86 self.assertEqual(get_cache_line_size(), new_cache_line_size) 87 88 # Run any command to initialize CommandInterpreter's execution context. 89 self.runCmd("target list") 90 91 # Test the local property again, is it set to new_cache_line_size? 92 self.assertEqual(get_cache_line_size(), new_cache_line_size) 93 94 def test_CreateTarget_platform(self): 95 exe = self.getBuildArtifact("a.out") 96 self.yaml2obj("elf.yaml", exe) 97 error = lldb.SBError() 98 target1 = self.dbg.CreateTarget(exe, None, "remote-linux", False, error) 99 self.assertSuccess(error) 100 platform1 = target1.GetPlatform() 101 platform1.SetWorkingDirectory("/foo/bar") 102 103 # Reuse a platform if it matches the currently selected one... 104 target2 = self.dbg.CreateTarget(exe, None, "remote-linux", False, error) 105 self.assertSuccess(error) 106 platform2 = target2.GetPlatform() 107 self.assertTrue( 108 platform2.GetWorkingDirectory().endswith("bar"), 109 platform2.GetWorkingDirectory(), 110 ) 111 112 # ... but create a new one if it doesn't. 113 self.dbg.SetSelectedPlatform(lldb.SBPlatform("remote-windows")) 114 target3 = self.dbg.CreateTarget(exe, None, "remote-linux", False, error) 115 self.assertSuccess(error) 116 platform3 = target3.GetPlatform() 117 self.assertIsNone(platform3.GetWorkingDirectory()) 118 119 def test_CreateTarget_arch(self): 120 exe = self.getBuildArtifact("a.out") 121 if lldbplatformutil.getHostPlatform() == "linux": 122 self.yaml2obj("macho.yaml", exe) 123 arch = "x86_64-apple-macosx" 124 expected_platform = "remote-macosx" 125 else: 126 self.yaml2obj("elf.yaml", exe) 127 arch = "x86_64-pc-linux" 128 expected_platform = "remote-linux" 129 130 fbsd = lldb.SBPlatform("remote-freebsd") 131 self.dbg.SetSelectedPlatform(fbsd) 132 133 error = lldb.SBError() 134 target1 = self.dbg.CreateTarget(exe, arch, None, False, error) 135 self.assertSuccess(error) 136 platform1 = target1.GetPlatform() 137 self.assertEqual(platform1.GetName(), expected_platform) 138 platform1.SetWorkingDirectory("/foo/bar") 139 140 # Reuse a platform even if it is not currently selected. 141 self.dbg.SetSelectedPlatform(fbsd) 142 target2 = self.dbg.CreateTarget(exe, arch, None, False, error) 143 self.assertSuccess(error) 144 platform2 = target2.GetPlatform() 145 self.assertEqual(platform2.GetName(), expected_platform) 146 self.assertTrue( 147 platform2.GetWorkingDirectory().endswith("bar"), 148 platform2.GetWorkingDirectory(), 149 ) 150 151 def test_SetDestroyCallback(self): 152 destroy_dbg_id = None 153 154 def foo(dbg_id): 155 # Need nonlocal to modify closure variable. 156 nonlocal destroy_dbg_id 157 destroy_dbg_id = dbg_id 158 159 self.dbg.SetDestroyCallback(foo) 160 161 original_dbg_id = self.dbg.GetID() 162 self.dbg.Destroy(self.dbg) 163 self.assertEqual(destroy_dbg_id, original_dbg_id) 164