xref: /xnu-12377.41.6/tools/lldbmacros/tests/integration_smoke/lldb_session.py (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828) !
1"""Defines the behavior for LLDB local at-desk GDB session."""
2import contextlib
3import functools
4import typing
5from pathlib import Path
6
7import lldb
8
9
10class AtDeskLLDBGdbSession:
11    def __init__(self, interpreter):
12        self._command_interpreter = interpreter
13
14    def refresh(self):
15        macros_base_path = Path(__file__).parent.parent.parent
16        self.exec('settings set target.load-script-from-symbol-file false')
17        self.exec(f'settings set target.process.python-os-plugin-path {macros_base_path}/core/operating_system.py')
18        self.exec(f'command script import {macros_base_path}/xnu.py')
19        return self
20
21    @classmethod
22    @contextlib.contextmanager
23    def create(cls, gdb_remote: typing.Optional[str]) -> 'AtDeskLLDBGdbSession':
24        debugger = lldb.SBDebugger.Create()
25        command_interpreter = debugger.GetCommandInterpreter()
26
27        session = AtDeskLLDBGdbSession(command_interpreter)
28        session.exec('settings set plugin.dynamic-loader.darwin-kernel.load-kexts false')
29
30        session.refresh()
31        with session._gdb(gdb_remote):
32            yield session
33
34        lldb.SBDebugger.Destroy(debugger)
35
36    @functools.lru_cache(maxsize=5096)
37    def exec(self, cmd) -> str:
38        # TODO: consider logging.
39        print(f'LLDBSession running command: `{cmd}`')
40        res = lldb.SBCommandReturnObject()
41        self._command_interpreter.HandleCommand(cmd, res)
42        if res.Succeeded():
43            return res.GetOutput()
44        raise RuntimeError(res.GetError())
45
46    @contextlib.contextmanager
47    def _gdb(self, remote_gdb: typing.Optional[str] = None) -> 'AtDeskLLDBGdbSession':
48        if remote_gdb is None:
49            yield self
50            return
51
52        self.exec(f'gdb {remote_gdb}')
53        yield self
54        self.exec('detach')
55