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
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 3, or (at your option) any later
12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License
20along 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
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
71typedef 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
100typedef 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
132typedef 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
144typedef 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
177typedef 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
191typedef 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
199/* Keep track of the active scopes.  */
200typedef 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
207struct filehdr global_hdr;	/* a.out header */
208
209int	 errors		= 0;	/* # of errors */
210int	 want_aux	= 0;	/* print aux table */
211int	 want_line	= 0;	/* print line numbers */
212int	 want_rfd	= 0;	/* print relative file desc's */
213int	 want_scope	= 0;	/* print scopes for every symbol */
214int	 tfile		= 0;	/* no global header file */
215int	 version	= 0;    /* print version # */
216int	 verbose	= 0;
217int	 tfile_fd;		/* file descriptor of .T file */
218off_t	 tfile_offset;		/* current offset in .T file */
219scope_t	*cur_scope	= 0;	/* list of active scopes */
220scope_t	*free_scope	= 0;	/* list of freed scopes */
221HDRR	 sym_hdr;		/* symbolic header */
222char	*l_strings;		/* local strings */
223char	*e_strings;		/* external strings */
224SYMR	*l_symbols;		/* local symbols */
225EXTR	*e_symbols;		/* external symbols */
226LINER	*lines;			/* line numbers */
227DNR	*dense_nums;		/* dense numbers */
228OPTR	*opt_symbols;		/* optimization symbols */
229AUXU	*aux_symbols;		/* Auxiliary symbols */
230char	*aux_used;		/* map of which aux syms are used */
231FDR	*file_desc;		/* file tables */
232ulong	*rfile_desc;		/* relative file tables */
233PDR	*proc_desc;		/* procedure tables */
234
235/* Forward reference for functions.  */
236static void *read_seek (void *, size_t, off_t, const char *);
237static void read_tfile (void);
238static void print_global_hdr (struct filehdr *);
239static void print_sym_hdr (HDRR *);
240static void print_file_desc (FDR *, int);
241static void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
242static void print_aux (AUXU, int, int);
243static void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
244static const char *st_to_string (st_t);
245static const char *sc_to_string (sc_t);
246static const char *glevel_to_string (glevel_t);
247static const char *lang_to_string (lang_t);
248static const char *type_to_string (AUXU *, int, FDR *);
249
250extern char *optarg;
251extern int   optind;
252extern 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},
257const 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
264static const struct option options[] =
265{
266  { "version", 0, 0, 'V' },
267  { "verbose", 0, 0, 'v' },
268  { 0, 0, 0, 0 }
269};
270
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
276static void *
277read_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
306/* Convert language code to string format.  */
307
308static const char *
309lang_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
328/* Convert storage class to string.  */
329
330static const char *
331sc_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
365/* Convert symbol type to string.  */
366
367static const char *
368st_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
405/* Convert debug level to string.  */
406
407static const char *
408glevel_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
422/* Convert the type information to string format.  */
423
424static const char *
425type_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
732/* Print out the global file header for object files.  */
733
734static void
735print_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
786/* Print out the symbolic header.  */
787
788static void
789print_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
859/* Print out a symbol.  */
860
861static void
862print_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
1034/* Print out a word from the aux. table in various formats.  */
1035
1036static void
1037print_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
1057/* Write aggregate information to a string.  */
1058
1059static void
1060emit_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
1091/* Print out information about a file descriptor, and the symbols,
1092   procedures, and line numbers within it.  */
1093
1094static void
1095print_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
1318/* Read in the portions of the .T file that we will print out.  */
1319
1320static void
1321read_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
1389
1390extern int main (int, char **);
1391
1392int
1393main (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\
1419warranty; 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}
1541