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