mips-tdump.c revision 169689
1294838Szbb/* Read and manage MIPS symbol tables from object modules.
2294838Szbb   Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
3294838Szbb   2006 Free Software Foundation, Inc.
4294838Szbb   Contributed by hartzell@boulder.colorado.edu,
5294838Szbb   Rewritten by meissner@osf.org.
6294838Szbb
7294838SzbbThis file is part of GCC.
8294838Szbb
9294838SzbbGCC is free software; you can redistribute it and/or modify it under
10294838Szbbthe terms of the GNU General Public License as published by the Free
11294838SzbbSoftware Foundation; either version 2, or (at your option) any later
12294838Szbbversion.
13294838Szbb
14294838SzbbGCC is distributed in the hope that it will be useful, but WITHOUT ANY
15294838SzbbWARRANTY; without even the implied warranty of MERCHANTABILITY or
16294838SzbbFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17294838Szbbfor more details.
18294838Szbb
19294838SzbbYou should have received a copy of the GNU General Public License
20294838Szbbalong with GCC; see the file COPYING.  If not, write to the Free
21294838SzbbSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22294838Szbb02110-1301, USA.  */
23294838Szbb
24294838Szbb#include "config.h"
25294838Szbb#include "system.h"
26294838Szbb#include "coretypes.h"
27294838Szbb#include "tm.h"
28294838Szbb#include "version.h"
29294838Szbb#ifdef index
30294838Szbb#undef index
31294838Szbb#endif
32294838Szbb#ifndef CROSS_COMPILE
33294838Szbb#include <a.out.h>
34294838Szbb#else
35294838Szbb#include "mips/a.out.h"
36294838Szbb#endif /* CROSS_COMPILE */
37294838Szbb
38294838Szbb/* Include getopt.h for the sake of getopt_long.  */
39294838Szbb#include "getopt.h"
40294838Szbb
41294838Szbb#ifndef MIPS_IS_STAB
42294838Szbb/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
43294838Szbb   and mips-tdump.c to print them out.  This is used on the Alpha,
44294838Szbb   which does not include mips.h.
45294838Szbb
46294838Szbb   These must match the corresponding definitions in gdb/mipsread.c.
47294838Szbb   Unfortunately, gcc and gdb do not currently share any directories.  */
48294838Szbb
49294838Szbb#define CODE_MASK 0x8F300
50294838Szbb#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
51294838Szbb#define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
52294838Szbb#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
53294838Szbb#endif
54294838Szbb
55294838Szbb#define uchar	unsigned char
56294838Szbb#define ushort	unsigned short
57294838Szbb#define uint	unsigned int
58294838Szbb#define ulong	unsigned long
59294838Szbb
60294838Szbb
61294838Szbb/* Redefinition of storage classes as an enumeration for better
62294838Szbb   debugging.  */
63294838Szbb
64294838Szbb#ifndef stStaParam
65294838Szbb#define stStaParam	16	/* Fortran static parameters */
66294838Szbb#endif
67294838Szbb
68294838Szbb#ifndef btVoid
69294838Szbb#define btVoid		26	/* void basic type */
70294838Szbb#endif
71294838Szbb
72294838Szbbtypedef enum sc {
73294838Szbb  sc_Nil	 = scNil,	  /* no storage class */
74294838Szbb  sc_Text	 = scText,	  /* text symbol */
75294838Szbb  sc_Data	 = scData,	  /* initialized data symbol */
76294838Szbb  sc_Bss	 = scBss,	  /* un-initialized data symbol */
77294838Szbb  sc_Register	 = scRegister,	  /* value of symbol is register number */
78294838Szbb  sc_Abs	 = scAbs,	  /* value of symbol is absolute */
79294838Szbb  sc_Undefined	 = scUndefined,	  /* who knows? */
80294838Szbb  sc_CdbLocal	 = scCdbLocal,	  /* variable's value is IN se->va.?? */
81294838Szbb  sc_Bits	 = scBits,	  /* this is a bit field */
82294838Szbb  sc_CdbSystem	 = scCdbSystem,	  /* var's value is IN CDB's address space */
83294838Szbb  sc_RegImage	 = scRegImage,	  /* register value saved on stack */
84294838Szbb  sc_Info	 = scInfo,	  /* symbol contains debugger information */
85294838Szbb  sc_UserStruct	 = scUserStruct,  /* addr in struct user for current process */
86294838Szbb  sc_SData	 = scSData,	  /* load time only small data */
87294838Szbb  sc_SBss	 = scSBss,	  /* load time only small common */
88294838Szbb  sc_RData	 = scRData,	  /* load time only read only data */
89294838Szbb  sc_Var	 = scVar,	  /* Var parameter (fortran,pascal) */
90294838Szbb  sc_Common	 = scCommon,	  /* common variable */
91294838Szbb  sc_SCommon	 = scSCommon,	  /* small common */
92294838Szbb  sc_VarRegister = scVarRegister, /* Var parameter in a register */
93294838Szbb  sc_Variant	 = scVariant,	  /* Variant record */
94294838Szbb  sc_SUndefined	 = scSUndefined,  /* small undefined(external) data */
95294838Szbb  sc_Init	 = scInit,	  /* .init section symbol */
96294838Szbb  sc_Max	 = scMax	  /* Max storage class+1 */
97294838Szbb} sc_t;
98294838Szbb
99294838Szbb/* Redefinition of symbol type.  */
100294838Szbb
101294838Szbbtypedef enum st {
102294838Szbb  st_Nil	= stNil,	/* Nuthin' special */
103294838Szbb  st_Global	= stGlobal,	/* external symbol */
104294838Szbb  st_Static	= stStatic,	/* static */
105294838Szbb  st_Param	= stParam,	/* procedure argument */
106294838Szbb  st_Local	= stLocal,	/* local variable */
107294838Szbb  st_Label	= stLabel,	/* label */
108294838Szbb  st_Proc	= stProc,	/*     "      "	 Procedure */
109294838Szbb  st_Block	= stBlock,	/* beginning of block */
110294838Szbb  st_End	= stEnd,	/* end (of anything) */
111294838Szbb  st_Member	= stMember,	/* member (of anything	- struct/union/enum */
112294838Szbb  st_Typedef	= stTypedef,	/* type definition */
113294838Szbb  st_File	= stFile,	/* file name */
114294838Szbb  st_RegReloc	= stRegReloc,	/* register relocation */
115294838Szbb  st_Forward	= stForward,	/* forwarding address */
116294838Szbb  st_StaticProc	= stStaticProc,	/* load time only static procs */
117294838Szbb  st_StaParam	= stStaParam,	/* Fortran static parameters */
118294838Szbb  st_Constant	= stConstant,	/* const */
119294838Szbb#ifdef stStruct
120294838Szbb  st_Struct	= stStruct,	/* struct */
121294838Szbb  st_Union	= stUnion,	/* union */
122294838Szbb  st_Enum	= stEnum,	/* enum */
123294838Szbb#endif
124294838Szbb  st_Str	= stStr,	/* string */
125294838Szbb  st_Number	= stNumber,	/* pure number (i.e. 4 NOR 2+2) */
126294838Szbb  st_Expr	= stExpr,	/* 2+2 vs. 4 */
127294838Szbb  st_Type	= stType,	/* post-coercion SER */
128294838Szbb  st_Max	= stMax		/* max type+1 */
129294838Szbb} st_t;
130294838Szbb
131294838Szbb/* Redefinition of type qualifiers.  */
132294838Szbb
133294838Szbbtypedef enum tq {
134294838Szbb  tq_Nil	= tqNil,	/* bt is what you see */
135294838Szbb  tq_Ptr	= tqPtr,	/* pointer */
136294838Szbb  tq_Proc	= tqProc,	/* procedure */
137294838Szbb  tq_Array	= tqArray,	/* duh */
138294838Szbb  tq_Far	= tqFar,	/* longer addressing - 8086/8 land */
139294838Szbb  tq_Vol	= tqVol,	/* volatile */
140294838Szbb  tq_Max	= tqMax		/* Max type qualifier+1 */
141294838Szbb} tq_t;
142294838Szbb
143294838Szbb/* Redefinition of basic types.  */
144294838Szbb
145294838Szbbtypedef enum bt {
146294838Szbb  bt_Nil	= btNil,	/* undefined */
147294838Szbb  bt_Adr	= btAdr,	/* address - integer same size as pointer */
148294838Szbb  bt_Char	= btChar,	/* character */
149294838Szbb  bt_UChar	= btUChar,	/* unsigned character */
150294838Szbb  bt_Short	= btShort,	/* short */
151294838Szbb  bt_UShort	= btUShort,	/* unsigned short */
152294838Szbb  bt_Int	= btInt,	/* int */
153294838Szbb  bt_UInt	= btUInt,	/* unsigned int */
154294838Szbb  bt_Long	= btLong,	/* long */
155294838Szbb  bt_ULong	= btULong,	/* unsigned long */
156294838Szbb  bt_Float	= btFloat,	/* float (real) */
157294838Szbb  bt_Double	= btDouble,	/* Double (real) */
158294838Szbb  bt_Struct	= btStruct,	/* Structure (Record) */
159294838Szbb  bt_Union	= btUnion,	/* Union (variant) */
160294838Szbb  bt_Enum	= btEnum,	/* Enumerated */
161294838Szbb  bt_Typedef	= btTypedef,	/* defined via a typedef, isymRef points */
162294838Szbb  bt_Range	= btRange,	/* subrange of int */
163294838Szbb  bt_Set	= btSet,	/* pascal sets */
164294838Szbb  bt_Complex	= btComplex,	/* fortran complex */
165294838Szbb  bt_DComplex	= btDComplex,	/* fortran double complex */
166294838Szbb  bt_Indirect	= btIndirect,	/* forward or unnamed typedef */
167294838Szbb  bt_FixedDec	= btFixedDec,	/* Fixed Decimal */
168294838Szbb  bt_FloatDec	= btFloatDec,	/* Float Decimal */
169294838Szbb  bt_String	= btString,	/* Varying Length Character String */
170294838Szbb  bt_Bit	= btBit,	/* Aligned Bit String */
171294838Szbb  bt_Picture	= btPicture,	/* Picture */
172294838Szbb  bt_Void	= btVoid,	/* void */
173294838Szbb  bt_Max	= btMax		/* Max basic type+1 */
174294838Szbb} bt_t;
175294838Szbb
176294838Szbb/* Redefinition of the language codes.  */
177294838Szbb
178294838Szbbtypedef enum lang {
179294838Szbb  lang_C	 = langC,
180294838Szbb  lang_Pascal	 = langPascal,
181294838Szbb  lang_Fortran	 = langFortran,
182294838Szbb  lang_Assembler = langAssembler,
183294838Szbb  lang_Machine	 = langMachine,
184294838Szbb  lang_Nil	 = langNil,
185294838Szbb  lang_Ada	 = langAda,
186294838Szbb  lang_Pl1	 = langPl1,
187294838Szbb  lang_Cobol	 = langCobol
188294838Szbb} lang_t;
189294838Szbb
190294838Szbb/* Redefinition of the debug level codes.  */
191294838Szbb
192294838Szbbtypedef enum glevel {
193294838Szbb  glevel_0	= GLEVEL_0,
194294838Szbb  glevel_1	= GLEVEL_1,
195294838Szbb  glevel_2	= GLEVEL_2,
196294838Szbb  glevel_3	= GLEVEL_3
197294838Szbb} glevel_t;
198294838Szbb
199294838Szbb
200294838Szbb/* Keep track of the active scopes.  */
201294838Szbbtypedef struct scope {
202294838Szbb  struct scope *prev;		/* previous scope */
203294838Szbb  ulong open_sym;		/* symbol opening scope */
204294838Szbb  sc_t sc;			/* storage class */
205294838Szbb  st_t st;			/* symbol type */
206294838Szbb} scope_t;
207294838Szbb
208294838Szbbstruct filehdr global_hdr;	/* a.out header */
209294838Szbb
210294838Szbbint	 errors		= 0;	/* # of errors */
211294838Szbbint	 want_aux	= 0;	/* print aux table */
212294838Szbbint	 want_line	= 0;	/* print line numbers */
213294838Szbbint	 want_rfd	= 0;	/* print relative file desc's */
214294838Szbbint	 want_scope	= 0;	/* print scopes for every symbol */
215294838Szbbint	 tfile		= 0;	/* no global header file */
216294838Szbbint	 version	= 0;    /* print version # */
217294838Szbbint	 verbose	= 0;
218294838Szbbint	 tfile_fd;		/* file descriptor of .T file */
219294838Szbboff_t	 tfile_offset;		/* current offset in .T file */
220294838Szbbscope_t	*cur_scope	= 0;	/* list of active scopes */
221294838Szbbscope_t	*free_scope	= 0;	/* list of freed scopes */
222294838SzbbHDRR	 sym_hdr;		/* symbolic header */
223294838Szbbchar	*l_strings;		/* local strings */
224294838Szbbchar	*e_strings;		/* external strings */
225294838SzbbSYMR	*l_symbols;		/* local symbols */
226294838SzbbEXTR	*e_symbols;		/* external symbols */
227294838SzbbLINER	*lines;			/* line numbers */
228294838SzbbDNR	*dense_nums;		/* dense numbers */
229294838SzbbOPTR	*opt_symbols;		/* optimization symbols */
230294838SzbbAUXU	*aux_symbols;		/* Auxiliary symbols */
231294838Szbbchar	*aux_used;		/* map of which aux syms are used */
232294838SzbbFDR	*file_desc;		/* file tables */
233294838Szbbulong	*rfile_desc;		/* relative file tables */
234294838SzbbPDR	*proc_desc;		/* procedure tables */
235294838Szbb
236294838Szbb/* Forward reference for functions.  */
237294838Szbbstatic void *read_seek (void *, size_t, off_t, const char *);
238294838Szbbstatic void read_tfile (void);
239294838Szbbstatic void print_global_hdr (struct filehdr *);
240294838Szbbstatic void print_sym_hdr (HDRR *);
241294838Szbbstatic void print_file_desc (FDR *, int);
242294838Szbbstatic void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
243294838Szbbstatic void print_aux (AUXU, int, int);
244294838Szbbstatic void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
245294838Szbbstatic const char *st_to_string (st_t);
246294838Szbbstatic const char *sc_to_string (sc_t);
247294838Szbbstatic const char *glevel_to_string (glevel_t);
248294838Szbbstatic const char *lang_to_string (lang_t);
249294838Szbbstatic const char *type_to_string (AUXU *, int, FDR *);
250294838Szbb
251294838Szbbextern char *optarg;
252294838Szbbextern int   optind;
253294838Szbbextern int   opterr;
254294838Szbb
255294838Szbb/* Create a table of debugging stab-codes and corresponding names.  */
256294838Szbb
257294838Szbb#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
258294838Szbbconst struct {const short code; const char string[10];} stab_names[]  = {
259294838Szbb#include "stab.def"
260294838Szbb#undef __define_stab
261294838Szbb};
262294838Szbb
263294838Szbb/* Command line options for getopt_long.  */
264294838Szbb
265294838Szbbstatic const struct option options[] =
266294838Szbb{
267294838Szbb  { "version", 0, 0, 'V' },
268294838Szbb  { "verbose", 0, 0, 'v' },
269294838Szbb  { 0, 0, 0, 0 }
270294838Szbb};
271294838Szbb
272294838Szbb/* Read some bytes at a specified location, and return a pointer.
273294838Szbb   Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE
274294838Szbb   bytes from offset OFFSET.  In case of errors CONTEXT is used as
275294838Szbb   error message.  */
276294838Szbb
277294838Szbbstatic void *
278294838Szbbread_seek (void *ptr, size_t size, off_t offset,  const char *context)
279294838Szbb{
280294838Szbb  long read_size = 0;
281294838Szbb
282294838Szbb  if (size == 0)		/* nothing to read */
283294838Szbb    return ptr;
284294838Szbb
285294838Szbb  if (!ptr)
286294838Szbb    ptr = xmalloc (size);
287294838Szbb
288294838Szbb  if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
289294838Szbb      || (read_size = read (tfile_fd, ptr, size)) < 0)
290294838Szbb    {
291294838Szbb      perror (context);
292294838Szbb      exit (1);
293294838Szbb    }
294294838Szbb
295294838Szbb  if (read_size != (long) size)
296294838Szbb    {
297294838Szbb      fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
298294838Szbb	       context, read_size, (long) size);
299294838Szbb      exit (1);
300294838Szbb    }
301294838Szbb
302294838Szbb  tfile_offset = offset + size;
303294838Szbb  return ptr;
304294838Szbb}
305294838Szbb
306294838Szbb
307294838Szbb/* Convert language code to string format.  */
308294838Szbb
309294838Szbbstatic const char *
310294838Szbblang_to_string (lang_t lang)
311294838Szbb{
312294838Szbb  switch (lang)
313294838Szbb    {
314294838Szbb    case langC:		return "C";
315294838Szbb    case langPascal:	return "Pascal";
316294838Szbb    case langFortran:	return "Fortran";
317294838Szbb    case langAssembler:	return "Assembler";
318294838Szbb    case langMachine:	return "Machine";
319294838Szbb    case langNil:	return "Nil";
320294838Szbb    case langAda:	return "Ada";
321294838Szbb    case langPl1:	return "Pl1";
322294838Szbb    case langCobol:	return "Cobol";
323294838Szbb    }
324294838Szbb
325294838Szbb  return "Unknown language";
326294838Szbb}
327294838Szbb
328294838Szbb
329294838Szbb/* Convert storage class to string.  */
330294838Szbb
331294838Szbbstatic const char *
332294838Szbbsc_to_string (sc_t storage_class)
333294838Szbb{
334294838Szbb  switch(storage_class)
335294838Szbb    {
336294838Szbb    case sc_Nil:	 return "Nil";
337294838Szbb    case sc_Text:	 return "Text";
338294838Szbb    case sc_Data:	 return "Data";
339294838Szbb    case sc_Bss:	 return "Bss";
340294838Szbb    case sc_Register:	 return "Register";
341294838Szbb    case sc_Abs:	 return "Abs";
342294838Szbb    case sc_Undefined:	 return "Undefined";
343294838Szbb    case sc_CdbLocal:	 return "CdbLocal";
344294838Szbb    case sc_Bits:	 return "Bits";
345294838Szbb    case sc_CdbSystem:	 return "CdbSystem";
346294838Szbb    case sc_RegImage:	 return "RegImage";
347294838Szbb    case sc_Info:	 return "Info";
348294838Szbb    case sc_UserStruct:	 return "UserStruct";
349294838Szbb    case sc_SData:	 return "SData";
350294838Szbb    case sc_SBss:	 return "SBss";
351294838Szbb    case sc_RData:	 return "RData";
352294838Szbb    case sc_Var:	 return "Var";
353294838Szbb    case sc_Common:	 return "Common";
354294838Szbb    case sc_SCommon:	 return "SCommon";
355294838Szbb    case sc_VarRegister: return "VarRegister";
356294838Szbb    case sc_Variant:	 return "Variant";
357294838Szbb    case sc_SUndefined:	 return "SUndefined";
358294838Szbb    case sc_Init:	 return "Init";
359294838Szbb    case sc_Max:	 return "Max";
360294838Szbb    }
361294838Szbb
362294838Szbb  return "???";
363294838Szbb}
364294838Szbb
365294838Szbb
366294838Szbb/* Convert symbol type to string.  */
367294838Szbb
368294838Szbbstatic const char *
369294838Szbbst_to_string (st_t symbol_type)
370294838Szbb{
371294838Szbb  switch(symbol_type)
372294838Szbb    {
373294838Szbb    case st_Nil:	return "Nil";
374294838Szbb    case st_Global:	return "Global";
375294838Szbb    case st_Static:	return "Static";
376294838Szbb    case st_Param:	return "Param";
377294838Szbb    case st_Local:	return "Local";
378294838Szbb    case st_Label:	return "Label";
379294838Szbb    case st_Proc:	return "Proc";
380294838Szbb    case st_Block:	return "Block";
381294838Szbb    case st_End:	return "End";
382294838Szbb    case st_Member:	return "Member";
383294838Szbb    case st_Typedef:	return "Typedef";
384294838Szbb    case st_File:	return "File";
385294838Szbb    case st_RegReloc:	return "RegReloc";
386294838Szbb    case st_Forward:	return "Forward";
387294838Szbb    case st_StaticProc:	return "StaticProc";
388294838Szbb    case st_Constant:	return "Constant";
389294838Szbb    case st_StaParam:	return "StaticParam";
390294838Szbb#ifdef stStruct
391294838Szbb    case st_Struct:	return "Struct";
392294838Szbb    case st_Union:	return "Union";
393294838Szbb    case st_Enum:	return "Enum";
394294838Szbb#endif
395294838Szbb    case st_Str:	return "String";
396294838Szbb    case st_Number:	return "Number";
397294838Szbb    case st_Expr:	return "Expr";
398294838Szbb    case st_Type:	return "Type";
399294838Szbb    case st_Max:	return "Max";
400294838Szbb    }
401294838Szbb
402294838Szbb  return "???";
403294838Szbb}
404294838Szbb
405294838Szbb
406294838Szbb/* Convert debug level to string.  */
407294838Szbb
408294838Szbbstatic const char *
409294838Szbbglevel_to_string (glevel_t g_level)
410294838Szbb{
411294838Szbb  switch(g_level)
412294838Szbb    {
413294838Szbb    case GLEVEL_0: return "G0";
414294838Szbb    case GLEVEL_1: return "G1";
415    case GLEVEL_2: return "G2";
416    case GLEVEL_3: return "G3";
417    }
418
419  return "??";
420}
421
422
423/* Convert the type information to string format.  */
424
425static const char *
426type_to_string (AUXU *aux_ptr, int index, FDR *fdp)
427{
428  AUXU u;
429  struct qual {
430    tq_t type;
431    int  low_bound;
432    int  high_bound;
433    int  stride;
434  } qualifiers[7];
435
436  bt_t basic_type;
437  int i;
438  static char buffer1[1024];
439  static char buffer2[1024];
440  char *p1 = buffer1;
441  char *p2 = buffer2;
442  char *used_ptr = aux_used + (aux_ptr - aux_symbols);
443
444  for (i = 0; i < 7; i++)
445    {
446      qualifiers[i].low_bound = 0;
447      qualifiers[i].high_bound = 0;
448      qualifiers[i].stride = 0;
449    }
450
451  used_ptr[index] = 1;
452  u = aux_ptr[index++];
453  if (u.isym == -1)
454    return "-1 (no type)";
455
456  basic_type = (bt_t) u.ti.bt;
457  qualifiers[0].type = (tq_t) u.ti.tq0;
458  qualifiers[1].type = (tq_t) u.ti.tq1;
459  qualifiers[2].type = (tq_t) u.ti.tq2;
460  qualifiers[3].type = (tq_t) u.ti.tq3;
461  qualifiers[4].type = (tq_t) u.ti.tq4;
462  qualifiers[5].type = (tq_t) u.ti.tq5;
463  qualifiers[6].type = tq_Nil;
464
465  /*
466   * Go get the basic type.
467   */
468  switch (basic_type)
469    {
470    case bt_Nil:		/* undefined */
471      strcpy (p1, "nil");
472      break;
473
474    case bt_Adr:		/* address - integer same size as pointer */
475      strcpy (p1, "address");
476      break;
477
478    case bt_Char:		/* character */
479      strcpy (p1, "char");
480      break;
481
482    case bt_UChar:		/* unsigned character */
483      strcpy (p1, "unsigned char");
484      break;
485
486    case bt_Short:		/* short */
487      strcpy (p1, "short");
488      break;
489
490    case bt_UShort:		/* unsigned short */
491      strcpy (p1, "unsigned short");
492      break;
493
494    case bt_Int:		/* int */
495      strcpy (p1, "int");
496      break;
497
498    case bt_UInt:		/* unsigned int */
499      strcpy (p1, "unsigned int");
500      break;
501
502    case bt_Long:		/* long */
503      strcpy (p1, "long");
504      break;
505
506    case bt_ULong:		/* unsigned long */
507      strcpy (p1, "unsigned long");
508      break;
509
510    case bt_Float:		/* float (real) */
511      strcpy (p1, "float");
512      break;
513
514    case bt_Double:		/* Double (real) */
515      strcpy (p1, "double");
516      break;
517
518      /* Structures add 1-2 aux words:
519	 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
520	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
521
522    case bt_Struct:		/* Structure (Record) */
523      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp);
524      used_ptr[index] = 1;
525      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
526	used_ptr[++index] = 1;
527
528      index++;			/* skip aux words */
529      break;
530
531      /* Unions add 1-2 aux words:
532	 1st word is [ST_RFDESCAPE, offset] pointer to union def;
533	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
534
535    case bt_Union:		/* Union */
536      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp);
537      used_ptr[index] = 1;
538      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
539	used_ptr[++index] = 1;
540
541      index++;			/* skip aux words */
542      break;
543
544      /* Enumerations add 1-2 aux words:
545	 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
546	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
547
548    case bt_Enum:		/* Enumeration */
549      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp);
550      used_ptr[index] = 1;
551      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
552	used_ptr[++index] = 1;
553
554      index++;			/* skip aux words */
555      break;
556
557    case bt_Typedef:		/* defined via a typedef, isymRef points */
558      strcpy (p1, "typedef");
559      break;
560
561    case bt_Range:		/* subrange of int */
562      strcpy (p1, "subrange");
563      break;
564
565    case bt_Set:		/* pascal sets */
566      strcpy (p1, "set");
567      break;
568
569    case bt_Complex:		/* fortran complex */
570      strcpy (p1, "complex");
571      break;
572
573    case bt_DComplex:		/* fortran double complex */
574      strcpy (p1, "double complex");
575      break;
576
577    case bt_Indirect:		/* forward or unnamed typedef */
578      strcpy (p1, "forward/unnamed typedef");
579      break;
580
581    case bt_FixedDec:		/* Fixed Decimal */
582      strcpy (p1, "fixed decimal");
583      break;
584
585    case bt_FloatDec:		/* Float Decimal */
586      strcpy (p1, "float decimal");
587      break;
588
589    case bt_String:		/* Varying Length Character String */
590      strcpy (p1, "string");
591      break;
592
593    case bt_Bit:		/* Aligned Bit String */
594      strcpy (p1, "bit");
595      break;
596
597    case bt_Picture:		/* Picture */
598      strcpy (p1, "picture");
599      break;
600
601    case bt_Void:		/* Void */
602      strcpy (p1, "void");
603      break;
604
605    default:
606      sprintf (p1, "Unknown basic type %d", (int) basic_type);
607      break;
608    }
609
610  p1 += strlen (buffer1);
611
612  /*
613   * If this is a bitfield, get the bitsize.
614   */
615  if (u.ti.fBitfield)
616    {
617      int bitsize;
618
619      used_ptr[index] = 1;
620      bitsize = aux_ptr[index++].width;
621      sprintf (p1, " : %d", bitsize);
622      p1 += strlen (buffer1);
623    }
624
625
626  /*
627   * Deal with any qualifiers.
628   */
629  if (qualifiers[0].type != tq_Nil)
630    {
631      /*
632       * Snarf up any array bounds in the correct order.  Arrays
633       * store 5 successive words in the aux. table:
634       *	word 0	RNDXR to type of the bounds (i.e., int)
635       *	word 1	Current file descriptor index
636       *	word 2	low bound
637       *	word 3	high bound (or -1 if [])
638       *	word 4	stride size in bits
639       */
640      for (i = 0; i < 7; i++)
641	{
642	  if (qualifiers[i].type == tq_Array)
643	    {
644	      qualifiers[i].low_bound  = aux_ptr[index+2].dnLow;
645	      qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
646	      qualifiers[i].stride     = aux_ptr[index+4].width;
647	      used_ptr[index] = 1;
648	      used_ptr[index+1] = 1;
649	      used_ptr[index+2] = 1;
650	      used_ptr[index+3] = 1;
651	      used_ptr[index+4] = 1;
652	      index += 5;
653	    }
654	}
655
656      /*
657       * Now print out the qualifiers.
658       */
659      for (i = 0; i < 6; i++)
660	{
661	  switch (qualifiers[i].type)
662	    {
663	    case tq_Nil:
664	    case tq_Max:
665	      break;
666
667	    case tq_Ptr:
668	      strcpy (p2, "ptr to ");
669	      p2 += sizeof ("ptr to ")-1;
670	      break;
671
672	    case tq_Vol:
673	      strcpy (p2, "volatile ");
674	      p2 += sizeof ("volatile ")-1;
675	      break;
676
677	    case tq_Far:
678	      strcpy (p2, "far ");
679	      p2 += sizeof ("far ")-1;
680	      break;
681
682	    case tq_Proc:
683	      strcpy (p2, "func. ret. ");
684	      p2 += sizeof ("func. ret. ");
685	      break;
686
687	    case tq_Array:
688	      {
689		int first_array = i;
690		int j;
691
692		/* Print array bounds reversed (i.e., in the order the C
693		   programmer writes them).  C is such a fun language....  */
694
695		while (i < 5 && qualifiers[i+1].type == tq_Array)
696		  i++;
697
698		for (j = i; j >= first_array; j--)
699		  {
700		    strcpy (p2, "array [");
701		    p2 += sizeof ("array [")-1;
702		    if (qualifiers[j].low_bound != 0)
703		      sprintf (p2,
704			       "%ld:%ld {%ld bits}",
705			       (long) qualifiers[j].low_bound,
706			       (long) qualifiers[j].high_bound,
707			       (long) qualifiers[j].stride);
708
709		    else if (qualifiers[j].high_bound != -1)
710		      sprintf (p2,
711			       "%ld {%ld bits}",
712			       (long) (qualifiers[j].high_bound + 1),
713			       (long) (qualifiers[j].stride));
714
715		    else
716		      sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
717
718		    p2 += strlen (p2);
719		    strcpy (p2, "] of ");
720		    p2 += sizeof ("] of ")-1;
721		  }
722	      }
723	      break;
724	    }
725	}
726    }
727
728  strcpy (p2, buffer1);
729  return buffer2;
730}
731
732
733/* Print out the global file header for object files.  */
734
735static void
736print_global_hdr (struct filehdr *ptr)
737{
738  char *time = ctime ((time_t *)&ptr->f_timdat);
739  ushort flags = ptr->f_flags;
740
741  printf("Global file header:\n");
742  printf("    %-*s 0x%x\n",    24, "magic number",	     (ushort) ptr->f_magic);
743  printf("    %-*s %d\n",      24, "# sections",	     (int)    ptr->f_nscns);
744  printf("    %-*s %ld, %s",   24, "timestamp",		     (long)   ptr->f_timdat, time);
745  printf("    %-*s %ld\n",     24, "symbolic header offset", (long)   ptr->f_symptr);
746  printf("    %-*s %ld\n",     24, "symbolic header size",   (long)   ptr->f_nsyms);
747  printf("    %-*s %ld\n",     24, "optional header",	     (long)   ptr->f_opthdr);
748  printf("    %-*s 0x%x",     24, "flags",		     (ushort) flags);
749
750  if ((flags & F_RELFLG) != 0)
751    printf (", F_RELFLG");
752
753  if ((flags & F_EXEC) != 0)
754    printf (", F_EXEC");
755
756  if ((flags & F_LNNO) != 0)
757    printf (", F_LNNO");
758
759  if ((flags & F_LSYMS) != 0)
760    printf (", F_LSYMS");
761
762  if ((flags & F_MINMAL) != 0)
763    printf (", F_MINMAL");
764
765  if ((flags & F_UPDATE) != 0)
766    printf (", F_UPDATE");
767
768  if ((flags & F_SWABD) != 0)
769    printf (", F_SWABD");
770
771  if ((flags & F_AR16WR) != 0)
772    printf (", F_AR16WR");
773
774  if ((flags & F_AR32WR) != 0)
775    printf (", F_AR32WR");
776
777  if ((flags & F_AR32W) != 0)
778    printf (", F_AR32W");
779
780  if ((flags & F_PATCH) != 0)
781    printf (", F_PATCH/F_NODF");
782
783  printf ("\n\n");
784}
785
786
787/* Print out the symbolic header.  */
788
789static void
790print_sym_hdr (HDRR *sym_ptr)
791{
792  int width = 20;
793
794  printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
795	 sym_ptr->magic & 0xffff,
796	 (sym_ptr->vstamp & 0xffff) >> 8,
797	 sym_ptr->vstamp & 0xff);
798
799  printf("    %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
800  printf("    %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
801
802  printf("    %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
803	 (long) sym_ptr->cbLineOffset,
804	 (long) sym_ptr->cbLine,
805	 (long) sym_ptr->cbLine,
806	 (int) sym_ptr->ilineMax);
807
808  printf("    %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
809	 (long) sym_ptr->cbDnOffset,
810	 (long) sym_ptr->idnMax,
811	 (long) (sym_ptr->idnMax * sizeof (DNR)));
812
813  printf("    %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
814	 (long) sym_ptr->cbPdOffset,
815	 (long) sym_ptr->ipdMax,
816	 (long) (sym_ptr->ipdMax * sizeof (PDR)));
817
818  printf("    %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
819	 (long) sym_ptr->cbSymOffset,
820	 (long) sym_ptr->isymMax,
821	 (long) (sym_ptr->isymMax * sizeof (SYMR)));
822
823  printf("    %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
824	 (long) sym_ptr->cbOptOffset,
825	 (long) sym_ptr->ioptMax,
826	 (long) (sym_ptr->ioptMax * sizeof (OPTR)));
827
828  printf("    %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
829	 (long) sym_ptr->cbAuxOffset,
830	 (long) sym_ptr->iauxMax,
831	 (long) (sym_ptr->iauxMax * sizeof (AUXU)));
832
833  printf("    %-*s %11ld %11ld %11ld\n", width, "Local Strings",
834	 (long) sym_ptr->cbSsOffset,
835	 (long) sym_ptr->issMax,
836	 (long) sym_ptr->issMax);
837
838  printf("    %-*s %11ld %11ld %11ld\n", width, "External Strings",
839	 (long) sym_ptr->cbSsExtOffset,
840	 (long) sym_ptr->issExtMax,
841	 (long) sym_ptr->issExtMax);
842
843  printf("    %-*s %11ld %11ld %11ld\n", width, "File Tables",
844	 (long) sym_ptr->cbFdOffset,
845	 (long) sym_ptr->ifdMax,
846	 (long) (sym_ptr->ifdMax * sizeof (FDR)));
847
848  printf("    %-*s %11ld %11ld %11ld\n", width, "Relative Files",
849	 (long) sym_ptr->cbRfdOffset,
850	 (long) sym_ptr->crfd,
851	 (long) (sym_ptr->crfd * sizeof (ulong)));
852
853  printf("    %-*s %11ld %11ld %11ld\n", width, "External Symbols",
854	 (long) sym_ptr->cbExtOffset,
855	 (long) sym_ptr->iextMax,
856	 (long) (sym_ptr->iextMax * sizeof (EXTR)));
857}
858
859
860/* Print out a symbol.  */
861
862static void
863print_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base,
864	      int ifd, FDR *fdp)
865{
866  sc_t storage_class = (sc_t) sym_ptr->sc;
867  st_t symbol_type   = (st_t) sym_ptr->st;
868  ulong index	     = sym_ptr->index;
869  char *used_ptr     = aux_used + (aux_base - aux_symbols);
870  scope_t *scope_ptr;
871
872  printf ("\n    Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
873
874  if (aux_base != (AUXU *) 0 && index != indexNil)
875    switch (symbol_type)
876      {
877      case st_Nil:
878      case st_Label:
879	break;
880
881      case st_File:
882      case st_Block:
883	printf ("      End+1 symbol: %ld\n", index);
884	if (want_scope)
885	  {
886	    if (free_scope == (scope_t *) 0)
887	      scope_ptr = xmalloc (sizeof (scope_t));
888	    else
889	      {
890		scope_ptr = free_scope;
891		free_scope = scope_ptr->prev;
892	      }
893	    scope_ptr->open_sym = number;
894	    scope_ptr->st = symbol_type;
895	    scope_ptr->sc = storage_class;
896	    scope_ptr->prev = cur_scope;
897	    cur_scope = scope_ptr;
898	  }
899	break;
900
901      case st_End:
902	if (storage_class == sc_Text || storage_class == sc_Info)
903	  printf ("      First symbol: %ld\n", index);
904	else
905	  {
906	    used_ptr[index] = 1;
907	    printf ("      First symbol: %ld\n", (long) aux_base[index].isym);
908	  }
909
910	if (want_scope)
911	  {
912	    if (cur_scope == (scope_t *) 0)
913	      printf ("      Can't pop end scope\n");
914	    else
915	      {
916		scope_ptr = cur_scope;
917		cur_scope = scope_ptr->prev;
918		scope_ptr->prev = free_scope;
919		free_scope = scope_ptr;
920	      }
921	  }
922	break;
923
924      case st_Proc:
925      case st_StaticProc:
926	if (MIPS_IS_STAB(sym_ptr))
927	  ;
928	else if (ifd == -1)		/* local symbol */
929	  {
930	    used_ptr[index] = used_ptr[index+1] = 1;
931	    printf ("      End+1 symbol: %-7ld   Type:  %s\n",
932		    (long) aux_base[index].isym,
933		    type_to_string (aux_base, index+1, fdp));
934	  }
935	else			/* global symbol */
936	  printf ("      Local symbol: %ld\n", index);
937
938	if (want_scope)
939	  {
940	    if (free_scope == (scope_t *) 0)
941	      scope_ptr = xmalloc (sizeof (scope_t));
942	    else
943	      {
944		scope_ptr = free_scope;
945		free_scope = scope_ptr->prev;
946	      }
947	    scope_ptr->open_sym = number;
948	    scope_ptr->st = symbol_type;
949	    scope_ptr->sc = storage_class;
950	    scope_ptr->prev = cur_scope;
951	    cur_scope = scope_ptr;
952	  }
953	break;
954
955#ifdef stStruct
956      case st_Struct:
957      case st_Union:
958      case st_Enum:
959	printf ("      End+1 symbol: %lu\n", index);
960	break;
961#endif
962
963      default:
964	if (!MIPS_IS_STAB (sym_ptr))
965	  {
966	    used_ptr[index] = 1;
967	    printf ("      Type: %s\n",
968		    type_to_string (aux_base, index, fdp));
969	  }
970	break;
971      }
972
973  if (want_scope)
974    {
975      printf ("      Scopes:  ");
976      if (cur_scope == (scope_t *) 0)
977	printf (" none\n");
978      else
979	{
980	  for (scope_ptr = cur_scope;
981	       scope_ptr != (scope_t *) 0;
982	       scope_ptr = scope_ptr->prev)
983	    {
984	      const char *class;
985	      if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
986		class = "func.";
987	      else if (scope_ptr->st == st_File)
988		class = "file";
989	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
990		class = "block";
991	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
992		class = "type";
993	      else
994		class = "???";
995
996	      printf (" %ld [%s]", scope_ptr->open_sym, class);
997	    }
998	  printf ("\n");
999	}
1000    }
1001
1002  printf ("      Value: %-13ld    ",
1003	  (long)sym_ptr->value);
1004  if (ifd == -1)
1005    printf ("String index: %ld\n", (long)sym_ptr->iss);
1006  else
1007    printf ("String index: %-11ld Ifd: %d\n",
1008	    (long)sym_ptr->iss, ifd);
1009
1010  printf ("      Symbol type: %-11sStorage class: %-11s",
1011	  st_to_string (symbol_type), sc_to_string (storage_class));
1012
1013  if (MIPS_IS_STAB(sym_ptr))
1014    {
1015      int i = ARRAY_SIZE (stab_names);
1016      const char *stab_name = "stab";
1017      short code = MIPS_UNMARK_STAB(sym_ptr->index);
1018
1019      while (--i >= 0)
1020	if (stab_names[i].code == code)
1021	  {
1022	    stab_name = stab_names[i].string;
1023	    break;
1024	  }
1025      printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
1026    }
1027  else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
1028    printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
1029  else
1030    printf ("Index: %ld\n", (long)sym_ptr->index);
1031
1032}
1033
1034
1035/* Print out a word from the aux. table in various formats.  */
1036
1037static void
1038print_aux (AUXU u, int auxi, int used)
1039{
1040  printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1041	  (used) ? "  " : "* ",
1042	  auxi,
1043	  (long) u.isym,
1044	  (long) u.rndx.rfd,
1045	  (long) u.rndx.index,
1046	  u.ti.bt,
1047	  u.ti.fBitfield,
1048	  u.ti.continued,
1049	  u.ti.tq0,
1050	  u.ti.tq1,
1051	  u.ti.tq2,
1052	  u.ti.tq3,
1053	  u.ti.tq4,
1054	  u.ti.tq5);
1055}
1056
1057
1058/* Write aggregate information to a string.  */
1059
1060static void
1061emit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp)
1062{
1063  unsigned int ifd = u.rndx.rfd;
1064  unsigned int index = u.rndx.index;
1065  const char *name;
1066
1067  if (ifd == ST_RFDESCAPE)
1068    ifd = u2.isym;
1069
1070  /* An ifd of -1 is an opaque type.  An escaped index of 0 is a
1071     struct return type of a procedure compiled without -g.  */
1072  if (ifd == 0xffffffff
1073      || (u.rndx.rfd == ST_RFDESCAPE && index == 0))
1074    name = "<undefined>";
1075  else if (index == indexNil)
1076    name = "<no name>";
1077  else
1078    {
1079      if (fdp == 0 || sym_hdr.crfd == 0)
1080	fdp = &file_desc[ifd];
1081      else
1082	fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]];
1083      name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss];
1084    }
1085
1086  sprintf (string,
1087	   "%s %s { ifd = %u, index = %u }",
1088	   which, name, ifd, index);
1089}
1090
1091
1092/* Print out information about a file descriptor, and the symbols,
1093   procedures, and line numbers within it.  */
1094
1095static void
1096print_file_desc (FDR *fdp, int number)
1097{
1098  char *str_base;
1099  AUXU *aux_base;
1100  int symi, pdi;
1101  int width = 20;
1102  char *used_base;
1103
1104  str_base = l_strings + fdp->issBase;
1105  aux_base = aux_symbols + fdp->iauxBase;
1106  used_base = aux_used + (aux_base - aux_symbols);
1107
1108  printf ("\nFile #%d, \"%s\"\n\n",
1109	  number,
1110	  fdp->rss != issNil ? str_base + fdp->rss : "<unknown>");
1111
1112  printf ("    Name index  = %-10ld Readin      = %s\n",
1113	  (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1114
1115  printf ("    Merge       = %-10s Endian      = %s\n",
1116	  (fdp->fMerge)  ? "Yes" : "No",
1117	  (fdp->fBigendian) ? "BIG" : "LITTLE");
1118
1119  printf ("    Debug level = %-10s Language    = %s\n",
1120	  glevel_to_string (fdp->glevel),
1121	  lang_to_string((lang_t) fdp->lang));
1122
1123  printf ("    Adr         = 0x%08lx\n\n", (long) fdp->adr);
1124
1125  printf("    %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1126  printf("    %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1127
1128  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1129	 width, "Local strings",
1130	 (ulong) fdp->issBase,
1131	 (ulong) fdp->cbSs,
1132	 (ulong) fdp->cbSs,
1133	 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1134
1135  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1136	 width, "Local symbols",
1137	 (ulong) fdp->isymBase,
1138	 (ulong) fdp->csym,
1139	 (ulong) (fdp->csym * sizeof (SYMR)),
1140	 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1141
1142  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1143	 width, "Line numbers",
1144	 (ulong) fdp->cbLineOffset,
1145	 (ulong) fdp->cline,
1146	 (ulong) fdp->cbLine,
1147	 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1148
1149  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1150	 width, "Optimization symbols",
1151	 (ulong) fdp->ioptBase,
1152	 (ulong) fdp->copt,
1153	 (ulong) (fdp->copt * sizeof (OPTR)),
1154	 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1155
1156  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1157	 width, "Procedures",
1158	 (ulong) fdp->ipdFirst,
1159	 (ulong) fdp->cpd,
1160	 (ulong) (fdp->cpd * sizeof (PDR)),
1161	 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1162
1163  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1164	 width, "Auxiliary symbols",
1165	 (ulong) fdp->iauxBase,
1166	 (ulong) fdp->caux,
1167	 (ulong) (fdp->caux * sizeof (AUXU)),
1168	 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1169
1170  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1171	 width, "Relative Files",
1172	 (ulong) fdp->rfdBase,
1173	 (ulong) fdp->crfd,
1174	 (ulong) (fdp->crfd * sizeof (ulong)),
1175	 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1176
1177
1178  if (want_scope && cur_scope != (scope_t *) 0)
1179    printf ("\n    Warning scope does not start at 0!\n");
1180
1181  /*
1182   * print the info about the symbol table.
1183   */
1184  printf ("\n    There are %lu local symbols, starting at %lu\n",
1185	  (ulong) fdp->csym,
1186	  (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1187
1188  for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1189    print_symbol (&l_symbols[symi],
1190		  symi - fdp->isymBase,
1191		  str_base,
1192		  aux_base,
1193		  -1,
1194		  fdp);
1195
1196  if (want_scope && cur_scope != (scope_t *) 0)
1197    printf ("\n    Warning scope does not end at 0!\n");
1198
1199  /*
1200   * print the aux. table if desired.
1201   */
1202
1203  if (want_aux && fdp->caux != 0)
1204    {
1205      int auxi;
1206
1207      printf ("\n    There are %lu auxiliary table entries, starting at %lu.\n\n",
1208	      (ulong) fdp->caux,
1209	      (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1210
1211      for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1212	print_aux (aux_base[auxi], auxi, used_base[auxi]);
1213    }
1214
1215  /*
1216   * print the relative file descriptors.
1217   */
1218  if (want_rfd && fdp->crfd != 0)
1219    {
1220      ulong *rfd_ptr, i;
1221
1222      printf ("\n    There are %lu relative file descriptors, starting at %lu.\n",
1223	      (ulong) fdp->crfd,
1224	      (ulong) fdp->rfdBase);
1225
1226      rfd_ptr = rfile_desc + fdp->rfdBase;
1227      for (i = 0; i < (ulong) fdp->crfd; i++)
1228	{
1229	  printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1230	  rfd_ptr++;
1231	}
1232    }
1233
1234  /*
1235   * do the procedure descriptors.
1236   */
1237  printf ("\n    There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1238  printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1239
1240  for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1241    {
1242      PDR *proc_ptr = &proc_desc[pdi];
1243      printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1244
1245      if (l_symbols != 0)
1246	printf ("\t    Name index   = %-11ld Name          = \"%s\"\n",
1247		(long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1248		l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1249
1250      printf ("\t    .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1251	      (long) proc_ptr->regmask,
1252	      (long) proc_ptr->regoffset,
1253	      (long) proc_ptr->fregmask,
1254	      (long) proc_ptr->fregoffset);
1255
1256      printf ("\t    .frame $%d,%ld,$%d\n",
1257	      (int)  proc_ptr->framereg,
1258	      (long) proc_ptr->frameoffset,
1259	      (int)  proc_ptr->pcreg);
1260
1261      printf ("\t    Opt. start   = %-11ld Symbols start = %ld\n",
1262	      (long) proc_ptr->iopt,
1263	      (long) proc_ptr->isym);
1264
1265      printf ("\t    First line # = %-11ld Last line #   = %ld\n",
1266	      (long) proc_ptr->lnLow,
1267	      (long) proc_ptr->lnHigh);
1268
1269      printf ("\t    Line Offset  = %-11ld Address       = 0x%08lx\n",
1270	      (long) proc_ptr->cbLineOffset,
1271	      (long) proc_ptr->adr);
1272
1273      /*
1274       * print the line number entries.
1275       */
1276
1277      if (want_line && fdp->cline != 0)
1278	{
1279	  int delta, count;
1280	  long cur_line = proc_ptr->lnLow;
1281	  uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset
1282			     + fdp->cbLineOffset);
1283	  uchar *line_end;
1284
1285	  if (pdi == fdp->cpd + fdp->ipdFirst - 1)	/* last procedure */
1286	    line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
1287	  else						/* not last proc.  */
1288	    line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
1289			+ fdp->cbLineOffset);
1290
1291	  printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1292		  (ulong) (line_end - line_ptr),
1293		  (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1294
1295	  while (line_ptr < line_end)
1296	    {						/* sign extend nibble */
1297	      delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1298	      count = (*line_ptr & 0xf) + 1;
1299	      if (delta != -8)
1300		line_ptr++;
1301	      else
1302		{
1303		  delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1304		  delta = (delta ^ 0x8000) - 0x8000;
1305		  line_ptr += 3;
1306		}
1307
1308	      cur_line += delta;
1309	      printf ("\t    Line %11ld,   delta %5d,   count %2d\n",
1310		      cur_line,
1311		      delta,
1312		      count);
1313	    }
1314	}
1315    }
1316}
1317
1318
1319/* Read in the portions of the .T file that we will print out.  */
1320
1321static void
1322read_tfile (void)
1323{
1324  short magic;
1325  off_t sym_hdr_offset = 0;
1326
1327  read_seek (&magic, sizeof (magic), 0, "Magic number");
1328  if (!tfile)
1329    {
1330      /* Print out the global header, since this is not a T-file.  */
1331
1332      read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header");
1333
1334      print_global_hdr (&global_hdr);
1335
1336      if (global_hdr.f_symptr == 0)
1337	{
1338	  printf ("No symbolic header, Goodbye!\n");
1339	  exit (1);
1340	}
1341
1342      sym_hdr_offset = global_hdr.f_symptr;
1343    }
1344
1345  read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header");
1346
1347  print_sym_hdr (&sym_hdr);
1348
1349  lines = read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset,
1350		     "Line numbers");
1351
1352  dense_nums = read_seek (NULL, sym_hdr.idnMax * sizeof (DNR),
1353			  sym_hdr.cbDnOffset, "Dense numbers");
1354
1355  proc_desc = read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR),
1356			 sym_hdr.cbPdOffset, "Procedure tables");
1357
1358  l_symbols = read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR),
1359			 sym_hdr.cbSymOffset, "Local symbols");
1360
1361  opt_symbols = read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR),
1362			   sym_hdr.cbOptOffset, "Optimization symbols");
1363
1364  aux_symbols = read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU),
1365			   sym_hdr.cbAuxOffset, "Auxiliary symbols");
1366
1367  if (sym_hdr.iauxMax > 0)
1368    aux_used = xcalloc (sym_hdr.iauxMax, 1);
1369
1370  l_strings = read_seek (NULL, sym_hdr.issMax,
1371			 sym_hdr.cbSsOffset, "Local string table");
1372
1373  e_strings = read_seek (NULL, sym_hdr.issExtMax,
1374			 sym_hdr.cbSsExtOffset, "External string table");
1375
1376  file_desc = read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR),
1377			 sym_hdr.cbFdOffset, "File tables");
1378
1379  rfile_desc = read_seek (NULL, sym_hdr.crfd * sizeof (ulong),
1380			  sym_hdr.cbRfdOffset, "Relative file tables");
1381
1382  e_symbols = read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR),
1383			 sym_hdr.cbExtOffset, "External symbols");
1384}
1385
1386
1387
1388extern int main (int, char **);
1389
1390int
1391main (int argc, char **argv)
1392{
1393  int i, opt;
1394
1395  /*
1396   * Process arguments
1397   */
1398  while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1)
1399    switch (opt)
1400      {
1401      default:	errors++;	break;
1402      case 'a': want_aux++;	break;	/* print aux table */
1403      case 'l': want_line++;	break;	/* print line numbers */
1404      case 'r': want_rfd++;	break;	/* print relative fd's */
1405      case 's':	want_scope++;	break;	/* print scope info */
1406      case 'v': verbose++;	break;  /* print version # */
1407      case 'V': version++;	break;  /* print version # */
1408      case 't': tfile++;	break;	/* this is a tfile (without header),
1409					   and not a .o */
1410      }
1411
1412  if (version)
1413    {
1414      printf ("mips-tdump (GCC) %s\n", version_string);
1415      fputs ("Copyright (C) 2006 Free Software Foundation, Inc.\n", stdout);
1416      fputs ("This is free software; see the source for copying conditions.  There is NO\n\
1417warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n",
1418             stdout);
1419      exit (0);
1420    }
1421
1422  if (optind != argc - 1)
1423    errors++;
1424
1425  if (verbose || errors)
1426    {
1427      fprintf (stderr, "mips-tdump (GCC) %s", version_string);
1428#ifdef TARGET_VERSION
1429      TARGET_VERSION;
1430#endif
1431      fputc ('\n', stderr);
1432    }
1433
1434  if (errors)
1435    {
1436      fprintf (stderr, "Calling Sequence:\n");
1437      fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]);
1438      fprintf (stderr, "\n");
1439      fprintf (stderr, "switches:\n");
1440      fprintf (stderr, "\t-a Print out auxiliary table.\n");
1441      fprintf (stderr, "\t-l Print out line numbers.\n");
1442      fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1443      fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1444      fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
1445      fprintf (stderr, "\t-v Print program version.\n");
1446      return 1;
1447    }
1448
1449  /*
1450   * Open and process the input file.
1451   */
1452  tfile_fd = open (argv[optind], O_RDONLY);
1453  if (tfile_fd < 0)
1454    {
1455      perror (argv[optind]);
1456      return 1;
1457    }
1458
1459  read_tfile ();
1460
1461  /*
1462   * Print any global aux words if any.
1463   */
1464  if (want_aux)
1465    {
1466      long last_aux_in_use;
1467
1468      if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1469	{
1470	  printf ("\nGlobal auxiliary entries before first file:\n");
1471	  for (i = 0; i < file_desc[0].iauxBase; i++)
1472	    print_aux (aux_symbols[i], 0, aux_used[i]);
1473	}
1474
1475      if (sym_hdr.ifdMax == 0)
1476	last_aux_in_use = 0;
1477      else
1478	last_aux_in_use
1479	  = (file_desc[sym_hdr.ifdMax-1].iauxBase
1480	     + file_desc[sym_hdr.ifdMax-1].caux - 1);
1481
1482      if (last_aux_in_use < sym_hdr.iauxMax-1)
1483	{
1484	  printf ("\nGlobal auxiliary entries after last file:\n");
1485	  for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1486	    print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1487	}
1488    }
1489
1490  /*
1491   * Print the information for each file.
1492   */
1493  for (i = 0; i < sym_hdr.ifdMax; i++)
1494    print_file_desc (&file_desc[i], i);
1495
1496  /*
1497   * Print the external symbols.
1498   */
1499  want_scope = 0;		/* scope info is meaning for extern symbols */
1500  printf ("\nThere are %lu external symbols, starting at %lu\n",
1501	  (ulong) sym_hdr.iextMax,
1502	  (ulong) sym_hdr.cbExtOffset);
1503
1504  for(i = 0; i < sym_hdr.iextMax; i++)
1505    print_symbol (&e_symbols[i].asym, i, e_strings,
1506		  aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1507		  e_symbols[i].ifd,
1508		  &file_desc[e_symbols[i].ifd]);
1509
1510  /*
1511   * Print unused aux symbols now.
1512   */
1513
1514  if (want_aux)
1515    {
1516      int first_time = 1;
1517
1518      for (i = 0; i < sym_hdr.iauxMax; i++)
1519	{
1520	  if (! aux_used[i])
1521	    {
1522	      if (first_time)
1523		{
1524		  printf ("\nThe following auxiliary table entries were unused:\n\n");
1525		  first_time = 0;
1526		}
1527
1528	      printf ("    #%-5d %11ld  0x%08lx  %s\n",
1529		      i,
1530		      (long) aux_symbols[i].isym,
1531		      (long) aux_symbols[i].isym,
1532		      type_to_string (aux_symbols, i, (FDR *) 0));
1533	    }
1534	}
1535    }
1536
1537  return 0;
1538}
1539