| # Copyright (C) 2023-2024 Free Software Foundation, Inc. |
| |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 3 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| |
| import os |
| from enum import Enum |
| |
| import gdb |
| from gdb.missing_debug import MissingDebugHandler |
| |
| # A global log that is filled in by instances of the LOG_HANDLER class |
| # when they are called. |
| handler_call_log = [] |
| |
| |
| class Mode(Enum): |
| RETURN_NONE = 0 |
| RETURN_TRUE = 1 |
| RETURN_FALSE = 2 |
| RETURN_STRING = 3 |
| |
| |
| class handler(MissingDebugHandler): |
| def __init__(self): |
| super().__init__("handler") |
| self._call_count = 0 |
| self._mode = Mode.RETURN_NONE |
| |
| def __call__(self, objfile): |
| global handler_call_log |
| handler_call_log.append(self.name) |
| self._call_count += 1 |
| if self._mode == Mode.RETURN_NONE: |
| return None |
| |
| if self._mode == Mode.RETURN_TRUE: |
| os.rename(self._src, self._dest) |
| return True |
| |
| if self._mode == Mode.RETURN_FALSE: |
| return False |
| |
| if self._mode == Mode.RETURN_STRING: |
| return self._dest |
| |
| assert False |
| |
| @property |
| def call_count(self): |
| """Return a count, the number of calls to __call__ since the last |
| call to set_mode. |
| """ |
| return self._call_count |
| |
| def set_mode(self, mode, *args): |
| self._call_count = 0 |
| self._mode = mode |
| |
| if mode == Mode.RETURN_NONE: |
| assert len(args) == 0 |
| return |
| |
| if mode == Mode.RETURN_TRUE: |
| assert len(args) == 2 |
| self._src = args[0] |
| self._dest = args[1] |
| return |
| |
| if mode == Mode.RETURN_FALSE: |
| assert len(args) == 0 |
| return |
| |
| if mode == Mode.RETURN_STRING: |
| assert len(args) == 1 |
| self._dest = args[0] |
| return |
| |
| assert False |
| |
| |
| class exception_handler(MissingDebugHandler): |
| def __init__(self): |
| super().__init__("exception_handler") |
| self.exception_type = None |
| |
| def __call__(self, objfile): |
| global handler_call_log |
| handler_call_log.append(self.name) |
| assert self.exception_type is not None |
| raise self.exception_type("message") |
| |
| |
| class log_handler(MissingDebugHandler): |
| def __call__(self, objfile): |
| global handler_call_log |
| handler_call_log.append(self.name) |
| return None |
| |
| |
| # A basic helper function, this keeps lines shorter in the TCL script. |
| def register(name, locus=None): |
| gdb.missing_debug.register_handler(locus, log_handler(name)) |
| |
| |
| # Create instances of the handlers, but don't install any. We install |
| # these as needed from the TCL script. |
| rhandler = exception_handler() |
| handler_obj = handler() |
| |
| print("Success") |