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