xref: /dragonfly/contrib/gcc-4.7/gcc/mips-tdump.c (revision 0ca59c34)
1 /* Read and manage MIPS symbol tables from object modules.
2    Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
3    2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
4    Contributed by hartzell@boulder.colorado.edu,
5    Rewritten by meissner@osf.org.
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13 
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22 
23 #include "config.h"
24 #include "system.h"
25 #include "version.h"
26 #ifdef index
27 #undef index
28 #endif
29 #include <a.out.h>
30 
31 /* Include getopt.h for the sake of getopt_long.  */
32 #include "getopt.h"
33 
34 /* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
35    mips-tdump.c to print them out.
36 
37    These must match the corresponding definitions in gdb/mipsread.c.
38    Unfortunately, gcc and gdb do not currently share any directories.  */
39 
40 #define CODE_MASK 0x8F300
41 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
42 #define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
43 #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
44 
45 #define uchar	unsigned char
46 #define ushort	unsigned short
47 #define uint	unsigned int
48 #define ulong	unsigned long
49 
50 
51 /* Redefinition of storage classes as an enumeration for better
52    debugging.  */
53 
54 #ifndef stStaParam
55 #define stStaParam	16	/* Fortran static parameters */
56 #endif
57 
58 #ifndef btVoid
59 #define btVoid		26	/* void basic type */
60 #endif
61 
62 typedef enum sc {
63   sc_Nil	 = scNil,	  /* no storage class */
64   sc_Text	 = scText,	  /* text symbol */
65   sc_Data	 = scData,	  /* initialized data symbol */
66   sc_Bss	 = scBss,	  /* un-initialized data symbol */
67   sc_Register	 = scRegister,	  /* value of symbol is register number */
68   sc_Abs	 = scAbs,	  /* value of symbol is absolute */
69   sc_Undefined	 = scUndefined,	  /* who knows? */
70   sc_CdbLocal	 = scCdbLocal,	  /* variable's value is IN se->va.?? */
71   sc_Bits	 = scBits,	  /* this is a bit field */
72   sc_CdbSystem	 = scCdbSystem,	  /* var's value is IN CDB's address space */
73   sc_RegImage	 = scRegImage,	  /* register value saved on stack */
74   sc_Info	 = scInfo,	  /* symbol contains debugger information */
75   sc_UserStruct	 = scUserStruct,  /* addr in struct user for current process */
76   sc_SData	 = scSData,	  /* load time only small data */
77   sc_SBss	 = scSBss,	  /* load time only small common */
78   sc_RData	 = scRData,	  /* load time only read only data */
79   sc_Var	 = scVar,	  /* Var parameter (fortran,pascal) */
80   sc_Common	 = scCommon,	  /* common variable */
81   sc_SCommon	 = scSCommon,	  /* small common */
82   sc_VarRegister = scVarRegister, /* Var parameter in a register */
83   sc_Variant	 = scVariant,	  /* Variant record */
84   sc_SUndefined	 = scSUndefined,  /* small undefined(external) data */
85   sc_Init	 = scInit,	  /* .init section symbol */
86   sc_Max	 = scMax	  /* Max storage class+1 */
87 } sc_t;
88 
89 /* Redefinition of symbol type.  */
90 
91 typedef enum st {
92   st_Nil	= stNil,	/* Nuthin' special */
93   st_Global	= stGlobal,	/* external symbol */
94   st_Static	= stStatic,	/* static */
95   st_Param	= stParam,	/* procedure argument */
96   st_Local	= stLocal,	/* local variable */
97   st_Label	= stLabel,	/* label */
98   st_Proc	= stProc,	/*     "      "	 Procedure */
99   st_Block	= stBlock,	/* beginning of block */
100   st_End	= stEnd,	/* end (of anything) */
101   st_Member	= stMember,	/* member (of anything	- struct/union/enum */
102   st_Typedef	= stTypedef,	/* type definition */
103   st_File	= stFile,	/* file name */
104   st_RegReloc	= stRegReloc,	/* register relocation */
105   st_Forward	= stForward,	/* forwarding address */
106   st_StaticProc	= stStaticProc,	/* load time only static procs */
107   st_StaParam	= stStaParam,	/* Fortran static parameters */
108   st_Constant	= stConstant,	/* const */
109 #ifdef stStruct
110   st_Struct	= stStruct,	/* struct */
111   st_Union	= stUnion,	/* union */
112   st_Enum	= stEnum,	/* enum */
113 #endif
114   st_Str	= stStr,	/* string */
115   st_Number	= stNumber,	/* pure number (i.e. 4 NOR 2+2) */
116   st_Expr	= stExpr,	/* 2+2 vs. 4 */
117   st_Type	= stType,	/* post-coercion SER */
118   st_Max	= stMax		/* max type+1 */
119 } st_t;
120 
121 /* Redefinition of type qualifiers.  */
122 
123 typedef enum tq {
124   tq_Nil	= tqNil,	/* bt is what you see */
125   tq_Ptr	= tqPtr,	/* pointer */
126   tq_Proc	= tqProc,	/* procedure */
127   tq_Array	= tqArray,	/* duh */
128   tq_Far	= tqFar,	/* longer addressing - 8086/8 land */
129   tq_Vol	= tqVol,	/* volatile */
130   tq_Max	= tqMax		/* Max type qualifier+1 */
131 } tq_t;
132 
133 /* Redefinition of basic types.  */
134 
135 typedef enum bt {
136   bt_Nil	= btNil,	/* undefined */
137   bt_Adr	= btAdr,	/* address - integer same size as pointer */
138   bt_Char	= btChar,	/* character */
139   bt_UChar	= btUChar,	/* unsigned character */
140   bt_Short	= btShort,	/* short */
141   bt_UShort	= btUShort,	/* unsigned short */
142   bt_Int	= btInt,	/* int */
143   bt_UInt	= btUInt,	/* unsigned int */
144   bt_Long	= btLong,	/* long */
145   bt_ULong	= btULong,	/* unsigned long */
146   bt_Float	= btFloat,	/* float (real) */
147   bt_Double	= btDouble,	/* Double (real) */
148   bt_Struct	= btStruct,	/* Structure (Record) */
149   bt_Union	= btUnion,	/* Union (variant) */
150   bt_Enum	= btEnum,	/* Enumerated */
151   bt_Typedef	= btTypedef,	/* defined via a typedef, isymRef points */
152   bt_Range	= btRange,	/* subrange of int */
153   bt_Set	= btSet,	/* pascal sets */
154   bt_Complex	= btComplex,	/* fortran complex */
155   bt_DComplex	= btDComplex,	/* fortran double complex */
156   bt_Indirect	= btIndirect,	/* forward or unnamed typedef */
157   bt_FixedDec	= btFixedDec,	/* Fixed Decimal */
158   bt_FloatDec	= btFloatDec,	/* Float Decimal */
159   bt_String	= btString,	/* Varying Length Character String */
160   bt_Bit	= btBit,	/* Aligned Bit String */
161   bt_Picture	= btPicture,	/* Picture */
162   bt_Void	= btVoid,	/* void */
163   bt_Max	= btMax		/* Max basic type+1 */
164 } bt_t;
165 
166 /* Redefinition of the language codes.  */
167 
168 typedef enum lang {
169   lang_C	 = langC,
170   lang_Pascal	 = langPascal,
171   lang_Fortran	 = langFortran,
172   lang_Assembler = langAssembler,
173   lang_Machine	 = langMachine,
174   lang_Nil	 = langNil,
175   lang_Ada	 = langAda,
176   lang_Pl1	 = langPl1,
177   lang_Cobol	 = langCobol
178 } lang_t;
179 
180 /* Redefinition of the debug level codes.  */
181 
182 typedef enum glevel {
183   glevel_0	= GLEVEL_0,
184   glevel_1	= GLEVEL_1,
185   glevel_2	= GLEVEL_2,
186   glevel_3	= GLEVEL_3
187 } glevel_t;
188 
189 
190 /* Keep track of the active scopes.  */
191 typedef struct scope {
192   struct scope *prev;		/* previous scope */
193   ulong open_sym;		/* symbol opening scope */
194   sc_t sc;			/* storage class */
195   st_t st;			/* symbol type */
196 } scope_t;
197 
198 struct filehdr global_hdr;	/* a.out header */
199 
200 int	 errors		= 0;	/* # of errors */
201 int	 want_aux	= 0;	/* print aux table */
202 int	 want_line	= 0;	/* print line numbers */
203 int	 want_rfd	= 0;	/* print relative file desc's */
204 int	 want_scope	= 0;	/* print scopes for every symbol */
205 int	 tfile		= 0;	/* no global header file */
206 int	 version	= 0;    /* print version # */
207 int	 verbose	= 0;
208 int	 tfile_fd;		/* file descriptor of .T file */
209 off_t	 tfile_offset;		/* current offset in .T file */
210 scope_t	*cur_scope	= 0;	/* list of active scopes */
211 scope_t	*free_scope	= 0;	/* list of freed scopes */
212 HDRR	 sym_hdr;		/* symbolic header */
213 char	*l_strings;		/* local strings */
214 char	*e_strings;		/* external strings */
215 SYMR	*l_symbols;		/* local symbols */
216 EXTR	*e_symbols;		/* external symbols */
217 LINER	*lines;			/* line numbers */
218 DNR	*dense_nums;		/* dense numbers */
219 OPTR	*opt_symbols;		/* optimization symbols */
220 AUXU	*aux_symbols;		/* Auxiliary symbols */
221 char	*aux_used;		/* map of which aux syms are used */
222 FDR	*file_desc;		/* file tables */
223 ulong	*rfile_desc;		/* relative file tables */
224 PDR	*proc_desc;		/* procedure tables */
225 
226 /* Forward reference for functions.  */
227 static void *read_seek (void *, size_t, off_t, const char *);
228 static void read_tfile (void);
229 static void print_global_hdr (struct filehdr *);
230 static void print_sym_hdr (HDRR *);
231 static void print_file_desc (FDR *, int);
232 static void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
233 static void print_aux (AUXU, int, int);
234 static void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
235 static const char *st_to_string (st_t);
236 static const char *sc_to_string (sc_t);
237 static const char *glevel_to_string (glevel_t);
238 static const char *lang_to_string (lang_t);
239 static const char *type_to_string (AUXU *, int, FDR *);
240 
241 extern char *optarg;
242 extern int   optind;
243 extern int   opterr;
244 
245 /* Create a table of debugging stab-codes and corresponding names.  */
246 
247 #define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
248 const struct {const short code; const char string[10];} stab_names[]  = {
249 #include "stab.def"
250 #undef __define_stab
251 };
252 
253 /* Command line options for getopt_long.  */
254 
255 static const struct option options[] =
256 {
257   { "version", 0, 0, 'V' },
258   { "verbose", 0, 0, 'v' },
259   { 0, 0, 0, 0 }
260 };
261 
262 /* Read some bytes at a specified location, and return a pointer.
263    Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE
264    bytes from offset OFFSET.  In case of errors CONTEXT is used as
265    error message.  */
266 
267 static void *
268 read_seek (void *ptr, size_t size, off_t offset,  const char *context)
269 {
270   long read_size = 0;
271 
272   if (size == 0)		/* nothing to read */
273     return ptr;
274 
275   if (!ptr)
276     ptr = xmalloc (size);
277 
278   if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
279       || (read_size = read (tfile_fd, ptr, size)) < 0)
280     {
281       perror (context);
282       exit (1);
283     }
284 
285   if (read_size != (long) size)
286     {
287       fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
288 	       context, read_size, (long) size);
289       exit (1);
290     }
291 
292   tfile_offset = offset + size;
293   return ptr;
294 }
295 
296 
297 /* Convert language code to string format.  */
298 
299 static const char *
300 lang_to_string (lang_t lang)
301 {
302   switch (lang)
303     {
304     case langC:		return "C";
305     case langPascal:	return "Pascal";
306     case langFortran:	return "Fortran";
307     case langAssembler:	return "Assembler";
308     case langMachine:	return "Machine";
309     case langNil:	return "Nil";
310     case langAda:	return "Ada";
311     case langPl1:	return "Pl1";
312     case langCobol:	return "Cobol";
313     }
314 
315   return "Unknown language";
316 }
317 
318 
319 /* Convert storage class to string.  */
320 
321 static const char *
322 sc_to_string (sc_t storage_class)
323 {
324   switch(storage_class)
325     {
326     case sc_Nil:	 return "Nil";
327     case sc_Text:	 return "Text";
328     case sc_Data:	 return "Data";
329     case sc_Bss:	 return "Bss";
330     case sc_Register:	 return "Register";
331     case sc_Abs:	 return "Abs";
332     case sc_Undefined:	 return "Undefined";
333     case sc_CdbLocal:	 return "CdbLocal";
334     case sc_Bits:	 return "Bits";
335     case sc_CdbSystem:	 return "CdbSystem";
336     case sc_RegImage:	 return "RegImage";
337     case sc_Info:	 return "Info";
338     case sc_UserStruct:	 return "UserStruct";
339     case sc_SData:	 return "SData";
340     case sc_SBss:	 return "SBss";
341     case sc_RData:	 return "RData";
342     case sc_Var:	 return "Var";
343     case sc_Common:	 return "Common";
344     case sc_SCommon:	 return "SCommon";
345     case sc_VarRegister: return "VarRegister";
346     case sc_Variant:	 return "Variant";
347     case sc_SUndefined:	 return "SUndefined";
348     case sc_Init:	 return "Init";
349     case sc_Max:	 return "Max";
350     }
351 
352   return "???";
353 }
354 
355 
356 /* Convert symbol type to string.  */
357 
358 static const char *
359 st_to_string (st_t symbol_type)
360 {
361   switch(symbol_type)
362     {
363     case st_Nil:	return "Nil";
364     case st_Global:	return "Global";
365     case st_Static:	return "Static";
366     case st_Param:	return "Param";
367     case st_Local:	return "Local";
368     case st_Label:	return "Label";
369     case st_Proc:	return "Proc";
370     case st_Block:	return "Block";
371     case st_End:	return "End";
372     case st_Member:	return "Member";
373     case st_Typedef:	return "Typedef";
374     case st_File:	return "File";
375     case st_RegReloc:	return "RegReloc";
376     case st_Forward:	return "Forward";
377     case st_StaticProc:	return "StaticProc";
378     case st_Constant:	return "Constant";
379     case st_StaParam:	return "StaticParam";
380 #ifdef stStruct
381     case st_Struct:	return "Struct";
382     case st_Union:	return "Union";
383     case st_Enum:	return "Enum";
384 #endif
385     case st_Str:	return "String";
386     case st_Number:	return "Number";
387     case st_Expr:	return "Expr";
388     case st_Type:	return "Type";
389     case st_Max:	return "Max";
390     }
391 
392   return "???";
393 }
394 
395 
396 /* Convert debug level to string.  */
397 
398 static const char *
399 glevel_to_string (glevel_t g_level)
400 {
401   switch(g_level)
402     {
403     case GLEVEL_0: return "G0";
404     case GLEVEL_1: return "G1";
405     case GLEVEL_2: return "G2";
406     case GLEVEL_3: return "G3";
407     }
408 
409   return "??";
410 }
411 
412 
413 /* Convert the type information to string format.  */
414 
415 static const char *
416 type_to_string (AUXU *aux_ptr, int index, FDR *fdp)
417 {
418   AUXU u;
419   struct qual {
420     tq_t type;
421     int  low_bound;
422     int  high_bound;
423     int  stride;
424   } qualifiers[7];
425 
426   bt_t basic_type;
427   int i;
428   static char buffer1[1024];
429   static char buffer2[1024];
430   char *p1 = buffer1;
431   char *p2 = buffer2;
432   char *used_ptr = aux_used + (aux_ptr - aux_symbols);
433 
434   for (i = 0; i < 7; i++)
435     {
436       qualifiers[i].low_bound = 0;
437       qualifiers[i].high_bound = 0;
438       qualifiers[i].stride = 0;
439     }
440 
441   used_ptr[index] = 1;
442   u = aux_ptr[index++];
443   if (u.isym == -1)
444     return "-1 (no type)";
445 
446   basic_type = (bt_t) u.ti.bt;
447   qualifiers[0].type = (tq_t) u.ti.tq0;
448   qualifiers[1].type = (tq_t) u.ti.tq1;
449   qualifiers[2].type = (tq_t) u.ti.tq2;
450   qualifiers[3].type = (tq_t) u.ti.tq3;
451   qualifiers[4].type = (tq_t) u.ti.tq4;
452   qualifiers[5].type = (tq_t) u.ti.tq5;
453   qualifiers[6].type = tq_Nil;
454 
455   /*
456    * Go get the basic type.
457    */
458   switch (basic_type)
459     {
460     case bt_Nil:		/* undefined */
461       strcpy (p1, "nil");
462       break;
463 
464     case bt_Adr:		/* address - integer same size as pointer */
465       strcpy (p1, "address");
466       break;
467 
468     case bt_Char:		/* character */
469       strcpy (p1, "char");
470       break;
471 
472     case bt_UChar:		/* unsigned character */
473       strcpy (p1, "unsigned char");
474       break;
475 
476     case bt_Short:		/* short */
477       strcpy (p1, "short");
478       break;
479 
480     case bt_UShort:		/* unsigned short */
481       strcpy (p1, "unsigned short");
482       break;
483 
484     case bt_Int:		/* int */
485       strcpy (p1, "int");
486       break;
487 
488     case bt_UInt:		/* unsigned int */
489       strcpy (p1, "unsigned int");
490       break;
491 
492     case bt_Long:		/* long */
493       strcpy (p1, "long");
494       break;
495 
496     case bt_ULong:		/* unsigned long */
497       strcpy (p1, "unsigned long");
498       break;
499 
500     case bt_Float:		/* float (real) */
501       strcpy (p1, "float");
502       break;
503 
504     case bt_Double:		/* Double (real) */
505       strcpy (p1, "double");
506       break;
507 
508       /* Structures add 1-2 aux words:
509 	 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
510 	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
511 
512     case bt_Struct:		/* Structure (Record) */
513       emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp);
514       used_ptr[index] = 1;
515       if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
516 	used_ptr[++index] = 1;
517 
518       index++;			/* skip aux words */
519       break;
520 
521       /* Unions add 1-2 aux words:
522 	 1st word is [ST_RFDESCAPE, offset] pointer to union def;
523 	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
524 
525     case bt_Union:		/* Union */
526       emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp);
527       used_ptr[index] = 1;
528       if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
529 	used_ptr[++index] = 1;
530 
531       index++;			/* skip aux words */
532       break;
533 
534       /* Enumerations add 1-2 aux words:
535 	 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
536 	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
537 
538     case bt_Enum:		/* Enumeration */
539       emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp);
540       used_ptr[index] = 1;
541       if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
542 	used_ptr[++index] = 1;
543 
544       index++;			/* skip aux words */
545       break;
546 
547     case bt_Typedef:		/* defined via a typedef, isymRef points */
548       strcpy (p1, "typedef");
549       break;
550 
551     case bt_Range:		/* subrange of int */
552       strcpy (p1, "subrange");
553       break;
554 
555     case bt_Set:		/* pascal sets */
556       strcpy (p1, "set");
557       break;
558 
559     case bt_Complex:		/* fortran complex */
560       strcpy (p1, "complex");
561       break;
562 
563     case bt_DComplex:		/* fortran double complex */
564       strcpy (p1, "double complex");
565       break;
566 
567     case bt_Indirect:		/* forward or unnamed typedef */
568       strcpy (p1, "forward/unnamed typedef");
569       break;
570 
571     case bt_FixedDec:		/* Fixed Decimal */
572       strcpy (p1, "fixed decimal");
573       break;
574 
575     case bt_FloatDec:		/* Float Decimal */
576       strcpy (p1, "float decimal");
577       break;
578 
579     case bt_String:		/* Varying Length Character String */
580       strcpy (p1, "string");
581       break;
582 
583     case bt_Bit:		/* Aligned Bit String */
584       strcpy (p1, "bit");
585       break;
586 
587     case bt_Picture:		/* Picture */
588       strcpy (p1, "picture");
589       break;
590 
591     case bt_Void:		/* Void */
592       strcpy (p1, "void");
593       break;
594 
595     default:
596       sprintf (p1, "Unknown basic type %d", (int) basic_type);
597       break;
598     }
599 
600   p1 += strlen (buffer1);
601 
602   /*
603    * If this is a bitfield, get the bitsize.
604    */
605   if (u.ti.fBitfield)
606     {
607       int bitsize;
608 
609       used_ptr[index] = 1;
610       bitsize = aux_ptr[index++].width;
611       sprintf (p1, " : %d", bitsize);
612       p1 += strlen (buffer1);
613     }
614 
615 
616   /*
617    * Deal with any qualifiers.
618    */
619   if (qualifiers[0].type != tq_Nil)
620     {
621       /*
622        * Snarf up any array bounds in the correct order.  Arrays
623        * store 5 successive words in the aux. table:
624        *	word 0	RNDXR to type of the bounds (i.e., int)
625        *	word 1	Current file descriptor index
626        *	word 2	low bound
627        *	word 3	high bound (or -1 if [])
628        *	word 4	stride size in bits
629        */
630       for (i = 0; i < 7; i++)
631 	{
632 	  if (qualifiers[i].type == tq_Array)
633 	    {
634 	      qualifiers[i].low_bound  = aux_ptr[index+2].dnLow;
635 	      qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
636 	      qualifiers[i].stride     = aux_ptr[index+4].width;
637 	      used_ptr[index] = 1;
638 	      used_ptr[index+1] = 1;
639 	      used_ptr[index+2] = 1;
640 	      used_ptr[index+3] = 1;
641 	      used_ptr[index+4] = 1;
642 	      index += 5;
643 	    }
644 	}
645 
646       /*
647        * Now print out the qualifiers.
648        */
649       for (i = 0; i < 6; i++)
650 	{
651 	  switch (qualifiers[i].type)
652 	    {
653 	    case tq_Nil:
654 	    case tq_Max:
655 	      break;
656 
657 	    case tq_Ptr:
658 	      strcpy (p2, "ptr to ");
659 	      p2 += sizeof ("ptr to ")-1;
660 	      break;
661 
662 	    case tq_Vol:
663 	      strcpy (p2, "volatile ");
664 	      p2 += sizeof ("volatile ")-1;
665 	      break;
666 
667 	    case tq_Far:
668 	      strcpy (p2, "far ");
669 	      p2 += sizeof ("far ")-1;
670 	      break;
671 
672 	    case tq_Proc:
673 	      strcpy (p2, "func. ret. ");
674 	      p2 += sizeof ("func. ret. ");
675 	      break;
676 
677 	    case tq_Array:
678 	      {
679 		int first_array = i;
680 		int j;
681 
682 		/* Print array bounds reversed (i.e., in the order the C
683 		   programmer writes them).  C is such a fun language....  */
684 
685 		while (i < 5 && qualifiers[i+1].type == tq_Array)
686 		  i++;
687 
688 		for (j = i; j >= first_array; j--)
689 		  {
690 		    strcpy (p2, "array [");
691 		    p2 += sizeof ("array [")-1;
692 		    if (qualifiers[j].low_bound != 0)
693 		      sprintf (p2,
694 			       "%ld:%ld {%ld bits}",
695 			       (long) qualifiers[j].low_bound,
696 			       (long) qualifiers[j].high_bound,
697 			       (long) qualifiers[j].stride);
698 
699 		    else if (qualifiers[j].high_bound != -1)
700 		      sprintf (p2,
701 			       "%ld {%ld bits}",
702 			       (long) (qualifiers[j].high_bound + 1),
703 			       (long) (qualifiers[j].stride));
704 
705 		    else
706 		      sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
707 
708 		    p2 += strlen (p2);
709 		    strcpy (p2, "] of ");
710 		    p2 += sizeof ("] of ")-1;
711 		  }
712 	      }
713 	      break;
714 	    }
715 	}
716     }
717 
718   strcpy (p2, buffer1);
719   return buffer2;
720 }
721 
722 
723 /* Print out the global file header for object files.  */
724 
725 static void
726 print_global_hdr (struct filehdr *ptr)
727 {
728   char *time = ctime ((time_t *)&ptr->f_timdat);
729   ushort flags = ptr->f_flags;
730 
731   printf("Global file header:\n");
732   printf("    %-*s 0x%x\n",    24, "magic number",	     (ushort) ptr->f_magic);
733   printf("    %-*s %d\n",      24, "# sections",	     (int)    ptr->f_nscns);
734   printf("    %-*s %ld, %s",   24, "timestamp",		     (long)   ptr->f_timdat, time);
735   printf("    %-*s %ld\n",     24, "symbolic header offset", (long)   ptr->f_symptr);
736   printf("    %-*s %ld\n",     24, "symbolic header size",   (long)   ptr->f_nsyms);
737   printf("    %-*s %ld\n",     24, "optional header",	     (long)   ptr->f_opthdr);
738   printf("    %-*s 0x%x",     24, "flags",		     (ushort) flags);
739 
740   if ((flags & F_RELFLG) != 0)
741     printf (", F_RELFLG");
742 
743   if ((flags & F_EXEC) != 0)
744     printf (", F_EXEC");
745 
746   if ((flags & F_LNNO) != 0)
747     printf (", F_LNNO");
748 
749   if ((flags & F_LSYMS) != 0)
750     printf (", F_LSYMS");
751 
752   if ((flags & F_MINMAL) != 0)
753     printf (", F_MINMAL");
754 
755   if ((flags & F_UPDATE) != 0)
756     printf (", F_UPDATE");
757 
758   if ((flags & F_SWABD) != 0)
759     printf (", F_SWABD");
760 
761   if ((flags & F_AR16WR) != 0)
762     printf (", F_AR16WR");
763 
764   if ((flags & F_AR32WR) != 0)
765     printf (", F_AR32WR");
766 
767   if ((flags & F_AR32W) != 0)
768     printf (", F_AR32W");
769 
770   if ((flags & F_PATCH) != 0)
771     printf (", F_PATCH/F_NODF");
772 
773   printf ("\n\n");
774 }
775 
776 
777 /* Print out the symbolic header.  */
778 
779 static void
780 print_sym_hdr (HDRR *sym_ptr)
781 {
782   int width = 20;
783 
784   printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
785 	 sym_ptr->magic & 0xffff,
786 	 (sym_ptr->vstamp & 0xffff) >> 8,
787 	 sym_ptr->vstamp & 0xff);
788 
789   printf("    %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
790   printf("    %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
791 
792   printf("    %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
793 	 (long) sym_ptr->cbLineOffset,
794 	 (long) sym_ptr->cbLine,
795 	 (long) sym_ptr->cbLine,
796 	 (int) sym_ptr->ilineMax);
797 
798   printf("    %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
799 	 (long) sym_ptr->cbDnOffset,
800 	 (long) sym_ptr->idnMax,
801 	 (long) (sym_ptr->idnMax * sizeof (DNR)));
802 
803   printf("    %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
804 	 (long) sym_ptr->cbPdOffset,
805 	 (long) sym_ptr->ipdMax,
806 	 (long) (sym_ptr->ipdMax * sizeof (PDR)));
807 
808   printf("    %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
809 	 (long) sym_ptr->cbSymOffset,
810 	 (long) sym_ptr->isymMax,
811 	 (long) (sym_ptr->isymMax * sizeof (SYMR)));
812 
813   printf("    %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
814 	 (long) sym_ptr->cbOptOffset,
815 	 (long) sym_ptr->ioptMax,
816 	 (long) (sym_ptr->ioptMax * sizeof (OPTR)));
817 
818   printf("    %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
819 	 (long) sym_ptr->cbAuxOffset,
820 	 (long) sym_ptr->iauxMax,
821 	 (long) (sym_ptr->iauxMax * sizeof (AUXU)));
822 
823   printf("    %-*s %11ld %11ld %11ld\n", width, "Local Strings",
824 	 (long) sym_ptr->cbSsOffset,
825 	 (long) sym_ptr->issMax,
826 	 (long) sym_ptr->issMax);
827 
828   printf("    %-*s %11ld %11ld %11ld\n", width, "External Strings",
829 	 (long) sym_ptr->cbSsExtOffset,
830 	 (long) sym_ptr->issExtMax,
831 	 (long) sym_ptr->issExtMax);
832 
833   printf("    %-*s %11ld %11ld %11ld\n", width, "File Tables",
834 	 (long) sym_ptr->cbFdOffset,
835 	 (long) sym_ptr->ifdMax,
836 	 (long) (sym_ptr->ifdMax * sizeof (FDR)));
837 
838   printf("    %-*s %11ld %11ld %11ld\n", width, "Relative Files",
839 	 (long) sym_ptr->cbRfdOffset,
840 	 (long) sym_ptr->crfd,
841 	 (long) (sym_ptr->crfd * sizeof (ulong)));
842 
843   printf("    %-*s %11ld %11ld %11ld\n", width, "External Symbols",
844 	 (long) sym_ptr->cbExtOffset,
845 	 (long) sym_ptr->iextMax,
846 	 (long) (sym_ptr->iextMax * sizeof (EXTR)));
847 }
848 
849 
850 /* Print out a symbol.  */
851 
852 static void
853 print_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base,
854 	      int ifd, FDR *fdp)
855 {
856   sc_t storage_class = (sc_t) sym_ptr->sc;
857   st_t symbol_type   = (st_t) sym_ptr->st;
858   ulong index	     = sym_ptr->index;
859   char *used_ptr     = aux_used + (aux_base - aux_symbols);
860   scope_t *scope_ptr;
861 
862   printf ("\n    Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
863 
864   if (aux_base != (AUXU *) 0 && index != indexNil)
865     switch (symbol_type)
866       {
867       case st_Nil:
868       case st_Label:
869 	break;
870 
871       case st_File:
872       case st_Block:
873 	printf ("      End+1 symbol: %ld\n", index);
874 	if (want_scope)
875 	  {
876 	    if (free_scope == (scope_t *) 0)
877 	      scope_ptr = (scope_t *) xmalloc (sizeof (scope_t));
878 	    else
879 	      {
880 		scope_ptr = free_scope;
881 		free_scope = scope_ptr->prev;
882 	      }
883 	    scope_ptr->open_sym = number;
884 	    scope_ptr->st = symbol_type;
885 	    scope_ptr->sc = storage_class;
886 	    scope_ptr->prev = cur_scope;
887 	    cur_scope = scope_ptr;
888 	  }
889 	break;
890 
891       case st_End:
892 	if (storage_class == sc_Text || storage_class == sc_Info)
893 	  printf ("      First symbol: %ld\n", index);
894 	else
895 	  {
896 	    used_ptr[index] = 1;
897 	    printf ("      First symbol: %ld\n", (long) aux_base[index].isym);
898 	  }
899 
900 	if (want_scope)
901 	  {
902 	    if (cur_scope == (scope_t *) 0)
903 	      printf ("      Can't pop end scope\n");
904 	    else
905 	      {
906 		scope_ptr = cur_scope;
907 		cur_scope = scope_ptr->prev;
908 		scope_ptr->prev = free_scope;
909 		free_scope = scope_ptr;
910 	      }
911 	  }
912 	break;
913 
914       case st_Proc:
915       case st_StaticProc:
916 	if (MIPS_IS_STAB(sym_ptr))
917 	  ;
918 	else if (ifd == -1)		/* local symbol */
919 	  {
920 	    used_ptr[index] = used_ptr[index+1] = 1;
921 	    printf ("      End+1 symbol: %-7ld   Type:  %s\n",
922 		    (long) aux_base[index].isym,
923 		    type_to_string (aux_base, index+1, fdp));
924 	  }
925 	else			/* global symbol */
926 	  printf ("      Local symbol: %ld\n", index);
927 
928 	if (want_scope)
929 	  {
930 	    if (free_scope == (scope_t *) 0)
931 	      scope_ptr = (scope_t *) xmalloc (sizeof (scope_t));
932 	    else
933 	      {
934 		scope_ptr = free_scope;
935 		free_scope = scope_ptr->prev;
936 	      }
937 	    scope_ptr->open_sym = number;
938 	    scope_ptr->st = symbol_type;
939 	    scope_ptr->sc = storage_class;
940 	    scope_ptr->prev = cur_scope;
941 	    cur_scope = scope_ptr;
942 	  }
943 	break;
944 
945 #ifdef stStruct
946       case st_Struct:
947       case st_Union:
948       case st_Enum:
949 	printf ("      End+1 symbol: %lu\n", index);
950 	break;
951 #endif
952 
953       default:
954 	if (!MIPS_IS_STAB (sym_ptr))
955 	  {
956 	    used_ptr[index] = 1;
957 	    printf ("      Type: %s\n",
958 		    type_to_string (aux_base, index, fdp));
959 	  }
960 	break;
961       }
962 
963   if (want_scope)
964     {
965       printf ("      Scopes:  ");
966       if (cur_scope == (scope_t *) 0)
967 	printf (" none\n");
968       else
969 	{
970 	  for (scope_ptr = cur_scope;
971 	       scope_ptr != (scope_t *) 0;
972 	       scope_ptr = scope_ptr->prev)
973 	    {
974 	      const char *sclass;
975 	      if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
976 		sclass = "func.";
977 	      else if (scope_ptr->st == st_File)
978 		sclass = "file";
979 	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
980 		sclass = "block";
981 	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
982 		sclass = "type";
983 	      else
984 		sclass = "???";
985 
986 	      printf (" %ld [%s]", scope_ptr->open_sym, sclass);
987 	    }
988 	  printf ("\n");
989 	}
990     }
991 
992   printf ("      Value: %-13ld    ",
993 	  (long)sym_ptr->value);
994   if (ifd == -1)
995     printf ("String index: %ld\n", (long)sym_ptr->iss);
996   else
997     printf ("String index: %-11ld Ifd: %d\n",
998 	    (long)sym_ptr->iss, ifd);
999 
1000   printf ("      Symbol type: %-11sStorage class: %-11s",
1001 	  st_to_string (symbol_type), sc_to_string (storage_class));
1002 
1003   if (MIPS_IS_STAB(sym_ptr))
1004     {
1005       int i = ARRAY_SIZE (stab_names);
1006       const char *stab_name = "stab";
1007       short code = MIPS_UNMARK_STAB(sym_ptr->index);
1008 
1009       while (--i >= 0)
1010 	if (stab_names[i].code == code)
1011 	  {
1012 	    stab_name = stab_names[i].string;
1013 	    break;
1014 	  }
1015       printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
1016     }
1017   else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
1018     printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
1019   else
1020     printf ("Index: %ld\n", (long)sym_ptr->index);
1021 
1022 }
1023 
1024 
1025 /* Print out a word from the aux. table in various formats.  */
1026 
1027 static void
1028 print_aux (AUXU u, int auxi, int used)
1029 {
1030   printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1031 	  (used) ? "  " : "* ",
1032 	  auxi,
1033 	  (long) u.isym,
1034 	  (long) u.rndx.rfd,
1035 	  (long) u.rndx.index,
1036 	  u.ti.bt,
1037 	  u.ti.fBitfield,
1038 	  u.ti.continued,
1039 	  u.ti.tq0,
1040 	  u.ti.tq1,
1041 	  u.ti.tq2,
1042 	  u.ti.tq3,
1043 	  u.ti.tq4,
1044 	  u.ti.tq5);
1045 }
1046 
1047 
1048 /* Write aggregate information to a string.  */
1049 
1050 static void
1051 emit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp)
1052 {
1053   unsigned int ifd = u.rndx.rfd;
1054   unsigned int index = u.rndx.index;
1055   const char *name;
1056 
1057   if (ifd == ST_RFDESCAPE)
1058     ifd = u2.isym;
1059 
1060   /* An ifd of -1 is an opaque type.  An escaped index of 0 is a
1061      struct return type of a procedure compiled without -g.  */
1062   if (ifd == 0xffffffff
1063       || (u.rndx.rfd == ST_RFDESCAPE && index == 0))
1064     name = "<undefined>";
1065   else if (index == indexNil)
1066     name = "<no name>";
1067   else
1068     {
1069       if (fdp == 0 || sym_hdr.crfd == 0)
1070 	fdp = &file_desc[ifd];
1071       else
1072 	fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]];
1073       name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss];
1074     }
1075 
1076   sprintf (string,
1077 	   "%s %s { ifd = %u, index = %u }",
1078 	   which, name, ifd, index);
1079 }
1080 
1081 
1082 /* Print out information about a file descriptor, and the symbols,
1083    procedures, and line numbers within it.  */
1084 
1085 static void
1086 print_file_desc (FDR *fdp, int number)
1087 {
1088   char *str_base;
1089   AUXU *aux_base;
1090   int symi, pdi;
1091   int width = 20;
1092   char *used_base;
1093 
1094   str_base = l_strings + fdp->issBase;
1095   aux_base = aux_symbols + fdp->iauxBase;
1096   used_base = aux_used + (aux_base - aux_symbols);
1097 
1098   printf ("\nFile #%d, \"%s\"\n\n",
1099 	  number,
1100 	  fdp->rss != issNil ? str_base + fdp->rss : "<unknown>");
1101 
1102   printf ("    Name index  = %-10ld Readin      = %s\n",
1103 	  (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1104 
1105   printf ("    Merge       = %-10s Endian      = %s\n",
1106 	  (fdp->fMerge)  ? "Yes" : "No",
1107 	  (fdp->fBigendian) ? "BIG" : "LITTLE");
1108 
1109   printf ("    Debug level = %-10s Language    = %s\n",
1110 	  glevel_to_string ((glevel_t) fdp->glevel),
1111 	  lang_to_string((lang_t) fdp->lang));
1112 
1113   printf ("    Adr         = 0x%08lx\n\n", (long) fdp->adr);
1114 
1115   printf("    %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1116   printf("    %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1117 
1118   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1119 	 width, "Local strings",
1120 	 (ulong) fdp->issBase,
1121 	 (ulong) fdp->cbSs,
1122 	 (ulong) fdp->cbSs,
1123 	 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1124 
1125   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1126 	 width, "Local symbols",
1127 	 (ulong) fdp->isymBase,
1128 	 (ulong) fdp->csym,
1129 	 (ulong) (fdp->csym * sizeof (SYMR)),
1130 	 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1131 
1132   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1133 	 width, "Line numbers",
1134 	 (ulong) fdp->cbLineOffset,
1135 	 (ulong) fdp->cline,
1136 	 (ulong) fdp->cbLine,
1137 	 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1138 
1139   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1140 	 width, "Optimization symbols",
1141 	 (ulong) fdp->ioptBase,
1142 	 (ulong) fdp->copt,
1143 	 (ulong) (fdp->copt * sizeof (OPTR)),
1144 	 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1145 
1146   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1147 	 width, "Procedures",
1148 	 (ulong) fdp->ipdFirst,
1149 	 (ulong) fdp->cpd,
1150 	 (ulong) (fdp->cpd * sizeof (PDR)),
1151 	 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1152 
1153   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1154 	 width, "Auxiliary symbols",
1155 	 (ulong) fdp->iauxBase,
1156 	 (ulong) fdp->caux,
1157 	 (ulong) (fdp->caux * sizeof (AUXU)),
1158 	 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1159 
1160   printf("    %-*s %11lu %11lu %11lu %11lu\n",
1161 	 width, "Relative Files",
1162 	 (ulong) fdp->rfdBase,
1163 	 (ulong) fdp->crfd,
1164 	 (ulong) (fdp->crfd * sizeof (ulong)),
1165 	 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1166 
1167 
1168   if (want_scope && cur_scope != (scope_t *) 0)
1169     printf ("\n    Warning scope does not start at 0!\n");
1170 
1171   /*
1172    * print the info about the symbol table.
1173    */
1174   printf ("\n    There are %lu local symbols, starting at %lu\n",
1175 	  (ulong) fdp->csym,
1176 	  (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1177 
1178   for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1179     print_symbol (&l_symbols[symi],
1180 		  symi - fdp->isymBase,
1181 		  str_base,
1182 		  aux_base,
1183 		  -1,
1184 		  fdp);
1185 
1186   if (want_scope && cur_scope != (scope_t *) 0)
1187     printf ("\n    Warning scope does not end at 0!\n");
1188 
1189   /*
1190    * print the aux. table if desired.
1191    */
1192 
1193   if (want_aux && fdp->caux != 0)
1194     {
1195       int auxi;
1196 
1197       printf ("\n    There are %lu auxiliary table entries, starting at %lu.\n\n",
1198 	      (ulong) fdp->caux,
1199 	      (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1200 
1201       for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1202 	print_aux (aux_base[auxi], auxi, used_base[auxi]);
1203     }
1204 
1205   /*
1206    * print the relative file descriptors.
1207    */
1208   if (want_rfd && fdp->crfd != 0)
1209     {
1210       ulong *rfd_ptr, i;
1211 
1212       printf ("\n    There are %lu relative file descriptors, starting at %lu.\n",
1213 	      (ulong) fdp->crfd,
1214 	      (ulong) fdp->rfdBase);
1215 
1216       rfd_ptr = rfile_desc + fdp->rfdBase;
1217       for (i = 0; i < (ulong) fdp->crfd; i++)
1218 	{
1219 	  printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1220 	  rfd_ptr++;
1221 	}
1222     }
1223 
1224   /*
1225    * do the procedure descriptors.
1226    */
1227   printf ("\n    There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1228   printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1229 
1230   for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1231     {
1232       PDR *proc_ptr = &proc_desc[pdi];
1233       printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1234 
1235       if (l_symbols != 0)
1236 	printf ("\t    Name index   = %-11ld Name          = \"%s\"\n",
1237 		(long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1238 		l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1239 
1240       printf ("\t    .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1241 	      (long) proc_ptr->regmask,
1242 	      (long) proc_ptr->regoffset,
1243 	      (long) proc_ptr->fregmask,
1244 	      (long) proc_ptr->fregoffset);
1245 
1246       printf ("\t    .frame $%d,%ld,$%d\n",
1247 	      (int)  proc_ptr->framereg,
1248 	      (long) proc_ptr->frameoffset,
1249 	      (int)  proc_ptr->pcreg);
1250 
1251       printf ("\t    Opt. start   = %-11ld Symbols start = %ld\n",
1252 	      (long) proc_ptr->iopt,
1253 	      (long) proc_ptr->isym);
1254 
1255       printf ("\t    First line # = %-11ld Last line #   = %ld\n",
1256 	      (long) proc_ptr->lnLow,
1257 	      (long) proc_ptr->lnHigh);
1258 
1259       printf ("\t    Line Offset  = %-11ld Address       = 0x%08lx\n",
1260 	      (long) proc_ptr->cbLineOffset,
1261 	      (long) proc_ptr->adr);
1262 
1263       /*
1264        * print the line number entries.
1265        */
1266 
1267       if (want_line && fdp->cline != 0)
1268 	{
1269 	  int delta, count;
1270 	  long cur_line = proc_ptr->lnLow;
1271 	  uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset
1272 			     + fdp->cbLineOffset);
1273 	  uchar *line_end;
1274 
1275 	  if (pdi == fdp->cpd + fdp->ipdFirst - 1)	/* last procedure */
1276 	    line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
1277 	  else						/* not last proc.  */
1278 	    line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
1279 			+ fdp->cbLineOffset);
1280 
1281 	  printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1282 		  (ulong) (line_end - line_ptr),
1283 		  (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1284 
1285 	  while (line_ptr < line_end)
1286 	    {						/* sign extend nibble */
1287 	      delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1288 	      count = (*line_ptr & 0xf) + 1;
1289 	      if (delta != -8)
1290 		line_ptr++;
1291 	      else
1292 		{
1293 		  delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1294 		  delta = (delta ^ 0x8000) - 0x8000;
1295 		  line_ptr += 3;
1296 		}
1297 
1298 	      cur_line += delta;
1299 	      printf ("\t    Line %11ld,   delta %5d,   count %2d\n",
1300 		      cur_line,
1301 		      delta,
1302 		      count);
1303 	    }
1304 	}
1305     }
1306 }
1307 
1308 
1309 /* Read in the portions of the .T file that we will print out.  */
1310 
1311 static void
1312 read_tfile (void)
1313 {
1314   short magic;
1315   off_t sym_hdr_offset = 0;
1316 
1317   read_seek (&magic, sizeof (magic), 0, "Magic number");
1318   if (!tfile)
1319     {
1320       /* Print out the global header, since this is not a T-file.  */
1321 
1322       read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header");
1323 
1324       print_global_hdr (&global_hdr);
1325 
1326       if (global_hdr.f_symptr == 0)
1327 	{
1328 	  printf ("No symbolic header, Goodbye!\n");
1329 	  exit (1);
1330 	}
1331 
1332       sym_hdr_offset = global_hdr.f_symptr;
1333     }
1334 
1335   read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header");
1336 
1337   print_sym_hdr (&sym_hdr);
1338 
1339   lines = (LINER *) read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset,
1340 			       "Line numbers");
1341 
1342   dense_nums = (DNR *) read_seek (NULL, sym_hdr.idnMax * sizeof (DNR),
1343 				  sym_hdr.cbDnOffset, "Dense numbers");
1344 
1345   proc_desc = (PDR *) read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR),
1346 				 sym_hdr.cbPdOffset, "Procedure tables");
1347 
1348   l_symbols = (SYMR *) read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR),
1349 				  sym_hdr.cbSymOffset, "Local symbols");
1350 
1351   opt_symbols = (OPTR *) read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR),
1352 				    sym_hdr.cbOptOffset,
1353 				    "Optimization symbols");
1354 
1355   aux_symbols = (AUXU *) read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU),
1356 				    sym_hdr.cbAuxOffset, "Auxiliary symbols");
1357 
1358   if (sym_hdr.iauxMax > 0)
1359     aux_used = (char *) xcalloc (sym_hdr.iauxMax, 1);
1360 
1361   l_strings = (char *) read_seek (NULL, sym_hdr.issMax,
1362 				  sym_hdr.cbSsOffset, "Local string table");
1363 
1364   e_strings = (char *) read_seek (NULL, sym_hdr.issExtMax,
1365 				  sym_hdr.cbSsExtOffset,
1366 				  "External string table");
1367 
1368   file_desc = (FDR *) read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR),
1369 				 sym_hdr.cbFdOffset, "File tables");
1370 
1371   rfile_desc = (ulong *) read_seek (NULL, sym_hdr.crfd * sizeof (ulong),
1372 				    sym_hdr.cbRfdOffset,
1373 				    "Relative file tables");
1374 
1375   e_symbols = (EXTR *) read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR),
1376 				  sym_hdr.cbExtOffset, "External symbols");
1377 }
1378 
1379 
1380 
1381 extern int main (int, char **);
1382 
1383 int
1384 main (int argc, char **argv)
1385 {
1386   int i, opt;
1387 
1388   /*
1389    * Process arguments
1390    */
1391   while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1)
1392     switch (opt)
1393       {
1394       default:	errors++;	break;
1395       case 'a': want_aux++;	break;	/* print aux table */
1396       case 'l': want_line++;	break;	/* print line numbers */
1397       case 'r': want_rfd++;	break;	/* print relative fd's */
1398       case 's':	want_scope++;	break;	/* print scope info */
1399       case 'v': verbose++;	break;  /* print version # */
1400       case 'V': version++;	break;  /* print version # */
1401       case 't': tfile++;	break;	/* this is a tfile (without header),
1402 					   and not a .o */
1403       }
1404 
1405   if (version)
1406     {
1407       printf ("mips-tdump %s%s\n", pkgversion_string, version_string);
1408       fputs ("Copyright (C) 2012 Free Software Foundation, Inc.\n", stdout);
1409       fputs ("This is free software; see the source for copying conditions.  There is NO\n\
1410 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n",
1411              stdout);
1412       exit (0);
1413     }
1414 
1415   if (optind != argc - 1)
1416     errors++;
1417 
1418   if (verbose || errors)
1419     fprintf (stderr, "mips-tdump (GCC) %s\n", version_string);
1420 
1421   if (errors)
1422     {
1423       fprintf (stderr, "Calling Sequence:\n");
1424       fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]);
1425       fprintf (stderr, "\n");
1426       fprintf (stderr, "switches:\n");
1427       fprintf (stderr, "\t-a Print out auxiliary table.\n");
1428       fprintf (stderr, "\t-l Print out line numbers.\n");
1429       fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1430       fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1431       fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
1432       fprintf (stderr, "\t-v Print program version.\n");
1433       return 1;
1434     }
1435 
1436   /*
1437    * Open and process the input file.
1438    */
1439   tfile_fd = open (argv[optind], O_RDONLY);
1440   if (tfile_fd < 0)
1441     {
1442       perror (argv[optind]);
1443       return 1;
1444     }
1445 
1446   read_tfile ();
1447 
1448   /*
1449    * Print any global aux words if any.
1450    */
1451   if (want_aux)
1452     {
1453       long last_aux_in_use;
1454 
1455       if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1456 	{
1457 	  printf ("\nGlobal auxiliary entries before first file:\n");
1458 	  for (i = 0; i < file_desc[0].iauxBase; i++)
1459 	    print_aux (aux_symbols[i], 0, aux_used[i]);
1460 	}
1461 
1462       if (sym_hdr.ifdMax == 0)
1463 	last_aux_in_use = 0;
1464       else
1465 	last_aux_in_use
1466 	  = (file_desc[sym_hdr.ifdMax-1].iauxBase
1467 	     + file_desc[sym_hdr.ifdMax-1].caux - 1);
1468 
1469       if (last_aux_in_use < sym_hdr.iauxMax-1)
1470 	{
1471 	  printf ("\nGlobal auxiliary entries after last file:\n");
1472 	  for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1473 	    print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1474 	}
1475     }
1476 
1477   /*
1478    * Print the information for each file.
1479    */
1480   for (i = 0; i < sym_hdr.ifdMax; i++)
1481     print_file_desc (&file_desc[i], i);
1482 
1483   /*
1484    * Print the external symbols.
1485    */
1486   want_scope = 0;		/* scope info is meaning for extern symbols */
1487   printf ("\nThere are %lu external symbols, starting at %lu\n",
1488 	  (ulong) sym_hdr.iextMax,
1489 	  (ulong) sym_hdr.cbExtOffset);
1490 
1491   for(i = 0; i < sym_hdr.iextMax; i++)
1492     print_symbol (&e_symbols[i].asym, i, e_strings,
1493 		  aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1494 		  e_symbols[i].ifd,
1495 		  &file_desc[e_symbols[i].ifd]);
1496 
1497   /*
1498    * Print unused aux symbols now.
1499    */
1500 
1501   if (want_aux)
1502     {
1503       int first_time = 1;
1504 
1505       for (i = 0; i < sym_hdr.iauxMax; i++)
1506 	{
1507 	  if (! aux_used[i])
1508 	    {
1509 	      if (first_time)
1510 		{
1511 		  printf ("\nThe following auxiliary table entries were unused:\n\n");
1512 		  first_time = 0;
1513 		}
1514 
1515 	      printf ("    #%-5d %11ld  0x%08lx  %s\n",
1516 		      i,
1517 		      (long) aux_symbols[i].isym,
1518 		      (long) aux_symbols[i].isym,
1519 		      type_to_string (aux_symbols, i, (FDR *) 0));
1520 	    }
1521 	}
1522     }
1523 
1524   return 0;
1525 }
1526