aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python/py-missing-objfile.py
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.python/py-missing-objfile.py')
-rw-r--r--gdb/testsuite/gdb.python/py-missing-objfile.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.py b/gdb/testsuite/gdb.python/py-missing-objfile.py
new file mode 100644
index 0000000..5efc36a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-missing-objfile.py
@@ -0,0 +1,167 @@
+# Copyright (C) 2024-2025 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
+import shutil
+from enum import Enum
+
+import gdb
+from gdb.missing_objfile import MissingObjfileHandler
+
+# A global log that is filled in by instances of the LOG_HANDLER class
+# when they are called.
+handler_call_log = []
+
+# A global holding a string, the build-id of the last missing objfile
+# which triggered the 'handler' class below. This is set in the
+# __call__ method of the 'handler' class and then checked from the
+# expect script.
+handler_last_buildid = None
+
+
+# A global holding a string, the filename of the last missing objfile
+# which triggered the 'handler' class below. This is set in the
+# __call__ method of the 'handler' class and then checked from the
+# expect script.
+handler_last_filename = None
+
+
+# A helper function that makes some assertions about the arguments
+# passed to a MissingObjfileHandler.__call__() method.
+def check_args(pspace, buildid, filename):
+ assert type(filename) == str
+ assert filename != ""
+ assert type(pspace) == gdb.Progspace
+ assert type(buildid) == str
+ assert buildid != ""
+
+
+# Enum used to configure the 'handler' class from the test script.
+class Mode(Enum):
+ RETURN_NONE = 0
+ RETURN_TRUE = 1
+ RETURN_FALSE = 2
+ RETURN_STRING = 3
+
+
+# A missing objfile handler which can be configured to return each of
+# the different possible return types.
+class handler(MissingObjfileHandler):
+ def __init__(self):
+ super().__init__("handler")
+ self._call_count = 0
+ self._mode = Mode.RETURN_NONE
+
+ def __call__(self, pspace, buildid, filename):
+ global handler_call_log, handler_last_buildid, handler_last_filename
+ check_args(pspace, buildid, filename)
+ handler_call_log.append(self.name)
+ handler_last_buildid = buildid
+ handler_last_filename = filename
+ self._call_count += 1
+ if self._mode == Mode.RETURN_NONE:
+ return None
+
+ if self._mode == Mode.RETURN_TRUE:
+ shutil.copy(self._src, self._dest)
+
+ # If we're using the fission-dwp board then there will
+ # also be a .dwp file that needs to be copied.
+ dwp_src = self._src + ".dwp"
+ if os.path.exists(dwp_src):
+ dwp_dest = self._dest + ".dwp"
+ shutil.copy(dwp_src, dwp_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
+
+
+# A missing objfile handler which raises an exception. The type of
+# exception to be raised is configured from the test script.
+class exception_handler(MissingObjfileHandler):
+ def __init__(self):
+ super().__init__("exception_handler")
+ self.exception_type = None
+
+ def __call__(self, pspace, buildid, filename):
+ global handler_call_log
+ check_args(pspace, buildid, filename)
+ handler_call_log.append(self.name)
+ assert self.exception_type is not None
+ raise self.exception_type("message")
+
+
+# A very simple logging missing objfile handler. Always returns None
+# so that GDB will try any other registered handlers, but first logs
+# the name of this handler into the global HANDLER_CALL_LOG, which can
+# then be checked from the test script.
+class log_handler(MissingObjfileHandler):
+ def __call__(self, pspace, buildid, filename):
+ global handler_call_log
+ check_args(pspace, buildid, filename)
+ 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_objfile.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")