# argument, and NAME is the name. Note that while the names could be
# auto-generated, this approach lets the "comment" field refer to
# arguments in a nicer way. It is also just nicer for users.
+#
+# * "param_checks" - optional, a list of strings. Each string is an
+# expression that is placed within a gdb_assert before the call is
+# made to the Function/Method implementation. Each expression is
+# something that should be true, and it is expected that the
+# expression will make use of the parameters named in 'params' (though
+# this is not required).
+#
+# * "result_checks" - optional, a list of strings. Each string is an
+# expression that is placed within a gdb_assert after the call to the
+# Function/Method implementation. Within each expression the variable
+# 'result' can be used to reference the result of the function/method
+# implementation. The 'result_checks' can only be used if the 'type'
+# of this Function/Method is not 'void'.
Info(
type="const struct bfd_arch_info *",
type="const char *",
name="register_name",
params=[("int", "regnr")],
+ param_checks=["regnr >= 0", "regnr < gdbarch_num_cooked_regs (gdbarch)"],
+ result_checks=["result != nullptr"],
predefault="0",
invalid=True,
)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->register_name != NULL);
+ gdb_assert (regnr >= 0);
+ gdb_assert (regnr < gdbarch_num_cooked_regs (gdbarch));
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_register_name called\n");
- return gdbarch->register_name (gdbarch, regnr);
+ auto result = gdbarch->register_name (gdbarch, regnr);
+ gdb_assert (result != nullptr);
+ return result;
}
void
setattr(self, key, kwargs[key])
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)
postdefault=None,
invalid=None,
printer=None,
+ param_checks=None,
+ result_checks=None,
):
super().__init__(
comment=comment,
invalid=invalid,
printer=printer,
params=params,
+ param_checks=param_checks,
+ result_checks=result_checks,
)
def ftype(self):
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");""",
)
print(" ", file=f, end="")
if c.type != "void":
- print("return ", file=f, end="")
+ 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)