mips-tdump.c revision 259563
1339640Smm/* Read and manage MIPS symbol tables from object modules.
2339640Smm   Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
3339640Smm   2006 Free Software Foundation, Inc.
4339640Smm   Contributed by hartzell@boulder.colorado.edu,
5339640Smm   Rewritten by meissner@osf.org.
6339640Smm
7339640SmmThis file is part of GCC.
8339640Smm
9339640SmmGCC is free software; you can redistribute it and/or modify it under
10339640Smmthe terms of the GNU General Public License as published by the Free
11339640SmmSoftware Foundation; either version 2, or (at your option) any later
12339640Smmversion.
13339640Smm
14339640SmmGCC is distributed in the hope that it will be useful, but WITHOUT ANY
15339640SmmWARRANTY; without even the implied warranty of MERCHANTABILITY or
16339640SmmFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17339640Smmfor more details.
18339640Smm
19339640SmmYou should have received a copy of the GNU General Public License
20339640Smmalong with GCC; see the file COPYING.  If not, write to the Free
21339640SmmSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22339640Smm02110-1301, USA.  */
23339640Smm
24339640Smm#include "config.h"
25339640Smm#include "system.h"
26339640Smm#include "coretypes.h"
27348608Smm#include "tm.h"
28339640Smm#include "version.h"
29339640Smm#ifdef index
30339640Smm#undef index
31339640Smm#endif
32339640Smm#ifndef CROSS_DIRECTORY_STRUCTURE
33339640Smm#include <a.out.h>
34339640Smm#else
35339640Smm#include "mips/a.out.h"
36348608Smm#endif /* CROSS_DIRECTORY_STRUCTURE */
37348608Smm
38348608Smm/* Include getopt.h for the sake of getopt_long.  */
39339640Smm#include "getopt.h"
40339640Smm
41339640Smm#ifndef MIPS_IS_STAB
42339640Smm/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
43339640Smm   and mips-tdump.c to print them out.  This is used on the Alpha,
44339640Smm   which does not include mips.h.
45339640Smm
46339640Smm   These must match the corresponding definitions in gdb/mipsread.c.
47339640Smm   Unfortunately, gcc and gdb do not currently share any directories.  */
48339640Smm
49339640Smm#define CODE_MASK 0x8F300
50339640Smm#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
51339640Smm#define MIPS_MARK_STAB(code) ((code)+CODE_MASK)
52339640Smm#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
53339640Smm#endif
54339640Smm
55339640Smm#define uchar	unsigned char
56339640Smm#define ushort	unsigned short
57339640Smm#define uint	unsigned int
58339640Smm#define ulong	unsigned long
59339640Smm
60339640Smm
61339640Smm/* Redefinition of storage classes as an enumeration for better
62339640Smm   debugging.  */
63339640Smm
64339640Smm#ifndef stStaParam
65339640Smm#define stStaParam	16	/* Fortran static parameters */
66358090Smm#endif
67339640Smm
68339640Smm#ifndef btVoid
69339640Smm#define btVoid		26	/* void basic type */
70339640Smm#endif
71339640Smm
72339640Smmtypedef enum sc {
73339640Smm  sc_Nil	 = scNil,	  /* no storage class */
74339640Smm  sc_Text	 = scText,	  /* text symbol */
75339640Smm  sc_Data	 = scData,	  /* initialized data symbol */
76358090Smm  sc_Bss	 = scBss,	  /* un-initialized data symbol */
77339640Smm  sc_Register	 = scRegister,	  /* value of symbol is register number */
78339640Smm  sc_Abs	 = scAbs,	  /* value of symbol is absolute */
79339640Smm  sc_Undefined	 = scUndefined,	  /* who knows? */
80339640Smm  sc_CdbLocal	 = scCdbLocal,	  /* variable's value is IN se->va.?? */
81339640Smm  sc_Bits	 = scBits,	  /* this is a bit field */
82339640Smm  sc_CdbSystem	 = scCdbSystem,	  /* var's value is IN CDB's address space */
83358090Smm  sc_RegImage	 = scRegImage,	  /* register value saved on stack */
84339746Smm  sc_Info	 = scInfo,	  /* symbol contains debugger information */
85339640Smm  sc_UserStruct	 = scUserStruct,  /* addr in struct user for current process */
86348608Smm  sc_SData	 = scSData,	  /* load time only small data */
87348608Smm  sc_SBss	 = scSBss,	  /* load time only small common */
88348608Smm  sc_RData	 = scRData,	  /* load time only read only data */
89348608Smm  sc_Var	 = scVar,	  /* Var parameter (fortran,pascal) */
90348608Smm  sc_Common	 = scCommon,	  /* common variable */
91339640Smm  sc_SCommon	 = scSCommon,	  /* small common */
92348608Smm  sc_VarRegister = scVarRegister, /* Var parameter in a register */
93348608Smm  sc_Variant	 = scVariant,	  /* Variant record */
94348608Smm  sc_SUndefined	 = scSUndefined,  /* small undefined(external) data */
95348608Smm  sc_Init	 = scInit,	  /* .init section symbol */
96339640Smm  sc_Max	 = scMax	  /* Max storage class+1 */
97348608Smm} sc_t;
98348608Smm
99348608Smm/* Redefinition of symbol type.  */
100348608Smm
101339640Smmtypedef enum st {
102348608Smm  st_Nil	= stNil,	/* Nuthin' special */
103348608Smm  st_Global	= stGlobal,	/* external symbol */
104348608Smm  st_Static	= stStatic,	/* static */
105348608Smm  st_Param	= stParam,	/* procedure argument */
106348608Smm  st_Local	= stLocal,	/* local variable */
107339640Smm  st_Label	= stLabel,	/* label */
108348608Smm  st_Proc	= stProc,	/*     "      "	 Procedure */
109348608Smm  st_Block	= stBlock,	/* beginning of block */
110348608Smm  st_End	= stEnd,	/* end (of anything) */
111348608Smm  st_Member	= stMember,	/* member (of anything	- struct/union/enum */
112348608Smm  st_Typedef	= stTypedef,	/* type definition */
113348608Smm  st_File	= stFile,	/* file name */
114348608Smm  st_RegReloc	= stRegReloc,	/* register relocation */
115348608Smm  st_Forward	= stForward,	/* forwarding address */
116348608Smm  st_StaticProc	= stStaticProc,	/* load time only static procs */
117348608Smm  st_StaParam	= stStaParam,	/* Fortran static parameters */
118358090Smm  st_Constant	= stConstant,	/* const */
119358090Smm#ifdef stStruct
120339640Smm  st_Struct	= stStruct,	/* struct */
121339640Smm  st_Union	= stUnion,	/* union */
122348608Smm  st_Enum	= stEnum,	/* enum */
123348608Smm#endif
124348608Smm  st_Str	= stStr,	/* string */
125348608Smm  st_Number	= stNumber,	/* pure number (i.e. 4 NOR 2+2) */
126348608Smm  st_Expr	= stExpr,	/* 2+2 vs. 4 */
127348608Smm  st_Type	= stType,	/* post-coercion SER */
128348608Smm  st_Max	= stMax		/* max type+1 */
129348608Smm} st_t;
130348608Smm
131348608Smm/* Redefinition of type qualifiers.  */
132348608Smm
133348608Smmtypedef enum tq {
134348608Smm  tq_Nil	= tqNil,	/* bt is what you see */
135348608Smm  tq_Ptr	= tqPtr,	/* pointer */
136348608Smm  tq_Proc	= tqProc,	/* procedure */
137348608Smm  tq_Array	= tqArray,	/* duh */
138348608Smm  tq_Far	= tqFar,	/* longer addressing - 8086/8 land */
139348608Smm  tq_Vol	= tqVol,	/* volatile */
140348608Smm  tq_Max	= tqMax		/* Max type qualifier+1 */
141348608Smm} tq_t;
142348608Smm
143348608Smm/* Redefinition of basic types.  */
144348608Smm
145348608Smmtypedef enum bt {
146348608Smm  bt_Nil	= btNil,	/* undefined */
147348608Smm  bt_Adr	= btAdr,	/* address - integer same size as pointer */
148348608Smm  bt_Char	= btChar,	/* character */
149339640Smm  bt_UChar	= btUChar,	/* unsigned character */
150348608Smm  bt_Short	= btShort,	/* short */
151348608Smm  bt_UShort	= btUShort,	/* unsigned short */
152348608Smm  bt_Int	= btInt,	/* int */
153348608Smm  bt_UInt	= btUInt,	/* unsigned int */
154348608Smm  bt_Long	= btLong,	/* long */
155348608Smm  bt_ULong	= btULong,	/* unsigned long */
156348608Smm  bt_Float	= btFloat,	/* float (real) */
157348608Smm  bt_Double	= btDouble,	/* Double (real) */
158348608Smm  bt_Struct	= btStruct,	/* Structure (Record) */
159348608Smm  bt_Union	= btUnion,	/* Union (variant) */
160339640Smm  bt_Enum	= btEnum,	/* Enumerated */
161339640Smm  bt_Typedef	= btTypedef,	/* defined via a typedef, isymRef points */
162339640Smm  bt_Range	= btRange,	/* subrange of int */
163348608Smm  bt_Set	= btSet,	/* pascal sets */
164348608Smm  bt_Complex	= btComplex,	/* fortran complex */
165348608Smm  bt_DComplex	= btDComplex,	/* fortran double complex */
166339640Smm  bt_Indirect	= btIndirect,	/* forward or unnamed typedef */
167348608Smm  bt_FixedDec	= btFixedDec,	/* Fixed Decimal */
168348608Smm  bt_FloatDec	= btFloatDec,	/* Float Decimal */
169348608Smm  bt_String	= btString,	/* Varying Length Character String */
170339640Smm  bt_Bit	= btBit,	/* Aligned Bit String */
171339640Smm  bt_Picture	= btPicture,	/* Picture */
172339640Smm  bt_Void	= btVoid,	/* void */
173348608Smm  bt_Max	= btMax		/* Max basic type+1 */
174348608Smm} bt_t;
175348608Smm
176348608Smm/* Redefinition of the language codes.  */
177339640Smm
178339640Smmtypedef enum lang {
179339640Smm  lang_C	 = langC,
180348608Smm  lang_Pascal	 = langPascal,
181348608Smm  lang_Fortran	 = langFortran,
182348608Smm  lang_Assembler = langAssembler,
183348608Smm  lang_Machine	 = langMachine,
184348608Smm  lang_Nil	 = langNil,
185339640Smm  lang_Ada	 = langAda,
186339640Smm  lang_Pl1	 = langPl1,
187339640Smm  lang_Cobol	 = langCobol
188348608Smm} lang_t;
189348608Smm
190348608Smm/* Redefinition of the debug level codes.  */
191348608Smm
192348608Smmtypedef enum glevel {
193348608Smm  glevel_0	= GLEVEL_0,
194348608Smm  glevel_1	= GLEVEL_1,
195339640Smm  glevel_2	= GLEVEL_2,
196339640Smm  glevel_3	= GLEVEL_3
197339640Smm} glevel_t;
198348608Smm
199348608Smm
200348608Smm/* Keep track of the active scopes.  */
201339640Smmtypedef struct scope {
202348608Smm  struct scope *prev;		/* previous scope */
203348608Smm  ulong open_sym;		/* symbol opening scope */
204339640Smm  sc_t sc;			/* storage class */
205348608Smm  st_t st;			/* symbol type */
206348608Smm} scope_t;
207348608Smm
208339640Smmstruct filehdr global_hdr;	/* a.out header */
209348608Smm
210348608Smmint	 errors		= 0;	/* # of errors */
211348608Smmint	 want_aux	= 0;	/* print aux table */
212339640Smmint	 want_line	= 0;	/* print line numbers */
213358090Smmint	 want_rfd	= 0;	/* print relative file desc's */
214339640Smmint	 want_scope	= 0;	/* print scopes for every symbol */
215348608Smmint	 tfile		= 0;	/* no global header file */
216348608Smmint	 version	= 0;    /* print version # */
217348608Smmint	 verbose	= 0;
218348608Smmint	 tfile_fd;		/* file descriptor of .T file */
219348608Smmoff_t	 tfile_offset;		/* current offset in .T file */
220348608Smmscope_t	*cur_scope	= 0;	/* list of active scopes */
221348608Smmscope_t	*free_scope	= 0;	/* list of freed scopes */
222348608SmmHDRR	 sym_hdr;		/* symbolic header */
223348608Smmchar	*l_strings;		/* local strings */
224348608Smmchar	*e_strings;		/* external strings */
225348608SmmSYMR	*l_symbols;		/* local symbols */
226348608SmmEXTR	*e_symbols;		/* external symbols */
227348608SmmLINER	*lines;			/* line numbers */
228348608SmmDNR	*dense_nums;		/* dense numbers */
229348608SmmOPTR	*opt_symbols;		/* optimization symbols */
230348608SmmAUXU	*aux_symbols;		/* Auxiliary symbols */
231348608Smmchar	*aux_used;		/* map of which aux syms are used */
232348608SmmFDR	*file_desc;		/* file tables */
233348608Smmulong	*rfile_desc;		/* relative file tables */
234348608SmmPDR	*proc_desc;		/* procedure tables */
235348608Smm
236348608Smm/* Forward reference for functions.  */
237348608Smmstatic void *read_seek (void *, size_t, off_t, const char *);
238339640Smmstatic void read_tfile (void);
239348608Smmstatic void print_global_hdr (struct filehdr *);
240339640Smmstatic void print_sym_hdr (HDRR *);
241339640Smmstatic void print_file_desc (FDR *, int);
242348608Smmstatic void print_symbol (SYMR *, int, const char *, AUXU *, int, FDR *);
243339640Smmstatic void print_aux (AUXU, int, int);
244348608Smmstatic void emit_aggregate (char *, AUXU, AUXU, const char *, FDR *);
245339640Smmstatic const char *st_to_string (st_t);
246348608Smmstatic const char *sc_to_string (sc_t);
247339640Smmstatic const char *glevel_to_string (glevel_t);
248348608Smmstatic const char *lang_to_string (lang_t);
249339640Smmstatic const char *type_to_string (AUXU *, int, FDR *);
250348608Smm
251339640Smmextern char *optarg;
252339640Smmextern int   optind;
253348608Smmextern int   opterr;
254348608Smm
255348608Smm/* Create a table of debugging stab-codes and corresponding names.  */
256348608Smm
257339640Smm#define __define_stab(NAME, CODE, STRING) {(int)CODE, STRING},
258348608Smmconst struct {const short code; const char string[10];} stab_names[]  = {
259348608Smm#include "stab.def"
260339640Smm#undef __define_stab
261348608Smm};
262348608Smm
263339640Smm/* Command line options for getopt_long.  */
264339640Smm
265339640Smmstatic const struct option options[] =
266339640Smm{
267348608Smm  { "version", 0, 0, 'V' },
268348608Smm  { "verbose", 0, 0, 'v' },
269339640Smm  { 0, 0, 0, 0 }
270339640Smm};
271348608Smm
272348608Smm/* Read some bytes at a specified location, and return a pointer.
273339640Smm   Read_seek takes a pointer PTR to a buffer or NULL and reads SIZE
274348608Smm   bytes from offset OFFSET.  In case of errors CONTEXT is used as
275348608Smm   error message.  */
276348608Smm
277348608Smmstatic void *
278348608Smmread_seek (void *ptr, size_t size, off_t offset,  const char *context)
279348608Smm{
280348608Smm  long read_size = 0;
281348608Smm
282348608Smm  if (size == 0)		/* nothing to read */
283339640Smm    return ptr;
284339640Smm
285339640Smm  if (!ptr)
286339640Smm    ptr = xmalloc (size);
287348608Smm
288348608Smm  if ((tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
289339640Smm      || (read_size = read (tfile_fd, ptr, size)) < 0)
290348608Smm    {
291348608Smm      perror (context);
292348608Smm      exit (1);
293348608Smm    }
294339640Smm
295348608Smm  if (read_size != (long) size)
296339640Smm    {
297339640Smm      fprintf (stderr, "%s: read %ld bytes, expected %ld bytes\n",
298339640Smm	       context, read_size, (long) size);
299348608Smm      exit (1);
300348608Smm    }
301348608Smm
302348608Smm  tfile_offset = offset + size;
303348608Smm  return ptr;
304339640Smm}
305339640Smm
306339640Smm
307348608Smm/* Convert language code to string format.  */
308348608Smm
309339640Smmstatic const char *
310339640Smmlang_to_string (lang_t lang)
311339640Smm{
312339640Smm  switch (lang)
313348608Smm    {
314339640Smm    case langC:		return "C";
315348608Smm    case langPascal:	return "Pascal";
316348608Smm    case langFortran:	return "Fortran";
317348608Smm    case langAssembler:	return "Assembler";
318339640Smm    case langMachine:	return "Machine";
319348608Smm    case langNil:	return "Nil";
320348608Smm    case langAda:	return "Ada";
321348608Smm    case langPl1:	return "Pl1";
322348608Smm    case langCobol:	return "Cobol";
323348608Smm    }
324339640Smm
325348608Smm  return "Unknown language";
326348608Smm}
327348608Smm
328348608Smm
329348608Smm/* Convert storage class to string.  */
330348608Smm
331339640Smmstatic const char *
332348608Smmsc_to_string (sc_t storage_class)
333348608Smm{
334348608Smm  switch(storage_class)
335348608Smm    {
336348608Smm    case sc_Nil:	 return "Nil";
337339640Smm    case sc_Text:	 return "Text";
338348608Smm    case sc_Data:	 return "Data";
339348608Smm    case sc_Bss:	 return "Bss";
340348608Smm    case sc_Register:	 return "Register";
341348608Smm    case sc_Abs:	 return "Abs";
342348608Smm    case sc_Undefined:	 return "Undefined";
343339640Smm    case sc_CdbLocal:	 return "CdbLocal";
344348608Smm    case sc_Bits:	 return "Bits";
345348608Smm    case sc_CdbSystem:	 return "CdbSystem";
346348608Smm    case sc_RegImage:	 return "RegImage";
347348608Smm    case sc_Info:	 return "Info";
348348608Smm    case sc_UserStruct:	 return "UserStruct";
349348608Smm    case sc_SData:	 return "SData";
350348608Smm    case sc_SBss:	 return "SBss";
351348608Smm    case sc_RData:	 return "RData";
352348608Smm    case sc_Var:	 return "Var";
353348608Smm    case sc_Common:	 return "Common";
354348608Smm    case sc_SCommon:	 return "SCommon";
355339640Smm    case sc_VarRegister: return "VarRegister";
356339640Smm    case sc_Variant:	 return "Variant";
357339640Smm    case sc_SUndefined:	 return "SUndefined";
358339640Smm    case sc_Init:	 return "Init";
359358090Smm    case sc_Max:	 return "Max";
360339640Smm    }
361339640Smm
362339640Smm  return "???";
363348608Smm}
364339640Smm
365339640Smm
366339640Smm/* Convert symbol type to string.  */
367348608Smm
368339640Smmstatic const char *
369339640Smmst_to_string (st_t symbol_type)
370339640Smm{
371339640Smm  switch(symbol_type)
372348608Smm    {
373348608Smm    case st_Nil:	return "Nil";
374348608Smm    case st_Global:	return "Global";
375339640Smm    case st_Static:	return "Static";
376339640Smm    case st_Param:	return "Param";
377339640Smm    case st_Local:	return "Local";
378339640Smm    case st_Label:	return "Label";
379339640Smm    case st_Proc:	return "Proc";
380339640Smm    case st_Block:	return "Block";
381348608Smm    case st_End:	return "End";
382348608Smm    case st_Member:	return "Member";
383339640Smm    case st_Typedef:	return "Typedef";
384348608Smm    case st_File:	return "File";
385348608Smm    case st_RegReloc:	return "RegReloc";
386339640Smm    case st_Forward:	return "Forward";
387358090Smm    case st_StaticProc:	return "StaticProc";
388348608Smm    case st_Constant:	return "Constant";
389339640Smm    case st_StaParam:	return "StaticParam";
390348608Smm#ifdef stStruct
391348608Smm    case st_Struct:	return "Struct";
392339640Smm    case st_Union:	return "Union";
393348608Smm    case st_Enum:	return "Enum";
394339640Smm#endif
395339640Smm    case st_Str:	return "String";
396339640Smm    case st_Number:	return "Number";
397339640Smm    case st_Expr:	return "Expr";
398348608Smm    case st_Type:	return "Type";
399339640Smm    case st_Max:	return "Max";
400339640Smm    }
401339640Smm
402339640Smm  return "???";
403339640Smm}
404339640Smm
405348608Smm
406339640Smm/* Convert debug level to string.  */
407339640Smm
408339640Smmstatic const char *
409339640Smmglevel_to_string (glevel_t g_level)
410339640Smm{
411348608Smm  switch(g_level)
412348608Smm    {
413348608Smm    case GLEVEL_0: return "G0";
414348608Smm    case GLEVEL_1: return "G1";
415348608Smm    case GLEVEL_2: return "G2";
416339640Smm    case GLEVEL_3: return "G3";
417339640Smm    }
418339640Smm
419339640Smm  return "??";
420339640Smm}
421348608Smm
422348608Smm
423339640Smm/* Convert the type information to string format.  */
424348608Smm
425348608Smmstatic const char *
426339640Smmtype_to_string (AUXU *aux_ptr, int index, FDR *fdp)
427348608Smm{
428348608Smm  AUXU u;
429348608Smm  struct qual {
430339640Smm    tq_t type;
431348608Smm    int  low_bound;
432339640Smm    int  high_bound;
433339640Smm    int  stride;
434339640Smm  } qualifiers[7];
435339640Smm
436339640Smm  bt_t basic_type;
437348608Smm  int i;
438348608Smm  static char buffer1[1024];
439348608Smm  static char buffer2[1024];
440339640Smm  char *p1 = buffer1;
441339640Smm  char *p2 = buffer2;
442348608Smm  char *used_ptr = aux_used + (aux_ptr - aux_symbols);
443339640Smm
444339640Smm  for (i = 0; i < 7; i++)
445348608Smm    {
446348608Smm      qualifiers[i].low_bound = 0;
447339640Smm      qualifiers[i].high_bound = 0;
448348608Smm      qualifiers[i].stride = 0;
449348608Smm    }
450339640Smm
451348608Smm  used_ptr[index] = 1;
452348608Smm  u = aux_ptr[index++];
453339640Smm  if (u.isym == -1)
454339640Smm    return "-1 (no type)";
455348608Smm
456339640Smm  basic_type = (bt_t) u.ti.bt;
457348608Smm  qualifiers[0].type = (tq_t) u.ti.tq0;
458339640Smm  qualifiers[1].type = (tq_t) u.ti.tq1;
459339640Smm  qualifiers[2].type = (tq_t) u.ti.tq2;
460348608Smm  qualifiers[3].type = (tq_t) u.ti.tq3;
461339640Smm  qualifiers[4].type = (tq_t) u.ti.tq4;
462348608Smm  qualifiers[5].type = (tq_t) u.ti.tq5;
463339640Smm  qualifiers[6].type = tq_Nil;
464339640Smm
465348608Smm  /*
466348608Smm   * Go get the basic type.
467348608Smm   */
468339640Smm  switch (basic_type)
469348608Smm    {
470348608Smm    case bt_Nil:		/* undefined */
471339640Smm      strcpy (p1, "nil");
472348608Smm      break;
473348608Smm
474339640Smm    case bt_Adr:		/* address - integer same size as pointer */
475348608Smm      strcpy (p1, "address");
476339640Smm      break;
477348608Smm
478348608Smm    case bt_Char:		/* character */
479348608Smm      strcpy (p1, "char");
480348608Smm      break;
481339640Smm
482339640Smm    case bt_UChar:		/* unsigned character */
483348608Smm      strcpy (p1, "unsigned char");
484348608Smm      break;
485348608Smm
486348608Smm    case bt_Short:		/* short */
487348608Smm      strcpy (p1, "short");
488348608Smm      break;
489348608Smm
490348608Smm    case bt_UShort:		/* unsigned short */
491348608Smm      strcpy (p1, "unsigned short");
492348608Smm      break;
493348608Smm
494348608Smm    case bt_Int:		/* int */
495348608Smm      strcpy (p1, "int");
496348608Smm      break;
497348608Smm
498339640Smm    case bt_UInt:		/* unsigned int */
499348608Smm      strcpy (p1, "unsigned int");
500339640Smm      break;
501339640Smm
502348608Smm    case bt_Long:		/* long */
503348608Smm      strcpy (p1, "long");
504348608Smm      break;
505348608Smm
506348608Smm    case bt_ULong:		/* unsigned long */
507348608Smm      strcpy (p1, "unsigned long");
508348608Smm      break;
509339640Smm
510348608Smm    case bt_Float:		/* float (real) */
511348608Smm      strcpy (p1, "float");
512348608Smm      break;
513348608Smm
514348608Smm    case bt_Double:		/* Double (real) */
515348608Smm      strcpy (p1, "double");
516339640Smm      break;
517339640Smm
518348608Smm      /* Structures add 1-2 aux words:
519348608Smm	 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
520348608Smm	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
521348608Smm
522339640Smm    case bt_Struct:		/* Structure (Record) */
523339640Smm      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "struct", fdp);
524339640Smm      used_ptr[index] = 1;
525348608Smm      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
526339640Smm	used_ptr[++index] = 1;
527348608Smm
528339640Smm      index++;			/* skip aux words */
529339640Smm      break;
530339640Smm
531339640Smm      /* Unions add 1-2 aux words:
532348608Smm	 1st word is [ST_RFDESCAPE, offset] pointer to union def;
533348608Smm	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
534339640Smm
535348608Smm    case bt_Union:		/* Union */
536348608Smm      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "union", fdp);
537348608Smm      used_ptr[index] = 1;
538339640Smm      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
539348608Smm	used_ptr[++index] = 1;
540348608Smm
541339640Smm      index++;			/* skip aux words */
542339640Smm      break;
543339640Smm
544348608Smm      /* Enumerations add 1-2 aux words:
545348608Smm	 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
546339640Smm	 2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
547348608Smm
548348608Smm    case bt_Enum:		/* Enumeration */
549348608Smm      emit_aggregate (p1, aux_ptr[index], aux_ptr[index+1], "enum", fdp);
550348608Smm      used_ptr[index] = 1;
551348608Smm      if (aux_ptr[index].rndx.rfd == ST_RFDESCAPE)
552348608Smm	used_ptr[++index] = 1;
553348608Smm
554339640Smm      index++;			/* skip aux words */
555348608Smm      break;
556348608Smm
557348608Smm    case bt_Typedef:		/* defined via a typedef, isymRef points */
558339640Smm      strcpy (p1, "typedef");
559348608Smm      break;
560348608Smm
561348608Smm    case bt_Range:		/* subrange of int */
562348608Smm      strcpy (p1, "subrange");
563348608Smm      break;
564339640Smm
565348608Smm    case bt_Set:		/* pascal sets */
566339640Smm      strcpy (p1, "set");
567339640Smm      break;
568339640Smm
569348608Smm    case bt_Complex:		/* fortran complex */
570339640Smm      strcpy (p1, "complex");
571348608Smm      break;
572348608Smm
573339640Smm    case bt_DComplex:		/* fortran double complex */
574348608Smm      strcpy (p1, "double complex");
575348608Smm      break;
576348608Smm
577348608Smm    case bt_Indirect:		/* forward or unnamed typedef */
578339640Smm      strcpy (p1, "forward/unnamed typedef");
579348608Smm      break;
580348608Smm
581348608Smm    case bt_FixedDec:		/* Fixed Decimal */
582348608Smm      strcpy (p1, "fixed decimal");
583339640Smm      break;
584348608Smm
585348608Smm    case bt_FloatDec:		/* Float Decimal */
586348608Smm      strcpy (p1, "float decimal");
587348608Smm      break;
588348608Smm
589339640Smm    case bt_String:		/* Varying Length Character String */
590348608Smm      strcpy (p1, "string");
591348608Smm      break;
592339640Smm
593348608Smm    case bt_Bit:		/* Aligned Bit String */
594348608Smm      strcpy (p1, "bit");
595348608Smm      break;
596339640Smm
597348608Smm    case bt_Picture:		/* Picture */
598348608Smm      strcpy (p1, "picture");
599348608Smm      break;
600348608Smm
601348608Smm    case bt_Void:		/* Void */
602348608Smm      strcpy (p1, "void");
603348608Smm      break;
604348608Smm
605348608Smm    default:
606348608Smm      sprintf (p1, "Unknown basic type %d", (int) basic_type);
607348608Smm      break;
608348608Smm    }
609339640Smm
610348608Smm  p1 += strlen (buffer1);
611348608Smm
612348608Smm  /*
613339640Smm   * If this is a bitfield, get the bitsize.
614348608Smm   */
615339640Smm  if (u.ti.fBitfield)
616339640Smm    {
617339640Smm      int bitsize;
618348608Smm
619348608Smm      used_ptr[index] = 1;
620339640Smm      bitsize = aux_ptr[index++].width;
621348608Smm      sprintf (p1, " : %d", bitsize);
622348608Smm      p1 += strlen (buffer1);
623348608Smm    }
624348608Smm
625339640Smm
626348608Smm  /*
627348608Smm   * Deal with any qualifiers.
628348608Smm   */
629349901Smm  if (qualifiers[0].type != tq_Nil)
630339640Smm    {
631349901Smm      /*
632348608Smm       * Snarf up any array bounds in the correct order.  Arrays
633348608Smm       * store 5 successive words in the aux. table:
634348608Smm       *	word 0	RNDXR to type of the bounds (i.e., int)
635348608Smm       *	word 1	Current file descriptor index
636339640Smm       *	word 2	low bound
637348608Smm       *	word 3	high bound (or -1 if [])
638348608Smm       *	word 4	stride size in bits
639348608Smm       */
640348608Smm      for (i = 0; i < 7; i++)
641348608Smm	{
642339640Smm	  if (qualifiers[i].type == tq_Array)
643348608Smm	    {
644339640Smm	      qualifiers[i].low_bound  = aux_ptr[index+2].dnLow;
645339640Smm	      qualifiers[i].high_bound = aux_ptr[index+3].dnHigh;
646339640Smm	      qualifiers[i].stride     = aux_ptr[index+4].width;
647348608Smm	      used_ptr[index] = 1;
648348608Smm	      used_ptr[index+1] = 1;
649339640Smm	      used_ptr[index+2] = 1;
650348608Smm	      used_ptr[index+3] = 1;
651339640Smm	      used_ptr[index+4] = 1;
652348608Smm	      index += 5;
653348608Smm	    }
654348608Smm	}
655348608Smm
656348608Smm      /*
657348608Smm       * Now print out the qualifiers.
658339640Smm       */
659348608Smm      for (i = 0; i < 6; i++)
660348608Smm	{
661348608Smm	  switch (qualifiers[i].type)
662348608Smm	    {
663339640Smm	    case tq_Nil:
664348608Smm	    case tq_Max:
665348608Smm	      break;
666348608Smm
667348608Smm	    case tq_Ptr:
668348608Smm	      strcpy (p2, "ptr to ");
669348608Smm	      p2 += sizeof ("ptr to ")-1;
670339640Smm	      break;
671348608Smm
672348608Smm	    case tq_Vol:
673348608Smm	      strcpy (p2, "volatile ");
674339640Smm	      p2 += sizeof ("volatile ")-1;
675348608Smm	      break;
676348608Smm
677348608Smm	    case tq_Far:
678348608Smm	      strcpy (p2, "far ");
679348608Smm	      p2 += sizeof ("far ")-1;
680348608Smm	      break;
681339640Smm
682348608Smm	    case tq_Proc:
683348608Smm	      strcpy (p2, "func. ret. ");
684348608Smm	      p2 += sizeof ("func. ret. ");
685348608Smm	      break;
686339640Smm
687348608Smm	    case tq_Array:
688348608Smm	      {
689348608Smm		int first_array = i;
690348608Smm		int j;
691348608Smm
692339640Smm		/* Print array bounds reversed (i.e., in the order the C
693348608Smm		   programmer writes them).  C is such a fun language....  */
694348608Smm
695339640Smm		while (i < 5 && qualifiers[i+1].type == tq_Array)
696348608Smm		  i++;
697348608Smm
698339640Smm		for (j = i; j >= first_array; j--)
699339640Smm		  {
700339640Smm		    strcpy (p2, "array [");
701339640Smm		    p2 += sizeof ("array [")-1;
702339640Smm		    if (qualifiers[j].low_bound != 0)
703339640Smm		      sprintf (p2,
704339640Smm			       "%ld:%ld {%ld bits}",
705348608Smm			       (long) qualifiers[j].low_bound,
706339640Smm			       (long) qualifiers[j].high_bound,
707348608Smm			       (long) qualifiers[j].stride);
708348608Smm
709348608Smm		    else if (qualifiers[j].high_bound != -1)
710339640Smm		      sprintf (p2,
711348608Smm			       "%ld {%ld bits}",
712348608Smm			       (long) (qualifiers[j].high_bound + 1),
713339640Smm			       (long) (qualifiers[j].stride));
714348608Smm
715348608Smm		    else
716348608Smm		      sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
717348608Smm
718339640Smm		    p2 += strlen (p2);
719348608Smm		    strcpy (p2, "] of ");
720348608Smm		    p2 += sizeof ("] of ")-1;
721348608Smm		  }
722348608Smm	      }
723348608Smm	      break;
724348608Smm	    }
725339640Smm	}
726348608Smm    }
727348608Smm
728348608Smm  strcpy (p2, buffer1);
729339640Smm  return buffer2;
730348608Smm}
731348608Smm
732348608Smm
733339640Smm/* Print out the global file header for object files.  */
734348608Smm
735348608Smmstatic void
736348608Smmprint_global_hdr (struct filehdr *ptr)
737348608Smm{
738348608Smm  char *time = ctime ((time_t *)&ptr->f_timdat);
739348608Smm  ushort flags = ptr->f_flags;
740348608Smm
741339640Smm  printf("Global file header:\n");
742348608Smm  printf("    %-*s 0x%x\n",    24, "magic number",	     (ushort) ptr->f_magic);
743348608Smm  printf("    %-*s %d\n",      24, "# sections",	     (int)    ptr->f_nscns);
744339640Smm  printf("    %-*s %ld, %s",   24, "timestamp",		     (long)   ptr->f_timdat, time);
745339640Smm  printf("    %-*s %ld\n",     24, "symbolic header offset", (long)   ptr->f_symptr);
746348608Smm  printf("    %-*s %ld\n",     24, "symbolic header size",   (long)   ptr->f_nsyms);
747339640Smm  printf("    %-*s %ld\n",     24, "optional header",	     (long)   ptr->f_opthdr);
748339640Smm  printf("    %-*s 0x%x",     24, "flags",		     (ushort) flags);
749348608Smm
750339640Smm  if ((flags & F_RELFLG) != 0)
751348608Smm    printf (", F_RELFLG");
752339640Smm
753339640Smm  if ((flags & F_EXEC) != 0)
754339640Smm    printf (", F_EXEC");
755348608Smm
756348608Smm  if ((flags & F_LNNO) != 0)
757348608Smm    printf (", F_LNNO");
758339640Smm
759348608Smm  if ((flags & F_LSYMS) != 0)
760339640Smm    printf (", F_LSYMS");
761348608Smm
762348608Smm  if ((flags & F_MINMAL) != 0)
763348608Smm    printf (", F_MINMAL");
764348608Smm
765348608Smm  if ((flags & F_UPDATE) != 0)
766348608Smm    printf (", F_UPDATE");
767348608Smm
768348608Smm  if ((flags & F_SWABD) != 0)
769348608Smm    printf (", F_SWABD");
770348608Smm
771348608Smm  if ((flags & F_AR16WR) != 0)
772348608Smm    printf (", F_AR16WR");
773348608Smm
774348608Smm  if ((flags & F_AR32WR) != 0)
775348608Smm    printf (", F_AR32WR");
776348608Smm
777348608Smm  if ((flags & F_AR32W) != 0)
778348608Smm    printf (", F_AR32W");
779348608Smm
780339640Smm  if ((flags & F_PATCH) != 0)
781348608Smm    printf (", F_PATCH/F_NODF");
782348608Smm
783348608Smm  printf ("\n\n");
784348608Smm}
785348608Smm
786339640Smm
787348608Smm/* Print out the symbolic header.  */
788348608Smm
789348608Smmstatic void
790348608Smmprint_sym_hdr (HDRR *sym_ptr)
791348608Smm{
792348608Smm  int width = 20;
793348608Smm
794348608Smm  printf("Symbolic header, magic number = 0x%04x, vstamp = %d.%d:\n\n",
795339640Smm	 sym_ptr->magic & 0xffff,
796348608Smm	 (sym_ptr->vstamp & 0xffff) >> 8,
797348608Smm	 sym_ptr->vstamp & 0xff);
798348608Smm
799348608Smm  printf("    %-*s %11s %11s %11s\n", width, "Info", "Offset", "Number", "Bytes");
800348608Smm  printf("    %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
801339640Smm
802348608Smm  printf("    %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
803348608Smm	 (long) sym_ptr->cbLineOffset,
804339640Smm	 (long) sym_ptr->cbLine,
805339640Smm	 (long) sym_ptr->cbLine,
806339640Smm	 (int) sym_ptr->ilineMax);
807348608Smm
808339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
809348608Smm	 (long) sym_ptr->cbDnOffset,
810348608Smm	 (long) sym_ptr->idnMax,
811348608Smm	 (long) (sym_ptr->idnMax * sizeof (DNR)));
812348608Smm
813339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
814339640Smm	 (long) sym_ptr->cbPdOffset,
815348608Smm	 (long) sym_ptr->ipdMax,
816348608Smm	 (long) (sym_ptr->ipdMax * sizeof (PDR)));
817348608Smm
818339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
819348608Smm	 (long) sym_ptr->cbSymOffset,
820348608Smm	 (long) sym_ptr->isymMax,
821339640Smm	 (long) (sym_ptr->isymMax * sizeof (SYMR)));
822348608Smm
823348608Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
824339640Smm	 (long) sym_ptr->cbOptOffset,
825339640Smm	 (long) sym_ptr->ioptMax,
826339640Smm	 (long) (sym_ptr->ioptMax * sizeof (OPTR)));
827348608Smm
828339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
829348608Smm	 (long) sym_ptr->cbAuxOffset,
830348608Smm	 (long) sym_ptr->iauxMax,
831348608Smm	 (long) (sym_ptr->iauxMax * sizeof (AUXU)));
832348608Smm
833339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Local Strings",
834348608Smm	 (long) sym_ptr->cbSsOffset,
835348608Smm	 (long) sym_ptr->issMax,
836348608Smm	 (long) sym_ptr->issMax);
837348608Smm
838339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "External Strings",
839348608Smm	 (long) sym_ptr->cbSsExtOffset,
840348608Smm	 (long) sym_ptr->issExtMax,
841348608Smm	 (long) sym_ptr->issExtMax);
842348608Smm
843339640Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "File Tables",
844348608Smm	 (long) sym_ptr->cbFdOffset,
845339640Smm	 (long) sym_ptr->ifdMax,
846348608Smm	 (long) (sym_ptr->ifdMax * sizeof (FDR)));
847348608Smm
848348608Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "Relative Files",
849339640Smm	 (long) sym_ptr->cbRfdOffset,
850339640Smm	 (long) sym_ptr->crfd,
851339640Smm	 (long) (sym_ptr->crfd * sizeof (ulong)));
852348608Smm
853348608Smm  printf("    %-*s %11ld %11ld %11ld\n", width, "External Symbols",
854339640Smm	 (long) sym_ptr->cbExtOffset,
855348608Smm	 (long) sym_ptr->iextMax,
856348608Smm	 (long) (sym_ptr->iextMax * sizeof (EXTR)));
857348608Smm}
858348608Smm
859348608Smm
860339640Smm/* Print out a symbol.  */
861348608Smm
862348608Smmstatic void
863348608Smmprint_symbol (SYMR *sym_ptr, int number, const char *strbase, AUXU *aux_base,
864339640Smm	      int ifd, FDR *fdp)
865348608Smm{
866348608Smm  sc_t storage_class = (sc_t) sym_ptr->sc;
867348608Smm  st_t symbol_type   = (st_t) sym_ptr->st;
868348608Smm  ulong index	     = sym_ptr->index;
869339640Smm  char *used_ptr     = aux_used + (aux_base - aux_symbols);
870339640Smm  scope_t *scope_ptr;
871339640Smm
872348608Smm  printf ("\n    Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
873339640Smm
874348608Smm  if (aux_base != (AUXU *) 0 && index != indexNil)
875348608Smm    switch (symbol_type)
876348608Smm      {
877339640Smm      case st_Nil:
878348608Smm      case st_Label:
879339640Smm	break;
880339640Smm
881339640Smm      case st_File:
882348608Smm      case st_Block:
883339640Smm	printf ("      End+1 symbol: %ld\n", index);
884358090Smm	if (want_scope)
885348608Smm	  {
886348608Smm	    if (free_scope == (scope_t *) 0)
887339640Smm	      scope_ptr = xmalloc (sizeof (scope_t));
888348608Smm	    else
889348608Smm	      {
890348608Smm		scope_ptr = free_scope;
891348608Smm		free_scope = scope_ptr->prev;
892339640Smm	      }
893348608Smm	    scope_ptr->open_sym = number;
894339640Smm	    scope_ptr->st = symbol_type;
895339640Smm	    scope_ptr->sc = storage_class;
896339640Smm	    scope_ptr->prev = cur_scope;
897348608Smm	    cur_scope = scope_ptr;
898339640Smm	  }
899348608Smm	break;
900348608Smm
901348608Smm      case st_End:
902339640Smm	if (storage_class == sc_Text || storage_class == sc_Info)
903348608Smm	  printf ("      First symbol: %ld\n", index);
904339640Smm	else
905339640Smm	  {
906339640Smm	    used_ptr[index] = 1;
907339640Smm	    printf ("      First symbol: %ld\n", (long) aux_base[index].isym);
908339640Smm	  }
909339640Smm
910339640Smm	if (want_scope)
911339640Smm	  {
912339640Smm	    if (cur_scope == (scope_t *) 0)
913339640Smm	      printf ("      Can't pop end scope\n");
914339640Smm	    else
915339640Smm	      {
916339640Smm		scope_ptr = cur_scope;
917339640Smm		cur_scope = scope_ptr->prev;
918339640Smm		scope_ptr->prev = free_scope;
919339640Smm		free_scope = scope_ptr;
920339640Smm	      }
921339640Smm	  }
922339640Smm	break;
923339640Smm
924348608Smm      case st_Proc:
925339640Smm      case st_StaticProc:
926348608Smm	if (MIPS_IS_STAB(sym_ptr))
927348608Smm	  ;
928348608Smm	else if (ifd == -1)		/* local symbol */
929348608Smm	  {
930339640Smm	    used_ptr[index] = used_ptr[index+1] = 1;
931348608Smm	    printf ("      End+1 symbol: %-7ld   Type:  %s\n",
932348608Smm		    (long) aux_base[index].isym,
933348608Smm		    type_to_string (aux_base, index+1, fdp));
934348608Smm	  }
935348608Smm	else			/* global symbol */
936339640Smm	  printf ("      Local symbol: %ld\n", index);
937348608Smm
938348608Smm	if (want_scope)
939339640Smm	  {
940348608Smm	    if (free_scope == (scope_t *) 0)
941348608Smm	      scope_ptr = xmalloc (sizeof (scope_t));
942348608Smm	    else
943339640Smm	      {
944348608Smm		scope_ptr = free_scope;
945348608Smm		free_scope = scope_ptr->prev;
946348608Smm	      }
947348608Smm	    scope_ptr->open_sym = number;
948348608Smm	    scope_ptr->st = symbol_type;
949348608Smm	    scope_ptr->sc = storage_class;
950348608Smm	    scope_ptr->prev = cur_scope;
951348608Smm	    cur_scope = scope_ptr;
952339640Smm	  }
953348608Smm	break;
954348608Smm
955348608Smm#ifdef stStruct
956348608Smm      case st_Struct:
957348608Smm      case st_Union:
958348608Smm      case st_Enum:
959348608Smm	printf ("      End+1 symbol: %lu\n", index);
960348608Smm	break;
961348608Smm#endif
962348608Smm
963348608Smm      default:
964348608Smm	if (!MIPS_IS_STAB (sym_ptr))
965348608Smm	  {
966348608Smm	    used_ptr[index] = 1;
967348608Smm	    printf ("      Type: %s\n",
968348608Smm		    type_to_string (aux_base, index, fdp));
969348608Smm	  }
970339640Smm	break;
971348608Smm      }
972348608Smm
973348608Smm  if (want_scope)
974348608Smm    {
975339640Smm      printf ("      Scopes:  ");
976348608Smm      if (cur_scope == (scope_t *) 0)
977348608Smm	printf (" none\n");
978348608Smm      else
979348608Smm	{
980348608Smm	  for (scope_ptr = cur_scope;
981348608Smm	       scope_ptr != (scope_t *) 0;
982339640Smm	       scope_ptr = scope_ptr->prev)
983348608Smm	    {
984348608Smm	      const char *class;
985348608Smm	      if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
986348608Smm		class = "func.";
987348608Smm	      else if (scope_ptr->st == st_File)
988348608Smm		class = "file";
989348608Smm	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Text)
990339640Smm		class = "block";
991348608Smm	      else if (scope_ptr->st == st_Block && scope_ptr->sc == sc_Info)
992339640Smm		class = "type";
993339640Smm	      else
994339640Smm		class = "???";
995348608Smm
996339640Smm	      printf (" %ld [%s]", scope_ptr->open_sym, class);
997348608Smm	    }
998348608Smm	  printf ("\n");
999339640Smm	}
1000348608Smm    }
1001348608Smm
1002339640Smm  printf ("      Value: %-13ld    ",
1003348608Smm	  (long)sym_ptr->value);
1004348608Smm  if (ifd == -1)
1005348608Smm    printf ("String index: %ld\n", (long)sym_ptr->iss);
1006339640Smm  else
1007348608Smm    printf ("String index: %-11ld Ifd: %d\n",
1008348608Smm	    (long)sym_ptr->iss, ifd);
1009348608Smm
1010348608Smm  printf ("      Symbol type: %-11sStorage class: %-11s",
1011339640Smm	  st_to_string (symbol_type), sc_to_string (storage_class));
1012348608Smm
1013339640Smm  if (MIPS_IS_STAB(sym_ptr))
1014339640Smm    {
1015339640Smm      int i = ARRAY_SIZE (stab_names);
1016348608Smm      const char *stab_name = "stab";
1017348608Smm      short code = MIPS_UNMARK_STAB(sym_ptr->index);
1018348608Smm
1019348608Smm      while (--i >= 0)
1020348608Smm	if (stab_names[i].code == code)
1021348608Smm	  {
1022348608Smm	    stab_name = stab_names[i].string;
1023348608Smm	    break;
1024339640Smm	  }
1025339640Smm      printf ("Index: 0x%lx (%s)\n", (long)sym_ptr->index, stab_name);
1026339640Smm    }
1027348608Smm  else if (sym_ptr->st == stLabel && sym_ptr->index != indexNil)
1028348608Smm    printf ("Index: %ld (line#)\n", (long)sym_ptr->index);
1029348608Smm  else
1030348608Smm    printf ("Index: %ld\n", (long)sym_ptr->index);
1031348608Smm
1032348608Smm}
1033339640Smm
1034339640Smm
1035339640Smm/* Print out a word from the aux. table in various formats.  */
1036348608Smm
1037348608Smmstatic void
1038348608Smmprint_aux (AUXU u, int auxi, int used)
1039339640Smm{
1040339640Smm  printf ("\t%s#%-5d %11ld, [%4ld/%7ld], [%2d %1d:%1d %1x:%1x:%1x:%1x:%1x:%1x]\n",
1041339640Smm	  (used) ? "  " : "* ",
1042339640Smm	  auxi,
1043348608Smm	  (long) u.isym,
1044339640Smm	  (long) u.rndx.rfd,
1045348608Smm	  (long) u.rndx.index,
1046348608Smm	  u.ti.bt,
1047339640Smm	  u.ti.fBitfield,
1048348608Smm	  u.ti.continued,
1049348608Smm	  u.ti.tq0,
1050348608Smm	  u.ti.tq1,
1051348608Smm	  u.ti.tq2,
1052348608Smm	  u.ti.tq3,
1053339640Smm	  u.ti.tq4,
1054348608Smm	  u.ti.tq5);
1055348608Smm}
1056348608Smm
1057339640Smm
1058348608Smm/* Write aggregate information to a string.  */
1059348608Smm
1060339640Smmstatic void
1061348608Smmemit_aggregate (char *string, AUXU u, AUXU u2, const char *which, FDR *fdp)
1062339640Smm{
1063348608Smm  unsigned int ifd = u.rndx.rfd;
1064348608Smm  unsigned int index = u.rndx.index;
1065339640Smm  const char *name;
1066348608Smm
1067339640Smm  if (ifd == ST_RFDESCAPE)
1068339640Smm    ifd = u2.isym;
1069339640Smm
1070348608Smm  /* An ifd of -1 is an opaque type.  An escaped index of 0 is a
1071348608Smm     struct return type of a procedure compiled without -g.  */
1072348608Smm  if (ifd == 0xffffffff
1073339640Smm      || (u.rndx.rfd == ST_RFDESCAPE && index == 0))
1074348608Smm    name = "<undefined>";
1075348608Smm  else if (index == indexNil)
1076339640Smm    name = "<no name>";
1077339640Smm  else
1078339640Smm    {
1079348608Smm      if (fdp == 0 || sym_hdr.crfd == 0)
1080348608Smm	fdp = &file_desc[ifd];
1081348608Smm      else
1082339640Smm	fdp = &file_desc[rfile_desc[fdp->rfdBase + ifd]];
1083348608Smm      name = &l_strings[fdp->issBase + l_symbols[index + fdp->isymBase].iss];
1084348608Smm    }
1085339640Smm
1086339640Smm  sprintf (string,
1087339640Smm	   "%s %s { ifd = %u, index = %u }",
1088348608Smm	   which, name, ifd, index);
1089358090Smm}
1090339640Smm
1091358090Smm
1092358090Smm/* Print out information about a file descriptor, and the symbols,
1093358090Smm   procedures, and line numbers within it.  */
1094348608Smm
1095339640Smmstatic void
1096358090Smmprint_file_desc (FDR *fdp, int number)
1097348608Smm{
1098339640Smm  char *str_base;
1099348608Smm  AUXU *aux_base;
1100339640Smm  int symi, pdi;
1101339640Smm  int width = 20;
1102339640Smm  char *used_base;
1103348608Smm
1104339640Smm  str_base = l_strings + fdp->issBase;
1105348608Smm  aux_base = aux_symbols + fdp->iauxBase;
1106348608Smm  used_base = aux_used + (aux_base - aux_symbols);
1107339640Smm
1108348608Smm  printf ("\nFile #%d, \"%s\"\n\n",
1109348608Smm	  number,
1110348608Smm	  fdp->rss != issNil ? str_base + fdp->rss : "<unknown>");
1111348608Smm
1112339640Smm  printf ("    Name index  = %-10ld Readin      = %s\n",
1113348608Smm	  (long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
1114339640Smm
1115339640Smm  printf ("    Merge       = %-10s Endian      = %s\n",
1116348608Smm	  (fdp->fMerge)  ? "Yes" : "No",
1117348608Smm	  (fdp->fBigendian) ? "BIG" : "LITTLE");
1118348608Smm
1119348608Smm  printf ("    Debug level = %-10s Language    = %s\n",
1120348608Smm	  glevel_to_string (fdp->glevel),
1121339640Smm	  lang_to_string((lang_t) fdp->lang));
1122348608Smm
1123348608Smm  printf ("    Adr         = 0x%08lx\n\n", (long) fdp->adr);
1124348608Smm
1125339640Smm  printf("    %-*s %11s %11s %11s %11s\n", width, "Info", "Start", "Number", "Size", "Offset");
1126348608Smm  printf("    %-*s %11s %11s %11s %11s\n", width, "====", "=====", "======", "====", "======");
1127339640Smm
1128339640Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1129339640Smm	 width, "Local strings",
1130348608Smm	 (ulong) fdp->issBase,
1131348608Smm	 (ulong) fdp->cbSs,
1132339640Smm	 (ulong) fdp->cbSs,
1133339640Smm	 (ulong) (fdp->issBase + sym_hdr.cbSsOffset));
1134349525Smm
1135349525Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1136349525Smm	 width, "Local symbols",
1137349525Smm	 (ulong) fdp->isymBase,
1138349525Smm	 (ulong) fdp->csym,
1139349525Smm	 (ulong) (fdp->csym * sizeof (SYMR)),
1140349525Smm	 (ulong) (fdp->isymBase * sizeof (SYMR) + sym_hdr.cbSymOffset));
1141339640Smm
1142348608Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1143348608Smm	 width, "Line numbers",
1144348608Smm	 (ulong) fdp->cbLineOffset,
1145348608Smm	 (ulong) fdp->cline,
1146348608Smm	 (ulong) fdp->cbLine,
1147348608Smm	 (ulong) (fdp->cbLineOffset + sym_hdr.cbLineOffset));
1148348608Smm
1149339640Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1150339640Smm	 width, "Optimization symbols",
1151339640Smm	 (ulong) fdp->ioptBase,
1152348608Smm	 (ulong) fdp->copt,
1153339640Smm	 (ulong) (fdp->copt * sizeof (OPTR)),
1154348608Smm	 (ulong) (fdp->ioptBase * sizeof (OPTR) + sym_hdr.cbOptOffset));
1155339640Smm
1156358090Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1157358090Smm	 width, "Procedures",
1158358090Smm	 (ulong) fdp->ipdFirst,
1159358090Smm	 (ulong) fdp->cpd,
1160348608Smm	 (ulong) (fdp->cpd * sizeof (PDR)),
1161348608Smm	 (ulong) (fdp->ipdFirst * sizeof (PDR) + sym_hdr.cbPdOffset));
1162348608Smm
1163339640Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1164348608Smm	 width, "Auxiliary symbols",
1165348608Smm	 (ulong) fdp->iauxBase,
1166348608Smm	 (ulong) fdp->caux,
1167348608Smm	 (ulong) (fdp->caux * sizeof (AUXU)),
1168339640Smm	 (ulong) (fdp->iauxBase * sizeof(AUXU) + sym_hdr.cbAuxOffset));
1169348608Smm
1170348608Smm  printf("    %-*s %11lu %11lu %11lu %11lu\n",
1171339640Smm	 width, "Relative Files",
1172348608Smm	 (ulong) fdp->rfdBase,
1173348608Smm	 (ulong) fdp->crfd,
1174348608Smm	 (ulong) (fdp->crfd * sizeof (ulong)),
1175348608Smm	 (ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
1176339640Smm
1177348608Smm
1178348608Smm  if (want_scope && cur_scope != (scope_t *) 0)
1179339640Smm    printf ("\n    Warning scope does not start at 0!\n");
1180348608Smm
1181339640Smm  /*
1182339640Smm   * print the info about the symbol table.
1183339640Smm   */
1184348608Smm  printf ("\n    There are %lu local symbols, starting at %lu\n",
1185339640Smm	  (ulong) fdp->csym,
1186358090Smm	  (ulong) (fdp->isymBase + sym_hdr.cbSymOffset));
1187348608Smm
1188339640Smm  for(symi = fdp->isymBase; symi < (fdp->csym + fdp->isymBase); symi++)
1189358090Smm    print_symbol (&l_symbols[symi],
1190358090Smm		  symi - fdp->isymBase,
1191358090Smm		  str_base,
1192358090Smm		  aux_base,
1193348608Smm		  -1,
1194348608Smm		  fdp);
1195339640Smm
1196348608Smm  if (want_scope && cur_scope != (scope_t *) 0)
1197348608Smm    printf ("\n    Warning scope does not end at 0!\n");
1198348608Smm
1199348608Smm  /*
1200339640Smm   * print the aux. table if desired.
1201348608Smm   */
1202348608Smm
1203348608Smm  if (want_aux && fdp->caux != 0)
1204348608Smm    {
1205348608Smm      int auxi;
1206339640Smm
1207348608Smm      printf ("\n    There are %lu auxiliary table entries, starting at %lu.\n\n",
1208348608Smm	      (ulong) fdp->caux,
1209339640Smm	      (ulong) (fdp->iauxBase + sym_hdr.cbAuxOffset));
1210348608Smm
1211348608Smm      for (auxi = fdp->iauxBase; auxi < (fdp->caux + fdp->iauxBase); auxi++)
1212339640Smm	print_aux (aux_base[auxi], auxi, used_base[auxi]);
1213348608Smm    }
1214348608Smm
1215348608Smm  /*
1216339640Smm   * print the relative file descriptors.
1217348608Smm   */
1218348608Smm  if (want_rfd && fdp->crfd != 0)
1219348608Smm    {
1220348608Smm      ulong *rfd_ptr, i;
1221348608Smm
1222348608Smm      printf ("\n    There are %lu relative file descriptors, starting at %lu.\n",
1223339640Smm	      (ulong) fdp->crfd,
1224348608Smm	      (ulong) fdp->rfdBase);
1225339640Smm
1226339640Smm      rfd_ptr = rfile_desc + fdp->rfdBase;
1227339640Smm      for (i = 0; i < (ulong) fdp->crfd; i++)
1228348608Smm	{
1229348608Smm	  printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
1230348608Smm	  rfd_ptr++;
1231339640Smm	}
1232339640Smm    }
1233339640Smm
1234348608Smm  /*
1235339640Smm   * do the procedure descriptors.
1236348608Smm   */
1237348608Smm  printf ("\n    There are %lu procedure descriptor entries, ", (ulong) fdp->cpd);
1238348608Smm  printf ("starting at %lu.\n", (ulong) fdp->ipdFirst);
1239348608Smm
1240339640Smm  for (pdi = fdp->ipdFirst; pdi < (fdp->cpd + fdp->ipdFirst); pdi++)
1241348608Smm    {
1242348608Smm      PDR *proc_ptr = &proc_desc[pdi];
1243348608Smm      printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
1244348608Smm
1245348608Smm      if (l_symbols != 0)
1246348608Smm	printf ("\t    Name index   = %-11ld Name          = \"%s\"\n",
1247339640Smm		(long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
1248348608Smm		l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
1249348608Smm
1250348608Smm      printf ("\t    .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
1251339640Smm	      (long) proc_ptr->regmask,
1252348608Smm	      (long) proc_ptr->regoffset,
1253339640Smm	      (long) proc_ptr->fregmask,
1254339640Smm	      (long) proc_ptr->fregoffset);
1255348608Smm
1256348608Smm      printf ("\t    .frame $%d,%ld,$%d\n",
1257348608Smm	      (int)  proc_ptr->framereg,
1258348608Smm	      (long) proc_ptr->frameoffset,
1259348608Smm	      (int)  proc_ptr->pcreg);
1260348608Smm
1261348608Smm      printf ("\t    Opt. start   = %-11ld Symbols start = %ld\n",
1262348608Smm	      (long) proc_ptr->iopt,
1263358090Smm	      (long) proc_ptr->isym);
1264348608Smm
1265348608Smm      printf ("\t    First line # = %-11ld Last line #   = %ld\n",
1266348608Smm	      (long) proc_ptr->lnLow,
1267348608Smm	      (long) proc_ptr->lnHigh);
1268348608Smm
1269348608Smm      printf ("\t    Line Offset  = %-11ld Address       = 0x%08lx\n",
1270348608Smm	      (long) proc_ptr->cbLineOffset,
1271348608Smm	      (long) proc_ptr->adr);
1272348608Smm
1273348608Smm      /*
1274348608Smm       * print the line number entries.
1275348608Smm       */
1276348608Smm
1277348608Smm      if (want_line && fdp->cline != 0)
1278348608Smm	{
1279348608Smm	  int delta, count;
1280348608Smm	  long cur_line = proc_ptr->lnLow;
1281348608Smm	  uchar *line_ptr = (((uchar *)lines) + proc_ptr->cbLineOffset
1282358090Smm			     + fdp->cbLineOffset);
1283348608Smm	  uchar *line_end;
1284348608Smm
1285348608Smm	  if (pdi == fdp->cpd + fdp->ipdFirst - 1)	/* last procedure */
1286348608Smm	    line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
1287348608Smm	  else						/* not last proc.  */
1288348608Smm	    line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
1289348608Smm			+ fdp->cbLineOffset);
1290348608Smm
1291348608Smm	  printf ("\n\tThere are %lu bytes holding line numbers, starting at %lu.\n",
1292348608Smm		  (ulong) (line_end - line_ptr),
1293348608Smm		  (ulong) (fdp->ilineBase + sym_hdr.cbLineOffset));
1294348608Smm
1295348608Smm	  while (line_ptr < line_end)
1296348608Smm	    {						/* sign extend nibble */
1297348608Smm	      delta = ((*line_ptr >> 4) ^ 0x8) - 0x8;
1298348608Smm	      count = (*line_ptr & 0xf) + 1;
1299348608Smm	      if (delta != -8)
1300348608Smm		line_ptr++;
1301348608Smm	      else
1302348608Smm		{
1303348608Smm		  delta = (((line_ptr[1]) & 0xff) << 8) + ((line_ptr[2]) & 0xff);
1304348608Smm		  delta = (delta ^ 0x8000) - 0x8000;
1305348608Smm		  line_ptr += 3;
1306348608Smm		}
1307348608Smm
1308348608Smm	      cur_line += delta;
1309339640Smm	      printf ("\t    Line %11ld,   delta %5d,   count %2d\n",
1310348608Smm		      cur_line,
1311339640Smm		      delta,
1312348608Smm		      count);
1313358090Smm	    }
1314348608Smm	}
1315339640Smm    }
1316348608Smm}
1317348608Smm
1318348608Smm
1319348608Smm/* Read in the portions of the .T file that we will print out.  */
1320348608Smm
1321348608Smmstatic void
1322348608Smmread_tfile (void)
1323339640Smm{
1324348608Smm  short magic;
1325348608Smm  off_t sym_hdr_offset = 0;
1326339640Smm
1327348608Smm  read_seek (&magic, sizeof (magic), 0, "Magic number");
1328348608Smm  if (!tfile)
1329348608Smm    {
1330348608Smm      /* Print out the global header, since this is not a T-file.  */
1331339640Smm
1332348608Smm      read_seek (&global_hdr, sizeof (global_hdr), 0, "Global file header");
1333339640Smm
1334348608Smm      print_global_hdr (&global_hdr);
1335348608Smm
1336348608Smm      if (global_hdr.f_symptr == 0)
1337348608Smm	{
1338348608Smm	  printf ("No symbolic header, Goodbye!\n");
1339339640Smm	  exit (1);
1340348608Smm	}
1341348608Smm
1342348608Smm      sym_hdr_offset = global_hdr.f_symptr;
1343348608Smm    }
1344348608Smm
1345339640Smm  read_seek (&sym_hdr, sizeof (sym_hdr), sym_hdr_offset, "Symbolic header");
1346348608Smm
1347348608Smm  print_sym_hdr (&sym_hdr);
1348348608Smm
1349348608Smm  lines = read_seek (NULL, sym_hdr.cbLine, sym_hdr.cbLineOffset,
1350348608Smm		     "Line numbers");
1351339640Smm
1352348608Smm  dense_nums = read_seek (NULL, sym_hdr.idnMax * sizeof (DNR),
1353348608Smm			  sym_hdr.cbDnOffset, "Dense numbers");
1354348608Smm
1355339640Smm  proc_desc = read_seek (NULL, sym_hdr.ipdMax * sizeof (PDR),
1356348608Smm			 sym_hdr.cbPdOffset, "Procedure tables");
1357348608Smm
1358339640Smm  l_symbols = read_seek (NULL, sym_hdr.isymMax * sizeof (SYMR),
1359348608Smm			 sym_hdr.cbSymOffset, "Local symbols");
1360339640Smm
1361339640Smm  opt_symbols = read_seek (NULL, sym_hdr.ioptMax * sizeof (OPTR),
1362348608Smm			   sym_hdr.cbOptOffset, "Optimization symbols");
1363348608Smm
1364339640Smm  aux_symbols = read_seek (NULL, sym_hdr.iauxMax * sizeof (AUXU),
1365348608Smm			   sym_hdr.cbAuxOffset, "Auxiliary symbols");
1366348608Smm
1367348608Smm  if (sym_hdr.iauxMax > 0)
1368348608Smm    aux_used = xcalloc (sym_hdr.iauxMax, 1);
1369339640Smm
1370348608Smm  l_strings = read_seek (NULL, sym_hdr.issMax,
1371348608Smm			 sym_hdr.cbSsOffset, "Local string table");
1372348608Smm
1373348608Smm  e_strings = read_seek (NULL, sym_hdr.issExtMax,
1374348608Smm			 sym_hdr.cbSsExtOffset, "External string table");
1375339640Smm
1376348608Smm  file_desc = read_seek (NULL, sym_hdr.ifdMax * sizeof (FDR),
1377348608Smm			 sym_hdr.cbFdOffset, "File tables");
1378348608Smm
1379348608Smm  rfile_desc = read_seek (NULL, sym_hdr.crfd * sizeof (ulong),
1380348608Smm			  sym_hdr.cbRfdOffset, "Relative file tables");
1381339640Smm
1382348608Smm  e_symbols = read_seek (NULL, sym_hdr.iextMax * sizeof (EXTR),
1383348608Smm			 sym_hdr.cbExtOffset, "External symbols");
1384348608Smm}
1385339640Smm
1386348608Smm
1387348608Smm
1388339640Smmextern int main (int, char **);
1389348608Smm
1390348608Smmint
1391348608Smmmain (int argc, char **argv)
1392348608Smm{
1393348608Smm  int i, opt;
1394339640Smm
1395348608Smm  /*
1396348608Smm   * Process arguments
1397348608Smm   */
1398348608Smm  while ((opt = getopt_long (argc, argv, "alrsvt", options, NULL)) != -1)
1399348608Smm    switch (opt)
1400339640Smm      {
1401348608Smm      default:	errors++;	break;
1402348608Smm      case 'a': want_aux++;	break;	/* print aux table */
1403339640Smm      case 'l': want_line++;	break;	/* print line numbers */
1404348608Smm      case 'r': want_rfd++;	break;	/* print relative fd's */
1405348608Smm      case 's':	want_scope++;	break;	/* print scope info */
1406348608Smm      case 'v': verbose++;	break;  /* print version # */
1407348608Smm      case 'V': version++;	break;  /* print version # */
1408348608Smm      case 't': tfile++;	break;	/* this is a tfile (without header),
1409348608Smm					   and not a .o */
1410348608Smm      }
1411348608Smm
1412348608Smm  if (version)
1413348608Smm    {
1414348608Smm      printf ("mips-tdump (GCC) %s\n", version_string);
1415348608Smm      fputs ("Copyright (C) 2006 Free Software Foundation, Inc.\n", stdout);
1416348608Smm      fputs ("This is free software; see the source for copying conditions.  There is NO\n\
1417348608Smmwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n",
1418348608Smm             stdout);
1419348608Smm      exit (0);
1420348608Smm    }
1421348608Smm
1422348608Smm  if (optind != argc - 1)
1423348608Smm    errors++;
1424348608Smm
1425348608Smm  if (verbose || errors)
1426348608Smm    {
1427348608Smm      fprintf (stderr, "mips-tdump (GCC) %s", version_string);
1428348608Smm#ifdef TARGET_VERSION
1429348608Smm      TARGET_VERSION;
1430348608Smm#endif
1431339640Smm      fputc ('\n', stderr);
1432339640Smm    }
1433348608Smm
1434348608Smm  if (errors)
1435348608Smm    {
1436348608Smm      fprintf (stderr, "Calling Sequence:\n");
1437348608Smm      fprintf (stderr, "\t%s [-alrst] <object-or-T-file>\n", argv[0]);
1438348608Smm      fprintf (stderr, "\n");
1439348608Smm      fprintf (stderr, "switches:\n");
1440348608Smm      fprintf (stderr, "\t-a Print out auxiliary table.\n");
1441348608Smm      fprintf (stderr, "\t-l Print out line numbers.\n");
1442348608Smm      fprintf (stderr, "\t-r Print out relative file descriptors.\n");
1443348608Smm      fprintf (stderr, "\t-s Print out the current scopes for an item.\n");
1444348608Smm      fprintf (stderr, "\t-t Assume there is no global header (ie, a T-file).\n");
1445348608Smm      fprintf (stderr, "\t-v Print program version.\n");
1446348608Smm      return 1;
1447348608Smm    }
1448348608Smm
1449348608Smm  /*
1450348608Smm   * Open and process the input file.
1451348608Smm   */
1452348608Smm  tfile_fd = open (argv[optind], O_RDONLY);
1453348608Smm  if (tfile_fd < 0)
1454348608Smm    {
1455348608Smm      perror (argv[optind]);
1456348608Smm      return 1;
1457348608Smm    }
1458348608Smm
1459348608Smm  read_tfile ();
1460348608Smm
1461348608Smm  /*
1462348608Smm   * Print any global aux words if any.
1463348608Smm   */
1464348608Smm  if (want_aux)
1465348608Smm    {
1466348608Smm      long last_aux_in_use;
1467348608Smm
1468348608Smm      if (sym_hdr.ifdMax != 0 && file_desc[0].iauxBase != 0)
1469348608Smm	{
1470348608Smm	  printf ("\nGlobal auxiliary entries before first file:\n");
1471348608Smm	  for (i = 0; i < file_desc[0].iauxBase; i++)
1472348608Smm	    print_aux (aux_symbols[i], 0, aux_used[i]);
1473348608Smm	}
1474348608Smm
1475348608Smm      if (sym_hdr.ifdMax == 0)
1476348608Smm	last_aux_in_use = 0;
1477348608Smm      else
1478348608Smm	last_aux_in_use
1479348608Smm	  = (file_desc[sym_hdr.ifdMax-1].iauxBase
1480348608Smm	     + file_desc[sym_hdr.ifdMax-1].caux - 1);
1481348608Smm
1482348608Smm      if (last_aux_in_use < sym_hdr.iauxMax-1)
1483348608Smm	{
1484348608Smm	  printf ("\nGlobal auxiliary entries after last file:\n");
1485348608Smm	  for (i = last_aux_in_use; i < sym_hdr.iauxMax; i++)
1486348608Smm	    print_aux (aux_symbols[i], i - last_aux_in_use, aux_used[i]);
1487348608Smm	}
1488348608Smm    }
1489348608Smm
1490348608Smm  /*
1491348608Smm   * Print the information for each file.
1492348608Smm   */
1493348608Smm  for (i = 0; i < sym_hdr.ifdMax; i++)
1494348608Smm    print_file_desc (&file_desc[i], i);
1495348608Smm
1496348608Smm  /*
1497348608Smm   * Print the external symbols.
1498348608Smm   */
1499348608Smm  want_scope = 0;		/* scope info is meaning for extern symbols */
1500348608Smm  printf ("\nThere are %lu external symbols, starting at %lu\n",
1501348608Smm	  (ulong) sym_hdr.iextMax,
1502348608Smm	  (ulong) sym_hdr.cbExtOffset);
1503348608Smm
1504348608Smm  for(i = 0; i < sym_hdr.iextMax; i++)
1505348608Smm    print_symbol (&e_symbols[i].asym, i, e_strings,
1506348608Smm		  aux_symbols + file_desc[e_symbols[i].ifd].iauxBase,
1507348608Smm		  e_symbols[i].ifd,
1508348608Smm		  &file_desc[e_symbols[i].ifd]);
1509348608Smm
1510348608Smm  /*
1511348608Smm   * Print unused aux symbols now.
1512348608Smm   */
1513348608Smm
1514348608Smm  if (want_aux)
1515348608Smm    {
1516348608Smm      int first_time = 1;
1517348608Smm
1518348608Smm      for (i = 0; i < sym_hdr.iauxMax; i++)
1519348608Smm	{
1520348608Smm	  if (! aux_used[i])
1521348608Smm	    {
1522348608Smm	      if (first_time)
1523348608Smm		{
1524348608Smm		  printf ("\nThe following auxiliary table entries were unused:\n\n");
1525348608Smm		  first_time = 0;
1526348608Smm		}
1527348608Smm
1528348608Smm	      printf ("    #%-5d %11ld  0x%08lx  %s\n",
1529348608Smm		      i,
1530348608Smm		      (long) aux_symbols[i].isym,
1531348608Smm		      (long) aux_symbols[i].isym,
1532348608Smm		      type_to_string (aux_symbols, i, (FDR *) 0));
1533348608Smm	    }
1534348608Smm	}
1535348608Smm    }
1536348608Smm
1537348608Smm  return 0;
1538348608Smm}
1539348608Smm