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