mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
722232dafd
This is a very small patch to straighten out dot-space-space in these comments in the gdbarch generated files: - /* Skip verify of short_bit, invalid_p == 0 */ + /* Skip verify of short_bit, invalid_p == 0. */ There is no functional change after this commit. Approved-By: Andrew Burgess <aburgess@redhat.com>
395 lines
15 KiB
Python
Executable File
395 lines
15 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Architecture commands for GDB, the GNU debugger.
|
|
#
|
|
# Copyright (C) 1998-2024 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 textwrap
|
|
|
|
# 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 Component, Function, Info, Value, components
|
|
|
|
|
|
def indentation(n_columns: int):
|
|
"""Return string with tabs and spaces to indent line to N_COLUMNS."""
|
|
return "\t" * (n_columns // 8) + " " * (n_columns % 8)
|
|
|
|
|
|
copyright = gdbcopyright.copyright(
|
|
"gdbarch.py", "Dynamic architecture support for GDB, the GNU debugger."
|
|
)
|
|
|
|
|
|
def info(c: Component):
|
|
"Filter function to only allow Info components."
|
|
return type(c) is Info
|
|
|
|
|
|
def not_info(c: Component):
|
|
"Filter function to omit Info components."
|
|
return type(c) is not Info
|
|
|
|
|
|
with open("gdbarch-gen.h", "w") as f:
|
|
print(copyright, file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
print("/* The following are pre-initialized by GDBARCH. */", file=f)
|
|
|
|
# Do Info components first.
|
|
for c in filter(info, components):
|
|
print(file=f)
|
|
print(
|
|
f"""extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);
|
|
/* set_gdbarch_{c.name}() - not applicable - pre-initialized. */""",
|
|
file=f,
|
|
)
|
|
|
|
print(file=f)
|
|
print(file=f)
|
|
print("/* The following are initialized by the target dependent code. */", file=f)
|
|
|
|
# Generate decls for accessors, setters, and predicates for all
|
|
# non-Info components.
|
|
for c in filter(not_info, components):
|
|
if c.comment:
|
|
print(file=f)
|
|
comment = c.comment.split("\n")
|
|
if comment[0] == "":
|
|
comment = comment[1:]
|
|
if comment[-1] == "":
|
|
comment = comment[:-1]
|
|
print("/* ", file=f, end="")
|
|
print(comment[0], file=f, end="")
|
|
if len(comment) > 1:
|
|
print(file=f)
|
|
print(
|
|
textwrap.indent("\n".join(comment[1:]), prefix=" "),
|
|
end="",
|
|
file=f,
|
|
)
|
|
print(" */", file=f)
|
|
|
|
if c.predicate:
|
|
print(file=f)
|
|
print(f"extern bool gdbarch_{c.name}_p (struct gdbarch *gdbarch);", file=f)
|
|
|
|
print(file=f)
|
|
if isinstance(c, Value):
|
|
print(
|
|
f"extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);",
|
|
file=f,
|
|
)
|
|
print(
|
|
f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.type} {c.name});",
|
|
file=f,
|
|
)
|
|
else:
|
|
assert isinstance(c, Function)
|
|
print(
|
|
f"typedef {c.type} ({c.ftype()}) ({c.param_list()});",
|
|
file=f,
|
|
)
|
|
if c.implement:
|
|
print(
|
|
f"extern {c.type} gdbarch_{c.name} ({c.set_list()});",
|
|
file=f,
|
|
)
|
|
print(
|
|
f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.ftype()} *{c.name});",
|
|
file=f,
|
|
)
|
|
|
|
with open("gdbarch-gen.c", "w") as f:
|
|
print(copyright, file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
print("/* Maintain the struct gdbarch object. */", file=f)
|
|
print(file=f)
|
|
#
|
|
# The struct definition body.
|
|
#
|
|
print("struct gdbarch", file=f)
|
|
print("{", file=f)
|
|
print(" /* Has this architecture been fully initialized? */", file=f)
|
|
print(" bool initialized_p = false;", file=f)
|
|
print(file=f)
|
|
print(" /* An obstack bound to the lifetime of the architecture. */", file=f)
|
|
print(" auto_obstack obstack;", file=f)
|
|
print(" /* Registry. */", file=f)
|
|
print(" registry<gdbarch> registry_fields;", file=f)
|
|
print(file=f)
|
|
print(" /* basic architectural information. */", file=f)
|
|
for c in filter(info, components):
|
|
print(f" {c.type} {c.name};", file=f)
|
|
print(file=f)
|
|
print(" /* target specific vector. */", file=f)
|
|
print(" gdbarch_tdep_up tdep;", file=f)
|
|
print(" gdbarch_dump_tdep_ftype *dump_tdep = nullptr;", file=f)
|
|
print(file=f)
|
|
for c in filter(not_info, components):
|
|
if isinstance(c, Function):
|
|
print(f" gdbarch_{c.name}_ftype *", file=f, end="")
|
|
else:
|
|
print(f" {c.type} ", file=f, end="")
|
|
print(f"{c.name} = ", file=f, end="")
|
|
if c.predefault is not None:
|
|
print(f"{c.predefault};", file=f)
|
|
elif isinstance(c, Value):
|
|
print("0;", file=f)
|
|
else:
|
|
assert isinstance(c, Function)
|
|
print("nullptr;", file=f)
|
|
print("};", file=f)
|
|
print(file=f)
|
|
#
|
|
# Initialization.
|
|
#
|
|
print("/* Create a new ``struct gdbarch'' based on information provided by", file=f)
|
|
print(" ``struct gdbarch_info''. */", file=f)
|
|
print(file=f)
|
|
print("struct gdbarch *", file=f)
|
|
print("gdbarch_alloc (const struct gdbarch_info *info,", file=f)
|
|
print(" gdbarch_tdep_up tdep)", file=f)
|
|
print("{", file=f)
|
|
print(" struct gdbarch *gdbarch;", file=f)
|
|
print("", file=f)
|
|
print(" gdbarch = new struct gdbarch;", file=f)
|
|
print(file=f)
|
|
print(" gdbarch->tdep = std::move (tdep);", file=f)
|
|
print(file=f)
|
|
for c in filter(info, components):
|
|
print(f" gdbarch->{c.name} = info->{c.name};", file=f)
|
|
print(file=f)
|
|
print(" return gdbarch;", file=f)
|
|
print("}", file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
#
|
|
# Post-initialization validation and updating
|
|
#
|
|
print("/* Ensure that all values in a GDBARCH are reasonable. */", file=f)
|
|
print(file=f)
|
|
print("static void", file=f)
|
|
print("verify_gdbarch (struct gdbarch *gdbarch)", file=f)
|
|
print("{", file=f)
|
|
print(" string_file log;", file=f)
|
|
print(file=f)
|
|
print(" /* fundamental */", file=f)
|
|
print(" if (gdbarch->byte_order == BFD_ENDIAN_UNKNOWN)", file=f)
|
|
print(""" log.puts ("\\n\\tbyte-order");""", file=f)
|
|
print(" if (gdbarch->bfd_arch_info == NULL)", file=f)
|
|
print(""" log.puts ("\\n\\tbfd_arch_info");""", file=f)
|
|
print(
|
|
" /* Check those that need to be defined for the given multi-arch level. */",
|
|
file=f,
|
|
)
|
|
for c in filter(not_info, components):
|
|
# An opportunity to write in the 'postdefault' value. We
|
|
# change field's value to the postdefault if its current value
|
|
# is not different to the initial value of the field.
|
|
if c.postdefault is not None:
|
|
init_value = c.predefault or "0"
|
|
print(f" if (gdbarch->{c.name} == {init_value})", file=f)
|
|
print(f" gdbarch->{c.name} = {c.postdefault};", file=f)
|
|
|
|
# Now validate the value.
|
|
if isinstance(c.invalid, str):
|
|
print(f" if ({c.invalid})", file=f)
|
|
print(f""" log.puts ("\\n\\t{c.name}");""", file=f)
|
|
elif c.predicate:
|
|
print(f" /* Skip verify of {c.name}, has predicate. */", file=f)
|
|
elif c.invalid:
|
|
if c.postdefault is not None:
|
|
# This component has its 'invalid' field set to True, but
|
|
# also has a postdefault. This makes no sense, the
|
|
# postdefault will have been applied above, so this field
|
|
# will not have a zero value.
|
|
raise Exception(
|
|
f"component {c.name} has postdefault and invalid set to True"
|
|
)
|
|
else:
|
|
init_value = c.predefault or "0"
|
|
print(f" if (gdbarch->{c.name} == {init_value})", file=f)
|
|
print(f""" log.puts ("\\n\\t{c.name}");""", file=f)
|
|
else:
|
|
print(f" /* Skip verify of {c.name}, invalid_p == 0. */", file=f)
|
|
print(" if (!log.empty ())", file=f)
|
|
print(
|
|
""" internal_error (_("verify_gdbarch: the following are invalid ...%s"),""",
|
|
file=f,
|
|
)
|
|
print(" log.c_str ());", file=f)
|
|
print("}", file=f)
|
|
print(file=f)
|
|
print(file=f)
|
|
#
|
|
# Dumping.
|
|
#
|
|
print("/* Print out the details of the current architecture. */", file=f)
|
|
print(file=f)
|
|
print("void", file=f)
|
|
print("gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)", file=f)
|
|
print("{", file=f)
|
|
print(""" const char *gdb_nm_file = "<not-defined>";""", file=f)
|
|
print(file=f)
|
|
print("#if defined (GDB_NM_FILE)", file=f)
|
|
print(" gdb_nm_file = GDB_NM_FILE;", file=f)
|
|
print("#endif", file=f)
|
|
print(" gdb_printf (file,", file=f)
|
|
print(""" "gdbarch_dump: GDB_NM_FILE = %s\\n",""", file=f)
|
|
print(" gdb_nm_file);", file=f)
|
|
for c in components:
|
|
if c.predicate:
|
|
print(" gdb_printf (file,", file=f)
|
|
print(
|
|
f""" "gdbarch_dump: gdbarch_{c.name}_p() = %d\\n",""",
|
|
file=f,
|
|
)
|
|
print(f" gdbarch_{c.name}_p (gdbarch));", file=f)
|
|
if isinstance(c, Function):
|
|
print(" gdb_printf (file,", file=f)
|
|
print(f""" "gdbarch_dump: {c.name} = <%s>\\n",""", file=f)
|
|
print(
|
|
f" host_address_to_string (gdbarch->{c.name}));",
|
|
file=f,
|
|
)
|
|
else:
|
|
if c.printer:
|
|
printer = c.printer
|
|
elif c.type == "CORE_ADDR":
|
|
printer = f"core_addr_to_string_nz (gdbarch->{c.name})"
|
|
else:
|
|
printer = f"plongest (gdbarch->{c.name})"
|
|
print(" gdb_printf (file,", file=f)
|
|
print(f""" "gdbarch_dump: {c.name} = %s\\n",""", file=f)
|
|
print(f" {printer});", file=f)
|
|
print(" if (gdbarch->dump_tdep != NULL)", file=f)
|
|
print(" gdbarch->dump_tdep (gdbarch, file);", file=f)
|
|
print("}", file=f)
|
|
print(file=f)
|
|
#
|
|
# Bodies of setter, accessor, and predicate functions.
|
|
#
|
|
for c in components:
|
|
if c.predicate:
|
|
print(file=f)
|
|
print("bool", file=f)
|
|
print(f"gdbarch_{c.name}_p (struct gdbarch *gdbarch)", file=f)
|
|
print("{", file=f)
|
|
print(" gdb_assert (gdbarch != NULL);", file=f)
|
|
print(f" return {c.get_predicate()};", file=f)
|
|
print("}", file=f)
|
|
if isinstance(c, Function):
|
|
if c.implement:
|
|
print(file=f)
|
|
print(f"{c.type}", file=f)
|
|
print(f"gdbarch_{c.name} ({c.set_list()})", file=f)
|
|
print("{", file=f)
|
|
print(" gdb_assert (gdbarch != NULL);", file=f)
|
|
print(f" gdb_assert (gdbarch->{c.name} != NULL);", file=f)
|
|
if c.predicate and c.predefault:
|
|
# Allow a call to a function with a predicate.
|
|
print(
|
|
f" /* Do not check predicate: {c.get_predicate()}, allow call. */",
|
|
file=f,
|
|
)
|
|
if c.param_checks:
|
|
for rule in c.param_checks:
|
|
print(f" gdb_assert ({rule});", file=f)
|
|
print(" if (gdbarch_debug >= 2)", file=f)
|
|
print(
|
|
f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
|
|
file=f,
|
|
)
|
|
print(" ", file=f, end="")
|
|
if c.type != "void":
|
|
if c.result_checks:
|
|
print("auto result = ", file=f, end="")
|
|
else:
|
|
print("return ", file=f, end="")
|
|
print(f"gdbarch->{c.name} ({c.actuals()});", file=f)
|
|
if c.type != "void" and c.result_checks:
|
|
for rule in c.result_checks:
|
|
print(f" gdb_assert ({rule});", file=f)
|
|
print(" return result;", file=f)
|
|
print("}", file=f)
|
|
print(file=f)
|
|
print("void", file=f)
|
|
setter_name = f"set_gdbarch_{c.name}"
|
|
ftype_name = f"gdbarch_{c.name}_ftype"
|
|
print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
|
|
indent_columns = len(f"{setter_name} (")
|
|
print(f"{indentation(indent_columns)}{ftype_name} {c.name})", file=f)
|
|
print("{", file=f)
|
|
print(f" gdbarch->{c.name} = {c.name};", file=f)
|
|
print("}", file=f)
|
|
elif isinstance(c, Value):
|
|
print(file=f)
|
|
print(f"{c.type}", file=f)
|
|
print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
|
|
print("{", file=f)
|
|
print(" gdb_assert (gdbarch != NULL);", file=f)
|
|
if isinstance(c.invalid, str):
|
|
print(" /* Check variable is valid. */", file=f)
|
|
print(f" gdb_assert (!({c.invalid}));", file=f)
|
|
elif c.predicate:
|
|
print(" /* Check predicate was used. */", file=f)
|
|
print(f" gdb_assert (gdbarch_{c.name}_p (gdbarch));", file=f)
|
|
elif c.invalid or c.postdefault is not None:
|
|
init_value = c.predefault or "0"
|
|
print(" /* Check variable changed from its initial value. */", file=f)
|
|
print(f" gdb_assert (gdbarch->{c.name} != {init_value});", file=f)
|
|
else:
|
|
print(f" /* Skip verify of {c.name}, invalid_p == 0. */", file=f)
|
|
print(" if (gdbarch_debug >= 2)", file=f)
|
|
print(
|
|
f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
|
|
file=f,
|
|
)
|
|
print(f" return gdbarch->{c.name};", file=f)
|
|
print("}", file=f)
|
|
print(file=f)
|
|
print("void", file=f)
|
|
setter_name = f"set_gdbarch_{c.name}"
|
|
print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
|
|
indent_columns = len(f"{setter_name} (")
|
|
print(f"{indentation(indent_columns)}{c.type} {c.name})", file=f)
|
|
print("{", file=f)
|
|
print(f" gdbarch->{c.name} = {c.name};", file=f)
|
|
print("}", file=f)
|
|
else:
|
|
assert isinstance(c, Info)
|
|
print(file=f)
|
|
print(f"{c.type}", file=f)
|
|
print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
|
|
print("{", file=f)
|
|
print(" gdb_assert (gdbarch != NULL);", file=f)
|
|
print(" if (gdbarch_debug >= 2)", file=f)
|
|
print(
|
|
f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
|
|
file=f,
|
|
)
|
|
print(f" return gdbarch->{c.name};", file=f)
|
|
print("}", file=f)
|