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