]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add check-gdbarch.py
authorTom Tromey <tom@tromey.com>
Sat, 2 Nov 2024 17:36:45 +0000 (11:36 -0600)
committerTom Tromey <tom@tromey.com>
Sat, 7 Feb 2026 14:56:27 +0000 (07:56 -0700)
This adds a new check-gdbarch.py script.  This script checks the
sources to see which gdbarch methods are set but never called, and
which ones are called but never set.

This uses Pygments to scan the sources, to ensure we don't
accidentally pick up gdbarch references from comments (or, less
likely, strings).  Because this is pretty slow, it also uses "tqdm" to
show a progress bar.  (You can "pip install tqdm" to get this.)

This version also sorts the output.

gdb/check-gdbarch.py [new file with mode: 0755]

diff --git a/gdb/check-gdbarch.py b/gdb/check-gdbarch.py
new file mode 100755 (executable)
index 0000000..3c68fd9
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+
+# gdbarch checker.
+#
+# Copyright (C) 2024, 2026 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/>.
+
+import glob
+import re
+import sys
+
+import tqdm
+from pygments import lexers, token
+
+# gdbarch_components is imported only for its side-effect of filling
+# `gdbarch_types.components`.
+import gdbarch_components  # noqa: F401 # type: ignore
+from gdbarch_types import Component, Info, components
+
+
+def not_info(c: Component):
+    "Filter function to omit Info components."
+    return type(c) is not Info
+
+
+if len(sys.argv) != 1:
+    # Must be run in gdb srcdir.
+    print("usage: check-gdbarch.py")
+    sys.exit(1)
+
+
+# Make a hash holding all the gdbarch customization names.
+defined_names = set()
+set_names = set()
+called_names = set()
+for c in filter(not_info, components):
+    if c.implement:
+        defined_names.add(c.name)
+    if c.predicate:
+        # Predicates are always "set".
+        pname = c.name + "_p"
+        set_names.add(pname)
+        defined_names.add(pname)
+
+
+def find_local_files():
+    result = []
+    for name in glob.glob("*.[chyl]"):
+        if "gdbarch" not in name:
+            result.append(name)
+    return result
+
+
+files = find_local_files()
+files.extend(glob.glob("*/*.[ch]"))
+
+# We're going to treat all the files as C++, because Pygments doesn't
+# have a yacc lexer.
+lexer = lexers.get_lexer_by_name("c++")
+
+# FIXME could keep counts here and then look for deletion
+# opportunities.
+rx = re.compile(r"^(set_)?gdbarch_([a-zA-Z0-9_]+)$")
+for filename in tqdm.tqdm(files, desc="Scanning", leave=False):
+    with open(filename, "r") as fd:
+        text = fd.read()
+    for tokentype, value in lexer.get_tokens(text):
+        if tokentype in token.Token.Name:
+            m = rx.search(value)
+            if m:
+                if m[0] == "gdbarch_p":
+                    # There are a few variables with this name, exclude them.
+                    pass
+                elif m[1]:
+                    set_names.add(m[2])
+                else:
+                    called_names.add(m[2])
+
+
+for elt in sorted(defined_names - set_names):
+    print(f"never set: {elt}")
+for elt in sorted(defined_names - called_names):
+    print(f"never called: {elt}")