OSDN Git Service

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