1*a9fa9459Szrj /* stabs.c -- Parse COFF debugging information
2*a9fa9459Szrj Copyright (C) 1996-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj Written by Ian Lance Taylor <ian@cygnus.com>.
4*a9fa9459Szrj
5*a9fa9459Szrj This file is part of GNU Binutils.
6*a9fa9459Szrj
7*a9fa9459Szrj This program is free software; you can redistribute it and/or modify
8*a9fa9459Szrj it under the terms of the GNU General Public License as published by
9*a9fa9459Szrj the Free Software Foundation; either version 3 of the License, or
10*a9fa9459Szrj (at your option) any later version.
11*a9fa9459Szrj
12*a9fa9459Szrj This program is distributed in the hope that it will be useful,
13*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
14*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*a9fa9459Szrj GNU General Public License for more details.
16*a9fa9459Szrj
17*a9fa9459Szrj You should have received a copy of the GNU General Public License
18*a9fa9459Szrj along with this program; if not, write to the Free Software
19*a9fa9459Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20*a9fa9459Szrj 02110-1301, USA. */
21*a9fa9459Szrj
22*a9fa9459Szrj /* This file contains code which parses COFF debugging information. */
23*a9fa9459Szrj
24*a9fa9459Szrj #include "sysdep.h"
25*a9fa9459Szrj #include "bfd.h"
26*a9fa9459Szrj #include "coff/internal.h"
27*a9fa9459Szrj #include "libiberty.h"
28*a9fa9459Szrj #include "bucomm.h"
29*a9fa9459Szrj #include "debug.h"
30*a9fa9459Szrj #include "budbg.h"
31*a9fa9459Szrj
32*a9fa9459Szrj /* FIXME: We should not need this BFD internal file. We need it for
33*a9fa9459Szrj the N_BTMASK, etc., values. */
34*a9fa9459Szrj #include "libcoff.h"
35*a9fa9459Szrj
36*a9fa9459Szrj /* These macros extract the right mask and shifts for this BFD. They
37*a9fa9459Szrj assume that there is a local variable named ABFD. This is so that
38*a9fa9459Szrj macros like ISFCN and DECREF, from coff/internal.h, will work
39*a9fa9459Szrj without modification. */
40*a9fa9459Szrj #define N_BTMASK (coff_data (abfd)->local_n_btmask)
41*a9fa9459Szrj #define N_BTSHFT (coff_data (abfd)->local_n_btshft)
42*a9fa9459Szrj #define N_TMASK (coff_data (abfd)->local_n_tmask)
43*a9fa9459Szrj #define N_TSHIFT (coff_data (abfd)->local_n_tshift)
44*a9fa9459Szrj
45*a9fa9459Szrj /* This structure is used to hold the symbols, as well as the current
46*a9fa9459Szrj location within the symbols. */
47*a9fa9459Szrj
48*a9fa9459Szrj struct coff_symbols
49*a9fa9459Szrj {
50*a9fa9459Szrj /* The symbols. */
51*a9fa9459Szrj asymbol **syms;
52*a9fa9459Szrj /* The number of symbols. */
53*a9fa9459Szrj long symcount;
54*a9fa9459Szrj /* The index of the current symbol. */
55*a9fa9459Szrj long symno;
56*a9fa9459Szrj /* The index of the current symbol in the COFF symbol table (where
57*a9fa9459Szrj each auxent counts as a symbol). */
58*a9fa9459Szrj long coff_symno;
59*a9fa9459Szrj };
60*a9fa9459Szrj
61*a9fa9459Szrj /* The largest basic type we are prepared to handle. */
62*a9fa9459Szrj
63*a9fa9459Szrj #define T_MAX (T_LNGDBL)
64*a9fa9459Szrj
65*a9fa9459Szrj /* This structure is used to hold slots. */
66*a9fa9459Szrj
67*a9fa9459Szrj struct coff_slots
68*a9fa9459Szrj {
69*a9fa9459Szrj /* Next set of slots. */
70*a9fa9459Szrj struct coff_slots *next;
71*a9fa9459Szrj /* Slots. */
72*a9fa9459Szrj #define COFF_SLOTS (16)
73*a9fa9459Szrj debug_type slots[COFF_SLOTS];
74*a9fa9459Szrj };
75*a9fa9459Szrj
76*a9fa9459Szrj /* This structure is used to map symbol indices to types. */
77*a9fa9459Szrj
78*a9fa9459Szrj struct coff_types
79*a9fa9459Szrj {
80*a9fa9459Szrj /* Slots. */
81*a9fa9459Szrj struct coff_slots *slots;
82*a9fa9459Szrj /* Basic types. */
83*a9fa9459Szrj debug_type basic[T_MAX + 1];
84*a9fa9459Szrj };
85*a9fa9459Szrj
86*a9fa9459Szrj static debug_type *coff_get_slot (struct coff_types *, long);
87*a9fa9459Szrj static debug_type parse_coff_type
88*a9fa9459Szrj (bfd *, struct coff_symbols *, struct coff_types *, long, int,
89*a9fa9459Szrj union internal_auxent *, bfd_boolean, void *);
90*a9fa9459Szrj static debug_type parse_coff_base_type
91*a9fa9459Szrj (bfd *, struct coff_symbols *, struct coff_types *, long, int,
92*a9fa9459Szrj union internal_auxent *, void *);
93*a9fa9459Szrj static debug_type parse_coff_struct_type
94*a9fa9459Szrj (bfd *, struct coff_symbols *, struct coff_types *, int,
95*a9fa9459Szrj union internal_auxent *, void *);
96*a9fa9459Szrj static debug_type parse_coff_enum_type
97*a9fa9459Szrj (bfd *, struct coff_symbols *, struct coff_types *,
98*a9fa9459Szrj union internal_auxent *, void *);
99*a9fa9459Szrj static bfd_boolean parse_coff_symbol
100*a9fa9459Szrj (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *,
101*a9fa9459Szrj void *, debug_type, bfd_boolean);
102*a9fa9459Szrj static bfd_boolean external_coff_symbol_p (int sym_class);
103*a9fa9459Szrj
104*a9fa9459Szrj /* Return the slot for a type. */
105*a9fa9459Szrj
106*a9fa9459Szrj static debug_type *
coff_get_slot(struct coff_types * types,long indx)107*a9fa9459Szrj coff_get_slot (struct coff_types *types, long indx)
108*a9fa9459Szrj {
109*a9fa9459Szrj struct coff_slots **pps;
110*a9fa9459Szrj
111*a9fa9459Szrj pps = &types->slots;
112*a9fa9459Szrj
113*a9fa9459Szrj /* PR 17512: file: 078-18333-0.001:0.1.
114*a9fa9459Szrj FIXME: The value of 1000 is a guess. Maybe a better heuristic is needed. */
115*a9fa9459Szrj if (indx / COFF_SLOTS > 1000)
116*a9fa9459Szrj fatal (_("Excessively large slot index: %lx"), indx);
117*a9fa9459Szrj
118*a9fa9459Szrj while (indx >= COFF_SLOTS)
119*a9fa9459Szrj {
120*a9fa9459Szrj if (*pps == NULL)
121*a9fa9459Szrj {
122*a9fa9459Szrj *pps = (struct coff_slots *) xmalloc (sizeof **pps);
123*a9fa9459Szrj memset (*pps, 0, sizeof **pps);
124*a9fa9459Szrj }
125*a9fa9459Szrj pps = &(*pps)->next;
126*a9fa9459Szrj indx -= COFF_SLOTS;
127*a9fa9459Szrj }
128*a9fa9459Szrj
129*a9fa9459Szrj if (*pps == NULL)
130*a9fa9459Szrj {
131*a9fa9459Szrj *pps = (struct coff_slots *) xmalloc (sizeof **pps);
132*a9fa9459Szrj memset (*pps, 0, sizeof **pps);
133*a9fa9459Szrj }
134*a9fa9459Szrj
135*a9fa9459Szrj return (*pps)->slots + indx;
136*a9fa9459Szrj }
137*a9fa9459Szrj
138*a9fa9459Szrj /* Parse a COFF type code in NTYPE. */
139*a9fa9459Szrj
140*a9fa9459Szrj static debug_type
parse_coff_type(bfd * abfd,struct coff_symbols * symbols,struct coff_types * types,long coff_symno,int ntype,union internal_auxent * pauxent,bfd_boolean useaux,void * dhandle)141*a9fa9459Szrj parse_coff_type (bfd *abfd, struct coff_symbols *symbols,
142*a9fa9459Szrj struct coff_types *types, long coff_symno, int ntype,
143*a9fa9459Szrj union internal_auxent *pauxent, bfd_boolean useaux,
144*a9fa9459Szrj void *dhandle)
145*a9fa9459Szrj {
146*a9fa9459Szrj debug_type type;
147*a9fa9459Szrj
148*a9fa9459Szrj if ((ntype & ~N_BTMASK) != 0)
149*a9fa9459Szrj {
150*a9fa9459Szrj int newtype;
151*a9fa9459Szrj
152*a9fa9459Szrj newtype = DECREF (ntype);
153*a9fa9459Szrj
154*a9fa9459Szrj if (ISPTR (ntype))
155*a9fa9459Szrj {
156*a9fa9459Szrj type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
157*a9fa9459Szrj pauxent, useaux, dhandle);
158*a9fa9459Szrj type = debug_make_pointer_type (dhandle, type);
159*a9fa9459Szrj }
160*a9fa9459Szrj else if (ISFCN (ntype))
161*a9fa9459Szrj {
162*a9fa9459Szrj type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
163*a9fa9459Szrj pauxent, useaux, dhandle);
164*a9fa9459Szrj type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
165*a9fa9459Szrj FALSE);
166*a9fa9459Szrj }
167*a9fa9459Szrj else if (ISARY (ntype))
168*a9fa9459Szrj {
169*a9fa9459Szrj int n;
170*a9fa9459Szrj
171*a9fa9459Szrj if (pauxent == NULL)
172*a9fa9459Szrj n = 0;
173*a9fa9459Szrj else
174*a9fa9459Szrj {
175*a9fa9459Szrj unsigned short *dim;
176*a9fa9459Szrj int i;
177*a9fa9459Szrj
178*a9fa9459Szrj /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
179*a9fa9459Szrj the c_naux field of the syment to 0. */
180*a9fa9459Szrj
181*a9fa9459Szrj /* Move the dimensions down, so that the next array
182*a9fa9459Szrj picks up the next one. */
183*a9fa9459Szrj dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
184*a9fa9459Szrj n = dim[0];
185*a9fa9459Szrj for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
186*a9fa9459Szrj *dim = *(dim + 1);
187*a9fa9459Szrj *dim = 0;
188*a9fa9459Szrj }
189*a9fa9459Szrj
190*a9fa9459Szrj type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
191*a9fa9459Szrj pauxent, FALSE, dhandle);
192*a9fa9459Szrj type = debug_make_array_type (dhandle, type,
193*a9fa9459Szrj parse_coff_base_type (abfd, symbols,
194*a9fa9459Szrj types,
195*a9fa9459Szrj coff_symno,
196*a9fa9459Szrj T_INT,
197*a9fa9459Szrj NULL, dhandle),
198*a9fa9459Szrj 0, n - 1, FALSE);
199*a9fa9459Szrj }
200*a9fa9459Szrj else
201*a9fa9459Szrj {
202*a9fa9459Szrj non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype);
203*a9fa9459Szrj return DEBUG_TYPE_NULL;
204*a9fa9459Szrj }
205*a9fa9459Szrj
206*a9fa9459Szrj return type;
207*a9fa9459Szrj }
208*a9fa9459Szrj
209*a9fa9459Szrj if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
210*a9fa9459Szrj {
211*a9fa9459Szrj debug_type *slot;
212*a9fa9459Szrj
213*a9fa9459Szrj /* This is a reference to an existing type. FIXME: gdb checks
214*a9fa9459Szrj that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */
215*a9fa9459Szrj slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
216*a9fa9459Szrj if (*slot != DEBUG_TYPE_NULL)
217*a9fa9459Szrj return *slot;
218*a9fa9459Szrj else
219*a9fa9459Szrj return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
220*a9fa9459Szrj }
221*a9fa9459Szrj
222*a9fa9459Szrj /* If the aux entry has already been used for something, useaux will
223*a9fa9459Szrj have been set to false, indicating that parse_coff_base_type
224*a9fa9459Szrj should not use it. We need to do it this way, rather than simply
225*a9fa9459Szrj passing pauxent as NULL, because we need to be able handle
226*a9fa9459Szrj multiple array dimensions while still discarding pauxent after
227*a9fa9459Szrj having handled all of them. */
228*a9fa9459Szrj if (! useaux)
229*a9fa9459Szrj pauxent = NULL;
230*a9fa9459Szrj
231*a9fa9459Szrj return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
232*a9fa9459Szrj pauxent, dhandle);
233*a9fa9459Szrj }
234*a9fa9459Szrj
235*a9fa9459Szrj /* Parse a basic COFF type in NTYPE. */
236*a9fa9459Szrj
237*a9fa9459Szrj static debug_type
parse_coff_base_type(bfd * abfd,struct coff_symbols * symbols,struct coff_types * types,long coff_symno,int ntype,union internal_auxent * pauxent,void * dhandle)238*a9fa9459Szrj parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols,
239*a9fa9459Szrj struct coff_types *types, long coff_symno, int ntype,
240*a9fa9459Szrj union internal_auxent *pauxent, void *dhandle)
241*a9fa9459Szrj {
242*a9fa9459Szrj debug_type ret;
243*a9fa9459Szrj bfd_boolean set_basic;
244*a9fa9459Szrj const char *name;
245*a9fa9459Szrj debug_type *slot;
246*a9fa9459Szrj
247*a9fa9459Szrj if (ntype >= 0
248*a9fa9459Szrj && ntype <= T_MAX
249*a9fa9459Szrj && types->basic[ntype] != DEBUG_TYPE_NULL)
250*a9fa9459Szrj return types->basic[ntype];
251*a9fa9459Szrj
252*a9fa9459Szrj set_basic = TRUE;
253*a9fa9459Szrj name = NULL;
254*a9fa9459Szrj
255*a9fa9459Szrj switch (ntype)
256*a9fa9459Szrj {
257*a9fa9459Szrj default:
258*a9fa9459Szrj ret = debug_make_void_type (dhandle);
259*a9fa9459Szrj break;
260*a9fa9459Szrj
261*a9fa9459Szrj case T_NULL:
262*a9fa9459Szrj case T_VOID:
263*a9fa9459Szrj ret = debug_make_void_type (dhandle);
264*a9fa9459Szrj name = "void";
265*a9fa9459Szrj break;
266*a9fa9459Szrj
267*a9fa9459Szrj case T_CHAR:
268*a9fa9459Szrj ret = debug_make_int_type (dhandle, 1, FALSE);
269*a9fa9459Szrj name = "char";
270*a9fa9459Szrj break;
271*a9fa9459Szrj
272*a9fa9459Szrj case T_SHORT:
273*a9fa9459Szrj ret = debug_make_int_type (dhandle, 2, FALSE);
274*a9fa9459Szrj name = "short";
275*a9fa9459Szrj break;
276*a9fa9459Szrj
277*a9fa9459Szrj case T_INT:
278*a9fa9459Szrj /* FIXME: Perhaps the size should depend upon the architecture. */
279*a9fa9459Szrj ret = debug_make_int_type (dhandle, 4, FALSE);
280*a9fa9459Szrj name = "int";
281*a9fa9459Szrj break;
282*a9fa9459Szrj
283*a9fa9459Szrj case T_LONG:
284*a9fa9459Szrj ret = debug_make_int_type (dhandle, 4, FALSE);
285*a9fa9459Szrj name = "long";
286*a9fa9459Szrj break;
287*a9fa9459Szrj
288*a9fa9459Szrj case T_FLOAT:
289*a9fa9459Szrj ret = debug_make_float_type (dhandle, 4);
290*a9fa9459Szrj name = "float";
291*a9fa9459Szrj break;
292*a9fa9459Szrj
293*a9fa9459Szrj case T_DOUBLE:
294*a9fa9459Szrj ret = debug_make_float_type (dhandle, 8);
295*a9fa9459Szrj name = "double";
296*a9fa9459Szrj break;
297*a9fa9459Szrj
298*a9fa9459Szrj case T_LNGDBL:
299*a9fa9459Szrj ret = debug_make_float_type (dhandle, 12);
300*a9fa9459Szrj name = "long double";
301*a9fa9459Szrj break;
302*a9fa9459Szrj
303*a9fa9459Szrj case T_UCHAR:
304*a9fa9459Szrj ret = debug_make_int_type (dhandle, 1, TRUE);
305*a9fa9459Szrj name = "unsigned char";
306*a9fa9459Szrj break;
307*a9fa9459Szrj
308*a9fa9459Szrj case T_USHORT:
309*a9fa9459Szrj ret = debug_make_int_type (dhandle, 2, TRUE);
310*a9fa9459Szrj name = "unsigned short";
311*a9fa9459Szrj break;
312*a9fa9459Szrj
313*a9fa9459Szrj case T_UINT:
314*a9fa9459Szrj ret = debug_make_int_type (dhandle, 4, TRUE);
315*a9fa9459Szrj name = "unsigned int";
316*a9fa9459Szrj break;
317*a9fa9459Szrj
318*a9fa9459Szrj case T_ULONG:
319*a9fa9459Szrj ret = debug_make_int_type (dhandle, 4, TRUE);
320*a9fa9459Szrj name = "unsigned long";
321*a9fa9459Szrj break;
322*a9fa9459Szrj
323*a9fa9459Szrj case T_STRUCT:
324*a9fa9459Szrj if (pauxent == NULL)
325*a9fa9459Szrj ret = debug_make_struct_type (dhandle, TRUE, 0,
326*a9fa9459Szrj (debug_field *) NULL);
327*a9fa9459Szrj else
328*a9fa9459Szrj ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
329*a9fa9459Szrj dhandle);
330*a9fa9459Szrj
331*a9fa9459Szrj slot = coff_get_slot (types, coff_symno);
332*a9fa9459Szrj *slot = ret;
333*a9fa9459Szrj
334*a9fa9459Szrj set_basic = FALSE;
335*a9fa9459Szrj break;
336*a9fa9459Szrj
337*a9fa9459Szrj case T_UNION:
338*a9fa9459Szrj if (pauxent == NULL)
339*a9fa9459Szrj ret = debug_make_struct_type (dhandle, FALSE, 0, (debug_field *) NULL);
340*a9fa9459Szrj else
341*a9fa9459Szrj ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
342*a9fa9459Szrj dhandle);
343*a9fa9459Szrj
344*a9fa9459Szrj slot = coff_get_slot (types, coff_symno);
345*a9fa9459Szrj *slot = ret;
346*a9fa9459Szrj
347*a9fa9459Szrj set_basic = FALSE;
348*a9fa9459Szrj break;
349*a9fa9459Szrj
350*a9fa9459Szrj case T_ENUM:
351*a9fa9459Szrj if (pauxent == NULL)
352*a9fa9459Szrj ret = debug_make_enum_type (dhandle, (const char **) NULL,
353*a9fa9459Szrj (bfd_signed_vma *) NULL);
354*a9fa9459Szrj else
355*a9fa9459Szrj ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
356*a9fa9459Szrj
357*a9fa9459Szrj slot = coff_get_slot (types, coff_symno);
358*a9fa9459Szrj *slot = ret;
359*a9fa9459Szrj
360*a9fa9459Szrj set_basic = FALSE;
361*a9fa9459Szrj break;
362*a9fa9459Szrj }
363*a9fa9459Szrj
364*a9fa9459Szrj if (name != NULL)
365*a9fa9459Szrj ret = debug_name_type (dhandle, name, ret);
366*a9fa9459Szrj
367*a9fa9459Szrj if (set_basic
368*a9fa9459Szrj && ntype >= 0
369*a9fa9459Szrj && ntype <= T_MAX)
370*a9fa9459Szrj types->basic[ntype] = ret;
371*a9fa9459Szrj
372*a9fa9459Szrj return ret;
373*a9fa9459Szrj }
374*a9fa9459Szrj
375*a9fa9459Szrj /* Parse a struct type. */
376*a9fa9459Szrj
377*a9fa9459Szrj static debug_type
parse_coff_struct_type(bfd * abfd,struct coff_symbols * symbols,struct coff_types * types,int ntype,union internal_auxent * pauxent,void * dhandle)378*a9fa9459Szrj parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols,
379*a9fa9459Szrj struct coff_types *types, int ntype,
380*a9fa9459Szrj union internal_auxent *pauxent, void *dhandle)
381*a9fa9459Szrj {
382*a9fa9459Szrj long symend;
383*a9fa9459Szrj int alloc;
384*a9fa9459Szrj debug_field *fields;
385*a9fa9459Szrj int count;
386*a9fa9459Szrj bfd_boolean done;
387*a9fa9459Szrj
388*a9fa9459Szrj symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
389*a9fa9459Szrj
390*a9fa9459Szrj alloc = 10;
391*a9fa9459Szrj fields = (debug_field *) xmalloc (alloc * sizeof *fields);
392*a9fa9459Szrj count = 0;
393*a9fa9459Szrj
394*a9fa9459Szrj done = FALSE;
395*a9fa9459Szrj while (! done
396*a9fa9459Szrj && symbols->coff_symno < symend
397*a9fa9459Szrj && symbols->symno < symbols->symcount)
398*a9fa9459Szrj {
399*a9fa9459Szrj asymbol *sym;
400*a9fa9459Szrj long this_coff_symno;
401*a9fa9459Szrj struct internal_syment syment;
402*a9fa9459Szrj union internal_auxent auxent;
403*a9fa9459Szrj union internal_auxent *psubaux;
404*a9fa9459Szrj bfd_vma bitpos = 0, bitsize = 0;
405*a9fa9459Szrj
406*a9fa9459Szrj sym = symbols->syms[symbols->symno];
407*a9fa9459Szrj
408*a9fa9459Szrj if (! bfd_coff_get_syment (abfd, sym, &syment))
409*a9fa9459Szrj {
410*a9fa9459Szrj non_fatal (_("bfd_coff_get_syment failed: %s"),
411*a9fa9459Szrj bfd_errmsg (bfd_get_error ()));
412*a9fa9459Szrj return DEBUG_TYPE_NULL;
413*a9fa9459Szrj }
414*a9fa9459Szrj
415*a9fa9459Szrj this_coff_symno = symbols->coff_symno;
416*a9fa9459Szrj
417*a9fa9459Szrj ++symbols->symno;
418*a9fa9459Szrj symbols->coff_symno += 1 + syment.n_numaux;
419*a9fa9459Szrj
420*a9fa9459Szrj if (syment.n_numaux == 0)
421*a9fa9459Szrj psubaux = NULL;
422*a9fa9459Szrj else
423*a9fa9459Szrj {
424*a9fa9459Szrj if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
425*a9fa9459Szrj {
426*a9fa9459Szrj non_fatal (_("bfd_coff_get_auxent failed: %s"),
427*a9fa9459Szrj bfd_errmsg (bfd_get_error ()));
428*a9fa9459Szrj return DEBUG_TYPE_NULL;
429*a9fa9459Szrj }
430*a9fa9459Szrj psubaux = &auxent;
431*a9fa9459Szrj }
432*a9fa9459Szrj
433*a9fa9459Szrj switch (syment.n_sclass)
434*a9fa9459Szrj {
435*a9fa9459Szrj case C_MOS:
436*a9fa9459Szrj case C_MOU:
437*a9fa9459Szrj bitpos = 8 * bfd_asymbol_value (sym);
438*a9fa9459Szrj bitsize = 0;
439*a9fa9459Szrj break;
440*a9fa9459Szrj
441*a9fa9459Szrj case C_FIELD:
442*a9fa9459Szrj bitpos = bfd_asymbol_value (sym);
443*a9fa9459Szrj bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
444*a9fa9459Szrj break;
445*a9fa9459Szrj
446*a9fa9459Szrj case C_EOS:
447*a9fa9459Szrj done = TRUE;
448*a9fa9459Szrj break;
449*a9fa9459Szrj }
450*a9fa9459Szrj
451*a9fa9459Szrj if (! done)
452*a9fa9459Szrj {
453*a9fa9459Szrj debug_type ftype;
454*a9fa9459Szrj debug_field f;
455*a9fa9459Szrj
456*a9fa9459Szrj ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
457*a9fa9459Szrj syment.n_type, psubaux, TRUE, dhandle);
458*a9fa9459Szrj f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
459*a9fa9459Szrj bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
460*a9fa9459Szrj if (f == DEBUG_FIELD_NULL)
461*a9fa9459Szrj return DEBUG_TYPE_NULL;
462*a9fa9459Szrj
463*a9fa9459Szrj if (count + 1 >= alloc)
464*a9fa9459Szrj {
465*a9fa9459Szrj alloc += 10;
466*a9fa9459Szrj fields = ((debug_field *)
467*a9fa9459Szrj xrealloc (fields, alloc * sizeof *fields));
468*a9fa9459Szrj }
469*a9fa9459Szrj
470*a9fa9459Szrj fields[count] = f;
471*a9fa9459Szrj ++count;
472*a9fa9459Szrj }
473*a9fa9459Szrj }
474*a9fa9459Szrj
475*a9fa9459Szrj fields[count] = DEBUG_FIELD_NULL;
476*a9fa9459Szrj
477*a9fa9459Szrj return debug_make_struct_type (dhandle, ntype == T_STRUCT,
478*a9fa9459Szrj pauxent->x_sym.x_misc.x_lnsz.x_size,
479*a9fa9459Szrj fields);
480*a9fa9459Szrj }
481*a9fa9459Szrj
482*a9fa9459Szrj /* Parse an enum type. */
483*a9fa9459Szrj
484*a9fa9459Szrj static debug_type
parse_coff_enum_type(bfd * abfd,struct coff_symbols * symbols,struct coff_types * types ATTRIBUTE_UNUSED,union internal_auxent * pauxent,void * dhandle)485*a9fa9459Szrj parse_coff_enum_type (bfd *abfd, struct coff_symbols *symbols,
486*a9fa9459Szrj struct coff_types *types ATTRIBUTE_UNUSED,
487*a9fa9459Szrj union internal_auxent *pauxent, void *dhandle)
488*a9fa9459Szrj {
489*a9fa9459Szrj long symend;
490*a9fa9459Szrj int alloc;
491*a9fa9459Szrj const char **names;
492*a9fa9459Szrj bfd_signed_vma *vals;
493*a9fa9459Szrj int count;
494*a9fa9459Szrj bfd_boolean done;
495*a9fa9459Szrj
496*a9fa9459Szrj symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
497*a9fa9459Szrj
498*a9fa9459Szrj alloc = 10;
499*a9fa9459Szrj names = (const char **) xmalloc (alloc * sizeof *names);
500*a9fa9459Szrj vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
501*a9fa9459Szrj count = 0;
502*a9fa9459Szrj
503*a9fa9459Szrj done = FALSE;
504*a9fa9459Szrj while (! done
505*a9fa9459Szrj && symbols->coff_symno < symend
506*a9fa9459Szrj && symbols->symno < symbols->symcount)
507*a9fa9459Szrj {
508*a9fa9459Szrj asymbol *sym;
509*a9fa9459Szrj struct internal_syment syment;
510*a9fa9459Szrj
511*a9fa9459Szrj sym = symbols->syms[symbols->symno];
512*a9fa9459Szrj
513*a9fa9459Szrj if (! bfd_coff_get_syment (abfd, sym, &syment))
514*a9fa9459Szrj {
515*a9fa9459Szrj non_fatal (_("bfd_coff_get_syment failed: %s"),
516*a9fa9459Szrj bfd_errmsg (bfd_get_error ()));
517*a9fa9459Szrj return DEBUG_TYPE_NULL;
518*a9fa9459Szrj }
519*a9fa9459Szrj
520*a9fa9459Szrj ++symbols->symno;
521*a9fa9459Szrj symbols->coff_symno += 1 + syment.n_numaux;
522*a9fa9459Szrj
523*a9fa9459Szrj switch (syment.n_sclass)
524*a9fa9459Szrj {
525*a9fa9459Szrj case C_MOE:
526*a9fa9459Szrj if (count + 1 >= alloc)
527*a9fa9459Szrj {
528*a9fa9459Szrj alloc += 10;
529*a9fa9459Szrj names = ((const char **)
530*a9fa9459Szrj xrealloc (names, alloc * sizeof *names));
531*a9fa9459Szrj vals = ((bfd_signed_vma *)
532*a9fa9459Szrj xrealloc (vals, alloc * sizeof *vals));
533*a9fa9459Szrj }
534*a9fa9459Szrj
535*a9fa9459Szrj names[count] = bfd_asymbol_name (sym);
536*a9fa9459Szrj vals[count] = bfd_asymbol_value (sym);
537*a9fa9459Szrj ++count;
538*a9fa9459Szrj break;
539*a9fa9459Szrj
540*a9fa9459Szrj case C_EOS:
541*a9fa9459Szrj done = TRUE;
542*a9fa9459Szrj break;
543*a9fa9459Szrj }
544*a9fa9459Szrj }
545*a9fa9459Szrj
546*a9fa9459Szrj names[count] = NULL;
547*a9fa9459Szrj
548*a9fa9459Szrj return debug_make_enum_type (dhandle, names, vals);
549*a9fa9459Szrj }
550*a9fa9459Szrj
551*a9fa9459Szrj /* Handle a single COFF symbol. */
552*a9fa9459Szrj
553*a9fa9459Szrj static bfd_boolean
parse_coff_symbol(bfd * abfd ATTRIBUTE_UNUSED,struct coff_types * types,asymbol * sym,long coff_symno,struct internal_syment * psyment,void * dhandle,debug_type type,bfd_boolean within_function)554*a9fa9459Szrj parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types,
555*a9fa9459Szrj asymbol *sym, long coff_symno,
556*a9fa9459Szrj struct internal_syment *psyment, void *dhandle,
557*a9fa9459Szrj debug_type type, bfd_boolean within_function)
558*a9fa9459Szrj {
559*a9fa9459Szrj switch (psyment->n_sclass)
560*a9fa9459Szrj {
561*a9fa9459Szrj case C_NULL:
562*a9fa9459Szrj break;
563*a9fa9459Szrj
564*a9fa9459Szrj case C_AUTO:
565*a9fa9459Szrj if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
566*a9fa9459Szrj DEBUG_LOCAL, bfd_asymbol_value (sym)))
567*a9fa9459Szrj return FALSE;
568*a9fa9459Szrj break;
569*a9fa9459Szrj
570*a9fa9459Szrj case C_WEAKEXT:
571*a9fa9459Szrj case C_EXT:
572*a9fa9459Szrj if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
573*a9fa9459Szrj DEBUG_GLOBAL, bfd_asymbol_value (sym)))
574*a9fa9459Szrj return FALSE;
575*a9fa9459Szrj break;
576*a9fa9459Szrj
577*a9fa9459Szrj case C_STAT:
578*a9fa9459Szrj if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
579*a9fa9459Szrj (within_function
580*a9fa9459Szrj ? DEBUG_LOCAL_STATIC
581*a9fa9459Szrj : DEBUG_STATIC),
582*a9fa9459Szrj bfd_asymbol_value (sym)))
583*a9fa9459Szrj return FALSE;
584*a9fa9459Szrj break;
585*a9fa9459Szrj
586*a9fa9459Szrj case C_REG:
587*a9fa9459Szrj /* FIXME: We may need to convert the register number. */
588*a9fa9459Szrj if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
589*a9fa9459Szrj DEBUG_REGISTER, bfd_asymbol_value (sym)))
590*a9fa9459Szrj return FALSE;
591*a9fa9459Szrj break;
592*a9fa9459Szrj
593*a9fa9459Szrj case C_LABEL:
594*a9fa9459Szrj break;
595*a9fa9459Szrj
596*a9fa9459Szrj case C_ARG:
597*a9fa9459Szrj if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
598*a9fa9459Szrj DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
599*a9fa9459Szrj return FALSE;
600*a9fa9459Szrj break;
601*a9fa9459Szrj
602*a9fa9459Szrj case C_REGPARM:
603*a9fa9459Szrj /* FIXME: We may need to convert the register number. */
604*a9fa9459Szrj if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
605*a9fa9459Szrj DEBUG_PARM_REG, bfd_asymbol_value (sym)))
606*a9fa9459Szrj return FALSE;
607*a9fa9459Szrj break;
608*a9fa9459Szrj
609*a9fa9459Szrj case C_TPDEF:
610*a9fa9459Szrj type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
611*a9fa9459Szrj if (type == DEBUG_TYPE_NULL)
612*a9fa9459Szrj return FALSE;
613*a9fa9459Szrj break;
614*a9fa9459Szrj
615*a9fa9459Szrj case C_STRTAG:
616*a9fa9459Szrj case C_UNTAG:
617*a9fa9459Szrj case C_ENTAG:
618*a9fa9459Szrj {
619*a9fa9459Szrj debug_type *slot;
620*a9fa9459Szrj
621*a9fa9459Szrj type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
622*a9fa9459Szrj if (type == DEBUG_TYPE_NULL)
623*a9fa9459Szrj return FALSE;
624*a9fa9459Szrj
625*a9fa9459Szrj /* Store the named type into the slot, so that references get
626*a9fa9459Szrj the name. */
627*a9fa9459Szrj slot = coff_get_slot (types, coff_symno);
628*a9fa9459Szrj *slot = type;
629*a9fa9459Szrj }
630*a9fa9459Szrj break;
631*a9fa9459Szrj
632*a9fa9459Szrj default:
633*a9fa9459Szrj break;
634*a9fa9459Szrj }
635*a9fa9459Szrj
636*a9fa9459Szrj return TRUE;
637*a9fa9459Szrj }
638*a9fa9459Szrj
639*a9fa9459Szrj /* Determine if a symbol has external visibility. */
640*a9fa9459Szrj
641*a9fa9459Szrj static bfd_boolean
external_coff_symbol_p(int sym_class)642*a9fa9459Szrj external_coff_symbol_p (int sym_class)
643*a9fa9459Szrj {
644*a9fa9459Szrj switch (sym_class)
645*a9fa9459Szrj {
646*a9fa9459Szrj case C_EXT:
647*a9fa9459Szrj case C_WEAKEXT:
648*a9fa9459Szrj return TRUE;
649*a9fa9459Szrj default:
650*a9fa9459Szrj break;
651*a9fa9459Szrj }
652*a9fa9459Szrj return FALSE;
653*a9fa9459Szrj }
654*a9fa9459Szrj
655*a9fa9459Szrj /* This is the main routine. It looks through all the symbols and
656*a9fa9459Szrj handles them. */
657*a9fa9459Szrj
658*a9fa9459Szrj bfd_boolean
parse_coff(bfd * abfd,asymbol ** syms,long symcount,void * dhandle)659*a9fa9459Szrj parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle)
660*a9fa9459Szrj {
661*a9fa9459Szrj struct coff_symbols symbols;
662*a9fa9459Szrj struct coff_types types;
663*a9fa9459Szrj int i;
664*a9fa9459Szrj long next_c_file;
665*a9fa9459Szrj const char *fnname;
666*a9fa9459Szrj int fnclass;
667*a9fa9459Szrj int fntype;
668*a9fa9459Szrj bfd_vma fnend;
669*a9fa9459Szrj alent *linenos;
670*a9fa9459Szrj bfd_boolean within_function;
671*a9fa9459Szrj long this_coff_symno;
672*a9fa9459Szrj
673*a9fa9459Szrj symbols.syms = syms;
674*a9fa9459Szrj symbols.symcount = symcount;
675*a9fa9459Szrj symbols.symno = 0;
676*a9fa9459Szrj symbols.coff_symno = 0;
677*a9fa9459Szrj
678*a9fa9459Szrj types.slots = NULL;
679*a9fa9459Szrj for (i = 0; i <= T_MAX; i++)
680*a9fa9459Szrj types.basic[i] = DEBUG_TYPE_NULL;
681*a9fa9459Szrj
682*a9fa9459Szrj next_c_file = -1;
683*a9fa9459Szrj fnname = NULL;
684*a9fa9459Szrj fnclass = 0;
685*a9fa9459Szrj fntype = 0;
686*a9fa9459Szrj fnend = 0;
687*a9fa9459Szrj linenos = NULL;
688*a9fa9459Szrj within_function = FALSE;
689*a9fa9459Szrj
690*a9fa9459Szrj while (symbols.symno < symcount)
691*a9fa9459Szrj {
692*a9fa9459Szrj asymbol *sym;
693*a9fa9459Szrj const char *name;
694*a9fa9459Szrj struct internal_syment syment;
695*a9fa9459Szrj union internal_auxent auxent;
696*a9fa9459Szrj union internal_auxent *paux;
697*a9fa9459Szrj debug_type type;
698*a9fa9459Szrj
699*a9fa9459Szrj sym = syms[symbols.symno];
700*a9fa9459Szrj
701*a9fa9459Szrj if (! bfd_coff_get_syment (abfd, sym, &syment))
702*a9fa9459Szrj {
703*a9fa9459Szrj non_fatal (_("bfd_coff_get_syment failed: %s"),
704*a9fa9459Szrj bfd_errmsg (bfd_get_error ()));
705*a9fa9459Szrj return FALSE;
706*a9fa9459Szrj }
707*a9fa9459Szrj
708*a9fa9459Szrj name = bfd_asymbol_name (sym);
709*a9fa9459Szrj
710*a9fa9459Szrj this_coff_symno = symbols.coff_symno;
711*a9fa9459Szrj
712*a9fa9459Szrj ++symbols.symno;
713*a9fa9459Szrj symbols.coff_symno += 1 + syment.n_numaux;
714*a9fa9459Szrj
715*a9fa9459Szrj /* We only worry about the first auxent, because that is the
716*a9fa9459Szrj only one which is relevant for debugging information. */
717*a9fa9459Szrj if (syment.n_numaux == 0)
718*a9fa9459Szrj paux = NULL;
719*a9fa9459Szrj else
720*a9fa9459Szrj {
721*a9fa9459Szrj if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
722*a9fa9459Szrj {
723*a9fa9459Szrj non_fatal (_("bfd_coff_get_auxent failed: %s"),
724*a9fa9459Szrj bfd_errmsg (bfd_get_error ()));
725*a9fa9459Szrj return FALSE;
726*a9fa9459Szrj }
727*a9fa9459Szrj paux = &auxent;
728*a9fa9459Szrj }
729*a9fa9459Szrj
730*a9fa9459Szrj if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
731*a9fa9459Szrj {
732*a9fa9459Szrj /* The last C_FILE symbol points to the first external
733*a9fa9459Szrj symbol. */
734*a9fa9459Szrj if (! debug_set_filename (dhandle, "*globals*"))
735*a9fa9459Szrj return FALSE;
736*a9fa9459Szrj }
737*a9fa9459Szrj
738*a9fa9459Szrj switch (syment.n_sclass)
739*a9fa9459Szrj {
740*a9fa9459Szrj case C_EFCN:
741*a9fa9459Szrj case C_EXTDEF:
742*a9fa9459Szrj case C_ULABEL:
743*a9fa9459Szrj case C_USTATIC:
744*a9fa9459Szrj case C_LINE:
745*a9fa9459Szrj case C_ALIAS:
746*a9fa9459Szrj case C_HIDDEN:
747*a9fa9459Szrj /* Just ignore these classes. */
748*a9fa9459Szrj break;
749*a9fa9459Szrj
750*a9fa9459Szrj case C_FILE:
751*a9fa9459Szrj next_c_file = syment.n_value;
752*a9fa9459Szrj if (! debug_set_filename (dhandle, name))
753*a9fa9459Szrj return FALSE;
754*a9fa9459Szrj break;
755*a9fa9459Szrj
756*a9fa9459Szrj case C_STAT:
757*a9fa9459Szrj /* Ignore static symbols with a type of T_NULL. These
758*a9fa9459Szrj represent section entries. */
759*a9fa9459Szrj if (syment.n_type == T_NULL)
760*a9fa9459Szrj break;
761*a9fa9459Szrj /* Fall through. */
762*a9fa9459Szrj case C_WEAKEXT:
763*a9fa9459Szrj case C_EXT:
764*a9fa9459Szrj if (ISFCN (syment.n_type))
765*a9fa9459Szrj {
766*a9fa9459Szrj fnname = name;
767*a9fa9459Szrj fnclass = syment.n_sclass;
768*a9fa9459Szrj fntype = syment.n_type;
769*a9fa9459Szrj if (syment.n_numaux > 0)
770*a9fa9459Szrj fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
771*a9fa9459Szrj else
772*a9fa9459Szrj fnend = 0;
773*a9fa9459Szrj linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
774*a9fa9459Szrj break;
775*a9fa9459Szrj }
776*a9fa9459Szrj type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
777*a9fa9459Szrj syment.n_type, paux, TRUE, dhandle);
778*a9fa9459Szrj if (type == DEBUG_TYPE_NULL)
779*a9fa9459Szrj return FALSE;
780*a9fa9459Szrj if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
781*a9fa9459Szrj dhandle, type, within_function))
782*a9fa9459Szrj return FALSE;
783*a9fa9459Szrj break;
784*a9fa9459Szrj
785*a9fa9459Szrj case C_FCN:
786*a9fa9459Szrj if (strcmp (name, ".bf") == 0)
787*a9fa9459Szrj {
788*a9fa9459Szrj if (fnname == NULL)
789*a9fa9459Szrj {
790*a9fa9459Szrj non_fatal (_("%ld: .bf without preceding function"),
791*a9fa9459Szrj this_coff_symno);
792*a9fa9459Szrj return FALSE;
793*a9fa9459Szrj }
794*a9fa9459Szrj
795*a9fa9459Szrj type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
796*a9fa9459Szrj DECREF (fntype), paux, FALSE, dhandle);
797*a9fa9459Szrj if (type == DEBUG_TYPE_NULL)
798*a9fa9459Szrj return FALSE;
799*a9fa9459Szrj
800*a9fa9459Szrj if (! debug_record_function (dhandle, fnname, type,
801*a9fa9459Szrj external_coff_symbol_p (fnclass),
802*a9fa9459Szrj bfd_asymbol_value (sym)))
803*a9fa9459Szrj return FALSE;
804*a9fa9459Szrj
805*a9fa9459Szrj if (linenos != NULL)
806*a9fa9459Szrj {
807*a9fa9459Szrj int base;
808*a9fa9459Szrj bfd_vma addr;
809*a9fa9459Szrj
810*a9fa9459Szrj if (syment.n_numaux == 0)
811*a9fa9459Szrj base = 0;
812*a9fa9459Szrj else
813*a9fa9459Szrj base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
814*a9fa9459Szrj
815*a9fa9459Szrj addr = bfd_get_section_vma (abfd, bfd_get_section (sym));
816*a9fa9459Szrj
817*a9fa9459Szrj ++linenos;
818*a9fa9459Szrj
819*a9fa9459Szrj while (linenos->line_number != 0)
820*a9fa9459Szrj {
821*a9fa9459Szrj if (! debug_record_line (dhandle,
822*a9fa9459Szrj linenos->line_number + base,
823*a9fa9459Szrj linenos->u.offset + addr))
824*a9fa9459Szrj return FALSE;
825*a9fa9459Szrj ++linenos;
826*a9fa9459Szrj }
827*a9fa9459Szrj }
828*a9fa9459Szrj
829*a9fa9459Szrj fnname = NULL;
830*a9fa9459Szrj linenos = NULL;
831*a9fa9459Szrj fnclass = 0;
832*a9fa9459Szrj fntype = 0;
833*a9fa9459Szrj
834*a9fa9459Szrj within_function = TRUE;
835*a9fa9459Szrj }
836*a9fa9459Szrj else if (strcmp (name, ".ef") == 0)
837*a9fa9459Szrj {
838*a9fa9459Szrj if (! within_function)
839*a9fa9459Szrj {
840*a9fa9459Szrj non_fatal (_("%ld: unexpected .ef\n"), this_coff_symno);
841*a9fa9459Szrj return FALSE;
842*a9fa9459Szrj }
843*a9fa9459Szrj
844*a9fa9459Szrj if (bfd_asymbol_value (sym) > fnend)
845*a9fa9459Szrj fnend = bfd_asymbol_value (sym);
846*a9fa9459Szrj if (! debug_end_function (dhandle, fnend))
847*a9fa9459Szrj return FALSE;
848*a9fa9459Szrj
849*a9fa9459Szrj fnend = 0;
850*a9fa9459Szrj within_function = FALSE;
851*a9fa9459Szrj }
852*a9fa9459Szrj break;
853*a9fa9459Szrj
854*a9fa9459Szrj case C_BLOCK:
855*a9fa9459Szrj if (strcmp (name, ".bb") == 0)
856*a9fa9459Szrj {
857*a9fa9459Szrj if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
858*a9fa9459Szrj return FALSE;
859*a9fa9459Szrj }
860*a9fa9459Szrj else if (strcmp (name, ".eb") == 0)
861*a9fa9459Szrj {
862*a9fa9459Szrj if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
863*a9fa9459Szrj return FALSE;
864*a9fa9459Szrj }
865*a9fa9459Szrj break;
866*a9fa9459Szrj
867*a9fa9459Szrj default:
868*a9fa9459Szrj type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
869*a9fa9459Szrj syment.n_type, paux, TRUE, dhandle);
870*a9fa9459Szrj if (type == DEBUG_TYPE_NULL)
871*a9fa9459Szrj return FALSE;
872*a9fa9459Szrj if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
873*a9fa9459Szrj dhandle, type, within_function))
874*a9fa9459Szrj return FALSE;
875*a9fa9459Szrj break;
876*a9fa9459Szrj }
877*a9fa9459Szrj }
878*a9fa9459Szrj
879*a9fa9459Szrj return TRUE;
880*a9fa9459Szrj }
881