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
22import textwrap
23import gdbcopyright
24
25# All the components created in gdbarch-components.py.
26components = []
27
28
29def indentation(n_columns):
30    """Return string with tabs and spaces to indent line to N_COLUMNS."""
31    return "\t" * (n_columns // 8) + " " * (n_columns % 8)
32
33
34def join_type_and_name(t, n):
35    "Combine the type T and the name N into a C declaration."
36    if t.endswith("*") or t.endswith("&"):
37        return t + n
38    else:
39        return t + " " + n
40
41
42def join_params(params):
43    """Given a sequence of (TYPE, NAME) pairs, generate a comma-separated
44    list of declarations."""
45    params = [join_type_and_name(p[0], p[1]) for p in params]
46    return ", ".join(params)
47
48
49class _Component:
50    "Base class for all components."
51
52    def __init__(self, **kwargs):
53        for key in kwargs:
54            setattr(self, key, kwargs[key])
55        components.append(self)
56
57        # It doesn't make sense to have a check of the result value
58        # for a function or method with void return type.
59        if self.type == "void" and self.result_checks:
60            raise Exception("can't have result checks with a void return type")
61
62    def get_predicate(self):
63        "Return the expression used for validity checking."
64        assert self.predicate and not isinstance(self.invalid, str)
65        if self.predefault:
66            predicate = f"gdbarch->{self.name} != {self.predefault}"
67        elif isinstance(c, Value):
68            predicate = f"gdbarch->{self.name} != 0"
69        else:
70            predicate = f"gdbarch->{self.name} != NULL"
71        return predicate
72
73
74class Info(_Component):
75    "An Info component is copied from the gdbarch_info."
76
77    def __init__(self, *, name, type, printer=None):
78        super().__init__(name=name, type=type, printer=printer)
79        # This little hack makes the generator a bit simpler.
80        self.predicate = None
81
82
83class Value(_Component):
84    "A Value component is just a data member."
85
86    def __init__(
87        self,
88        *,
89        name,
90        type,
91        comment=None,
92        predicate=None,
93        predefault=None,
94        postdefault=None,
95        invalid=None,
96        printer=None,
97    ):
98        super().__init__(
99            comment=comment,
100            name=name,
101            type=type,
102            predicate=predicate,
103            predefault=predefault,
104            postdefault=postdefault,
105            invalid=invalid,
106            printer=printer,
107        )
108
109
110class Function(_Component):
111    "A Function component is a function pointer member."
112
113    def __init__(
114        self,
115        *,
116        name,
117        type,
118        params,
119        comment=None,
120        predicate=None,
121        predefault=None,
122        postdefault=None,
123        invalid=None,
124        printer=None,
125        param_checks=None,
126        result_checks=None,
127    ):
128        super().__init__(
129            comment=comment,
130            name=name,
131            type=type,
132            predicate=predicate,
133            predefault=predefault,
134            postdefault=postdefault,
135            invalid=invalid,
136            printer=printer,
137            params=params,
138            param_checks=param_checks,
139            result_checks=result_checks,
140        )
141
142    def ftype(self):
143        "Return the name of the function typedef to use."
144        return f"gdbarch_{self.name}_ftype"
145
146    def param_list(self):
147        "Return the formal parameter list as a string."
148        return join_params(self.params)
149
150    def set_list(self):
151        """Return the formal parameter list of the caller function,
152        as a string.  This list includes the gdbarch."""
153        arch_arg = ("struct gdbarch *", "gdbarch")
154        arch_tuple = [arch_arg]
155        return join_params(arch_tuple + list(self.params))
156
157    def actuals(self):
158        "Return the actual parameters to forward, as a string."
159        return ", ".join([p[1] for p in self.params])
160
161
162class Method(Function):
163    "A Method is like a Function but passes the gdbarch through."
164
165    def param_list(self):
166        "See superclass."
167        return self.set_list()
168
169    def actuals(self):
170        "See superclass."
171        result = ["gdbarch"] + [p[1] for p in self.params]
172        return ", ".join(result)
173
174
175# Read the components.
176with open("gdbarch-components.py") as fd:
177    exec(fd.read())
178
179copyright = gdbcopyright.copyright(
180    "gdbarch.py", "Dynamic architecture support for GDB, the GNU debugger."
181)
182
183
184def info(c):
185    "Filter function to only allow Info components."
186    return type(c) is Info
187
188
189def not_info(c):
190    "Filter function to omit Info components."
191    return type(c) is not Info
192
193
194with open("gdbarch-gen.h", "w") as f:
195    print(copyright, file=f)
196    print(file=f)
197    print(file=f)
198    print("/* The following are pre-initialized by GDBARCH.  */", file=f)
199
200    # Do Info components first.
201    for c in filter(info, components):
202        print(file=f)
203        print(
204            f"""extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);
205/* set_gdbarch_{c.name}() - not applicable - pre-initialized.  */""",
206            file=f,
207        )
208
209    print(file=f)
210    print(file=f)
211    print("/* The following are initialized by the target dependent code.  */", file=f)
212
213    # Generate decls for accessors, setters, and predicates for all
214    # non-Info components.
215    for c in filter(not_info, components):
216        if c.comment:
217            print(file=f)
218            comment = c.comment.split("\n")
219            if comment[0] == "":
220                comment = comment[1:]
221            if comment[-1] == "":
222                comment = comment[:-1]
223            print("/* ", file=f, end="")
224            print(comment[0], file=f, end="")
225            if len(comment) > 1:
226                print(file=f)
227                print(
228                    textwrap.indent("\n".join(comment[1:]), prefix="   "),
229                    end="",
230                    file=f,
231                )
232            print(" */", file=f)
233
234        if c.predicate:
235            print(file=f)
236            print(f"extern bool gdbarch_{c.name}_p (struct gdbarch *gdbarch);", file=f)
237
238        print(file=f)
239        if isinstance(c, Value):
240            print(
241                f"extern {c.type} gdbarch_{c.name} (struct gdbarch *gdbarch);",
242                file=f,
243            )
244            print(
245                f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.type} {c.name});",
246                file=f,
247            )
248        else:
249            assert isinstance(c, Function)
250            print(
251                f"typedef {c.type} ({c.ftype()}) ({c.param_list()});",
252                file=f,
253            )
254            print(
255                f"extern {c.type} gdbarch_{c.name} ({c.set_list()});",
256                file=f,
257            )
258            print(
259                f"extern void set_gdbarch_{c.name} (struct gdbarch *gdbarch, {c.ftype()} *{c.name});",
260                file=f,
261            )
262
263with open("gdbarch.c", "w") as f:
264    print(copyright, file=f)
265    print(file=f)
266    print("/* Maintain the struct gdbarch object.  */", file=f)
267    print(file=f)
268    #
269    # The struct definition body.
270    #
271    print("struct gdbarch", file=f)
272    print("{", file=f)
273    print("  /* Has this architecture been fully initialized?  */", file=f)
274    print("  bool initialized_p = false;", file=f)
275    print(file=f)
276    print("  /* An obstack bound to the lifetime of the architecture.  */", file=f)
277    print("  auto_obstack obstack;", file=f)
278    print("  /* Registry.  */", file=f)
279    print("  registry<gdbarch> registry_fields;", file=f)
280    print(file=f)
281    print("  /* basic architectural information.  */", file=f)
282    for c in filter(info, components):
283        print(f"  {c.type} {c.name};", file=f)
284    print(file=f)
285    print("  /* target specific vector.  */", file=f)
286    print("  struct gdbarch_tdep_base *tdep = nullptr;", file=f)
287    print("  gdbarch_dump_tdep_ftype *dump_tdep = nullptr;", file=f)
288    print(file=f)
289    print("  /* per-architecture data-pointers.  */", file=f)
290    print("  unsigned nr_data = 0;", file=f)
291    print("  void **data = nullptr;", file=f)
292    print(file=f)
293    for c in filter(not_info, components):
294        if isinstance(c, Function):
295            print(f"  gdbarch_{c.name}_ftype *", file=f, end="")
296        else:
297            print(f"  {c.type} ", file=f, end="")
298        print(f"{c.name} = ", file=f, end="")
299        if c.predefault is not None:
300            print(f"{c.predefault};", file=f)
301        elif isinstance(c, Value):
302            print("0;", file=f)
303        else:
304            assert isinstance(c, Function)
305            print("nullptr;", file=f)
306    print("};", file=f)
307    print(file=f)
308    #
309    # Initialization.
310    #
311    print("/* Create a new ``struct gdbarch'' based on information provided by", file=f)
312    print("   ``struct gdbarch_info''.  */", file=f)
313    print(file=f)
314    print("struct gdbarch *", file=f)
315    print("gdbarch_alloc (const struct gdbarch_info *info,", file=f)
316    print("	       struct gdbarch_tdep_base *tdep)", file=f)
317    print("{", file=f)
318    print("  struct gdbarch *gdbarch;", file=f)
319    print("", file=f)
320    print("  gdbarch = new struct gdbarch;", file=f)
321    print(file=f)
322    print("  gdbarch->tdep = tdep;", file=f)
323    print(file=f)
324    for c in filter(info, components):
325        print(f"  gdbarch->{c.name} = info->{c.name};", file=f)
326    print(file=f)
327    print("  return gdbarch;", file=f)
328    print("}", file=f)
329    print(file=f)
330    print(file=f)
331    print(file=f)
332    #
333    # Post-initialization validation and updating
334    #
335    print("/* Ensure that all values in a GDBARCH are reasonable.  */", file=f)
336    print(file=f)
337    print("static void", file=f)
338    print("verify_gdbarch (struct gdbarch *gdbarch)", file=f)
339    print("{", file=f)
340    print("  string_file log;", file=f)
341    print(file=f)
342    print("  /* fundamental */", file=f)
343    print("  if (gdbarch->byte_order == BFD_ENDIAN_UNKNOWN)", file=f)
344    print("""    log.puts ("\\n\\tbyte-order");""", file=f)
345    print("  if (gdbarch->bfd_arch_info == NULL)", file=f)
346    print("""    log.puts ("\\n\\tbfd_arch_info");""", file=f)
347    print(
348        "  /* Check those that need to be defined for the given multi-arch level.  */",
349        file=f,
350    )
351    for c in filter(not_info, components):
352        if c.invalid is False:
353            print(f"  /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
354        elif c.predicate:
355            print(f"  /* Skip verify of {c.name}, has predicate.  */", file=f)
356        elif isinstance(c.invalid, str) and c.postdefault is not None:
357            print(f"  if ({c.invalid})", file=f)
358            print(f"    gdbarch->{c.name} = {c.postdefault};", file=f)
359        elif c.predefault is not None and c.postdefault is not None:
360            print(f"  if (gdbarch->{c.name} == {c.predefault})", file=f)
361            print(f"    gdbarch->{c.name} = {c.postdefault};", file=f)
362        elif c.postdefault is not None:
363            print(f"  if (gdbarch->{c.name} == 0)", file=f)
364            print(f"    gdbarch->{c.name} = {c.postdefault};", file=f)
365        elif isinstance(c.invalid, str):
366            print(f"  if ({c.invalid})", file=f)
367            print(f"""    log.puts ("\\n\\t{c.name}");""", file=f)
368        elif c.predefault is not None:
369            print(f"  if (gdbarch->{c.name} == {c.predefault})", file=f)
370            print(f"""    log.puts ("\\n\\t{c.name}");""", file=f)
371        elif c.invalid is True:
372            print(f"  if (gdbarch->{c.name} == 0)", file=f)
373            print(f"""    log.puts ("\\n\\t{c.name}");""", file=f)
374        else:
375            # We should not allow ourselves to simply do nothing here
376            # because no other case applies.  If we end up here then
377            # either the input data needs adjusting so one of the
378            # above cases matches, or we need additional cases adding
379            # here.
380            raise Exception("unhandled case when generating gdbarch validation")
381    print("  if (!log.empty ())", file=f)
382    print(
383        """    internal_error (_("verify_gdbarch: the following are invalid ...%s"),""",
384        file=f,
385    )
386    print("		    log.c_str ());", file=f)
387    print("}", file=f)
388    print(file=f)
389    print(file=f)
390    #
391    # Dumping.
392    #
393    print("/* Print out the details of the current architecture.  */", file=f)
394    print(file=f)
395    print("void", file=f)
396    print("gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)", file=f)
397    print("{", file=f)
398    print("""  const char *gdb_nm_file = "<not-defined>";""", file=f)
399    print(file=f)
400    print("#if defined (GDB_NM_FILE)", file=f)
401    print("  gdb_nm_file = GDB_NM_FILE;", file=f)
402    print("#endif", file=f)
403    print("  gdb_printf (file,", file=f)
404    print("""	      "gdbarch_dump: GDB_NM_FILE = %s\\n",""", file=f)
405    print("	      gdb_nm_file);", file=f)
406    for c in components:
407        if c.predicate:
408            print("  gdb_printf (file,", file=f)
409            print(
410                f"""	      "gdbarch_dump: gdbarch_{c.name}_p() = %d\\n",""",
411                file=f,
412            )
413            print(f"	      gdbarch_{c.name}_p (gdbarch));", file=f)
414        if isinstance(c, Function):
415            print("  gdb_printf (file,", file=f)
416            print(f"""	      "gdbarch_dump: {c.name} = <%s>\\n",""", file=f)
417            print(
418                f"	      host_address_to_string (gdbarch->{c.name}));",
419                file=f,
420            )
421        else:
422            if c.printer:
423                printer = c.printer
424            elif c.type == "CORE_ADDR":
425                printer = f"core_addr_to_string_nz (gdbarch->{c.name})"
426            else:
427                printer = f"plongest (gdbarch->{c.name})"
428            print("  gdb_printf (file,", file=f)
429            print(f"""	      "gdbarch_dump: {c.name} = %s\\n",""", file=f)
430            print(f"	      {printer});", file=f)
431    print("  if (gdbarch->dump_tdep != NULL)", file=f)
432    print("    gdbarch->dump_tdep (gdbarch, file);", file=f)
433    print("}", file=f)
434    print(file=f)
435    #
436    # Bodies of setter, accessor, and predicate functions.
437    #
438    for c in components:
439        if c.predicate:
440            print(file=f)
441            print("bool", file=f)
442            print(f"gdbarch_{c.name}_p (struct gdbarch *gdbarch)", file=f)
443            print("{", file=f)
444            print("  gdb_assert (gdbarch != NULL);", file=f)
445            print(f"  return {c.get_predicate()};", file=f)
446            print("}", file=f)
447        if isinstance(c, Function):
448            print(file=f)
449            print(f"{c.type}", file=f)
450            print(f"gdbarch_{c.name} ({c.set_list()})", file=f)
451            print("{", file=f)
452            print("  gdb_assert (gdbarch != NULL);", file=f)
453            print(f"  gdb_assert (gdbarch->{c.name} != NULL);", file=f)
454            if c.predicate and c.predefault:
455                # Allow a call to a function with a predicate.
456                print(
457                    f"  /* Do not check predicate: {c.get_predicate()}, allow call.  */",
458                    file=f,
459                )
460            if c.param_checks:
461                for rule in c.param_checks:
462                    print(f"  gdb_assert ({rule});", file=f)
463            print("  if (gdbarch_debug >= 2)", file=f)
464            print(
465                f"""    gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
466                file=f,
467            )
468            print("  ", file=f, end="")
469            if c.type != "void":
470                if c.result_checks:
471                    print("auto result = ", file=f, end="")
472                else:
473                    print("return ", file=f, end="")
474            print(f"gdbarch->{c.name} ({c.actuals()});", file=f)
475            if c.type != "void" and c.result_checks:
476                for rule in c.result_checks:
477                    print(f"  gdb_assert ({rule});", file=f)
478                print("  return result;", file=f)
479            print("}", file=f)
480            print(file=f)
481            print("void", file=f)
482            setter_name = f"set_gdbarch_{c.name}"
483            ftype_name = f"gdbarch_{c.name}_ftype"
484            print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
485            indent_columns = len(f"{setter_name} (")
486            print(f"{indentation(indent_columns)}{ftype_name} {c.name})", file=f)
487            print("{", file=f)
488            print(f"  gdbarch->{c.name} = {c.name};", file=f)
489            print("}", file=f)
490        elif isinstance(c, Value):
491            print(file=f)
492            print(f"{c.type}", file=f)
493            print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
494            print("{", file=f)
495            print("  gdb_assert (gdbarch != NULL);", file=f)
496            if c.invalid is False:
497                print(f"  /* Skip verify of {c.name}, invalid_p == 0 */", file=f)
498            elif isinstance(c.invalid, str):
499                print("  /* Check variable is valid.  */", file=f)
500                print(f"  gdb_assert (!({c.invalid}));", file=f)
501            elif c.predefault:
502                print("  /* Check variable changed from pre-default.  */", file=f)
503                print(f"  gdb_assert (gdbarch->{c.name} != {c.predefault});", file=f)
504            print("  if (gdbarch_debug >= 2)", file=f)
505            print(
506                f"""    gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
507                file=f,
508            )
509            print(f"  return gdbarch->{c.name};", file=f)
510            print("}", file=f)
511            print(file=f)
512            print("void", file=f)
513            setter_name = f"set_gdbarch_{c.name}"
514            print(f"{setter_name} (struct gdbarch *gdbarch,", file=f)
515            indent_columns = len(f"{setter_name} (")
516            print(f"{indentation(indent_columns)}{c.type} {c.name})", file=f)
517            print("{", file=f)
518            print(f"  gdbarch->{c.name} = {c.name};", file=f)
519            print("}", file=f)
520        else:
521            assert isinstance(c, Info)
522            print(file=f)
523            print(f"{c.type}", file=f)
524            print(f"gdbarch_{c.name} (struct gdbarch *gdbarch)", file=f)
525            print("{", file=f)
526            print("  gdb_assert (gdbarch != NULL);", file=f)
527            print("  if (gdbarch_debug >= 2)", file=f)
528            print(
529                f"""    gdb_printf (gdb_stdlog, "gdbarch_{c.name} called\\n");""",
530                file=f,
531            )
532            print(f"  return gdbarch->{c.name};", file=f)
533            print("}", file=f)
534