diff --git a/gdb/gdbarch.py b/gdb/gdbarch.py
index 63c3aee1dc0e..d1ac414d0eb3 100755
--- a/gdb/gdbarch.py
+++ b/gdb/gdbarch.py
@@ -20,10 +20,12 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import textwrap
-import gdbcopyright
 
-# All the components created in gdbarch-components.py.
-components = []
+# gdbarch_components is imported only for its side-effect of filling
+# `gdbarch_types.components`.
+import gdbarch_components  # noqa: F401 # type: ignore
+import gdbcopyright
+from gdbarch_types import Function, Info, Value, components
 
 
 def indentation(n_columns):
@@ -31,176 +33,6 @@ def indentation(n_columns):
     return "\t" * (n_columns // 8) + " " * (n_columns % 8)
 
 
-def join_type_and_name(t, n):
-    "Combine the type T and the name N into a C declaration."
-    if t.endswith("*") or t.endswith("&"):
-        return t + n
-    else:
-        return t + " " + n
-
-
-def join_params(params):
-    """Given a sequence of (TYPE, NAME) pairs, generate a comma-separated
-    list of declarations."""
-    params = [join_type_and_name(p[0], p[1]) for p in params]
-    return ", ".join(params)
-
-
-class _Component:
-    "Base class for all components."
-
-    def __init__(
-        self,
-        name,
-        type,
-        printer,
-        comment=None,
-        predicate=False,
-        predefault=None,
-        postdefault=None,
-        invalid=None,
-        params=None,
-        param_checks=None,
-        result_checks=None,
-        implement=True,
-    ):
-        self.name = name
-        self.type = type
-        self.printer = printer
-        self.comment = comment
-        self.predicate = predicate
-        self.predefault = predefault
-        self.postdefault = postdefault
-        self.invalid = invalid
-        self.params = params
-        self.param_checks = param_checks
-        self.result_checks = result_checks
-        self.implement = implement
-
-        components.append(self)
-
-        # It doesn't make sense to have a check of the result value
-        # for a function or method with void return type.
-        if self.type == "void" and self.result_checks:
-            raise Exception("can't have result checks with a void return type")
-
-    def get_predicate(self):
-        "Return the expression used for validity checking."
-        assert self.predicate and not isinstance(self.invalid, str)
-        if self.predefault:
-            predicate = f"gdbarch->{self.name} != {self.predefault}"
-        else:
-            predicate = f"gdbarch->{self.name} != NULL"
-        return predicate
-
-
-class Info(_Component):
-    "An Info component is copied from the gdbarch_info."
-
-    def __init__(self, *, name, type, printer=None):
-        super().__init__(name=name, type=type, printer=printer)
-        # This little hack makes the generator a bit simpler.
-        self.predicate = None
-
-
-class Value(_Component):
-    "A Value component is just a data member."
-
-    def __init__(
-        self,
-        *,
-        name,
-        type,
-        comment=None,
-        predicate=False,
-        predefault=None,
-        postdefault=None,
-        invalid=None,
-        printer=None,
-    ):
-        super().__init__(
-            comment=comment,
-            name=name,
-            type=type,
-            predicate=predicate,
-            predefault=predefault,
-            postdefault=postdefault,
-            invalid=invalid,
-            printer=printer,
-        )
-
-
-class Function(_Component):
-    "A Function component is a function pointer member."
-
-    def __init__(
-        self,
-        *,
-        name,
-        type,
-        params,
-        comment=None,
-        predicate=False,
-        predefault=None,
-        postdefault=None,
-        invalid=None,
-        printer=None,
-        param_checks=None,
-        result_checks=None,
-        implement=True,
-    ):
-        super().__init__(
-            comment=comment,
-            name=name,
-            type=type,
-            predicate=predicate,
-            predefault=predefault,
-            postdefault=postdefault,
-            invalid=invalid,
-            printer=printer,
-            params=params,
-            param_checks=param_checks,
-            result_checks=result_checks,
-            implement=implement,
-        )
-
-    def ftype(self):
-        "Return the name of the function typedef to use."
-        return f"gdbarch_{self.name}_ftype"
-
-    def param_list(self):
-        "Return the formal parameter list as a string."
-        return join_params(self.params)
-
-    def set_list(self):
-        """Return the formal parameter list of the caller function,
-        as a string.  This list includes the gdbarch."""
-        arch_arg = ("struct gdbarch *", "gdbarch")
-        arch_tuple = [arch_arg]
-        return join_params(arch_tuple + list(self.params))
-
-    def actuals(self):
-        "Return the actual parameters to forward, as a string."
-        return ", ".join([p[1] for p in self.params])
-
-
-class Method(Function):
-    "A Method is like a Function but passes the gdbarch through."
-
-    def param_list(self):
-        "See superclass."
-        return self.set_list()
-
-    def actuals(self):
-        "See superclass."
-        result = ["gdbarch"] + [p[1] for p in self.params]
-        return ", ".join(result)
-
-
-# Read the components.
-with open("gdbarch-components.py") as fd:
-    exec(fd.read())
-
 copyright = gdbcopyright.copyright(
     "gdbarch.py", "Dynamic architecture support for GDB, the GNU debugger."
 )
diff --git a/gdb/gdbarch-components.py b/gdb/gdbarch_components.py
similarity index 99%
rename from gdb/gdbarch-components.py
rename to gdb/gdbarch_components.py
index 76ad2832d8a2..fe5c3b3b4bcd 100644
--- a/gdb/gdbarch-components.py
+++ b/gdb/gdbarch_components.py
@@ -117,6 +117,8 @@
 # * "implement" - optional, a boolean.  If True (the default), a
 # wrapper function for this function will be emitted.
 
+from gdbarch_types import Function, Info, Method, Value
+
 Info(
     type="const struct bfd_arch_info *",
     name="bfd_arch_info",
diff --git a/gdb/gdbarch_types.py b/gdb/gdbarch_types.py
new file mode 100755
index 000000000000..95d9b5e65bc5
--- /dev/null
+++ b/gdb/gdbarch_types.py
@@ -0,0 +1,188 @@
+# Architecture commands for GDB, the GNU debugger.
+#
+# Copyright (C) 1998-2023 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# 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/>.
+
+
+def join_type_and_name(t, n):
+    "Combine the type T and the name N into a C declaration."
+    if t.endswith("*") or t.endswith("&"):
+        return t + n
+    else:
+        return t + " " + n
+
+
+def join_params(params):
+    """Given a sequence of (TYPE, NAME) pairs, generate a comma-separated
+    list of declarations."""
+    params = [join_type_and_name(p[0], p[1]) for p in params]
+    return ", ".join(params)
+
+
+class _Component:
+    "Base class for all components."
+
+    def __init__(
+        self,
+        name,
+        type,
+        printer,
+        comment=None,
+        predicate=False,
+        predefault=None,
+        postdefault=None,
+        invalid=None,
+        params=None,
+        param_checks=None,
+        result_checks=None,
+        implement=True,
+    ):
+        self.name = name
+        self.type = type
+        self.printer = printer
+        self.comment = comment
+        self.predicate = predicate
+        self.predefault = predefault
+        self.postdefault = postdefault
+        self.invalid = invalid
+        self.params = params
+        self.param_checks = param_checks
+        self.result_checks = result_checks
+        self.implement = implement
+
+        components.append(self)
+
+        # It doesn't make sense to have a check of the result value
+        # for a function or method with void return type.
+        if self.type == "void" and self.result_checks:
+            raise Exception("can't have result checks with a void return type")
+
+    def get_predicate(self):
+        "Return the expression used for validity checking."
+        assert self.predicate and not isinstance(self.invalid, str)
+        if self.predefault:
+            predicate = f"gdbarch->{self.name} != {self.predefault}"
+        else:
+            predicate = f"gdbarch->{self.name} != NULL"
+        return predicate
+
+
+class Info(_Component):
+    "An Info component is copied from the gdbarch_info."
+
+    def __init__(self, *, name, type, printer=None):
+        super().__init__(name=name, type=type, printer=printer)
+        # This little hack makes the generator a bit simpler.
+        self.predicate = None
+
+
+class Value(_Component):
+    "A Value component is just a data member."
+
+    def __init__(
+        self,
+        *,
+        name,
+        type,
+        comment=None,
+        predicate=False,
+        predefault=None,
+        postdefault=None,
+        invalid=None,
+        printer=None,
+    ):
+        super().__init__(
+            comment=comment,
+            name=name,
+            type=type,
+            predicate=predicate,
+            predefault=predefault,
+            postdefault=postdefault,
+            invalid=invalid,
+            printer=printer,
+        )
+
+
+class Function(_Component):
+    "A Function component is a function pointer member."
+
+    def __init__(
+        self,
+        *,
+        name,
+        type,
+        params,
+        comment=None,
+        predicate=False,
+        predefault=None,
+        postdefault=None,
+        invalid=None,
+        printer=None,
+        param_checks=None,
+        result_checks=None,
+        implement=True,
+    ):
+        super().__init__(
+            comment=comment,
+            name=name,
+            type=type,
+            predicate=predicate,
+            predefault=predefault,
+            postdefault=postdefault,
+            invalid=invalid,
+            printer=printer,
+            params=params,
+            param_checks=param_checks,
+            result_checks=result_checks,
+            implement=implement,
+        )
+
+    def ftype(self):
+        "Return the name of the function typedef to use."
+        return f"gdbarch_{self.name}_ftype"
+
+    def param_list(self):
+        "Return the formal parameter list as a string."
+        return join_params(self.params)
+
+    def set_list(self):
+        """Return the formal parameter list of the caller function,
+        as a string.  This list includes the gdbarch."""
+        arch_arg = ("struct gdbarch *", "gdbarch")
+        arch_tuple = [arch_arg]
+        return join_params(arch_tuple + list(self.params))
+
+    def actuals(self):
+        "Return the actual parameters to forward, as a string."
+        return ", ".join([p[1] for p in self.params])
+
+
+class Method(Function):
+    "A Method is like a Function but passes the gdbarch through."
+
+    def param_list(self):
+        "See superclass."
+        return self.set_list()
+
+    def actuals(self):
+        "See superclass."
+        result = ["gdbarch"] + [p[1] for p in self.params]
+        return ", ".join(result)
+
+
+# All the components created in gdbarch-components.py.
+components: list[_Component] = []
