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