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