gdbarch: improve generation of validation in gdbarch getters
[binutils-gdb.git] / gdb / gdbarch.py
1 #!/usr/bin/env python3
2
3 # Architecture commands for GDB, the GNU debugger.
4 #
5 # Copyright (C) 1998-2023 Free Software Foundation, Inc.
6 #
7 # This file is part of GDB.
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 import textwrap
23
24 # gdbarch_components is imported only for its side-effect of filling
25 # `gdbarch_types.components`.
26 import gdbarch_components # noqa: F401 # type: ignore
27 import gdbcopyright
28 from gdbarch_types import Component, Function, Info, Value, components
29
30
31 def indentation(n_columns: int):
32 """Return string with tabs and spaces to indent line to N_COLUMNS."""
33 return "\t" * (n_columns // 8) + " " * (n_columns % 8)
34
35
36 copyright = gdbcopyright.copyright(
37 "gdbarch.py", "Dynamic architecture support for GDB, the GNU debugger."
38 )
39
40
41 def info(c: Component):
42 "Filter function to only allow Info components."
43 return type(c) is Info
44
45
46 def not_info(c: Component):
47 "Filter function to omit Info components."
48 return type(c) is not Info
49
50
51 with open("gdbarch-gen.h", "w") as f:
52 print(copyright, file=f)
53 print(file=f)
54 print(file=f)
55 print("/* The following are pre-initialized by GDBARCH. */", file=f)
56
57 # Do Info components first.
58 for c in filter(info, components):
59 print(file=f)
60 print(
61 f"""extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);
62 /* set_gdbarch_{c.name}() - not applicable - pre-initialized. */""",
63 file=f,
64 )
65
66 print(file=f)
67 print(file=f)
68 print("/* The following are initialized by the target dependent code. */", file=f)
69
70 # Generate decls for accessors, setters, and predicates for all
71 # non-Info components.
72 for c in filter(not_info, components):
73 if c.comment:
74 print(file=f)
75 comment = c.comment.split("\n")
76 if comment[0] == "":
77 comment = comment[1:]
78 if comment[-1] == "":
79 comment = comment[:-1]
80 print("/* ", file=f, end="")
81 print(comment[0], file=f, end="")
82 if len(comment) > 1:
83 print(file=f)
84 print(
85 textwrap.indent("\n".join(comment[1:]), prefix=" "),
86 end="",
87 file=f,
88 )
89 print(" */", file=f)
90
91 if c.predicate:
92 print(file=f)
93 print(f"extern bool gdbarch_{c.name}_p (struct gdbarch *gdbarch);", file=f)
94
95 print(file=f)
96 if isinstance(c, Value):
97 print(
98 f"extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);",
99 file=f,
100 )
101 print(
102 f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.type} {c.name});",
103 file=f,
104 )
105 else:
106 assert isinstance(c, Function)
107 print(
108 f"typedef {c.type} ({c.ftype()}) ({c.param_list()});",
109 file=f,
110 )
111 if c.implement:
112 print(
113 f"extern {c.type} gdbarch_{c.name} ({c.set_list()});",
114 file=f,
115 )
116 print(
117 f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.ftype()} *{c.name});",
118 file=f,
119 )
120
121 with open("gdbarch.c", "w") as f:
122 print(copyright, file=f)
123 print(file=f)
124 print("/* Maintain the struct gdbarch object. */", file=f)
125 print(file=f)
126 #
127 # The struct definition body.
128 #
129 print("struct gdbarch", file=f)
130 print("{", file=f)
131 print(" /* Has this architecture been fully initialized? */", file=f)
132 print(" bool initialized_p = false;", file=f)
133 print(file=f)
134 print(" /* An obstack bound to the lifetime of the architecture. */", file=f)
135 print(" auto_obstack obstack;", file=f)
136 print(" /* Registry. */", file=f)
137 print(" registry<gdbarch> registry_fields;", file=f)
138 print(file=f)
139 print(" /* basic architectural information. */", file=f)
140 for c in filter(info, components):
141 print(f" {c.type} {c.name};", file=f)
142 print(file=f)
143 print(" /* target specific vector. */", file=f)
144 print(" gdbarch_tdep_up tdep;", file=f)
145 print(" gdbarch_dump_tdep_ftype *dump_tdep = nullptr;", file=f)
146 print(file=f)
147 for c in filter(not_info, components):
148 if isinstance(c, Function):
149 print(f" gdbarch_{c.name}_ftype *", file=f, end="")
150 else:
151 print(f" {c.type} ", file=f, end="")
152 print(f"{c.name} = ", file=f, end="")
153 if c.predefault is not None:
154 print(f"{c.predefault};", file=f)
155 elif isinstance(c, Value):
156 print("0;", file=f)
157 else:
158 assert isinstance(c, Function)
159 print("nullptr;", file=f)
160 print("};", file=f)
161 print(file=f)
162 #
163 # Initialization.
164 #
165 print("/* Create a new ``struct gdbarch'' based on information provided by", file=f)
166 print(" ``struct gdbarch_info''. */", file=f)
167 print(file=f)
168 print("struct gdbarch *", file=f)
169 print("gdbarch_alloc (const struct gdbarch_info *info,", file=f)
170 print(" gdbarch_tdep_up tdep)", file=f)
171 print("{", file=f)
172 print(" struct gdbarch *gdbarch;", file=f)
173 print("", file=f)
174 print(" gdbarch = new struct gdbarch;", file=f)
175 print(file=f)
176 print(" gdbarch->tdep = std::move (tdep);", file=f)
177 print(file=f)
178 for c in filter(info, components):
179 print(f" gdbarch->{c.name} = info->{c.name};", file=f)
180 print(file=f)
181 print(" return gdbarch;", file=f)
182 print("}", file=f)
183 print(file=f)
184 print(file=f)
185 print(file=f)
186 #
187 # Post-initialization validation and updating
188 #
189 print("/* Ensure that all values in a GDBARCH are reasonable. */", file=f)
190 print(file=f)
191 print("static void", file=f)
192 print("verify_gdbarch (struct gdbarch *gdbarch)", file=f)
193 print("{", file=f)
194 print(" string_file log;", file=f)
195 print(file=f)
196 print(" /* fundamental */", file=f)
197 print(" if (gdbarch->byte_order == BFD_ENDIAN_UNKNOWN)", file=f)
198 print(""" log.puts ("\\n\\tbyte-order");""", file=f)
199 print(" if (gdbarch->bfd_arch_info == NULL)", file=f)
200 print(""" log.puts ("\\n\\tbfd_arch_info");""", file=f)
201 print(
202 " /* Check those that need to be defined for the given multi-arch level. */",
203 file=f,
204 )
205 for c in filter(not_info, components):
206 # An opportunity to write in the 'postdefault' value. We
207 # change field's value to the postdefault if its current value
208 # is not different to the initial value of the field.
209 if c.postdefault is not None:
210 init_value = c.predefault or "0"
211 print(f" if (gdbarch->{c.name} == {init_value})", file=f)
212 print(f" gdbarch->{c.name} = {c.postdefault};", file=f)
213
214 # Now validate the value.
215 if isinstance(c.invalid, str):
216 print(f" if ({c.invalid})", file=f)
217 print(f""" log.puts ("\\n\\t{c.name}");""", file=f)
218 elif c.predicate:
219 print(f" /* Skip verify of {c.name}, has predicate. */", file=f)
220 elif c.invalid:
221 if c.postdefault is not None:
222 # This component has its 'invalid' field set to True, but
223 # also has a postdefault. This makes no sense, the
224 # postdefault will have been applied above, so this field
225 # will not have a zero value.
226 raise Exception(
227 f"component {c.name} has postdefault and invalid set to True"
228 )
229 else:
230 init_value = c.predefault or "0"
231 print(f" if (gdbarch->{c.name} == {init_value})", file=f)
232 print(f""" log.puts ("\\n\\t{c.name}");""", file=f)
233 else:
234 print(f" /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
235 print(" if (!log.empty ())", file=f)
236 print(
237 """ internal_error (_("verify_gdbarch: the following are invalid ...%s"),""",
238 file=f,
239 )
240 print(" log.c_str ());", file=f)
241 print("}", file=f)
242 print(file=f)
243 print(file=f)
244 #
245 # Dumping.
246 #
247 print("/* Print out the details of the current architecture. */", file=f)
248 print(file=f)
249 print("void", file=f)
250 print("gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)", file=f)
251 print("{", file=f)
252 print(""" const char *gdb_nm_file = "<not-defined>";""", file=f)
253 print(file=f)
254 print("#if defined (GDB_NM_FILE)", file=f)
255 print(" gdb_nm_file = GDB_NM_FILE;", file=f)
256 print("#endif", file=f)
257 print(" gdb_printf (file,", file=f)
258 print(""" "gdbarch_dump: GDB_NM_FILE = %s\\n",""", file=f)
259 print(" gdb_nm_file);", file=f)
260 for c in components:
261 if c.predicate:
262 print(" gdb_printf (file,", file=f)
263 print(
264 f""" "gdbarch_dump: gdbarch_{c.name}_p() = %d\\n",""",
265 file=f,
266 )
267 print(f" gdbarch_{c.name}_p (gdbarch));", file=f)
268 if isinstance(c, Function):
269 print(" gdb_printf (file,", file=f)
270 print(f""" "gdbarch_dump: {c.name} = <%s>\\n",""", file=f)
271 print(
272 f" host_address_to_string (gdbarch->{c.name}));",
273 file=f,
274 )
275 else:
276 if c.printer:
277 printer = c.printer
278 elif c.type == "CORE_ADDR":
279 printer = f"core_addr_to_string_nz (gdbarch->{c.name})"
280 else:
281 printer = f"plongest (gdbarch->{c.name})"
282 print(" gdb_printf (file,", file=f)
283 print(f""" "gdbarch_dump: {c.name} = %s\\n",""", file=f)
284 print(f" {printer});", file=f)
285 print(" if (gdbarch->dump_tdep != NULL)", file=f)
286 print(" gdbarch->dump_tdep (gdbarch, file);", file=f)
287 print("}", file=f)
288 print(file=f)
289 #
290 # Bodies of setter, accessor, and predicate functions.
291 #
292 for c in components:
293 if c.predicate:
294 print(file=f)
295 print("bool", file=f)
296 print(f"gdbarch_{c.name}_p (struct gdbarch *gdbarch)", file=f)
297 print("{", file=f)
298 print(" gdb_assert (gdbarch != NULL);", file=f)
299 print(f" return {c.get_predicate()};", file=f)
300 print("}", file=f)
301 if isinstance(c, Function):
302 if c.implement:
303 print(file=f)
304 print(f"{c.type}", file=f)
305 print(f"gdbarch_{c.name} ({c.set_list()})", file=f)
306 print("{", file=f)
307 print(" gdb_assert (gdbarch != NULL);", file=f)
308 print(f" gdb_assert (gdbarch->{c.name} != NULL);", file=f)
309 if c.predicate and c.predefault:
310 # Allow a call to a function with a predicate.
311 print(
312 f" /* Do not check predicate: {c.get_predicate()}, allow call. */",
313 file=f,
314 )
315 if c.param_checks:
316 for rule in c.param_checks:
317 print(f" gdb_assert ({rule});", file=f)
318 print(" if (gdbarch_debug >= 2)", file=f)
319 print(
320 f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
321 file=f,
322 )
323 print(" ", file=f, end="")
324 if c.type != "void":
325 if c.result_checks:
326 print("auto result = ", file=f, end="")
327 else:
328 print("return ", file=f, end="")
329 print(f"gdbarch->{c.name} ({c.actuals()});", file=f)
330 if c.type != "void" and c.result_checks:
331 for rule in c.result_checks:
332 print(f" gdb_assert ({rule});", file=f)
333 print(" return result;", file=f)
334 print("}", file=f)
335 print(file=f)
336 print("void", file=f)
337 setter_name = f"set_gdbarch_{c.name}"
338 ftype_name = f"gdbarch_{c.name}_ftype"
339 print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
340 indent_columns = len(f"{setter_name} (")
341 print(f"{indentation(indent_columns)}{ftype_name} {c.name})", file=f)
342 print("{", file=f)
343 print(f" gdbarch->{c.name} = {c.name};", file=f)
344 print("}", file=f)
345 elif isinstance(c, Value):
346 print(file=f)
347 print(f"{c.type}", file=f)
348 print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
349 print("{", file=f)
350 print(" gdb_assert (gdbarch != NULL);", file=f)
351 if isinstance(c.invalid, str):
352 print(" /* Check variable is valid. */", file=f)
353 print(f" gdb_assert (!({c.invalid}));", file=f)
354 elif c.predicate:
355 print(" /* Check predicate was used. */", file=f)
356 print(f" gdb_assert (gdbarch_{c.name}_p (gdbarch));", file=f)
357 elif c.invalid or c.postdefault is not None:
358 init_value = c.predefault or "0"
359 print(" /* Check variable changed from its initial value. */", file=f)
360 print(f" gdb_assert (gdbarch->{c.name} != {init_value});", file=f)
361 else:
362 print(f" /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
363 print(" if (gdbarch_debug >= 2)", file=f)
364 print(
365 f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
366 file=f,
367 )
368 print(f" return gdbarch->{c.name};", file=f)
369 print("}", file=f)
370 print(file=f)
371 print("void", file=f)
372 setter_name = f"set_gdbarch_{c.name}"
373 print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
374 indent_columns = len(f"{setter_name} (")
375 print(f"{indentation(indent_columns)}{c.type} {c.name})", file=f)
376 print("{", file=f)
377 print(f" gdbarch->{c.name} = {c.name};", file=f)
378 print("}", file=f)
379 else:
380 assert isinstance(c, Info)
381 print(file=f)
382 print(f"{c.type}", file=f)
383 print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
384 print("{", file=f)
385 print(" gdb_assert (gdbarch != NULL);", file=f)
386 print(" if (gdbarch_debug >= 2)", file=f)
387 print(
388 f""" gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
389 file=f,
390 )
391 print(f" return gdbarch->{c.name};", file=f)
392 print("}", file=f)