# Copyright (C) 2023 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 . import gdb from gdb.missing_debug import MissingDebugHandler from enum import Enum import os # 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")