manual copyright year range of various GDB files to add 2023
[binutils-gdb.git] / binutils / rdcoff.c
blob50e19a757afd2141c8526e2b1d4fc6f8a2657958
1 /* stabs.c -- Parse COFF debugging information
2 Copyright (C) 1996-2023 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor <ian@cygnus.com>.
5 This file is part of GNU Binutils.
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.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 /* This file contains code which parses COFF debugging information. */
24 #include "sysdep.h"
25 #include "bfd.h"
26 #include "coff/internal.h"
27 #include "libiberty.h"
28 #include "bucomm.h"
29 #include "debug.h"
30 #include "budbg.h"
32 /* FIXME: We should not need this BFD internal file. We need it for
33 the N_BTMASK, etc., values. */
34 #include "libcoff.h"
36 /* These macros extract the right mask and shifts for this BFD. They
37 assume that there is a local variable named ABFD. This is so that
38 macros like ISFCN and DECREF, from coff/internal.h, will work
39 without modification. */
40 #define N_BTMASK (coff_data (abfd)->local_n_btmask)
41 #define N_BTSHFT (coff_data (abfd)->local_n_btshft)
42 #define N_TMASK (coff_data (abfd)->local_n_tmask)
43 #define N_TSHIFT (coff_data (abfd)->local_n_tshift)
45 /* This structure is used to hold the symbols, as well as the current
46 location within the symbols. */
48 struct coff_symbols
50 /* The symbols. */
51 asymbol **syms;
52 /* The number of symbols. */
53 long symcount;
54 /* The index of the current symbol. */
55 long symno;
56 /* The index of the current symbol in the COFF symbol table (where
57 each auxent counts as a symbol). */
58 long coff_symno;
61 /* The largest basic type we are prepared to handle. */
63 #define T_MAX (T_LNGDBL)
65 /* This structure is used to hold slots. */
67 struct coff_slots
69 /* Next set of slots. */
70 struct coff_slots *next;
71 /* Slots. */
72 #define COFF_SLOTS (16)
73 debug_type slots[COFF_SLOTS];
76 /* This structure is used to map symbol indices to types. */
78 struct coff_types
80 /* Slots. */
81 struct coff_slots *slots;
82 /* Basic types. */
83 debug_type basic[T_MAX + 1];
86 static debug_type *coff_get_slot (struct coff_types *, long);
87 static debug_type parse_coff_type
88 (bfd *, struct coff_symbols *, struct coff_types *, long, int,
89 union internal_auxent *, bool, void *);
90 static debug_type parse_coff_base_type
91 (bfd *, struct coff_symbols *, struct coff_types *, long, int,
92 union internal_auxent *, void *);
93 static debug_type parse_coff_struct_type
94 (bfd *, struct coff_symbols *, struct coff_types *, int,
95 union internal_auxent *, void *);
96 static debug_type parse_coff_enum_type
97 (bfd *, struct coff_symbols *, struct coff_types *,
98 union internal_auxent *, void *);
99 static bool parse_coff_symbol
100 (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *,
101 void *, debug_type, bool);
102 static bool external_coff_symbol_p (int sym_class);
104 /* Return the slot for a type. */
106 static debug_type *
107 coff_get_slot (struct coff_types *types, long indx)
109 struct coff_slots **pps;
111 pps = &types->slots;
113 /* PR 17512: file: 078-18333-0.001:0.1.
114 FIXME: The value of 1000 is a guess. Maybe a better heuristic is needed. */
115 if (indx / COFF_SLOTS > 1000)
116 fatal (_("Excessively large slot index: %lx"), indx);
118 while (indx >= COFF_SLOTS)
120 if (*pps == NULL)
122 *pps = (struct coff_slots *) xmalloc (sizeof **pps);
123 memset (*pps, 0, sizeof **pps);
125 pps = &(*pps)->next;
126 indx -= COFF_SLOTS;
129 if (*pps == NULL)
131 *pps = (struct coff_slots *) xmalloc (sizeof **pps);
132 memset (*pps, 0, sizeof **pps);
135 return (*pps)->slots + indx;
138 /* Parse a COFF type code in NTYPE. */
140 static debug_type
141 parse_coff_type (bfd *abfd, struct coff_symbols *symbols,
142 struct coff_types *types, long coff_symno, int ntype,
143 union internal_auxent *pauxent, bool useaux,
144 void *dhandle)
146 debug_type type;
148 if ((ntype & ~N_BTMASK) != 0)
150 int newtype;
152 newtype = DECREF (ntype);
154 if (ISPTR (ntype))
156 type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
157 pauxent, useaux, dhandle);
158 type = debug_make_pointer_type (dhandle, type);
160 else if (ISFCN (ntype))
162 type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
163 pauxent, useaux, dhandle);
164 type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
165 false);
167 else if (ISARY (ntype))
169 int n;
171 if (pauxent == NULL)
172 n = 0;
173 else
175 unsigned short *dim;
176 int i;
178 /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
179 the c_naux field of the syment to 0. */
181 /* Move the dimensions down, so that the next array
182 picks up the next one. */
183 dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
184 n = dim[0];
185 for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
186 *dim = *(dim + 1);
187 *dim = 0;
190 type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
191 pauxent, false, dhandle);
192 type = debug_make_array_type (dhandle, type,
193 parse_coff_base_type (abfd, symbols,
194 types,
195 coff_symno,
196 T_INT,
197 NULL, dhandle),
198 0, n - 1, false);
200 else
202 non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype);
203 return DEBUG_TYPE_NULL;
206 return type;
209 if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
211 debug_type *slot;
213 /* This is a reference to an existing type. FIXME: gdb checks
214 that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */
215 slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
216 if (*slot != DEBUG_TYPE_NULL)
217 return *slot;
218 else
219 return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
222 /* If the aux entry has already been used for something, useaux will
223 have been set to false, indicating that parse_coff_base_type
224 should not use it. We need to do it this way, rather than simply
225 passing pauxent as NULL, because we need to be able handle
226 multiple array dimensions while still discarding pauxent after
227 having handled all of them. */
228 if (! useaux)
229 pauxent = NULL;
231 return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
232 pauxent, dhandle);
235 /* Parse a basic COFF type in NTYPE. */
237 static debug_type
238 parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols,
239 struct coff_types *types, long coff_symno, int ntype,
240 union internal_auxent *pauxent, void *dhandle)
242 debug_type ret;
243 bool set_basic;
244 const char *name;
245 debug_type *slot;
247 if (ntype >= 0
248 && ntype <= T_MAX
249 && types->basic[ntype] != DEBUG_TYPE_NULL)
250 return types->basic[ntype];
252 set_basic = true;
253 name = NULL;
255 switch (ntype)
257 default:
258 ret = debug_make_void_type (dhandle);
259 break;
261 case T_NULL:
262 case T_VOID:
263 ret = debug_make_void_type (dhandle);
264 name = "void";
265 break;
267 case T_CHAR:
268 ret = debug_make_int_type (dhandle, 1, false);
269 name = "char";
270 break;
272 case T_SHORT:
273 ret = debug_make_int_type (dhandle, 2, false);
274 name = "short";
275 break;
277 case T_INT:
278 /* FIXME: Perhaps the size should depend upon the architecture. */
279 ret = debug_make_int_type (dhandle, 4, false);
280 name = "int";
281 break;
283 case T_LONG:
284 ret = debug_make_int_type (dhandle, 4, false);
285 name = "long";
286 break;
288 case T_FLOAT:
289 ret = debug_make_float_type (dhandle, 4);
290 name = "float";
291 break;
293 case T_DOUBLE:
294 ret = debug_make_float_type (dhandle, 8);
295 name = "double";
296 break;
298 case T_LNGDBL:
299 ret = debug_make_float_type (dhandle, 12);
300 name = "long double";
301 break;
303 case T_UCHAR:
304 ret = debug_make_int_type (dhandle, 1, true);
305 name = "unsigned char";
306 break;
308 case T_USHORT:
309 ret = debug_make_int_type (dhandle, 2, true);
310 name = "unsigned short";
311 break;
313 case T_UINT:
314 ret = debug_make_int_type (dhandle, 4, true);
315 name = "unsigned int";
316 break;
318 case T_ULONG:
319 ret = debug_make_int_type (dhandle, 4, true);
320 name = "unsigned long";
321 break;
323 case T_STRUCT:
324 if (pauxent == NULL)
325 ret = debug_make_struct_type (dhandle, true, 0,
326 (debug_field *) NULL);
327 else
328 ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
329 dhandle);
331 slot = coff_get_slot (types, coff_symno);
332 *slot = ret;
334 set_basic = false;
335 break;
337 case T_UNION:
338 if (pauxent == NULL)
339 ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL);
340 else
341 ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
342 dhandle);
344 slot = coff_get_slot (types, coff_symno);
345 *slot = ret;
347 set_basic = false;
348 break;
350 case T_ENUM:
351 if (pauxent == NULL)
352 ret = debug_make_enum_type (dhandle, (const char **) NULL,
353 (bfd_signed_vma *) NULL);
354 else
355 ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
357 slot = coff_get_slot (types, coff_symno);
358 *slot = ret;
360 set_basic = false;
361 break;
364 if (name != NULL)
365 ret = debug_name_type (dhandle, name, ret);
367 if (set_basic
368 && ntype >= 0
369 && ntype <= T_MAX)
370 types->basic[ntype] = ret;
372 return ret;
375 /* Parse a struct type. */
377 static debug_type
378 parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols,
379 struct coff_types *types, int ntype,
380 union internal_auxent *pauxent, void *dhandle)
382 long symend;
383 int alloc;
384 debug_field *fields;
385 int count;
386 bool done;
388 symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
390 alloc = 10;
391 fields = (debug_field *) xmalloc (alloc * sizeof *fields);
392 count = 0;
394 done = false;
395 while (! done
396 && symbols->coff_symno < symend
397 && symbols->symno < symbols->symcount)
399 asymbol *sym;
400 long this_coff_symno;
401 struct internal_syment syment;
402 union internal_auxent auxent;
403 union internal_auxent *psubaux;
404 bfd_vma bitpos = 0, bitsize = 0;
406 sym = symbols->syms[symbols->symno];
408 if (! bfd_coff_get_syment (abfd, sym, &syment))
410 non_fatal (_("bfd_coff_get_syment failed: %s"),
411 bfd_errmsg (bfd_get_error ()));
412 free (fields);
413 return DEBUG_TYPE_NULL;
416 this_coff_symno = symbols->coff_symno;
418 ++symbols->symno;
419 symbols->coff_symno += 1 + syment.n_numaux;
421 if (syment.n_numaux == 0)
422 psubaux = NULL;
423 else
425 if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
427 non_fatal (_("bfd_coff_get_auxent failed: %s"),
428 bfd_errmsg (bfd_get_error ()));
429 free (fields);
430 return DEBUG_TYPE_NULL;
432 psubaux = &auxent;
435 switch (syment.n_sclass)
437 case C_MOS:
438 case C_MOU:
439 bitpos = 8 * bfd_asymbol_value (sym);
440 bitsize = 0;
441 break;
443 case C_FIELD:
444 bitpos = bfd_asymbol_value (sym);
445 bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
446 break;
448 case C_EOS:
449 done = true;
450 break;
453 if (! done)
455 debug_type ftype;
456 debug_field f;
458 ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
459 syment.n_type, psubaux, true, dhandle);
460 f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
461 bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
462 if (f == DEBUG_FIELD_NULL)
463 return DEBUG_TYPE_NULL;
465 if (count + 1 >= alloc)
467 alloc += 10;
468 fields = ((debug_field *)
469 xrealloc (fields, alloc * sizeof *fields));
472 fields[count] = f;
473 ++count;
477 fields[count] = DEBUG_FIELD_NULL;
479 return debug_make_struct_type (dhandle, ntype == T_STRUCT,
480 pauxent->x_sym.x_misc.x_lnsz.x_size,
481 fields);
484 /* Parse an enum type. */
486 static debug_type
487 parse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols,
488 struct coff_types *types ATTRIBUTE_UNUSED,
489 union internal_auxent *pauxent, void *dhandle)
491 long symend;
492 int alloc;
493 const char **names;
494 bfd_signed_vma *vals;
495 int count;
496 bool done;
498 symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
500 alloc = 10;
501 names = (const char **) xmalloc (alloc * sizeof *names);
502 vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
503 count = 0;
505 done = false;
506 while (! done
507 && symbols->coff_symno < symend
508 && symbols->symno < symbols->symcount)
510 asymbol *sym;
511 struct internal_syment syment;
513 sym = symbols->syms[symbols->symno];
515 if (! bfd_coff_get_syment (abfd, sym, &syment))
517 non_fatal (_("bfd_coff_get_syment failed: %s"),
518 bfd_errmsg (bfd_get_error ()));
519 free (names);
520 free (vals);
521 return DEBUG_TYPE_NULL;
524 ++symbols->symno;
525 symbols->coff_symno += 1 + syment.n_numaux;
527 switch (syment.n_sclass)
529 case C_MOE:
530 if (count + 1 >= alloc)
532 alloc += 10;
533 names = ((const char **)
534 xrealloc (names, alloc * sizeof *names));
535 vals = ((bfd_signed_vma *)
536 xrealloc (vals, alloc * sizeof *vals));
539 names[count] = bfd_asymbol_name (sym);
540 vals[count] = bfd_asymbol_value (sym);
541 ++count;
542 break;
544 case C_EOS:
545 done = true;
546 break;
550 names[count] = NULL;
552 return debug_make_enum_type (dhandle, names, vals);
555 /* Handle a single COFF symbol. */
557 static bool
558 parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types,
559 asymbol *sym, long coff_symno,
560 struct internal_syment *psyment, void *dhandle,
561 debug_type type, bool within_function)
563 switch (psyment->n_sclass)
565 case C_NULL:
566 break;
568 case C_AUTO:
569 if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
570 DEBUG_LOCAL, bfd_asymbol_value (sym)))
571 return false;
572 break;
574 case C_WEAKEXT:
575 case C_EXT:
576 if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
577 DEBUG_GLOBAL, bfd_asymbol_value (sym)))
578 return false;
579 break;
581 case C_STAT:
582 if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
583 (within_function
584 ? DEBUG_LOCAL_STATIC
585 : DEBUG_STATIC),
586 bfd_asymbol_value (sym)))
587 return false;
588 break;
590 case C_REG:
591 /* FIXME: We may need to convert the register number. */
592 if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
593 DEBUG_REGISTER, bfd_asymbol_value (sym)))
594 return false;
595 break;
597 case C_LABEL:
598 break;
600 case C_ARG:
601 if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
602 DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
603 return false;
604 break;
606 case C_REGPARM:
607 /* FIXME: We may need to convert the register number. */
608 if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
609 DEBUG_PARM_REG, bfd_asymbol_value (sym)))
610 return false;
611 break;
613 case C_TPDEF:
614 type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
615 if (type == DEBUG_TYPE_NULL)
616 return false;
617 break;
619 case C_STRTAG:
620 case C_UNTAG:
621 case C_ENTAG:
623 debug_type *slot;
625 type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
626 if (type == DEBUG_TYPE_NULL)
627 return false;
629 /* Store the named type into the slot, so that references get
630 the name. */
631 slot = coff_get_slot (types, coff_symno);
632 *slot = type;
634 break;
636 default:
637 break;
640 return true;
643 /* Determine if a symbol has external visibility. */
645 static bool
646 external_coff_symbol_p (int sym_class)
648 switch (sym_class)
650 case C_EXT:
651 case C_WEAKEXT:
652 return true;
653 default:
654 break;
656 return false;
659 /* This is the main routine. It looks through all the symbols and
660 handles them. */
662 bool
663 parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle)
665 struct coff_symbols symbols;
666 struct coff_types types;
667 int i;
668 long next_c_file;
669 const char *fnname;
670 int fnclass;
671 int fntype;
672 bfd_vma fnend;
673 alent *linenos;
674 bool within_function;
675 long this_coff_symno;
677 symbols.syms = syms;
678 symbols.symcount = symcount;
679 symbols.symno = 0;
680 symbols.coff_symno = 0;
682 types.slots = NULL;
683 for (i = 0; i <= T_MAX; i++)
684 types.basic[i] = DEBUG_TYPE_NULL;
686 next_c_file = -1;
687 fnname = NULL;
688 fnclass = 0;
689 fntype = 0;
690 fnend = 0;
691 linenos = NULL;
692 within_function = false;
694 while (symbols.symno < symcount)
696 asymbol *sym;
697 const char *name;
698 struct internal_syment syment;
699 union internal_auxent auxent;
700 union internal_auxent *paux;
701 debug_type type;
703 sym = syms[symbols.symno];
705 if (! bfd_coff_get_syment (abfd, sym, &syment))
707 non_fatal (_("bfd_coff_get_syment failed: %s"),
708 bfd_errmsg (bfd_get_error ()));
709 return false;
712 name = bfd_asymbol_name (sym);
714 this_coff_symno = symbols.coff_symno;
716 ++symbols.symno;
717 symbols.coff_symno += 1 + syment.n_numaux;
719 /* We only worry about the first auxent, because that is the
720 only one which is relevant for debugging information. */
721 if (syment.n_numaux == 0)
722 paux = NULL;
723 else
725 if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
727 non_fatal (_("bfd_coff_get_auxent failed: %s"),
728 bfd_errmsg (bfd_get_error ()));
729 return false;
731 paux = &auxent;
734 if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
736 /* The last C_FILE symbol points to the first external
737 symbol. */
738 if (! debug_set_filename (dhandle, "*globals*"))
739 return false;
742 switch (syment.n_sclass)
744 case C_EFCN:
745 case C_EXTDEF:
746 case C_ULABEL:
747 case C_USTATIC:
748 case C_LINE:
749 case C_ALIAS:
750 case C_HIDDEN:
751 /* Just ignore these classes. */
752 break;
754 case C_FILE:
755 next_c_file = syment.n_value;
756 if (! debug_set_filename (dhandle, name))
757 return false;
758 break;
760 case C_STAT:
761 /* Ignore static symbols with a type of T_NULL. These
762 represent section entries. */
763 if (syment.n_type == T_NULL)
764 break;
765 /* Fall through. */
766 case C_WEAKEXT:
767 case C_EXT:
768 if (ISFCN (syment.n_type))
770 fnname = name;
771 fnclass = syment.n_sclass;
772 fntype = syment.n_type;
773 if (syment.n_numaux > 0)
774 fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
775 else
776 fnend = 0;
777 linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
778 break;
780 type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
781 syment.n_type, paux, true, dhandle);
782 if (type == DEBUG_TYPE_NULL)
783 return false;
784 if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
785 dhandle, type, within_function))
786 return false;
787 break;
789 case C_FCN:
790 if (strcmp (name, ".bf") == 0)
792 if (fnname == NULL)
794 non_fatal (_("%ld: .bf without preceding function"),
795 this_coff_symno);
796 return false;
799 type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
800 DECREF (fntype), paux, false, dhandle);
801 if (type == DEBUG_TYPE_NULL)
802 return false;
804 if (! debug_record_function (dhandle, fnname, type,
805 external_coff_symbol_p (fnclass),
806 bfd_asymbol_value (sym)))
807 return false;
809 if (linenos != NULL)
811 int base;
812 bfd_vma addr;
814 if (syment.n_numaux == 0)
815 base = 0;
816 else
817 base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
819 addr = bfd_section_vma (bfd_asymbol_section (sym));
821 ++linenos;
823 while (linenos->line_number != 0)
825 if (! debug_record_line (dhandle,
826 linenos->line_number + base,
827 linenos->u.offset + addr))
828 return false;
829 ++linenos;
833 fnname = NULL;
834 linenos = NULL;
835 fnclass = 0;
836 fntype = 0;
838 within_function = true;
840 else if (strcmp (name, ".ef") == 0)
842 if (! within_function)
844 non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno);
845 return false;
848 if (bfd_asymbol_value (sym) > fnend)
849 fnend = bfd_asymbol_value (sym);
850 if (! debug_end_function (dhandle, fnend))
851 return false;
853 fnend = 0;
854 within_function = false;
856 break;
858 case C_BLOCK:
859 if (strcmp (name, ".bb") == 0)
861 if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
862 return false;
864 else if (strcmp (name, ".eb") == 0)
866 if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
867 return false;
869 break;
871 default:
872 type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
873 syment.n_type, paux, true, dhandle);
874 if (type == DEBUG_TYPE_NULL)
875 return false;
876 if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
877 dhandle, type, within_function))
878 return false;
879 break;
883 return true;