]> Git Repo - binutils.git/blob - gdb/osabi.c
gdb: remove SYMBOL_CLASS macro, add getter
[binutils.git] / gdb / osabi.c
1 /* OS ABI variant handling for GDB.
2
3    Copyright (C) 2001-2022 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21
22 #include "osabi.h"
23 #include "arch-utils.h"
24 #include "gdbcmd.h"
25 #include "command.h"
26 #include "gdb_bfd.h"
27
28 #include "elf-bfd.h"
29
30 #ifndef GDB_OSABI_DEFAULT
31 #define GDB_OSABI_DEFAULT GDB_OSABI_UNKNOWN
32 #endif
33
34 /* State for the "set osabi" command.  */
35 static enum { osabi_auto, osabi_default, osabi_user } user_osabi_state;
36 static enum gdb_osabi user_selected_osabi;
37 static const char *gdb_osabi_available_names[GDB_OSABI_INVALID + 3] = {
38   "auto",
39   "default",
40   "none",
41   NULL
42 };
43 static const char *set_osabi_string;
44
45 /* Names associated with each osabi.  */
46
47 struct osabi_names
48 {
49   /* The "pretty" name.  */
50
51   const char *pretty;
52
53   /* The triplet regexp, or NULL if not known.  */
54
55   const char *regexp;
56 };
57
58 /* This table matches the indices assigned to enum gdb_osabi.  Keep
59    them in sync.  */
60 static const struct osabi_names gdb_osabi_names[] =
61 {
62   { "unknown", NULL },
63   { "none", NULL },
64
65   { "SVR4", NULL },
66   { "GNU/Hurd", NULL },
67   { "Solaris", NULL },
68   { "GNU/Linux", "linux(-gnu[^-]*)?" },
69   { "FreeBSD", NULL },
70   { "NetBSD", NULL },
71   { "OpenBSD", NULL },
72   { "WindowsCE", NULL },
73   { "DJGPP", NULL },
74   { "QNX-Neutrino", NULL },
75   { "Cygwin", NULL },
76   { "Windows", NULL },
77   { "AIX", NULL },
78   { "DICOS", NULL },
79   { "Darwin", NULL },
80   { "OpenVMS", NULL },
81   { "LynxOS178", NULL },
82   { "Newlib", NULL },
83   { "SDE", NULL },
84   { "PikeOS", NULL },
85
86   { "<invalid>", NULL }
87 };
88
89 const char *
90 gdbarch_osabi_name (enum gdb_osabi osabi)
91 {
92   if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
93     return gdb_osabi_names[osabi].pretty;
94
95   return gdb_osabi_names[GDB_OSABI_INVALID].pretty;
96 }
97
98 /* See osabi.h.  */
99
100 const char *
101 osabi_triplet_regexp (enum gdb_osabi osabi)
102 {
103   if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
104     return gdb_osabi_names[osabi].regexp;
105
106   return gdb_osabi_names[GDB_OSABI_INVALID].regexp;
107 }
108
109 /* Lookup the OS ABI corresponding to the specified target description
110    string.  */
111
112 enum gdb_osabi
113 osabi_from_tdesc_string (const char *name)
114 {
115   int i;
116
117   for (i = 0; i < ARRAY_SIZE (gdb_osabi_names); i++)
118     if (strcmp (name, gdb_osabi_names[i].pretty) == 0)
119       {
120         /* See note above: the name table matches the indices assigned
121            to enum gdb_osabi.  */
122         enum gdb_osabi osabi = (enum gdb_osabi) i;
123
124         if (osabi == GDB_OSABI_INVALID)
125           return GDB_OSABI_UNKNOWN;
126         else
127           return osabi;
128       }
129
130   return GDB_OSABI_UNKNOWN;
131 }
132
133 /* Handler for a given architecture/OS ABI pair.  There should be only
134    one handler for a given OS ABI each architecture family.  */
135 struct gdb_osabi_handler
136 {
137   struct gdb_osabi_handler *next;
138   const struct bfd_arch_info *arch_info;
139   enum gdb_osabi osabi;
140   void (*init_osabi)(struct gdbarch_info, struct gdbarch *);
141 };
142
143 static struct gdb_osabi_handler *gdb_osabi_handler_list;
144
145 void
146 gdbarch_register_osabi (enum bfd_architecture arch, unsigned long machine,
147                         enum gdb_osabi osabi,
148                         void (*init_osabi)(struct gdbarch_info,
149                                            struct gdbarch *))
150 {
151   struct gdb_osabi_handler **handler_p;
152   const struct bfd_arch_info *arch_info = bfd_lookup_arch (arch, machine);
153   const char **name_ptr;
154
155   /* Registering an OS ABI handler for "unknown" is not allowed.  */
156   if (osabi == GDB_OSABI_UNKNOWN)
157     {
158       internal_error
159         (__FILE__, __LINE__,
160          _("gdbarch_register_osabi: An attempt to register a handler for "
161          "OS ABI \"%s\" for architecture %s was made.  The handler will "
162          "not be registered"),
163          gdbarch_osabi_name (osabi),
164          bfd_printable_arch_mach (arch, machine));
165       return;
166     }
167
168   gdb_assert (arch_info);
169
170   for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL;
171        handler_p = &(*handler_p)->next)
172     {
173       if ((*handler_p)->arch_info == arch_info
174           && (*handler_p)->osabi == osabi)
175         {
176           internal_error
177             (__FILE__, __LINE__,
178              _("gdbarch_register_osabi: A handler for OS ABI \"%s\" "
179              "has already been registered for architecture %s"),
180              gdbarch_osabi_name (osabi),
181              arch_info->printable_name);
182           /* If user wants to continue, override previous definition.  */
183           (*handler_p)->init_osabi = init_osabi;
184           return;
185         }
186     }
187
188   (*handler_p) = XNEW (struct gdb_osabi_handler);
189   (*handler_p)->next = NULL;
190   (*handler_p)->arch_info = arch_info;
191   (*handler_p)->osabi = osabi;
192   (*handler_p)->init_osabi = init_osabi;
193
194   /* Add this OS ABI to the list of enum values for "set osabi", if it isn't
195      already there.  */
196   for (name_ptr = gdb_osabi_available_names; *name_ptr; name_ptr ++)
197     {
198       if (*name_ptr == gdbarch_osabi_name (osabi))
199         return;
200     }
201   *name_ptr++ = gdbarch_osabi_name (osabi);
202   *name_ptr = NULL;
203 }
204 \f
205
206 /* Sniffer to find the OS ABI for a given file's architecture and flavour.
207    It is legal to have multiple sniffers for each arch/flavour pair, to
208    disambiguate one OS's a.out from another, for example.  The first sniffer
209    to return something other than GDB_OSABI_UNKNOWN wins, so a sniffer should
210    be careful to claim a file only if it knows for sure what it is.  */
211 struct gdb_osabi_sniffer
212 {
213   struct gdb_osabi_sniffer *next;
214   enum bfd_architecture arch;   /* bfd_arch_unknown == wildcard */
215   enum bfd_flavour flavour;
216   enum gdb_osabi (*sniffer)(bfd *);
217 };
218
219 static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list;
220
221 void
222 gdbarch_register_osabi_sniffer (enum bfd_architecture arch,
223                                 enum bfd_flavour flavour,
224                                 enum gdb_osabi (*sniffer_fn)(bfd *))
225 {
226   struct gdb_osabi_sniffer *sniffer;
227
228   sniffer = XNEW (struct gdb_osabi_sniffer);
229   sniffer->arch = arch;
230   sniffer->flavour = flavour;
231   sniffer->sniffer = sniffer_fn;
232
233   sniffer->next = gdb_osabi_sniffer_list;
234   gdb_osabi_sniffer_list = sniffer;
235 }
236 \f
237
238 enum gdb_osabi
239 gdbarch_lookup_osabi (bfd *abfd)
240 {
241   struct gdb_osabi_sniffer *sniffer;
242   enum gdb_osabi osabi, match;
243   int match_specific;
244
245   /* If we aren't in "auto" mode, return the specified OS ABI.  */
246   if (user_osabi_state == osabi_user)
247     return user_selected_osabi;
248
249   /* If we don't have a binary, just return unknown.  The caller may
250      have other sources the OSABI can be extracted from, e.g., the
251      target description.  */
252   if (abfd == NULL)
253     return GDB_OSABI_UNKNOWN;
254
255   match = GDB_OSABI_UNKNOWN;
256   match_specific = 0;
257
258   for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL;
259        sniffer = sniffer->next)
260     {
261       if ((sniffer->arch == bfd_arch_unknown /* wildcard */
262            || sniffer->arch == bfd_get_arch (abfd))
263           && sniffer->flavour == bfd_get_flavour (abfd))
264         {
265           osabi = (*sniffer->sniffer) (abfd);
266           if (osabi < GDB_OSABI_UNKNOWN || osabi >= GDB_OSABI_INVALID)
267             {
268               internal_error
269                 (__FILE__, __LINE__,
270                  _("gdbarch_lookup_osabi: invalid OS ABI (%d) from sniffer "
271                  "for architecture %s flavour %d"),
272                  (int) osabi,
273                  bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
274                  (int) bfd_get_flavour (abfd));
275             }
276           else if (osabi != GDB_OSABI_UNKNOWN)
277             {
278               /* A specific sniffer always overrides a generic sniffer.
279                  Croak on multiple match if the two matches are of the
280                  same class.  If the user wishes to continue, we'll use
281                  the first match.  */
282               if (match != GDB_OSABI_UNKNOWN)
283                 {
284                   if ((match_specific && sniffer->arch != bfd_arch_unknown)
285                    || (!match_specific && sniffer->arch == bfd_arch_unknown))
286                     {
287                       internal_error
288                         (__FILE__, __LINE__,
289                          _("gdbarch_lookup_osabi: multiple %sspecific OS ABI "
290                          "match for architecture %s flavour %d: first "
291                          "match \"%s\", second match \"%s\""),
292                          match_specific ? "" : "non-",
293                          bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
294                          (int) bfd_get_flavour (abfd),
295                          gdbarch_osabi_name (match),
296                          gdbarch_osabi_name (osabi));
297                     }
298                   else if (sniffer->arch != bfd_arch_unknown)
299                     {
300                       match = osabi;
301                       match_specific = 1;
302                     }
303                 }
304               else
305                 {
306                   match = osabi;
307                   if (sniffer->arch != bfd_arch_unknown)
308                     match_specific = 1;
309                 }
310             }
311         }
312     }
313
314   return match;
315 }
316
317
318 /* Return non-zero if architecture A can run code written for
319    architecture B.  */
320 static int
321 can_run_code_for (const struct bfd_arch_info *a, const struct bfd_arch_info *b)
322 {
323   /* BFD's 'A->compatible (A, B)' functions return zero if A and B are
324      incompatible.  But if they are compatible, it returns the 'more
325      featureful' of the two arches.  That is, if A can run code
326      written for B, but B can't run code written for A, then it'll
327      return A.
328
329      struct bfd_arch_info objects are singletons: that is, there's
330      supposed to be exactly one instance for a given machine.  So you
331      can tell whether two are equivalent by comparing pointers.  */
332   return (a == b || a->compatible (a, b) == a);
333 }
334
335
336 void
337 gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
338 {
339   struct gdb_osabi_handler *handler;
340
341   gdb_assert (info.osabi != GDB_OSABI_UNKNOWN);
342
343   for (handler = gdb_osabi_handler_list; handler != NULL;
344        handler = handler->next)
345     {
346       if (handler->osabi != info.osabi)
347         continue;
348
349       /* If the architecture described by ARCH_INFO can run code for
350          the architecture we registered the handler for, then the
351          handler is applicable.  Note, though, that if the handler is
352          for an architecture that is a superset of ARCH_INFO, we can't
353          use that --- it would be perfectly correct for it to install
354          gdbarch methods that refer to registers / instructions /
355          other facilities ARCH_INFO doesn't have.
356
357          NOTE: kettenis/20021027: There may be more than one machine
358          type that is compatible with the desired machine type.  Right
359          now we simply return the first match, which is fine for now.
360          However, we might want to do something smarter in the future.  */
361       /* NOTE: cagney/2003-10-23: The code for "a can_run_code_for b"
362          is implemented using BFD's compatible method (a->compatible
363          (b) == a -- the lowest common denominator between a and b is
364          a).  That method's definition of compatible may not be as you
365          expect.  For instance the test "amd64 can run code for i386"
366          (or more generally "64-bit ISA can run code for the 32-bit
367          ISA").  BFD doesn't normally consider 32-bit and 64-bit
368          "compatible" so it doesn't succeed.  */
369       if (can_run_code_for (info.bfd_arch_info, handler->arch_info))
370         {
371           (*handler->init_osabi) (info, gdbarch);
372           return;
373         }
374     }
375
376   if (info.osabi == GDB_OSABI_NONE)
377     {
378       /* Don't complain about no OSABI.  Assume the user knows
379          what they are doing.  */
380       return;
381     }
382
383   warning
384     ("A handler for the OS ABI \"%s\" is not built into this configuration\n"
385      "of GDB.  Attempting to continue with the default %s settings.\n",
386      gdbarch_osabi_name (info.osabi),
387      info.bfd_arch_info->printable_name);
388 }
389 \f
390 /* Limit on the amount of data to be read.  */
391 #define MAX_NOTESZ      128
392
393 /* Return non-zero if NOTE matches NAME, DESCSZ and TYPE.  If
394    *SECTSIZE is non-zero, then this reads that many bytes from
395    the start of the section and clears *SECTSIZE.  */
396
397 static int
398 check_note (bfd *abfd, asection *sect, char *note, unsigned int *sectsize,
399             const char *name, unsigned long descsz, unsigned long type)
400 {
401   unsigned long notesz;
402
403   if (*sectsize)
404     {
405       if (!bfd_get_section_contents (abfd, sect, note, 0, *sectsize))
406         return 0;
407       *sectsize = 0;
408     }
409
410   /* Calculate the size of this note.  */
411   notesz = strlen (name) + 1;
412   notesz = ((notesz + 3) & ~3);
413   notesz += descsz;
414   notesz = ((notesz + 3) & ~3);
415
416   /* If this assertion triggers, increase MAX_NOTESZ.  */
417   gdb_assert (notesz <= MAX_NOTESZ);
418
419   /* Check whether SECT is big enough to contain the complete note.  */
420   if (notesz > bfd_section_size (sect))
421     return 0;
422
423   /* Check the note name.  */
424   if (bfd_h_get_32 (abfd, note) != (strlen (name) + 1)
425       || strcmp (note + 12, name) != 0)
426     return 0;
427
428   /* Check the descriptor size.  */
429   if (bfd_h_get_32 (abfd, note + 4) != descsz)
430     return 0;
431
432   /* Check the note type.  */
433   if (bfd_h_get_32 (abfd, note + 8) != type)
434     return 0;
435
436   return 1;
437 }
438
439 /* Generic sniffer for ELF flavoured files.  */
440
441 void
442 generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect,
443                                           enum gdb_osabi *osabi)
444 {
445   const char *name;
446   unsigned int sectsize;
447   char *note;
448
449   name = bfd_section_name (sect);
450   sectsize = bfd_section_size (sect);
451
452   /* Limit the amount of data to read.  */
453   if (sectsize > MAX_NOTESZ)
454     sectsize = MAX_NOTESZ;
455
456   /* We lazily read the section data here.  Since we use
457      BFD_DECOMPRESS, we can't use bfd_get_section_contents on a
458      compressed section.  But, since note sections are not compressed,
459      deferring the reading until we recognize the section avoids any
460      error.  */
461   note = (char *) alloca (sectsize);
462
463   /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD.  */
464   if (strcmp (name, ".note.ABI-tag") == 0)
465     {
466       /* GNU.  */
467       if (check_note (abfd, sect, note, &sectsize, "GNU", 16, NT_GNU_ABI_TAG))
468         {
469           unsigned int abi_tag = bfd_h_get_32 (abfd, note + 16);
470
471           switch (abi_tag)
472             {
473             case GNU_ABI_TAG_LINUX:
474               *osabi = GDB_OSABI_LINUX;
475               break;
476
477             case GNU_ABI_TAG_HURD:
478               *osabi = GDB_OSABI_HURD;
479               break;
480
481             case GNU_ABI_TAG_SOLARIS:
482               *osabi = GDB_OSABI_SOLARIS;
483               break;
484
485             case GNU_ABI_TAG_FREEBSD:
486               *osabi = GDB_OSABI_FREEBSD;
487               break;
488
489             case GNU_ABI_TAG_NETBSD:
490               *osabi = GDB_OSABI_NETBSD;
491               break;
492
493             default:
494               warning (_("GNU ABI tag value %u unrecognized."), abi_tag);
495               break;
496             }
497           return;
498         }
499
500       /* FreeBSD.  */
501       if (check_note (abfd, sect, note, &sectsize, "FreeBSD", 4,
502                       NT_FREEBSD_ABI_TAG))
503         {
504           /* There is no need to check the version yet.  */
505           *osabi = GDB_OSABI_FREEBSD;
506           return;
507         }
508
509       return;
510     }
511
512   /* .note.netbsd.ident notes, used by NetBSD.  */
513   if (strcmp (name, ".note.netbsd.ident") == 0
514       && check_note (abfd, sect, note, &sectsize, "NetBSD", 4, NT_NETBSD_IDENT))
515     {
516       /* There is no need to check the version yet.  */
517       *osabi = GDB_OSABI_NETBSD;
518       return;
519     }
520
521   /* .note.openbsd.ident notes, used by OpenBSD.  */
522   if (strcmp (name, ".note.openbsd.ident") == 0
523       && check_note (abfd, sect, note, &sectsize, "OpenBSD", 4,
524                      NT_OPENBSD_IDENT))
525     {
526       /* There is no need to check the version yet.  */
527       *osabi = GDB_OSABI_OPENBSD;
528       return;
529     }
530
531   /* .note.netbsdcore.procinfo notes, used by NetBSD.  */
532   if (strcmp (name, ".note.netbsdcore.procinfo") == 0)
533     {
534       *osabi = GDB_OSABI_NETBSD;
535       return;
536     }
537 }
538
539 static enum gdb_osabi
540 generic_elf_osabi_sniffer (bfd *abfd)
541 {
542   unsigned int elfosabi;
543   enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
544
545   elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
546
547   switch (elfosabi)
548     {
549     case ELFOSABI_NONE:
550     case ELFOSABI_GNU:
551     case ELFOSABI_HPUX:
552       /* When the EI_OSABI field in the ELF header is ELFOSABI_NONE
553          (0), then the ELF structures in the file are conforming to
554          the base specification for that machine (there are no
555          OS-specific extensions).  In order to determine the real OS
556          in use, we must look for OS-specific notes.
557
558          The same applies for ELFOSABI_GNU: this can mean GNU/Hurd,
559          GNU/Linux, and possibly more.  */
560
561       /* And likewise ELFOSABI_HPUX.  For some reason the default
562          value for the EI_OSABI field is ELFOSABI_HPUX for all PA-RISC
563          targets (with the exception of GNU/Linux).  */
564       for (asection *sect : gdb_bfd_sections (abfd))
565         generic_elf_osabi_sniff_abi_tag_sections (abfd, sect, &osabi);
566       break;
567
568     case ELFOSABI_FREEBSD:
569       osabi = GDB_OSABI_FREEBSD;
570       break;
571
572     case ELFOSABI_NETBSD:
573       osabi = GDB_OSABI_NETBSD;
574       break;
575
576     case ELFOSABI_SOLARIS:
577       osabi = GDB_OSABI_SOLARIS;
578       break;
579
580     case ELFOSABI_OPENVMS:
581       osabi = GDB_OSABI_OPENVMS;
582       break;
583     }
584
585   if (osabi == GDB_OSABI_UNKNOWN)
586     {
587       /* The FreeBSD folks have been naughty; they stored the string
588          "FreeBSD" in the padding of the e_ident field of the ELF
589          header to "brand" their ELF binaries in FreeBSD 3.x.  */
590       if (memcmp (&elf_elfheader (abfd)->e_ident[8],
591                   "FreeBSD", sizeof ("FreeBSD")) == 0)
592         osabi = GDB_OSABI_FREEBSD;
593     }
594
595   return osabi;
596 }
597 \f
598 static void
599 set_osabi (const char *args, int from_tty, struct cmd_list_element *c)
600 {
601   if (strcmp (set_osabi_string, "auto") == 0)
602     user_osabi_state = osabi_auto;
603   else if (strcmp (set_osabi_string, "default") == 0)
604     {
605       user_selected_osabi = GDB_OSABI_DEFAULT;
606       user_osabi_state = osabi_user;
607     }
608   else
609     {
610       int i;
611
612       for (i = 1; i < GDB_OSABI_INVALID; i++)
613         {
614           enum gdb_osabi osabi = (enum gdb_osabi) i;
615
616           if (strcmp (set_osabi_string, gdbarch_osabi_name (osabi)) == 0)
617             {
618               user_selected_osabi = osabi;
619               user_osabi_state = osabi_user;
620               break;
621             }
622         }
623       if (i == GDB_OSABI_INVALID)
624         internal_error (__FILE__, __LINE__,
625                         _("Invalid OS ABI \"%s\" passed to command handler."),
626                         set_osabi_string);
627     }
628
629   /* NOTE: At some point (true multiple architectures) we'll need to be more
630      graceful here.  */
631   gdbarch_info info;
632   if (! gdbarch_update_p (info))
633     internal_error (__FILE__, __LINE__, _("Updating OS ABI failed."));
634 }
635
636 static void
637 show_osabi (struct ui_file *file, int from_tty, struct cmd_list_element *c,
638             const char *value)
639 {
640   if (user_osabi_state == osabi_auto)
641     fprintf_filtered (file,
642                       _("The current OS ABI is \"auto\" "
643                         "(currently \"%s\").\n"),
644                       gdbarch_osabi_name (gdbarch_osabi (get_current_arch ())));
645   else
646     fprintf_filtered (file, _("The current OS ABI is \"%s\".\n"),
647                       gdbarch_osabi_name (user_selected_osabi));
648
649   if (GDB_OSABI_DEFAULT != GDB_OSABI_UNKNOWN)
650     fprintf_filtered (file, _("The default OS ABI is \"%s\".\n"),
651                       gdbarch_osabi_name (GDB_OSABI_DEFAULT));
652 }
653
654 void _initialize_gdb_osabi ();
655 void
656 _initialize_gdb_osabi ()
657 {
658   if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID].pretty, "<invalid>") != 0)
659     internal_error
660       (__FILE__, __LINE__,
661        _("_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent"));
662
663   /* Register a generic sniffer for ELF flavoured files.  */
664   gdbarch_register_osabi_sniffer (bfd_arch_unknown,
665                                   bfd_target_elf_flavour,
666                                   generic_elf_osabi_sniffer);
667
668   /* Register the "set osabi" command.  */
669   user_osabi_state = osabi_auto;
670   set_osabi_string = gdb_osabi_available_names[0];
671   gdb_assert (strcmp (set_osabi_string, "auto") == 0);
672   add_setshow_enum_cmd ("osabi", class_support, gdb_osabi_available_names,
673                         &set_osabi_string,
674                         _("Set OS ABI of target."),
675                         _("Show OS ABI of target."),
676                         NULL, set_osabi, show_osabi,
677                         &setlist, &showlist);
678 }
This page took 0.064089 seconds and 4 git commands to generate.